# Sora Python SDK for Raspberry Pi

Sora Python SDK は Raspberry Pi OS (64 bit) 向けに通常とは異なるパッケージを提供しています。

これは Raspberry Pi の H.264 ハードウェアアクセラレーターや libcamera を利用するためです。

## インストール

```bash
# Raspberry Pi OS (64 bit) 向けの sora-sdk をインストールする
uv add sora-sdk-rpi
```

## 利用方法

Raspberry Pi OS (64 bit) 向けの sora-sdk-rpi をインストールした後は、通常の sora-sdk と同じように利用できます。

### V4L2-M2M 経由でのハードウェアアクセラレーターの利用

> **注釈**
>
> Raspberry Pi 5 には H.264 ハードウェアアクセラレーターが搭載されていません。

Sora Python SDK for Raspberry Pi は Raspberry Pi に搭載されている H.264 ハードウェアアクセラレーターを利用することができます。

```python
video_codec_preference = SoraVideoCodecPreference(
    codecs=[
        # Raspberry Pi 5 には H.264 ハードウェアアクセラレーターが搭載されていません。
        SoraVideoCodecPreference.Codec(
            # H.264 を指定します
            type=SoraVideoCodecType.H264,
            # encoder と decoder に V4L2 M2M を指定します
            encoder=SoraVideoCodecImplementation.RASPI_V4L2M2M,
            decoder=SoraVideoCodecImplementation.RASPI_V4L2M2M,
        ),
    ],
)
```

### libcamera の利用

Raspberry Pi Camera を利用する場合は libcamera を利用する必要があります。
Sora Python SDK for Raspberry Pi では libcamera を利用するためのライブラリを提供しています。

```python
sora = Sora(
    video_codec_preference=video_codec_preference,
    # native_frame_output=True を指定する場合 force_i420_conversion=False を指定します
    force_i420_conversion=False,
)

# libcamera を利用するには create_libcamera_source
video_source = sora.create_libcamera_source(
    width=1280,
    height=720,
    fps=30,
    # native_frame_output=True を指定すると libcamera から直接 I420 フォーマットのフレームが取得できます。
    native_frame_output=True,
    # libcamera のオートフォーカスを有効にする。
    # libcamera-controls をタプル形式で指定出来ます
    controls=[("AsFocusMode", "1")],
)
```

## libcamera コントロール

libcamera は 75 以上のカメラパラメーターを提供しています。 Sora Python SDK for Raspberry Pi の `create_libcamera_source` では `controls` で libcamera コントロールを指定する事が出来ます。

### 指定方法

- `[tuple[str, str]]` の形式で指定します
- `[("AsFocusMode", "1"), ("AeEnable", "1")]` のように複数指定できます
- 値は数字やブーリアンでも文字列で指定してください
- `AsFocusMode` のように数値を指定する場合も `"1"` と文字列で指定してください

### 対応している値の形式

#### 基本型

- bool: `"0"` または `"1"`、 `"true"` または `"false"````python
  [("AeEnable", "1")]
  [("AeEnable", "true")]
  ```
- int32: 整数値```python
  [("ExposureTime", "10000")]
  ```
- int64: 長整数値```python
  [("FrameDuration", "33333")]
  ```
- float: 小数値```python
  [("AnalogueGain", "2.0")]
  [("Brightness", "-0.5")]
  ```
- enum: 文字列または数値（主要な enum のみ文字列対応）

  ```python
  [("AfMode", "Continuous")]
  # または
  [("AfMode", "2")]
  ```

  文字列対応済みの enum:

  - `AfMode`, `AfRange`, `AfSpeed`
  - `AeMeteringMode`
  - `AwbMode`
  - `ExposureTimeMode`, `AnalogueGainMode`

#### 複合型

- 配列: カンマ区切り

  ```python
  [("ColourGains", "1.5,2.0")]
  [("FrameDurationLimits", "33333,33333")]
  ```

  対応済み: `float[]`, `int32[]`, `int64[]`
