ドキュメント
ESP32クイックスタート
プレビュー版:機能とAPIは変更される場合があります。
PDFはブラウザーの印刷ダイアログで作成します。ホスト型のエクスポートサービスではありません。
タスクだけを使うアプリケーションにはタスク音声を、ルームでのライブ音声にはリアルタイム音声(RTC)を選んでください。OneSay OSは不要です。SDKはプレビュー版で、まだ公開されていません。プロジェクトにESP-IDFコンポーネントとして組み込んで使います。クライアントのバイナリやローカルのケイパビリティフラグが変わっても、権限はすべて引き続きサーバーが最終的に判断します。
ESP32 + タスク音声#
sdks/esp32/examples/voice_button(タスク専用のスタンドアロンESP-IDFアプリケーション)から始めます。これを新しいプロジェクトディレクトリにコピーし、OneSay ESP32コンポーネント(sdks/esp32の内容)をcomponents/onesayとして追加します。サンプルはコンポーネントがその場所にあることを前提としており、コンポーネントがないと単独ではビルドできません。idf_component.ymlにあるコンポーネントの依存関係の固定は維持してください。不足している依存関係は、初回のビルド時にESP-IDFのコンポーネントマネージャーがダウンロードします。
そのプロジェクトでESP-IDF 6.0.2を使ってビルドし、ボードに書き込んでシリアル出力を確認します。
idf.py set-target esp32s3
idf.py build
idf.py -p <PORT> flash monitorビルドにボードは不要です。書き込むのはアプリケーションだけで、デバイス認証情報のプロビジョニングは行いません。
sdks/esp32/examples/voice_button/README.mdと、サンプル内のmain/voice_button.hに従ってください。onesay_voice_button_configureには、安全なデバイス認証情報ストレージ、認可済みの既存のプロジェクト/環境/アプリケーションとソース/ルームのバインディング、ネットワークアクセス、信頼できるUTC時刻/証明書、上限付きの16 kHzモノラルPCM s16leプロデューサーを渡します。既定のフックは接続前にONESAY_ERR_AUTHを返すため、変更していないサンプルは接続しません。キャプチャ、GPIO、I2S、コーデック、ボードのチューニングは、ボード側のコードが担当します。
呼び出し元は、onesay_voice_button_init、onesay_voice_button_connect、上限付きのonesay_voice_button_stepの呼び出しを直列化します。SDKが、WSS/OSAF、シーケンス/ACK、バックプレッシャー、リプレイ/再開、キャンセルを担います。保持中のPCMは、ACKで解放されるまで破棄しないでください。キャンセルの送信に成功しても、それはタスクの最終結果ではありません。onesay_voice_button_closeは、ストレージと依存関係を解放する前にトランスポートを解放する必要があります。このパスはRTCセッションを開きません。
ESP32 + リアルタイム音声(RTC)#
sdks/esp32にあるコンポーネントは、onesay_esp32_rtc.hを公開します(CONFIG_ONESAY_RTC_ENABLEDが選択されている場合)。RTCはLiveKit ESP32 SDKをベースに構築されており、sdks/esp32/idf_component.ymlがテスト済みのバージョンを固定しています。ESP-IDF 6.0.2を使用し、コンポーネントの依存関係グラフはそのまま維持してください。コンポーネントのsdkconfig.rtc.defaultsはRTC設定フラグメントで、アプリケーションのデフォルトより先に読み込まれます。ボードの設定ではありません。タスクのサンプルでRTCを有効にしても、RTCアプリケーションにはなりません。下記のRTCプロジェクトから始めてください。
実行可能なプロジェクト:rtc_smoke#
ボードに依存しないプロジェクトsdks/esp32/examples/rtc_smoke (../../sdks/esp32/examples/rtc_smoke/README.md)は、実行可能なRTCの出発点です。OneSayコンポーネントとvoice_buttonのタスクフローだけを使う、独立したESP-IDFアプリケーションです。GPIO、I2S、コーデック、BSP、AEC、Wi-Fi、NVSのコードはなく、OneSay OSにも依存しません。1回の実行でタスクをストリーミングした後、合成キャプチャでRTCに接続し、パケットを1つ送信して、すべてを解放し、内容を含まない要約行をシリアルコンソールに1行出力します。
プロジェクトはタスクのサンプルと同じ方法で作成します。rtc_smokeを新しいディレクトリにコピーし、コンポーネントをcomponents/onesayとして追加して、main/voice_button.cとmain/voice_button.hをvoice_buttonサンプルからそのmain/にコピーします。その後、上記のidf.pyコマンドでビルドして書き込みます。
強いシンボルとしてonesay_rtc_smoke_configureを用意してください。弱いシンボルの既定実装は、ネットワーク通信の前にONESAY_ERR_AUTHを返します。ONESAY_OKを返す前に、ファームウェアでネットワークを起動し、信頼できるUTC時刻を設定し、安全なストアから設定値を埋めます。プロジェクトのREADMEに、すべてのフィールドが記載されています。ボードの設定(フラッシュサイズ、PSRAM、コンソール)は、3つ目のデフォルトファイルに記述します。
デバイス認証情報からRTCベアラーへ#
RTCオーナーは呼び出し元のベアラーを受け取り、デバイスシークレットを交換することはありません。公開APIの呼び出しだけでデバイス認証情報からRTCに至るには、スモークの設定でrtc_bearer_from_device_credential = trueを設定します。チェーンは次のとおりです。
- デバイス実行前のオーナー権限。オーナーが委任を作成し、同意リクエストを許可または拒否します。デバイスは、その委任のもとで
createAppSessionを使ってAppSessionを作成します。デバイスは、ルーム、AppSession、ソース、委任のIDを受け取ります。IDは何の権限も与えません。サーバーは、リクエストのたびに実際のグラント、委任、同意を確認します。 - デバイスシークレットから短期トークンへ。
rtc_bearerステップは、既存の安全なストアのコールバック(task.credentials.load)を通じて、デバイスシークレットを1回だけ読み込みます。シークレットはAuthorizationとしてのみ送信します。送信するのは1回のexchangeDeviceAccessTokenリクエスト(POST /v1/device-access-tokens、ボディ{})で、公開のonesay_esp32_control_requestを通じて行います。RTCのControl設定には、タスクの設定と同じ接続先、デバイス、プロジェクト、環境を指定する必要があります。そうでない場合、シークレットが読み込まれる前にステップが失敗します。シークレットは、結果にかかわらず消去されます。保持されるのはaccess_tokenだけで、これは{"data":{"access_token","token_type":"Bearer","expires_at"}}レスポンスエンベロープに含まれるものです。ストアのerase(ファクトリーリセット)が呼び出されることはありません。 - トークンからRTCへ。
onesay_esp32_rtc_prepare、onesay_esp32_rtc_connect_audio、およびパケットポリシーは、同じControlオーナー上で、その短期のデバイスアクセストークンだけを受け取ります。スモークは、解放後に自身のコピーを消去します。
冪等キーのコールバックは、exchangeDeviceAccessTokenに対して実行ごとに新しいキーを返します。リプレイされたキーでは、元の有効期限が返るためです。RTCの各オペレーションに対しては、同意に結び付いた元のキーを返します。別の確立済みフローのベアラーを代わりに使うには、load_rtc_bearerコールバックを指定します。2つの取得元のうち、指定できるのはどちらか一方だけです。長期のデバイスシークレット、Platformキー、プロバイダーキー、LiveKitシークレットを、ファームウェアのソースコード、ログ、ドキュメントに決して含めないでください。
アプリケーションの入力を準備する#
onesay_esp32_control_context_tを、onesay_esp32_control_initとアプリケーションのonesay_esp32_control_config_tで初期化します。想定するデバイス/プロジェクト/環境/アプリケーションのバインディング、証明書または検証済みの証明書バンドル、上限付きのリクエストタイムアウト、next_idempotency_keyコールバックを指定します。共有のControlイニシャライザーは、RTC用の別のベアラーが人間のユーザーのものである場合でも、有効なdevice_idを必要とします。設定したこのIDによって、ベアラーの主体が変わったり、RTCが認可されたりすることはありません。environmentには、使用が認可されている環境に対応するSDKの列挙値を設定します。ネットワークの設定、信頼できるUTC時刻、証明書の保存は、引き続きアプリケーションの責務です。TLSのホスト名や日付の検証を無効にしないでください。
以下の音声シーケンスには、呼び出し元が所有する次の入力が必要です。
| 入力 | 公開コントラクト |
|---|---|
control | 初期化済みのControlオーナー。使用中は、その証明書とキーコールバックの依存関係を保持してください。 |
bearer / bearer_length | 現在有効な、人間のユーザーの短期ベアラー、または委任されたデバイス/AppSessionのベアラー。たとえばデバイス認証情報のチェーンで得たデバイスアクセストークンです。RTCのprepareは、デバイスシークレットの交換もAppSessionの作成も行いません。Platform、プロバイダー、LiveKitの長期シークレットを埋め込まないでください。 |
input | onesay_action_rtc_connection_create_input_t。既存のroom_idとapp_session_idを含み、文字列は終端されている必要があります。リソースはすでに存在し、認可されている必要があります。 |
connection_delegation | 選択した接続オペレーションのdelegation_id、または省略する場合はNULL。これはリクエストのメタデータであり、許可ではありません。 |
audio | onesay_rtc_audio_config_t:認可済みのsource_id、そのパブリケーションオペレーション用の別個のdelegation_id(空の場合は省略)、キャプチャ/レンダリングのコールバック、now_unix_msとそのコンテキスト。 |
owner | 呼び出し元が保持する、NULLで初期化されたポインター。すでにセッションを所有しているスロットを、prepareに渡さないでください。 |
キーコールバックは、論理オペレーションごとに元のキーを返す必要があります。createRTCConnectionとcreateRTCPublicationは別々のオペレーションです。同意や委任が適用される場合、各キーはそれぞれの確認済みアクションと一致する必要があります。接続のセレクターは、パブリケーションに継承されません。最終的な判断は常にサーバーのチェックです。ローカルのセレクターやコールバックが有効でも、アクセスは付与されません。
準備、接続、観測、解放#
これは公開ヘッダーを使用したアプリケーションのコードであり、別のSDKエクスポートでも、完全なボードアプリケーションでもありません。上記の入力が必要です。
#include "onesay_esp32_rtc.h"
onesay_err_t example_begin_rtc_audio(
onesay_esp32_control_context_t *control,
const uint8_t *bearer, size_t bearer_length,
const onesay_action_rtc_connection_create_input_t *input,
const char *connection_delegation,
const onesay_rtc_audio_config_t *audio,
onesay_esp32_rtc_t **owner) {
if (owner == NULL || *owner != NULL) return ONESAY_ERR_INVALID_ARG;
onesay_err_t result = onesay_esp32_rtc_prepare(
control, bearer, bearer_length, input, connection_delegation, owner);
if (result != ONESAY_OK) return result;
/* Keep *owner even on failure: the caller still owns cleanup. */
return onesay_esp32_rtc_connect_audio(
*owner, control, bearer, bearer_length, audio);
}これらの公開呼び出しは、すべてのメディア、ネットワーク、クロックのコールバックの外で、アプリケーションスレッド上で直列化してください。関数が戻った後も、ポインターとコールバックのコンテキストを維持してください。prepareが失敗した場合、最初に空だったポインターはNULLのままですが、HTTPの結果があいまいな場合は、引き続きサーバーとの照合が必要です。prepareが成功した後は、connectが失敗した場合でも所有権のあるポインターが残るため、クローズが必要です。connectからのONESAY_OKは、接続の試行が受け付けられたことを意味します。接続済み、パブリッシュ済み、音声が相手に届いた、または取り消しが実際に有効になった、ということを意味するものではありません。
次の呼び出し(ownerは保持しているセッションポインター) | 意味と必要な処理 |
|---|---|
onesay_esp32_rtc_read_binding(owner, &connection)(onesay_rtc_binding_t connection = {0}を使用) | 元のOneSay ID、世代、期限、観測された状態をコピーします。PREPARED/CONNECTING/CONNECTED/RECONNECTING/FAILED/CLOSEDを区別して扱ってください。いずれもサーバーの権限に代わるものではありません。 |
onesay_esp32_rtc_read_audio_binding(owner, &publication)(onesay_rtc_audio_binding_t publication = {0}を使用) | 利用可能な場合は、接続の失敗後も含め、内容を含まないパブリケーションIDをコピーします。戻り値を確認してください。パブリケーションが利用できない場合はONESAY_ERR_INVALID_ARGが返り、出力はクリアされます。作り上げたIDが返ることはありません。 |
onesay_esp32_rtc_close(&owner)(owner != NULLの場合) | ボードのI/Oをキャンセルし、RTCセッションを停止して、メディアのオーナーを解放します。ポインターがクリアされるのはONESAY_OKの場合のみです。失敗した場合は、後で明示的にクリーンアップを再試行できるよう、ポインターとすべてのコールバックコンテキストを保持してください。それらを解放したり再初期化したりしないでください。 |
サーバーとの照合に必要なIDは、クローズが成功する前に読み取って保持してください。CLOSEDの観測だけでは、クリーンアップの証明になりません。クローズに失敗すると、所有権のあるポインターが残ることがあります。ローカルのクローズはendRTCPublicationやrevokeRTCConnectionを実行しません。サーバーのクリーンアップでは、これらの公開オペレーションを、それぞれ現在の認可と冪等キー/同意のバインディングを使って実行します。
キャプチャは、要求された16 kHzモノラルs16leのサンプルを正確に供給する必要があり、1回の読み取りあたり最大640サンプルです。レンダリングは、実際にデコードされたs16le形式を受け入れる必要があります。8/12/16/24/48 kHz、モノラルまたはステレオで、1回のコールバックあたり最大120 ms(48 kHzで5,760フレーム)です。すべてのコールバックは、戻るまでバッファーを借用し、40 msの時間予算に従います。冪等なcancelコールバックは並行して実行される場合があり、コンテキストを解放せずにI/Oを起こす必要があります。コールバックからSDKのライフサイクル関数を呼び出してはなりません。GPIO、コーデック、リサンプリング、ボードのチューニングは、このアプリケーションのコードでは提供されません。エンコードとフォーマット変換は、SDKのメディアパイプラインが担います。
認可が拒否された場合は、onesay_esp32_control_last_error(control)でエラーコード、リクエストID、再試行可能かどうかを確認してください。トークン、接続情報、トランスポートのボディをダンプしないでください。初回使用の情報が期限切れになった場合、業務上の期限を延ばしたり、クライアントの時計を変更したりしても救済できません。失敗した、または結果があいまいなパブリケーション/接続の試行を、connectを再度呼び出したり代替のキーを発行したりして再試行してはなりません。元のID/キーを保持し、ローカルのオーナーを解放して、アプリケーションの明示的な認可フローを通じて照合してください。
インターフェースの全体については、SDKのaudio-ownerドキュメント (../../sdks/esp32/README.md#rtc-audio)を参照してください。
rtc_smokeプロジェクトは、合成キャプチャとカウント用のレンダリングシンクを使用します。マイク、スピーカー、AEC、音質のチューニングは提供しません。それらはボード側の担当です。タスク専用のvoice_buttonサンプルはRTCを使いません。また、タスクやJavaScriptである機能がサポートされていても、ESP32のRTCでその機能がサポートされているとは限りません。
ボード上の認証情報#
デバイスごとに専用のデバイス認証情報をプロビジョニングし、暗号化されたNVSなどの保護されたストレージに保管してください。プロジェクトのAPIキーやデバイス認証情報をファームウェアにコンパイルして組み込んだり、シリアルログに出力したりしないでください。最初の接続の前に、証明書と信頼できるUTC時刻を用意してください。
元のMarkdownを表示
# ESP32クイックスタート
タスクだけを使うアプリケーションには[タスク音声](#esp32-task-voice)を、ルームでのライブ音声には[リアルタイム音声(RTC)](#esp32-realtime-rtc)を選んでください。OneSay OSは不要です。SDKはプレビュー版で、まだ公開されていません。プロジェクトにESP-IDFコンポーネントとして組み込んで使います。クライアントのバイナリやローカルのケイパビリティフラグが変わっても、権限はすべて引き続きサーバーが最終的に判断します。
## ESP32 + タスク音声
`sdks/esp32/examples/voice_button`(タスク専用のスタンドアロンESP-IDFアプリケーション)から始めます。これを新しいプロジェクトディレクトリにコピーし、OneSay ESP32コンポーネント(`sdks/esp32`の内容)を`components/onesay`として追加します。サンプルはコンポーネントがその場所にあることを前提としており、コンポーネントがないと単独ではビルドできません。`idf_component.yml`にあるコンポーネントの依存関係の固定は維持してください。不足している依存関係は、初回のビルド時にESP-IDFのコンポーネントマネージャーがダウンロードします。
そのプロジェクトでESP-IDF 6.0.2を使ってビルドし、ボードに書き込んでシリアル出力を確認します。
```text
idf.py set-target esp32s3
idf.py build
idf.py -p <PORT> flash monitor
```
ビルドにボードは不要です。書き込むのはアプリケーションだけで、デバイス認証情報のプロビジョニングは行いません。
`sdks/esp32/examples/voice_button/README.md`と、サンプル内の`main/voice_button.h`に従ってください。`onesay_voice_button_configure`には、安全なデバイス認証情報ストレージ、認可済みの既存のプロジェクト/環境/アプリケーションとソース/ルームのバインディング、ネットワークアクセス、信頼できるUTC時刻/証明書、上限付きの16 kHzモノラルPCM s16leプロデューサーを渡します。既定のフックは接続前に`ONESAY_ERR_AUTH`を返すため、変更していないサンプルは接続しません。キャプチャ、GPIO、I2S、コーデック、ボードのチューニングは、ボード側のコードが担当します。
呼び出し元は、`onesay_voice_button_init`、`onesay_voice_button_connect`、上限付きの`onesay_voice_button_step`の呼び出しを直列化します。SDKが、WSS/OSAF、シーケンス/ACK、バックプレッシャー、リプレイ/再開、キャンセルを担います。保持中のPCMは、ACKで解放されるまで破棄しないでください。キャンセルの送信に成功しても、それはタスクの最終結果ではありません。`onesay_voice_button_close`は、ストレージと依存関係を解放する前にトランスポートを解放する必要があります。このパスはRTCセッションを開きません。
## ESP32 + リアルタイム音声(RTC)
`sdks/esp32`にあるコンポーネントは、`onesay_esp32_rtc.h`を公開します(`CONFIG_ONESAY_RTC_ENABLED`が選択されている場合)。RTCはLiveKit ESP32 SDKをベースに構築されており、`sdks/esp32/idf_component.yml`がテスト済みのバージョンを固定しています。ESP-IDF 6.0.2を使用し、コンポーネントの依存関係グラフはそのまま維持してください。コンポーネントの`sdkconfig.rtc.defaults`はRTC設定フラグメントで、アプリケーションのデフォルトより先に読み込まれます。ボードの設定ではありません。タスクのサンプルでRTCを有効にしても、RTCアプリケーションにはなりません。下記のRTCプロジェクトから始めてください。
### 実行可能なプロジェクト:`rtc_smoke`
ボードに依存しないプロジェクト[`sdks/esp32/examples/rtc_smoke`](../../sdks/esp32/examples/rtc_smoke/README.md)は、実行可能なRTCの出発点です。OneSayコンポーネントと`voice_button`のタスクフローだけを使う、独立したESP-IDFアプリケーションです。GPIO、I2S、コーデック、BSP、AEC、Wi-Fi、NVSのコードはなく、OneSay OSにも依存しません。1回の実行でタスクをストリーミングした後、合成キャプチャでRTCに接続し、パケットを1つ送信して、すべてを解放し、内容を含まない要約行をシリアルコンソールに1行出力します。
プロジェクトはタスクのサンプルと同じ方法で作成します。`rtc_smoke`を新しいディレクトリにコピーし、コンポーネントを`components/onesay`として追加して、`main/voice_button.c`と`main/voice_button.h`を`voice_button`サンプルからその`main/`にコピーします。その後、上記の`idf.py`コマンドでビルドして書き込みます。
強いシンボルとして`onesay_rtc_smoke_configure`を用意してください。弱いシンボルの既定実装は、ネットワーク通信の前に`ONESAY_ERR_AUTH`を返します。`ONESAY_OK`を返す前に、ファームウェアでネットワークを起動し、信頼できるUTC時刻を設定し、安全なストアから設定値を埋めます。プロジェクトのREADMEに、すべてのフィールドが記載されています。ボードの設定(フラッシュサイズ、PSRAM、コンソール)は、3つ目のデフォルトファイルに記述します。
### デバイス認証情報からRTCベアラーへ
RTCオーナーは呼び出し元のベアラーを受け取り、デバイスシークレットを交換することはありません。公開APIの呼び出しだけでデバイス認証情報からRTCに至るには、スモークの設定で`rtc_bearer_from_device_credential = true`を設定します。チェーンは次のとおりです。
1. **デバイス実行前のオーナー権限**。オーナーが委任を作成し、同意リクエストを許可または拒否します。デバイスは、その委任のもとで`createAppSession`を使ってAppSessionを作成します。デバイスは、ルーム、AppSession、ソース、委任のIDを受け取ります。IDは何の権限も与えません。サーバーは、リクエストのたびに実際のグラント、委任、同意を確認します。
2. **デバイスシークレットから短期トークンへ**。`rtc_bearer`ステップは、既存の安全なストアのコールバック(`task.credentials.load`)を通じて、デバイスシークレットを1回だけ読み込みます。シークレットは`Authorization`としてのみ送信します。送信するのは1回の`exchangeDeviceAccessToken`リクエスト(`POST /v1/device-access-tokens`、ボディ`{}`)で、公開の`onesay_esp32_control_request`を通じて行います。RTCのControl設定には、タスクの設定と同じ接続先、デバイス、プロジェクト、環境を指定する必要があります。そうでない場合、シークレットが読み込まれる前にステップが失敗します。シークレットは、結果にかかわらず消去されます。保持されるのは`access_token`だけで、これは`{"data":{"access_token","token_type":"Bearer","expires_at"}}`レスポンスエンベロープに含まれるものです。ストアの`erase`(ファクトリーリセット)が呼び出されることはありません。
3. **トークンからRTCへ**。`onesay_esp32_rtc_prepare`、`onesay_esp32_rtc_connect_audio`、およびパケットポリシーは、同じControlオーナー上で、その短期のデバイスアクセストークンだけを受け取ります。スモークは、解放後に自身のコピーを消去します。
冪等キーのコールバックは、`exchangeDeviceAccessToken`に対して実行ごとに新しいキーを返します。リプレイされたキーでは、元の有効期限が返るためです。RTCの各オペレーションに対しては、同意に結び付いた元のキーを返します。別の確立済みフローのベアラーを代わりに使うには、`load_rtc_bearer`コールバックを指定します。2つの取得元のうち、指定できるのはどちらか一方だけです。長期のデバイスシークレット、Platformキー、プロバイダーキー、LiveKitシークレットを、ファームウェアのソースコード、ログ、ドキュメントに決して含めないでください。
### アプリケーションの入力を準備する
`onesay_esp32_control_context_t`を、`onesay_esp32_control_init`とアプリケーションの`onesay_esp32_control_config_t`で初期化します。想定するデバイス/プロジェクト/環境/アプリケーションのバインディング、証明書または検証済みの証明書バンドル、上限付きのリクエストタイムアウト、`next_idempotency_key`コールバックを指定します。共有のControlイニシャライザーは、RTC用の別のベアラーが人間のユーザーのものである場合でも、有効な`device_id`を必要とします。設定したこのIDによって、ベアラーの主体が変わったり、RTCが認可されたりすることはありません。`environment`には、使用が認可されている環境に対応するSDKの列挙値を設定します。ネットワークの設定、信頼できるUTC時刻、証明書の保存は、引き続きアプリケーションの責務です。TLSのホスト名や日付の検証を無効にしないでください。
以下の音声シーケンスには、呼び出し元が所有する次の入力が必要です。
| 入力 | 公開コントラクト |
| --- | --- |
| `control` | 初期化済みのControlオーナー。使用中は、その証明書とキーコールバックの依存関係を保持してください。 |
| `bearer` / `bearer_length` | 現在有効な、人間のユーザーの短期ベアラー、または委任されたデバイス/AppSessionのベアラー。たとえば[デバイス認証情報のチェーン](#device-credential-to-rtc-bearer)で得たデバイスアクセストークンです。RTCのprepareは、デバイスシークレットの交換もAppSessionの作成も行いません。Platform、プロバイダー、LiveKitの長期シークレットを埋め込まないでください。 |
| `input` | `onesay_action_rtc_connection_create_input_t`。既存の`room_id`と`app_session_id`を含み、文字列は終端されている必要があります。リソースはすでに存在し、認可されている必要があります。 |
| `connection_delegation` | 選択した接続オペレーションの`delegation_id`、または省略する場合は`NULL`。これはリクエストのメタデータであり、許可ではありません。 |
| `audio` | `onesay_rtc_audio_config_t`:認可済みの`source_id`、そのパブリケーションオペレーション用の別個の`delegation_id`(空の場合は省略)、キャプチャ/レンダリングのコールバック、`now_unix_ms`とそのコンテキスト。 |
| `owner` | 呼び出し元が保持する、`NULL`で初期化されたポインター。すでにセッションを所有しているスロットを、prepareに渡さないでください。 |
キーコールバックは、論理オペレーションごとに元のキーを返す必要があります。`createRTCConnection`と`createRTCPublication`は別々のオペレーションです。同意や委任が適用される場合、各キーはそれぞれの確認済みアクションと一致する必要があります。接続のセレクターは、パブリケーションに継承されません。最終的な判断は常にサーバーのチェックです。ローカルのセレクターやコールバックが有効でも、アクセスは付与されません。
### 準備、接続、観測、解放
これは公開ヘッダーを使用したアプリケーションのコードであり、別のSDKエクスポートでも、完全なボードアプリケーションでもありません。上記の入力が必要です。
```c
#include "onesay_esp32_rtc.h"
onesay_err_t example_begin_rtc_audio(
onesay_esp32_control_context_t *control,
const uint8_t *bearer, size_t bearer_length,
const onesay_action_rtc_connection_create_input_t *input,
const char *connection_delegation,
const onesay_rtc_audio_config_t *audio,
onesay_esp32_rtc_t **owner) {
if (owner == NULL || *owner != NULL) return ONESAY_ERR_INVALID_ARG;
onesay_err_t result = onesay_esp32_rtc_prepare(
control, bearer, bearer_length, input, connection_delegation, owner);
if (result != ONESAY_OK) return result;
/* Keep *owner even on failure: the caller still owns cleanup. */
return onesay_esp32_rtc_connect_audio(
*owner, control, bearer, bearer_length, audio);
}
```
これらの公開呼び出しは、すべてのメディア、ネットワーク、クロックのコールバックの外で、アプリケーションスレッド上で直列化してください。関数が戻った後も、ポインターとコールバックのコンテキストを維持してください。prepareが失敗した場合、最初に空だったポインターは`NULL`のままですが、HTTPの結果があいまいな場合は、引き続きサーバーとの照合が必要です。prepareが成功した後は、connectが失敗した場合でも所有権のあるポインターが残るため、クローズが必要です。connectからの`ONESAY_OK`は、接続の試行が受け付けられたことを意味します。接続済み、パブリッシュ済み、音声が相手に届いた、または取り消しが実際に有効になった、ということを意味するものではありません。
| 次の呼び出し(`owner`は保持しているセッションポインター) | 意味と必要な処理 |
| --- | --- |
| `onesay_esp32_rtc_read_binding(owner, &connection)`(`onesay_rtc_binding_t connection = {0}`を使用) | 元のOneSay ID、世代、期限、観測された状態をコピーします。PREPARED/CONNECTING/CONNECTED/RECONNECTING/FAILED/CLOSEDを区別して扱ってください。いずれもサーバーの権限に代わるものではありません。 |
| `onesay_esp32_rtc_read_audio_binding(owner, &publication)`(`onesay_rtc_audio_binding_t publication = {0}`を使用) | 利用可能な場合は、接続の失敗後も含め、内容を含まないパブリケーションIDをコピーします。戻り値を確認してください。パブリケーションが利用できない場合は`ONESAY_ERR_INVALID_ARG`が返り、出力はクリアされます。作り上げたIDが返ることはありません。 |
| `onesay_esp32_rtc_close(&owner)`(`owner != NULL`の場合) | ボードのI/Oをキャンセルし、RTCセッションを停止して、メディアのオーナーを解放します。ポインターがクリアされるのは`ONESAY_OK`の場合のみです。失敗した場合は、後で明示的にクリーンアップを再試行できるよう、ポインターとすべてのコールバックコンテキストを保持してください。それらを解放したり再初期化したりしないでください。 |
サーバーとの照合に必要なIDは、クローズが成功する前に読み取って保持してください。`CLOSED`の観測だけでは、クリーンアップの証明になりません。クローズに失敗すると、所有権のあるポインターが残ることがあります。ローカルのクローズは`endRTCPublication`や`revokeRTCConnection`を実行しません。サーバーのクリーンアップでは、これらの公開オペレーションを、それぞれ現在の認可と冪等キー/同意のバインディングを使って実行します。
キャプチャは、要求された16 kHzモノラルs16leのサンプルを正確に供給する必要があり、1回の読み取りあたり最大640サンプルです。レンダリングは、実際にデコードされたs16le形式を受け入れる必要があります。8/12/16/24/48 kHz、モノラルまたはステレオで、1回のコールバックあたり最大120 ms(48 kHzで5,760フレーム)です。すべてのコールバックは、戻るまでバッファーを借用し、40 msの時間予算に従います。冪等な`cancel`コールバックは並行して実行される場合があり、コンテキストを解放せずにI/Oを起こす必要があります。コールバックからSDKのライフサイクル関数を呼び出してはなりません。GPIO、コーデック、リサンプリング、ボードのチューニングは、このアプリケーションのコードでは提供されません。エンコードとフォーマット変換は、SDKのメディアパイプラインが担います。
認可が拒否された場合は、`onesay_esp32_control_last_error(control)`でエラーコード、リクエストID、再試行可能かどうかを確認してください。トークン、接続情報、トランスポートのボディをダンプしないでください。初回使用の情報が期限切れになった場合、業務上の期限を延ばしたり、クライアントの時計を変更したりしても救済できません。失敗した、または結果があいまいなパブリケーション/接続の試行を、connectを再度呼び出したり代替のキーを発行したりして再試行してはなりません。元のID/キーを保持し、ローカルのオーナーを解放して、アプリケーションの明示的な認可フローを通じて照合してください。
インターフェースの全体については、[SDKのaudio-ownerドキュメント](../../sdks/esp32/README.md#rtc-audio)を参照してください。
`rtc_smoke`プロジェクトは、合成キャプチャとカウント用のレンダリングシンクを使用します。マイク、スピーカー、AEC、音質のチューニングは提供しません。それらはボード側の担当です。タスク専用の`voice_button`サンプルはRTCを使いません。また、タスクやJavaScriptである機能がサポートされていても、ESP32のRTCでその機能がサポートされているとは限りません。
## ボード上の認証情報
デバイスごとに専用のデバイス認証情報をプロビジョニングし、暗号化されたNVSなどの保護されたストレージに保管してください。プロジェクトのAPIキーやデバイス認証情報をファームウェアにコンパイルして組み込んだり、シリアルログに出力したりしないでください。最初の接続の前に、証明書と信頼できるUTC時刻を用意してください。