# sora_sdk モジュール


## 概要

sora_sdk ライブラリは Sora C++ SDK をラップしたライブラリです。
Sora のシグナリングなどを意識する必要はありません。

## 音声と映像の扱い

Sora Python SDK では音声や映像をデバイスから取得したり、画面に描画する機能を提供していません。
その部分は OpenCV や sounddevice などのライブラリを別途利用する必要があります。

## NDArray 型と LikeArray 型の注意

Sora Python SDK では音声や映像のデータを取り扱う際に NumPy の NDArray 型を利用します。

ただし [nanobind](https://nanobind.readthedocs.io/en/latest/) の制約により、
`pyi` では NDArray 型が ArrayLike 型になっています。

### 参考

- [Use `NDArray` instead of `ArrayLike` when `dtype` is given by yosh-matsuda · Pull Request #442 · wjakob/nanobind](https://github.com/wjakob/nanobind/pull/442)
- [nanobind 2.0.0: How can I customize the stubgen type used for `Eigen` arguments/return parameters? · wjakob/nanobind · Discussion #630](https://github.com/wjakob/nanobind/discussions/630)

## libwebrtc ログ指定

libwebrtc のログ出力を指定できます。

以下のように :py:class:`Sora` クライアントを生成する前に libwebrtc のログレベルを指定してください。

.. code-block::

   import sora_sdk

   if __name__ == '__main__':
      sora_sdk.enable_libwebrtc_log(sora_sdk.SoraLoggingSeverity.VERBOSE)

## 利用できるコーデック一覧の取得


## SoraVideoCodecCapability オブジェクト

.. py:method:: to_json()

   :rtype: str

   JSON 形式の文字列を返します。

.. py:attribute:: engines

   :rtype: List[:py:class:`SoraVideoCodecCapability.Engine`]

   :py:class:`SoraVideoCodecCapability.Engine` のリストを返します。


.. py:class:: Codec

.. py:class:: Engine

.. py:class:: Parameters

## Sora オブジェクト

Sora SDK の主要なクラスです。このクラスを使用して Sora への接続や、音声と映像のソースを作成します。

 :param video_codec_preference: :py:class:`SoraVideoCodecPreference` を指定します。何も指定しない場合は None で全てのコーデックは :py:class:`SoraVideoCodecImplementation.INTERNAL` を利用します。
 :type: :py:class:`SoraVideoCodecPreference` | None

 :param openh264: OpenH264 のパスを指定します。
 :type: str | None

 .. py:method:: create_audio_source(channels, sample_rate)
    
    :param int channels: チャンネル
    :param int sample_rate: サンプルレート
    :rtype: sora_sdk.SoraAudioSource

    Sora に音声を送るための :py:class:`SoraAudioSource` を作成します。

    :py:class:`SoraAudioSource` は送信する際に、ここで指定したチャネル数とサンプリングレートに入力されたデータを変換した上で送信します。

 .. py:method:: create_video_source()
    
    :rtype: sora_sdk.SoraVideoSource

    Sora に映像を送るための :py:class:`SoraVideoSource` を作成します。

.. py:method:: create_connection(signaling_urls, role, channel_id, \
      client_id=None, bundle_id=None, metadata=None, \
      signaling_notify_metadata=None, audio_source=None, video_source=None \
      audio=True, video=True, audio_codec_type=None, video_codec_type=None, \
      audio_bit_rate=None, video_bit_rate=None, video_vp9_params=None, \
      video_av1_params=None, video_h264_params=None, simulcast=None, \
      spotlight=None, spotlight_number=None, simulcast_rid=None, simulcast_request_rid=None, \
      spotlight_focus_rid=None, spotlight_unfocus_rid=None, \
      forwarding_filter=None, forwarding_filters=None, data_channels=None, \
      data_channel_signaling=None, ignore_disconnect_websocket=None, \
      data_channel_signaling_timeout=None, disconnect_wait_timeout=None, \
      websocket_close_timeout=None, websocket_connection_timeout=None, \
      audio_streaming_language_code=None, insecure=None, \
      client_cert=None, client_key=None, proxy_url=None, \
      proxy_username=None, proxy_password=None, proxy_agent=None)

   :param List[str] signaling_urls: シグナリング URLのリスト
   :param str role: ロール
   :param str channel_id: チャネル ID
   :param Optional[str] client_id: クライアント ID
   :param Optional[str] bundle_id: バンドル ID
   :param Optional[object] metadata: 認証メタデータ
   :param Optional[object] signaling_notify_metadata: シグナリング通知メタデータ
   :param Optional[sora_sdk.SoraTrackInterface] audio_source: 音声ソース
   :param Optional[sora_sdk.SoraTrackInterface] video_source: 映像ソース
   :param Optional[sora_sdk.SoraAudioFrameTransformer] audio_frame_transformer: 音声フレーム変換器
   :param Optional[sora_sdk.SoraVideoFrameTransformer] video_frame_transformer: 映像フレーム変換器
   :param Optional[bool] audio: 音声
   :param Optional[bool] video: 映像
   :param Optional[str] audio_codec_type: 音声コーデックタイプ
   :param Optional[str] video_codec_type: 映像コーデックタイプ
   :param Optional[int] audio_bit_rate: 音声ビットレート
   :param Optional[int] video_bit_rate: 映像ビットレート
   :param Optional[object] audio_opus_params: 音声 Opus 設定指定
   :param Optional[object] video_vp9_params: 映像 VP9 設定指定
   :param Optional[object] video_av1_params: 映像 AV1 設定指定
   :param Optional[object] video_h264_params: 映像 H.264 設定指定
   :param Optional[object] video_h265_params: 映像 H.265 設定指定
   :param Optional[bool] simulcast: サイマルキャスト
   :param Optional[bool] spotlight: スポットライト
   :param Optional[int] spotlight_number: スポットライトナンバー
   :param Optional[str] simulcast_rid: サイマルキャスト RID
   :param Optional[str] simulcast_request_rid: サイマルキャスト RID リクエスト
   :param Optional[str] spotlight_focus_rid: スポットライトフォーカス RID
   :param Optional[str] spotlight_unfocus_rid: スポットライトアンフォーカス RID
   :param Optional[object] forwarding_filter: 転送フィルター
   :param Optional[list[object]] forwarding_filters: 転送フィルターのリスト
   :param Optional[object] data_channels: データチャネル
   :param Optional[bool] data_channel_signaling: データチャネルシグナリング
   :param Optional[bool] ignore_disconnect_websocket: ウェブソケット切断無視
   :param Optional[int] data_channel_signaling_timeout: データチャネルシグナリングタイムアウト
   :param Optional[int] disconnect_wait_timeout: 切断待ちタイムアウト
   :param Optional[int] websocket_close_timeout: ウェブソケットクローズタイムアウト
   :param Optional[int] websocket_connection_timeout: ウェブソケット接続タイムアウト
   :param Optional[str] audio_streaming_language_code: 音声ストリーミング言語コード
   :param Optional[bool] insecure: サーバー証明書のチェックを無視する
   :param Optional[bytes] client_cert: クライアント証明書
   :param Optional[bytes] client_key: クライアント証明書シークレットキー
   :param Optional[bytes] ca_cert: サーバー証明書のチェックを行う CA 証明書
   :param Optional[str] proxy_url: Proxy URL
   :param Optional[str] proxy_username: Proxy ユーザ名
   :param Optional[str] proxy_password: Proxy パスワード
   :param Optional[str] proxy_agent: Proxy エージェント
   :param Optional[SoraDegradationPreference] degradation_preference: デグラデーション優先度
   :rtype: sora_sdk.SoraConnection

   Sora と接続するための SoraConnection を作成します。

### 接続して切断する最小コード

ただ繫いで、切断するだけのコードです。

```python
import time

from sora_sdk import Sora

if __name__ == "__main__":
    # Sora インスタンスを生成
    sora = Sora()
    # Sora に接続する
    conn = sora.create_connection(
        signaling_urls=["wss://example.com/signaling"],
        role="sendonly",
        channel_id="sora",
    )
    conn.connect()

    # 接続するまで待つ
    time.sleep(3)

    # connect() を呼んだら disconnect を呼ぶ
    conn.disconnect()
```

### mTLS を利用する際の最小コード

mTLS を利用する際の証明書は `open('cert.pem', 'rb').read()` のように読み込んだバイナリを渡してください。

```python
import time

from sora_sdk import Sora

if __name__ == "__main__":
    # Sora インスタンスを生成
    sora = Sora()
    # Sora に接続する
    conn = sora.create_connection(
        signaling_urls=["wss://example.com/signaling"],
        role="sendonly",
        channel_id="sora",
        # クライアント証明書を読み込む
        client_cert=open("cert.pem", "rb").read(),
        # クライアント証明書シークレットキーを読み込む
        client_key=open("cert-key.pem", "rb").read(),
        # CA 証明書を読み込む
        ca_cert=open("ca.pem", "rb").read(),
    )
    conn.connect()

    # 接続するまで待つ
    time.sleep(3)

    # Sora から切断する
    conn.disconnect()
```

### metadata にアクセストークンを指定する最小コード

Sora Cloud や Sora Labo を利用する際に metadata にアクセストークンを指定してください。

```python
import time

from sora_sdk import Sora

if __name__ == "__main__":
    # Sora インスタンスを生成
    sora = Sora()
    # Sora に接続する
    conn = sora.create_connection(
        signaling_urls=["wss://example.com/signaling"],
        role="sendonly",
        channel_id="sora",
        # dict をそのまま指定してください
        metadata={"access_token": "access_token"},
    )
    conn.connect()

    # 接続するまで待つ
    time.sleep(3)

    # Sora から切断する
    conn.disconnect()
```

### video_codec_preference を指定する最小コード

映像コーデックのエンコード/デコードを細かく指定する場合は Sora.video_codec_preference を指定してください。

```python
import time

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

if __name__ == "__main__":
    # Sora インスタンスを生成
    sora = Sora(
        # ビデオコーデックプリファレンスを指定する
        video_codec_preference=SoraVideoCodecPreference(
            codecs=[
                # H.264 のみを利用する
                SoraVideoCodecPreference.Codec(
                    type=SoraVideoCodecType.H264,
                    # H.264 のエンコーダーに OpenH264 を指定する
                    encoder=SoraVideoCodecImplementation.CISCO_OPENH264,
                    # sendonly なのでデコーダーは指定しない
                ),
            ],
        ),
        openh264="/path/to/libopenh264-2.6.0-linux64.7.so",
    )
    # Sora に接続する
    conn = sora.create_connection(
        signaling_urls=["wss://example.com/signaling"],
        role="sendonly",
        channel_id="sora",
    )
    conn.connect()

    # 接続するまで待つ
    time.sleep(3)

    # Sora から切断する
    conn.disconnect()
```

## SoraConnection オブジェクト

Sora との接続を制御する機能を提供します。

:py:meth:`Sora.create_connection` から生成します。

.. py:method:: connect()
   
   :return: None

   Sora に接続します。

   .. important:: もしスレッドを起動して audio/video の入力ループを開始する場合は、かならず connect() を呼び出す **前に** 開始してください。

.. py:method:: disconnect()

   :return: None

   Sora から切断します。 

   .. important:: connect() を呼んだ場合は、切断時または例外が上がった場合でも disconnect() を呼んでください。

.. py:method:: get_stats()

   :return: W3C 準拠の WebRTC 統計情報。
   :rtype: str

   クライアントの WebRTC 統計情報を取得します。
   形式は `Identifiers for WebRTC's Statistics API <https://w3c.github.io/webrtc-stats/>`_ に準拠しています。

.. literalinclude:: ./sora_sdk/stats.py
   :language: python

.. py:attribute:: on_disconnect(error_code, message)
   
   :type: Callable[[sora_sdk.SoraSignalingErrorCode, str], None]

   コネクション切断時のコールバックです。 :py:class:`SoraSignalingErrorCode` で表されるエラーコードとメッセージを引数に取ります。

.. literalinclude:: ./sora_sdk/on_disconnect.py
   :language: python


.. py:method:: send_data_channel(label, data)
   
   :param str label: データチャンネルのラベル。
   :param bytes data: 送信するデータ。
   :return: 成功した場合は True 、それ以外の場合は False 。
   :rtype: bool

   Sora にデータチャンネルを介してデータを送信します。

.. py:attribute:: on_data_channel(label)
   
   :type: Callable[[label: str], None]

   データチャネルが追加された際に呼び出されるコールバックです。 追加されたデータチャネルのラベルを引数に取ります。

.. py:attribute:: on_message(label, data)
   
   :type: Callable[[label: str, data: bytes], None]

   データチャネルでメッセージ通知を受信した際に呼び出されるコールバックです。 受信したデータチャネルのラベルとデータを引数に取ります。

.. literalinclude:: ./sora_sdk/on_message.py
   :language: python


.. py:attribute:: on_notify(message)
   
   :type: Callable[[str], None]

   シグナリング通知を受信した際に呼び出されるコールバックです。 受信したメッセージを引数に取ります。

.. literalinclude:: ./sora_sdk/on_notify.py
   :language: python

.. py:attribute:: on_push(message)
   
   :type: Callable[[message: str], None]

   シグナリングプッシュを受信した際に呼び出されるコールバックです。 受信したメッセージを引数に取ります。

.. py:attribute:: on_set_offer
   
   :type: Callable[[message: str], None]

   Sora から受け取った Offer を設定した際に呼び出されるコールバックです。 受信した Offer を引数に取ります。

.. py:attribute:: on_track(track)
   
   :type: Callable[[track: sora_sdk.SoraMediaTrack], None]

   Track が追加された際に呼び出されるコールバックです。追加された Track の :py:class:`SoraMediaTrack` を引数に取ります。

   コールバックで受け取った後に :py:attr:`SoraTrackInterface.kind` から video か audio かを判別し、適切な Sink に渡すことで受信した映像、音声データを受け取ることができます。


.. py:attribute:: on_switched(message)
   
   :type: Callable[[message: str], None]

   シグナリングが DataChannel に切り替わったタイミングで呼ばれるコールバックです。受信したメッセージを引数に取ります。
   主にログ出力などに利用する事を想定しており、戻り値を返すことはできません。

.. py:attribute:: on_signaling_message(type, direction, message)

   :type: Callable[[sora_sdk.SoraSignalingType, sora_sdk.SoraSignalingDirection, str], None]

   シグナリングメッセージを送受信した際に呼ばれるコールバックです。
   主にログ出力などに利用する事を想定しており、戻り値を返すことはできません。

   - "type": "connect"
   - "type": "redirect"
   - "type": "offer"
   - "type": "answer"
   - "type": "candidate"
   - "type": "re-offer"
   - "type": "re-answer"
   - "type": "disconnect"
   - "type": "close"

   ``"type": "close"`` は Sora 2024.2.0 から利用可能なメッセージです。

   ``"type": "switched"`` は :py:attr:`SoraConnection.on_switched` を利用してください。

   ``"type": "ping"`` と ``"type": "pong"`` は取得できません。


.. literalinclude:: ./sora_sdk/on_signaling_message.py
   :language: python

.. py:attribute:: on_ws_close(code, reason)

   :type: Callable[[int, str], None]

   WebSocket 切断時のコールバックです。
   SDK 側で閉じた場合は reason には ``"SELF-CLOSED"`` が入ります。
   主にログ出力などに利用する事を想定しており、戻り値を返すことはできません。

.. literalinclude:: ./sora_sdk/on_ws_close.py
   :language: python

## SoraAudioSource オブジェクト

Sora に Python で生成した音声データを送る機能を提供します。このクラスは :py:class:`SoraTrackInterface` を継承しています。

:py:meth:`Sora.create_audio_source` から生成します。

.. py:method:: on_data(ndarray)
   
   :param ``ndarray[dtype=int16, shape=(*, *), order='C', device='cpu']`` ndarray: チャンネルごとのサンプル数 x チャンネル数 になっている音声データ。
   :rtype: None
   
   Sora に送る音声データを渡します。

   タイムスタンプが引数にないオーバーロードです。タイムスタンプは先に受け取ったデータと連続になっていると想定してサンプル数から自動生成します。

.. .. py:method:: on_data(ndarray, timestamp)
..    :no-index:

..    :param ``ndarray[dtype=int16, shape=(*, *), order='C', device='cpu']`` ndarray: チャンネルごとのサンプル数 x チャンネル数 になっている音声データ。
..    :param float timestamp: time.time() で取得できるエポック秒で表されるフレームのタイムスタンプ。
..    :rtype: None

..    .. danger:: このメソッドは非推奨です。
..    
..    Sora に送る音声データを渡します。


.. py:method:: on_data(data, samples_per_channel)
   :no-index:
   
   :param int data: 16bit PCM データのポインタ。
   :param int samples_per_channel: 送信するチャンネル毎のサンプル数。
   :rtype: None
   
   Sora に送る音声データを渡します。

   タイムスタンプが引数にないオーバーロードです。タイムスタンプは先に受け取ったデータと連続になっていると想定してサンプル数から自動生成します。

.. .. py:method:: on_data(data, samples_per_channel, timestamp)
..    :no-index:
..    
..    :param int data: 16bit PCM データのポインタ。
..    :param int samples_per_channel: 送信するチャンネル毎のサンプル数
..    :param float timestamp: タイムスタンプ
..    :rtype: None
..    
..    .. danger:: このメソッドは非推奨です。
..    
..    Sora に送る音声データを渡します。

## SoraAudioSink オブジェクト

AudioTrack から音声データを取り出す機能を提供します。

受け取った音声はコンストラクタで設定したサンプリングレートとチャンネル数に変換し、内部のバッファに溜め込まれるため、任意のタイミングで音声を取り出すことができます。

.. py:method:: read(frames=0, timeout=1)
   
   :param int frames: 受け取るチャンネルごとのサンプル数。0 を指定した場合には、受信済みのすべてのサンプルを返します。デフォルトは 0。
   :param float timeout: 溜まっているサンプル数が frames で指定した数を満たさない場合の待ち時間。秒単位で指定します。デフォルトは 1。
   :return: タプルでインデックス 0 には bool で成否を、成功した場合のみインデックス 1 に ``ndarray[dtype=int16, shape=(*, *)]`` で チャンネルごとのサンプル数 x チャンネル数 になっている音声データを返します。
   :rtype: tuple

   受信済みのデータをバッファから読み出します。

.. py:attribute:: on_data
   
   :type: ``Callable[[numpy.ndarray[dtype=int16, shape=(*, *)]], None]``

   音声データを AudioTrack から受け取った際に呼び出されるコールバックです。音声データが格納された ndarray で チャンネルごとのサンプル数 x チャンネル数 になっている音声データを引数にとります。
   
   **このコールバック関数内では重い処理は行わないでください。**

   **このコールバックは廃止予定です。**

.. py:attribute:: on_format(sample_rate, number_of_channels)
   
   :type: Callable[[int, int], None]

   AudioTrack から受け取った音声データのサンプリングレートもしくはチャンネル数が変化した場合に呼び出されるコールバックです。新しいサンプリングレートとチャンネル数を引数にとります。
   
   **このコールバック関数内では重い処理は行わないでください。**

   **このコールバックは廃止予定です。**

```python
from sora_sdk import SoraAudioSink

audio_sink = None


def on_track(track):
    # 音声トラックの場合
    if track.kind == "audio":
        # 音声トラックのため込み場所を指定
        _audio_sink = SoraAudioSink(
            track=track,
            # 音声出力デバイスが利用可能な値を指定してください
            output_frequency=16000,
            # 音声出力デバイスが利用可能な値を指定してください
            output_channels=1,
        )
```

音声を取り出す場合は SoraAudioSink.read を利用してください。

```python
# frames はバッファサイズです
success, data = audio_sink.read(frames)
if success:
else:
```

## SoraVideoSource オブジェクト

Sora に Python で生成した映像のフレームデータを送る機能を提供します。このクラスは :py:class:`SoraTrackInterface` を継承しています。

:py:meth:`Sora.create_video_source` から生成します。

.. py:method:: on_captured(ndarray)
   
   :param ``ndarray[dtype=uint8, shape=(*, *, 3), order='C', device='cpu']`` ndarray: H x W x BGR になっているフレームデータ。
   :rtype: None

   この関数が呼び出された時点のタイムスタンプでフレームを送信します。

   映像になるように一定のタイミングで呼び出さない場合、受信側でコマ送りになります。

.. .. py:method:: on_captured(ndarray, timestamp)
..    :no-index:
..    
..    :param ``ndarray[dtype=uint8, shape=(*, *, 3), order='C', device='cpu']`` ndarray: H x W x BGR になっているフレームデータ。
..    :param float timestamp: time.time() で取得できるエポック秒で表されるフレームのタイムスタンプ。
..    :rtype: None
..    
..    .. danger:: このメソッドは非推奨です。

..    timestamp 引数で渡されたタイムスタンプでフレームを送信します。
..    
..    フレームのタイムスタンプを指定できるようにするため用意したオーバーロードです。
..    
..    timestamp が映像になるように一定の時間差がない場合、受信側で正しく表示されない場合があります。
..    
..    表示側で音声データの timestamp と同期を取るため遅延が発生する場合があります。

.. .. py:method:: on_captured(ndarray, timestamp_us)
..    :no-index:
..    
..    :param ``ndarray[dtype=uint8, shape=(*, *, 3), order='C', device='cpu']`` ndarray: H x W x BGR になっているフレームデータ。
..    :param int timestamp_us: マイクロ秒単位の整数で表されるフレームのタイムスタンプ。
..    :rtype: None
..    
..    .. danger:: このメソッドは非推奨です。
..    
..    timestamp_us 引数で渡されたマイクロ秒精度の整数で表されるタイムスタンプでフレームを送信します。
..    
..    libWebRTC のタイムスタンプはマイクロ秒精度のため用意したオーバーロードです。
..    
..    timestamp が映像になるように一定の時間差がない場合、受信側で正しく表示されない場合があります。
..    
..    表示側で音声データの timestamp と同期を取るため遅延が発生する場合があります。

## SoraTrackInterface オブジェクト

AudioTrack もしくは VideoTrack を表すために使用されます。

:py:attr:`SoraConnection.on_track` コールバックで引数として渡されます。

.. py:method:: set_enabled(enable)
   
   :param bool enable: 有効または無効を表すブール値。
   :rtype: bool
   
   トラックの有効/無効を設定します。

.. py:attribute:: enabled
   
   :type: bool
   :readonly: True

   トラックが有効かどうかを示すブール値。

.. py:attribute:: id
   
   :type: str
   :readonly: True

   トラックの ID を示す文字列。

.. py:attribute:: kind
   
   :type: str
   :readonly: True

   トラックの種類を示す文字列。 video もしくは audio が入っています。 AudioTrack か VideoTrack かを判別することができます。

.. py:attribute:: state
   
   :type: sora_sdk.SoraTrackState
   :readonly: True

   トラックの状態。

## SoraAudioFrame オブジェクト

libwebrtc 内の音声処理単位である 10ms の音声データが格納されています。 picklable です。

.. py:method:: data()
   
   :return: numpy.ndarray で サンプル数 x チャンネル数 になっている音声データ。
   :rtype: ``numpy.ndarray[dtype=int16, shape=(*, *)]``

   :py:class:`SoraAudioFrame` 内のフレームデータへの numpy.ndarray での参照を返します。

.. py:attribute:: samples_per_channel
   
   :type: int

   チャンネルあたりのサンプル数。

.. py:attribute:: num_channels
   
   :type: int

   チャンネル数 (モノラルの場合は 1、ステレオの場合は 2)。

.. py:attribute:: sample_rate_hz
   
   :type: int

   サンプリングレート。

.. py:attribute:: absolute_capture_timestamp_ms
   
   :type: int

   キャプチャした際のタイムスタンプ。ない場合は None。

## SoraAudioStreamSink オブジェクト

AudioTrack の音声データを受け取って **逐次** Python に渡す on_frame コールバックを提供します。

出力には on_frame にコールバック関数を指定する必要があります。

.. py:attribute:: on_frame
   
   :type: Callable[[track: sora_sdk.SoraAudioFrame], None]

   音声データを AudioTrack から受け取った際に呼び出されるコールバック。音声データが格納された :py:class:`SoraAudioFrame` オブジェクトを引数に取ります。

```python
from sora_sdk import SoraAudioStreamSink

audio_stream_sink = None


def on_frame(frame):
    pass


def on_track(track):
    # 音声トラックの場合
    if track.kind == "audio":
        # トラックの音声データの受け口として SoraAudioStreamSink を生成
        audio_stream_sink = SoraAudioStreamSink(
            track=track,
            # 24kHz にリサンプリングするように指定
            output_frequency=24000,
            # モノラルにミキシングするように指定
            output_channels=1,
        )
        # 音声データが来た際のコールバックを指定
        audio_stream_sink.on_frame = on_frame
```

## SoraMediaTrack オブジェクト

**py**: attr:SoraConnection.on_track コールバックで引数として渡されます。

Sora から受け取った AudioTrack もしくは VideoTrack を扱うために提供されます。このクラスは :py:class:`SoraTrackInterface` を継承しています。

.. py:attribute:: stream_id

   :type: str

   この Track の Stream ID を返します。

.. py:method:: set_frame_transformer(transformer)

   :param sora_sdk.SoraFrameTransformer transformer: フレームを変換する :py:class:`SoraFrameTransformer` オブジェクト。
   :rtype: None

   フレームを変換する :py:class:`SoraFrameTransformer` オブジェクトを設定します。

## SoraVAD オブジェクト

.. py:method:: analyze(frame)
   
   :param sora_sdk.SoraAudioFrame frame: 音声である確率を求める :py:class:`SoraAudioFrame` オブジェクト。
   :return: 0 - 1 で表される音声である確率。
   :rtype: int

   :py:class:`SoraAudioFrame` 内の音声データが音声である確率を返します。

   frame 内の音声データが 24 kHz 以外の時は 24 kHz にリサンプリングを、2 チャンネル以上の時は 1 チャンネルにミキシングをそれぞれ変換した上で VAD を行います。VAD しか使わない場合は :py:class:`SoraAudioStreamSink` で事前に変換しておくことをお勧めします。

SoraAudioStreamSink と組み合わせて以下のように使います。

```python
from sora_sdk import SoraAudioStreamSink, SoraVAD

audio_stream_sink = None
vad = SoraVAD()


def on_frame(frame):
    # frame が音声である確率を求める
    voice_probability = vad.analyze(frame)
    if voice_probability > 0.95:  # 0.95 は libwebrtc の判定値
        print(f"Voice! voice_probability={voice_probability}")
    else:
        print("Not a voice!")


def on_track(track):
    if track.kind == "audio":
        audio_stream_sink = SoraAudioStreamSink(
            track=track,
            # VAD はサンプリングレートが 24 kHz 以外の時 24kHz にリサンプリングするので、 24kHz にしておく。
            output_frequency=24000,
            # VAD はチャネル数が 2 以上の時 1 チャンネルにミキシングするので、 1 チャンネルにしておく。
            output_channels=1,
        )
        audio_stream_sink.on_frame = on_frame
```

## SoraVideoFrame オブジェクト

.. py:method:: data()
   
   :return: H x W x BGR になっているフレームデータ。
   :rtype: ``numpy.ndarray[dtype=uint8, shape=(*, *, 3)]``

   :py:class:`SoraVideoFrame` 内のフレームデータへの numpy.ndarray での参照を返します。

   OpenCV の cv2.imshow にそのまま渡すと表示されるように成型されています。

## SoraVideoSink オブジェクト

VideoTrack からフレームデータを受け取って、 **逐次** Python に渡す on_frame コールバックを提供します。

出力には on_frame にコールバック関数を指定する必要があります。

.. py:attribute:: on_frame
   
   :type: Callable[[track: sora_sdk.SoraVideoFrame], None]

   フレームデータを VideoTrack から受け取った際に呼び出されるコールバックです。フレームデータが格納された :py:class:`SoraVideoFrame` オブジェクトを引数に取ります。

   **このコールバック関数内では重い処理は行わないでください。** サンプルを参考に queue を利用するなどの対応を推奨します。
   
   この関数はメインスレッドから呼び出されないため、関数内で OpenCV の cv2.imshow を実行しても macOS の場合は表示されません。

```python
from sora_sdk import SoraVideoSink

video_sink = None


def on_frame(frame):
    pass


def on_track(track):
    # 映像トラックの場合
    if track.kind == "video":
        # 映像トラックのため込み場所を指定
        video_sink = SoraVideoSink(track=track)
        # 映像フレームコールバックを指定
        video_sink.on_frame = on_frame
```

### OpenCV

Sora Python SDK サンプルでは OpenCV を利用して映像を出力しています。

## SoraVideoCodecType オブジェクト

*バージョン 2025.1.0 で追加。*

映像コーデックの種類を表す列挙型です。

.. py:attribute:: VP8
   :type: SoraVideoCodecType
   :value: 1

   VP8 コーデック

.. py:attribute:: VP9 
   :type: SoraVideoCodecType
   :value: 2

   VP9 コーデック

.. py:attribute:: AV1
   :type: SoraVideoCodecType
   :value: 3

   AV1 コーデック

.. py:attribute:: H264
   :type: SoraVideoCodecType
   :value: 4

   H.264 コーデック

.. py:attribute:: H265
   :type: SoraVideoCodecType
   :value: 5

   H.265 コーデック

## SoraVideoCodecPreference オブジェクト

*バージョン 2025.1.0 で追加。*

映像コーデックのエンコード/デコードを細かく指定するためのオブジェクトです。
未指定の場合は全てのコーデックで :py:class:`SoraVideoCodecImplementation.INTERNAL` を利用します。

.. warning::
   
   SoraVideoCodecPreference を指定した場合は **指定したコーデックのみ** を利用します。
   H.264 のみを指定した場合は H.264 しか利用できなくなります。

.. py:method:: Codec(type, encoder=None, decoder=None)

   :param SoraVideoCodecType type: コーデックの種類。
   :param SoraVideoCodecImplementation encoder: エンコードに利用する実装。
   :param SoraVideoCodecImplementation decoder: デコードに利用する実装。

   コーデックの種類とエンコード/デコードに利用する実装を指定します。
   encoder や decoder を指定しない場合は None が指定され、利用できなくなります。

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

Sora(
    # ビデオコーデックプリファレンスを指定する
    video_codec_preference=SoraVideoCodecPreference(
        codecs=[
            # VP9 は libwebrtc 組込のソフトウェアコーデック libvpx を利用する
            SoraVideoCodecPreference.Codec(
                type=SoraVideoCodecType.VP9,
                encoder=SoraVideoCodecImplementation.INTERNAL,
                decoder=SoraVideoCodecImplementation.INTERNAL,
            ),
            # AV1 は NVIDIA Video Codec を利用する
            SoraVideoCodecPreference.Codec(
                type=SoraVideoCodecType.AV1,
                encoder=SoraVideoCodecImplementation.NVIDIA_VIDEO_CODEC_SDK,
                decoder=SoraVideoCodecImplementation.NVIDIA_VIDEO_CODEC_SDK,
            ),
            # H.264 は Cisco OpenH264 を利用する
            SoraVideoCodecPreference.Codec(
                type=SoraVideoCodecType.H264,
                encoder=SoraVideoCodecImplementation.CISCO_OPENH264,
                decoder=SoraVideoCodecImplementation.CISCO_OPENH264,
            ),
            # H.265 は Intel VPL を利用する
            SoraVideoCodecPreference.Codec(
                type=SoraVideoCodecType.H265,
                encoder=SoraVideoCodecImplementation.INTEL_VPL,
                decoder=SoraVideoCodecImplementation.INTEL_VPL,
            ),
        ]
    ),
    openh264="/path/to/libopenh264-2.5.0-linux64.7.so",
)
```

## SoraVideoCodecImplementation オブジェクト

*バージョン 2025.1.0 で追加。*

映像コーデックの実装を表す列挙型です。

.. py:attribute:: INTERNAL
   :type: SoraVideoCodecImplementation
   :value: 0

   INTERNAL は Sora Python SDK がベースにしている ``libwebrtc`` に含まれるデコーダーやエンコーダーを利用します。
   端末のハードウェアアクセラレーターが利用できる場合、自動的に利用します。

   macOS で ``INTERNAL`` を指定し、コーデックに H.264 や H.265 を指定した場合は Apple Video Toolbox を利用します。

.. py:attribute:: CISCO_OPENH264
   :type: SoraVideoCodecImplementation
   :value: 1

   Cisco OpenH264 を利用します。OpenH264 を利用する場合は ``openh264`` に OpenH264 のパスを指定してください。

.. py:attribute:: INTEL_VPL
   :type: SoraVideoCodecImplementation
   :value: 2

   Intel VPL によるハードウェアアクセラレーターを利用します。
   利用できるコーデックは AV1 / H.264 / H.265 です。 

.. py:attribute:: NVIDIA_VIDEO_CODEC_SDK
   :type: SoraVideoCodecImplementation
   :value: 3

   NVIDIA Video Codec によるハードウェアアクセラレーターを利用します。
   利用できるコーデックは VP9 / H.264 / H.265 です。

## SoraTransformableFrame オブジェクト

*バージョン 2025.1.0 で追加。*

.. py:attribute:: direction

   :rtype: sora_sdk.sora_sdk_ext.SoraTransformableFrameDirection

.. py:attribute:: mime_type

   :rtype: str

.. py:attribute:: payload_type

   :rtype: int

.. py:attribute:: ssrc

   :rtype: int

.. py:attribute:: rtp_timestamp

   :rtype: int

## SoraTransformableAudioFrame オブジェクト

*バージョン 2025.1.0 で追加。*

.. py:method:: get_data()

   :rtype: numpy.ndarray[dtype=uint8, shape=(*), writable=False]

   映像データを取得します。

.. py:method:: set_data(data)

   :param numpy.ndarray[dtype=uint8, shape=(*), order='C', device='cpu', writable=False] data: 
   :rtype: None

   映像データを設定します。

.. py:attribute:: absolute_capture_timestamp

   :rtype: int | None

   Abs-Capture-Time RTP 拡張の値が含まれます。

.. py:attribute:: audio_level

   :rtype: int | None

   Audio-Level RTP 拡張の値が含まれます。

.. py:attribute:: contributing_sources

   :rtype: numpy.ndarray[dtype=uint32, shape=(*), writable=False]

   RTP CSRC のリストが含まれます。

   https://www.w3.org/TR/webrtc-encoded-transform/#dom-rtcencodedaudioframemetadata-sequencenumber

.. py:attribute:: receive_time

   :rtype: int | None

.. py:attribute:: sequence_number

   :rtype: int | None

   RTP シーケンス番号が含まれます。受信する音声パケットにのみ含まれます。

   https://www.w3.org/TR/webrtc-encoded-transform/#dom-rtcencodedaudioframemetadata-sequencenumber

.. py:attribute:: type

   :rtype: sora_sdk.sora_sdk_ext.SoraTransformableAudioFrameType

.. py:attribute:: direction

   :rtype: sora_sdk.sora_sdk_ext.SoraTransformableFrameDirection

.. py:attribute:: mine_type

   :rtype: str

   音声の MIME タイプが含まれます。多くの場合 `audio/opus` です。

   https://www.w3.org/TR/webrtc-encoded-transform/#dom-rtcencodedaudioframemetadata-mimetype

.. py:attribute:: payload_type

   :rtype: int

   RTP ペイロードタイプが含まれます。

   https://www.w3.org/TR/webrtc-encoded-transform/#dom-rtcencodedaudioframemetadata-payloadtype

.. py:attribute:: ssrc

   :rtype: int

   RTP SSRC が含まれます。

   https://www.w3.org/TR/webrtc-encoded-transform/#dom-rtcencodedaudioframemetadata-sequencenumber

.. py:attribute:: rtp_timestamp

   :rtype: int

   RTP タイムスタンプが含まれます。

   https://www.w3.org/TR/webrtc-encoded-transform/#dom-rtcencodedaudioframemetadata-rtptimestamp

## SoraTransformableVideoFrame オブジェクト

*バージョン 2025.1.0 で追加。*

.. py:method:: get_data()

   :rtype: numpy.ndarray[dtype=uint8, shape=(*), writable=False]

   映像データを取得します。

.. py:method:: set_data(data)

   :param numpy.ndarray[dtype=uint8, shape=(*), order='C', device='cpu', writable=False] data: 
   :rtype: None

   映像データを設定します。

.. py:attribute:: contributing_sources

   :rtype: numpy.ndarray[dtype=uint32, shape=(*), writable=False]

   https://www.w3.org/TR/webrtc-encoded-transform/#dom-rtcencodedvideoframemetadata-contributingsources

.. py:attribute:: frame_dependencies

   :rtype: numpy.ndarray[dtype=int64, shape=(*), writable=False]

   https://www.w3.org/TR/webrtc-encoded-transform/#dom-rtcencodedvideoframemetadata-dependencies

.. py:attribute:: frame_id

   :rtype: int | None

   https://www.w3.org/TR/webrtc-encoded-transform/#dom-rtcencodedvideoframemetadata-frameid

.. py:attribute:: is_key_frame

   :rtype: bool

   キーフレームかどうかが含まれます。

.. py:attribute:: spatial_index

   :rtype: int

   https://www.w3.org/TR/webrtc-encoded-transform/#dom-rtcencodedvideoframemetadata-spatialindex

.. py:attribute:: temporal_index

   :rtype: int

   https://www.w3.org/TR/webrtc-encoded-transform/#dom-rtcencodedvideoframemetadata-temporalindex   

.. py:attribute:: height

   :rtype: int

   https://www.w3.org/TR/webrtc-encoded-transform/#dom-rtcencodedvideoframemetadata-height

.. py:attribute:: width

   :rtype: int

   https://www.w3.org/TR/webrtc-encoded-transform/#dom-rtcencodedvideoframemetadata-width

.. py:attribute:: direction

   :rtype: sora_sdk.sora_sdk_ext.SoraTransformableFrameDirection

.. py:attribute:: mine_type

   :rtype: str

   https://www.w3.org/TR/webrtc-encoded-transform/#dom-rtcencodedvideoframemetadata-mimetype

.. py:attribute:: payload_type

   :rtype: int

   https://www.w3.org/TR/webrtc-encoded-transform/#dom-rtcencodedvideoframemetadata-rtptimestamp

.. py:attribute:: ssrc

   :rtype: int

   https://www.w3.org/TR/webrtc-encoded-transform/#dom-rtcencodedvideoframemetadata-rtptimestamp

.. py:attribute:: rtp_timestamp

   :rtype: int

   https://www.w3.org/TR/webrtc-encoded-transform/#dom-rtcencodedvideoframemetadata-rtptimestamp

## SoraFrameTransformer オブジェクト

*バージョン 2025.1.0 で追加。*

.. py:attribute:: on_transform

   :type: Callable[[sora_sdk.SoraTransformableAudioFrame], None]

.. py:method:: enqueue(frame)

   :param sora_sdk.SoraTransformableFrame frame: 変換する :py:class:`SoraTransformableFrame` オブジェクト。
   :rtype: None

.. py:method:: start_short_circuiting()

   :rtype: None

## SoraAudioFrameTransformer オブジェクト

*バージョン 2025.1.0 で追加。*

.. py:attribute:: on_transform

   :type: Callable[[sora_sdk.SoraTransformableAudioFrame], None]

.. py:method:: enqueue(frame)

   :param sora_sdk.SoraTransformableAudioFrame frame: 変換する :py:class:`SoraTransformableAudioFrame` オブジェクト。
   :rtype: None

.. py:method:: start_short_circuiting()

   :rtype: None

## SoraVideoFrameTransformer オブジェクト

*バージョン 2025.1.0 で追加。*

.. py:attribute:: on_transform

   :type: Callable[[sora_sdk.SoraTransformableVideoFrame], None]

.. py:method:: enqueue(frame)

   :param sora_sdk.SoraTransformableVideoFrame frame: 変換する :py:class:`SoraTransformableVideoFrame` オブジェクト。
   :rtype: None

.. py:method:: start_short_circuiting()

   :rtype: None

## SoraSignalingType オブジェクト

.. py:attribute:: WEBSOCKET

   :type: sora_sdk.SoraSignalingType
   :readonly: True

   WebSocket を利用することを示す定数です。

.. py:attribute:: DATACHANNEL

   :type: sora_sdk.SoraSignalingType
   :readonly: True

   DataChannel を利用することを示す定数です。

## SoraDegradationPreference オブジェクト

*バージョン 2025.1.0 で追加。*

.. py:attribute:: MAINTAIN_FRAMERATE

   :type: sora_sdk.SoraDegradationPreference
   :readonly: True

   フレームレートを優先することを示す定数です。

.. py:attribute:: MAINTAIN_RESOLUTION

   :type: sora_sdk.SoraDegradationPreference
   :readonly: True

   解像度を優先することを示す定数です。

.. py:attribute:: BALANCED

   :type: sora_sdk.SoraDegradationPreference
   :readonly: True

   フレームレートと解像度のバランスを優先することを示す定数です。

.. py:attribute:: DISABLED

   :type: sora_sdk.SoraDegradationPreference
   :readonly: True

   デグラデーションを無効化することを示す定数です。

## SoraSignalingDirection オブジェクト

.. py:attribute:: SENT

   :type: sora_sdk.SoraSignalingDirection
   :readonly: True

   送信したメッセージを示す定数です。

.. py:attribute:: RECEIVED

   :type: sora_sdk.SoraSignalingDirection
   :readonly: True

   受信したメッセージを示す定数です。

## SoraSignalingErrorCode オブジェクト

.. py:attribute:: CLOSE_FAILED

   :type: sora_sdk.SoraSignalingErrorCode
   :readonly: True

   接続のクローズに失敗したことを示すエラーコードです。

.. py:attribute:: CLOSE_SUCCEEDED

   :type: sora_sdk.SoraSignalingErrorCode
   :readonly: True

   接続のクローズが成功したことを示すエラーコードです。

.. py:attribute:: ICE_FAILED

   :type: sora_sdk.SoraSignalingErrorCode
   :readonly: True

   ICE の処理に失敗したことを示すエラーコードです。

.. py:attribute:: INTERNAL_ERROR

   :type: sora_sdk.SoraSignalingErrorCode
   :readonly: True

   内部エラーが発生したことを示すエラーコードです。

.. py:attribute:: INVALID_PARAMETER

   :type: sora_sdk.SoraSignalingErrorCode
   :readonly: True

   無効なパラメータが指定されたことを示すエラーコードです。

.. py:attribute:: PEER_CONNECTION_STATE_FAILED

   :type: sora_sdk.SoraSignalingErrorCode
   :readonly: True

   ピア接続の状態が異常なことを示すエラーコードです。

.. py:attribute:: WEBSOCKET_HANDSHAKE_FAILED

   :type: sora_sdk.SoraSignalingErrorCode
   :readonly: True

   WebSocket のハンドシェイクに失敗したことを示すエラーコードです。

.. py:attribute:: WEBSOCKET_ONCLOSE

   :type: sora_sdk.SoraSignalingErrorCode
   :readonly: True

   WebSocket の接続が閉じられたことを示すエラーコードです。

.. py:attribute:: WEBSOCKET_ONERROR

   :type: sora_sdk.SoraSignalingErrorCode
   :readonly: True

   WebSocket でエラーが発生したことを示すエラーコードです。

## SoraLoggingSeverity オブジェクト

.. py:attribute:: VERBOSE

   :type: sora_sdk.SoraLoggingSeverity
   :readonly: True

   最も詳細なログレベルを示す定数です。

.. py:attribute:: INFO

   :type: sora_sdk.SoraLoggingSeverity
   :readonly: True

   情報レベルのログを示す定数です。

.. py:attribute:: WARNING

   :type: sora_sdk.SoraLoggingSeverity
   :readonly: True

   警告レベルのログを示す定数です。

.. py:attribute:: ERROR

   :type: sora_sdk.SoraLoggingSeverity
   :readonly: True

   エラーレベルのログを示す定数です。

.. py:attribute:: NONE

   :type: sora_sdk.SoraLoggingSeverity
   :readonly: True

   ログ出力を無効化するための定数です。