- 矩形（Rectangle）: x,y,width,height```python
  [("ScalerCrop", "100,100,640,480")]
  ```
- 複数矩形: セミコロン区切り```python
  [("AfWindows", "100,100,200,200;300,300,200,200")]
  ```
  > **注釈**
  >
  > Rectangle 配列の場合、セミコロンで複数の矩形を区切ります
- マトリクス: カンマ区切り（行優先）（未対応）```python
  [("ColourCorrectionMatrix", "1.0,0,0,0,1.0,0,0,0,1.0")]
  ```

#### 未対応の型

- Size 型
- Point 型
- マトリクス型（3x3 など）
- その他の複雑な構造体

### 主要なコントロール

#### 露出制御（AE: Auto Exposure）

* - コントロール
  - 型
  - 説明
  - 値の例
* - AeEnable
  - bool
  - 自動露出の有効/無効
  - "0", "1"
* - ExposureTime
  - int32
  - 露出時間（マイクロ秒）
  - 10000 (1/100秒)
* - AnalogueGain
  - float
  - アナログゲイン（1.0以上）
  - 2.0
* - ExposureTimeMode
  - enum
  - 露出時間モード
  - Auto, Manual
* - AnalogueGainMode
  - enum
  - ゲインモード
  - Auto, Manual
* - AeMeteringMode
  - enum
  - 測光モード
  - CentreWeighted, Spot, Matrix
* - ExposureValue
  - float
  - EV補正値
  - -2.0 〜 2.0

#### オートフォーカス（AF）

* - コントロール
  - 型
  - 説明
  - 値の例
* - AfMode
  - enum
  - AFモード
  - Manual, Auto, Continuous
* - AfRange
  - enum
  - フォーカス範囲
  - Normal, Macro, Full
* - AfSpeed
  - enum
  - フォーカス速度
  - Normal, Fast
* - AfTrigger
  - enum
  - AFトリガー
  - Start, Cancel
* - AfWindows
  - Rectangle[]
  - AFエリア
  - "256,192,512,384"
* - LensPosition
  - float
  - レンズ位置（ジオプター）
  - 2.0

#### ホワイトバランス（AWB）

* - コントロール
  - 型
  - 説明
  - 値の例
* - AwbEnable
  - bool
  - AWBの有効/無効
  - "0", "1"
* - AwbMode
  - enum
  - AWBモード
  - Auto, Daylight, Cloudy, Tungsten
* - ColourTemperature
  - int32
  - 色温度（ケルビン）
  - 5500
* - ColourGains
  - float[2]
  - 赤・青ゲイン
  - 1.5,2.0

#### 画質調整

* - コントロール
  - 型
  - 説明
  - 値の例
* - Brightness
  - float
  - 明るさ
  - -1.0 〜 1.0
* - Contrast
  - float
  - コントラスト
  - 1.0（標準）
* - Saturation
  - float
  - 彩度
  - 1.0（標準）, 0.0（モノクロ）
* - Sharpness
  - float
  - シャープネス
  - 0.0 〜 10.0
* - Gamma
  - float
  - ガンマ値
  - 2.2（標準）

#### フレームレート制御

* - コントロール
  - 型
  - 説明
  - 値の例
* - FrameDurationLimits
  - int64[2]
  - フレーム時間の最小/最大（マイクロ秒）
  - 33333,33333 (30fps固定)

### enum 値一覧

#### AfMode（オートフォーカスモード）

- 手動フォーカス- `Manual` または `"0"`
- シングルAF（一度フォーカスして停止）- `Auto` または `"1"`
- コンティニュアスAF- `Continuous` または `"2"`

#### AfRange（フォーカス範囲）

- 通常範囲- `Normal` または `"0"`
- マクロ（接写）- `Macro` または `"1"`
- フルレンジ- `Full` または `"2"`

#### AfSpeed（フォーカス速度）

- 通常速度- `Normal` または `"0"`
- 高速- `Fast` または `"1"`

#### ExposureTimeMode / AnalogueGainMode

- 自動- `Auto` または `"0"`
- 手動- `Manual` または `"1"`

#### AeMeteringMode（測光モード）

- 中央重点測光- `CentreWeighted` または `"0"`
- スポット測光- `Spot` または `"1"`
- マトリックス測光- `Matrix` または `"2"`

#### AwbMode（ホワイトバランスモード）

- 自動- `Auto` または `"0"`
- 白熱灯- `Incandescent` または `"1"`
- タングステン- `Tungsten` または `"2"`
- 蛍光灯- `Fluorescent` または `"3"`
- 屋内- `Indoor` または `"4"`
- 昼光- `Daylight` または `"5"`
- 曇天- `Cloudy` または `"6"`

#### HdrMode（HDRモード）

- 無効- `Off` または `"0"`
- 複数露出（未合成）- `MultiExposureUnmerged` または `"1"`
- 複数露出（合成）- `MultiExposure` または `"2"`
- 単一露出HDR- `SingleExposure` または `"3"`
- ナイトモード- `Night` または `"4"`

### controls 指定例

#### 例1: 明るい屋外での撮影設定

```python
controls=[
    ("AeEnable", "1"),
    ("AeExposureMode", "Short"),
    ("AwbMode", "Daylight"),
    ("Contrast", "1.2"),
]
```

#### 例2: 暗所での撮影設定

```python
controls=[
    ("ExposureTimeMode", "Manual"),
    ("ExposureTime", "50000"),
    ("AnalogueGain", "8.0"),
    ("NoiseReductionMode", "HighQuality"),
]
```

#### 例3: マクロ撮影設定

```python
controls=[
    ("AfMode", "Continuous"),
    ("AfRange", "Macro"),
    ("AfSpeed", "Normal"),
    ("Sharpness", "2.0"),
]
```

#### 例4: フレームレート固定（30fps）

```python
controls=[
    ("FrameDurationLimits", "33333,33333"),
]
```

#### 例5: 手動設定での完全制御

```python
controls=[
    ("AeEnable", "0"),
    ("AwbEnable", "0"),
    ("ExposureTime", "20000"),
    ("AnalogueGain", "4.0"),
    ("ColourGains", "1.8,1.5"),
    ("AfMode", "Manual"),
    ("LensPosition", "2.0"),
]
```

## サンプル

`V4L2 M2M` で H.264 を指定し、 `libcamera` を利用したサンプルコードです。

```python
from sora_sdk import (
    Sora,
    SoraVideoCodecImplementation,
    SoraVideoCodecPreference,
    SoraVideoCodecType,
)


def main():
    signaling_urls = ["wss://sora.example.com/signaling"]
    video_codec_preference = SoraVideoCodecPreference(
        codecs=[
            # Raspberry Pi 5 には H.264 ハードウェアアクセラレーターが搭載されていません。
            SoraVideoCodecPreference.Codec(
                type=SoraVideoCodecType.H264,
                encoder=SoraVideoCodecImplementation.RASPI_V4L2M2M,
                decoder=SoraVideoCodecImplementation.RASPI_V4L2M2M,
            ),
        ],
    )
    sora = Sora(
        video_codec_preference=video_codec_preference,
        # native_frame_output=True を指定する場合は force_i420_conversion=False を指定する必要があります。
        force_i420_conversion=False,
    )

    video_source = sora.create_libcamera_source(
        width=1280,
        height=720,
        fps=30,
        # native_frame_output=True を指定すると、libcamera から直接 I420 フォーマットのフレームが取得できます。
        native_frame_output=True,
        # libcamera のオートフォーカスを有効にする。
        controls=[("AsFocusMode", "1")],
    )

    # V4L2 M2M による H.264 と libcamera を利用して Sora に接続して映像を送信する。
    sora.create_connection(
        signaling_urls=signaling_urls,
        role="sendonly",
        channel_id="raspberry-pi",
        video=True,
        video_codec_type="H264",
        video_source=video_source,
    )
```
