# WebRTC SFU Sora ドキュメント このドキュメントは WebRTC SFU Sora 2026.1.0 に対応しています。 製品のお問い合わせなどは sora at shiguredo.jp までお願いいたします。 (このメールアドレスへの特定電子メールの送信を拒否いたします) # 公開ノートブック 利用するのに Google アカウントが必要になりますが、 Google NotebookLM を利用した公開ノートブックを提供しています。 # LLM 向け LLM が読み込みやすい形式でドキュメントを提供しています。 - 目次は [llms.txt](/llms.txt) にあります - 全文は [llms-full.txt](/llms-full.txt) にあります ## 重要なお知らせについて [重要なお知らせ](IMPORTANT.html) をご確認ください。 ## 古いドキュメントについて [古いドキュメント](OLD_DOCUMENT.html) をご確認ください。 - [重要なお知らせ](IMPORTANT.html) - [リリースノート](RELEASE_NOTE.html) - [用語集](GLOSSARY.html) - [動作環境](REQUIREMENT.html) - [既知の問題](KNOWN_ISSUES.html) - .. NEW_HTTP_API - [実験的機能](EXPERIMENTAL.html) - [非推奨機能](DEPRECATED.html) - [廃止機能](OBSOLETE.html) - [サポート](SUPPORT.html) - [Sora に問題が発生した場合の問い合わせについて](SUPPORT_ISSUE.html) - [サポートライフサイクル](SUPPORT_LIFECYCLE.html) - [FAQ](FAQ.html) - [トラブルシューティング](TROUBLESHOOTING.html) - [ワークアラウンド](WORKAROUND.html) - [開発ツール](DEVTOOLS.html) - [チュートリアル](TUTORIAL.html) - [本番稼働に向けて](PRODUCTION.html) - [ライセンス](LICENSE.html) - [sora.conf リファレンス](SORA_CONF.html) - [systemd](SYSTEMD.html) - [Linux カーネルチューニング](LINUX_KERNEL_TUNING.html) - [IPv6 での動作について](IPV6.html) - [メタデータ](METADATA.html) - [センシティブデータ](SENSITIVE_DATA.html) - [ログファイル](LOG.html) - [ログの型定義](LOG_TYPE.html) - [アプリケーション連携チュートリアル](APP_INTEGRATE_TUTORIAL.html) - [シグナリング](SIGNALING.html) - [WebSocket 経由のシグナリング](WEBSOCKET_SIGNALING.html) - [DataChannel 経由のシグナリング](DATA_CHANNEL_SIGNALING.html) - [シグナリングの型定義](SIGNALING_TYPE.html) - [シグナリング通知](SIGNALING_NOTIFY.html) - [シグナリング通知メタデータ](SIGNALING_NOTIFY_METADATA.html) - [シグナリング通知メタデータ拡張機能](SIGNALING_NOTIFY_METADATA_EXT.html) - [Sora クライアント要求仕様](SORA_CLIENT.html) - [ウェブフック](WEBHOOK.html) - [認証ウェブフック](AUTH_WEBHOOK.html) - [認証ウェブフック成功時の払い出し](AUTH_WEBHOOK_RETURN.html) - [セッションウェブフック](SESSION_WEBHOOK.html) - [イベントウェブフック](EVENT_WEBHOOK.html) - [統計ウェブフック](STATS_WEBHOOK.html) - [ウェブフックの型定義](WEBHOOK_TYPE.html) - [API](API.html) - [シグナリング API](API_SIGNALING.html) - [コネクション API](API_CONNECTION.html) - [セッション API](API_SESSION.html) - [サイマルキャスト API](API_SIMULCAST.html) - [スポットライト API](API_SPOTLIGHT.html) - [プッシュ API](API_PUSH.html) - [録画 (セッション単位) API](API_RECORDING.html) - [統計 API](API_STATS.html) - [ライセンス API](API_LICENSE.html) - [モード API](API_MODE.html) - [転送フィルター API](API_FORWARDING_FILTER.html) - [シグナリング通知メタデータ拡張 API](API_SIGNALING_NOTIFY_METADATA_EXT.html) - [音声ストリーミング API](API_AUDIO_STREAMING.html) - [RTC 統計情報 API](API_RTC_STATS.html) - [実験的 API](EXPERIMENTAL_API.html) - [シグナリング API](EXPERIMENTAL_API_SIGNALING.html) - [RTP 転送 API](EXPERIMENTAL_API_RTP_FORWARDING.html) - [サイマルキャスト API](EXPERIMENTAL_API_SIMULCAST.html) - [統計 API](EXPERIMENTAL_API_STATS.html) - [非推奨 API](DEPRECATED_API.html) - [非推奨 サイマルキャスト API](DEPRECATED_API_SIMULCAST.html) - [廃止 API](OBSOLETE_API.html) - [テスト API](TEST_API.html) - [クラスター機能](CLUSTER.html) - [クラスター機能チュートリアル](CLUSTER_TUTORIAL.html) - [クラスター機能運用](CLUSTER_OPS.html) - [クラスター機能録画](CLUSTER_RECORDING.html) - [クラスター API](API_CLUSTER.html) - [サイマルキャスト機能](SIMULCAST.html) - [サイマルキャストマルチコーデック機能](SIMULCAST_MULTICODEC.html) - [スポットライト機能](SPOTLIGHT.html) - [WHIP 機能](WHIP.html) - [WHEP 機能](WHEP.html) - [組み込み TURN 機能](TURN.html) - [録画機能 (セッション単位)](RECORDING.html) - [リアルタイムメッセージング機能](MESSAGING.html) - [ICE コネクションステート機能](ICE_CONNECTION_STATE.html) - [モード機能](MODE.html) - [ヘルスチェック機能](OK.html) - [RPC 機能](RPC.html) - [音声ストリーミング機能](AUDIO_STREAMING.html) - [転送フィルター機能](FORWARDING_FILTER.html) - [マルチ転送フィルター機能](MULTI_FORWARDING_FILTER.html) - [プレイアウト遅延機能](PLAYOUT_DELAY.html) - [ノード単位での最大同時接続数制限機能](NODE_MAX_CONNECTIONS.html) - [セッション単位での最大同時接続数制限機能](SESSION_MAX_CONNECTIONS.html) - [セッション単位でのクライアント ID 重複時の既存接続の追い出し機能](SESSION_DUPLICATE_CLIENT_ID.html) - [レガシー録画機能](OBSOLETE_LEGACY_RECORDING.html) - [統計エクスポーター機能](OBSOLETE_STATS_EXPORTER.html) - [Sora のクライアント SDK](CLIENT_SDK.html) - [Sora JavaScript (TypeScript) SDK](JS_SDK.html) - [Sora iOS (Swift) SDK](IOS_SDK.html) - [Sora Android (Kotlin) SDK](ANDROID_SDK.html) - [Sora Unity (C++) SDK](UNITY_SDK.html) - [Sora C++ SDK](CPP_SDK.html) - [Sora Python (C++) SDK](PYTHON_SDK.html) - [Sora Rust SDK](RUST_SDK.html) - [Sora Flutter SDK](FLUTTER_SDK.html) - [Sora 専用ツール](TOOL.html) - [WebRTC 負荷試験ツール Zakuro](ZAKURO.html) - [WebRTC 録画合成ツール Hisui](HISUI.html) - [WebRTC 統計解析ツール Kohaku](KOHAKU.html) - [音声ストリーミングゲートウェイ Suzu](SUZU.html) - [Sora Archive Uploader](SORA_ARCHIVE_UPLOADER.html) - [Sora Exporter](SORA_EXPORTER.html) - [Media Processors](MEDIA_PROCESSORS.html) - [libwebrtc 音声処理](LIBWEBRTC_AUDIO.html) - [libwebrtc リップシンク](LIBWEBRTC_LIP_SYNC.html) - [libwebrtc ペーサー](LIBWEBRTC_PACER.html) - [libwebrtc ミキサーのストリーム数上限](LIBWEBRTC_AUDIO_MIXER_MAX_STREAMS.html) - [マルチストリーム](MULTISTREAM.html) - [Microsoft Edge の WebRTC について](EDGE.html) - [Apple Safari の WebRTC について](SAFARI.html) - [NGINX](NGINX.html) - [オープンソースライセンス](OSS_LICENSE.html) - [古いリリースノート](OLD_RELEASE_NOTE.html) - [古いドキュメント](OLD_DOCUMENT.html) # 重要なお知らせ ## 映像ビットレート自動シェアリング機能の無効化について > **重要** > > 映像ビットレート自動シェアリング機能を Sora 2025 年 12 月リリースの Sora 2025.2.0 からデフォルトで無効にしました。 [multistream_auto_sharing_video_bit_rate](SORA_CONF.html#93f542) は [スポットライト機能](SPOTLIGHT.html) がまだない時代に、参加者が増えた場合でも視聴側の負担を減らす機能でした。 しかし、現在はスポットライト機能を利用することで、参加者が増えた場合でも視聴側の負荷を減らせることや、シェアリング機能の結果、指定したビットレートとは異なる配信が行われて混乱を招くことが多いことから、デフォルトで無効にすることにしました。 今後は、同一チャネルで複数人により双方向配信を行う場合は、スポットライト機能の利用を強くおすすめします。 もしスポットライト機能を利用していない場合で、映像ビットレート自動シェアリング機能を利用したい場合は、 [multistream_auto_sharing_video_bit_rate](SORA_CONF.html#93f542) を `true` に設定してください。 ## Safari 18.4 から Safari 18.5 において H.264 または H.265 の録画が正常に行えない問題が発生します > **重要** > > - この問題は Safari 18.6 に上げることで解決します > - このワークアラウンドは 2026 年 12 月リリース予定の Sora にて廃止します これは Safari の問題で、Sora の問題ではありません。 Safari が H.264 または H.265 の映像を配信する際に、正常なタイムスタンプを生成できない問題が発生しています。 この問題により、Safari で H.264 または H.265 の録画が正常に行われません。 この問題に対応したワークアラウンドを Sora 2024.2.3 で追加しています。 詳細は [Safari タイムスタンプバグに対するワークアラウンド](WORKAROUND.html#e73b7a) をご確認ください。 ## Sora RHEL 版の追加料金について Sora RHEL 版をご利用の場合、2027 年 6 月 1 日以降に有効期間が開始するライセンスについて、 サポート費用としてライセンス料金に 10% (ただし、一契約あたり最大で 10 万円) の料金を加算させていただきます。 ### 料金例 - ライセンス料金が 60 万円の場合は 6 万円 - ライセンス料金が 84 万円の場合は 8.4 万円 - ライセンス料金が 120 万円の場合は 10 万円 - ライセンス料金が 252 万円の場合は 10 万円 RHEL の場合、Ubuntu と比べて環境の維持や Sora の動作検証コストが大きいためで、 ご理解いただきますようお願いいたします。 ## Red Hat Enterprise Linux 10 x86_64 版の提供開始について Sora 2025.1.0 から RHEL 10 x86_64 版の提供を開始しました。 RHEL 10 x86_64 版への切り替えをご希望のお客様はサポートまでご連絡ください。 # リリースノート **CHANGE** : 後方互換性のない変更 **UPDATE** : 後方互換性がある変更 **ADD** : 後方互換性がある追加 **FIX** : バグ修正 ## 2026.1.0 **メジャーアップデート** **リリース**: 2026 年 6 月 24 日 ### ハイライト - OBS Studio 32.1 以降の WHIP サイマルキャストに対応しました - クラスター機能利用時の負荷分散処理を強化しました - クラスター機能利用時に、接続先ノードの範囲を指定できるようにしました - ログの出力先ディレクトリを指定できるようにしました - Ubuntu 26.04 x86_64 / arm64 版の提供を開始しました - 暗号ライブラリを OpenSSL から AWS-LC に変更しました ### 正式版 - ネットワークの状態をシグナリング経由で通知する機能が正式版になりました ### 破壊的変更 今回のリリースで破壊的変更はありません。 ### 廃止機能 今回のリリースで廃止される機能はありません。 ### 変更履歴 - [ADD] Ubuntu 26.04 x86_64 / arm64 版の提供を開始しました - [ADD] シグナリング利用時の offer メッセージの data_channels に `ordered` / `max_packet_life_time` / `max_retransmits` / `protocol` を含めるようになりました- `ordered` は常に含まれます - `max_packet_life_time` と `max_retransmits` と `protocol` はそれぞれ指定されている場合に含まれます - [ADD] 録画機能利用時の `recording.started` と `recording.report` セッションウェブフックに、録画の開始または終了のきっかけを確認できる `trigger` フィールドを追加しました- `recording.started` の `trigger` には `api` / `auth_webhook` / `session_webhook` のいずれかが入ります - `recording.report` の `trigger` には `api` / `expired` / `session_destroyed` のいずれかが入ります - [ADD] `signaling.jsonl` に他のログと同様にユニークな値を持つ `id` フィールドを追加しました - [ADD] 認証ウェブフックログの `auth_webhook.jsonl` / `auth_webhook_error.jsonl` に `response_time_ms` フィールドを追加しました- `auth_webhook_url` 設定が未指定の場合はウェブフックを送信しないため、 `response_time_ms` キーを含めません - [ADD] セッションウェブフックログの `session_webhook.jsonl` / `session_webhook_error.jsonl` に `response_time_ms` フィールドを追加しました- `session_webhook_url` 設定が未指定、もしくは `ignore_*_webhook` 設定で対象のウェブフックを無視するように指定した場合は、ウェブフックを送信しないため、 `response_time_ms` キーを含めません - [ADD] [GetStatsReport](EXPERIMENTAL_API_STATS.html#bbbfca) API にウェブフック応答時間の累積合計時間 (ミリ秒) を計測する項目を追加しました- 認証ウェブフックは `total_auth_webhook_response_time_ms` - セッションウェブフックは `total_session_webhook_response_time_ms` - イベントウェブフックは `total_event_webhook_response_time_ms` - 統計ウェブフックは `total_stats_webhook_response_time_ms` - [ADD] [GetStatsReport](EXPERIMENTAL_API_STATS.html#bbbfca) API にウェブフック応答時間のヒストグラム項目を追加しました- 認証ウェブフックは `auth_webhook_response_time_ms_buckets` - セッションウェブフックは `session_webhook_response_time_ms_buckets` - イベントウェブフックは `event_webhook_response_time_ms_buckets` - 統計ウェブフックは `stats_webhook_response_time_ms_buckets` - [CHANGE] DataChannel 切り替え後の WebSocket シグナリングの `"type": "ping"` 送信間隔のデフォルト値を 30 秒から 15 秒に変更しました- 送信間隔は新たに追加された [switched_websocket_signaling_ping_interval](SORA_CONF.html#6c5676) で変更できます - [FIX] 既に廃止している `signaling_notify_rtp_stream` の設定が `sora.conf` に残っていたので削除しました - [FIX] H.265 コーデックで録画した MP4 ファイルが Apple QuickTime Player で再生できない問題を修正しました - [FIX] AV1 コーデックで録画した MP4 ファイルのメタデータに FPS 情報が含まれていない問題を修正しました - [FIX] WHIP 機能利用時に Answer SDP の RTP ヘッダー拡張の ID マップを固定しました #### 暗号ライブラリを AWS-LC に変更 暗号ライブラリを OpenSSL から AWS が公開している OpenSSL 互換の暗号ライブラリである [AWS-LC](https://github.com/aws/aws-lc) に変更しました。 AWS-LC は OpenSSL と比較してセキュリティ面や性能面での優位性があります。 #### ログ出力先ディレクトリ指定 - [ADD] ログの出力先を指定できる [log_dir](SORA_CONF.html#ddcdf0) を追加しました- デフォルトは `log` です - 相対パスの場合は Sora のパッケージディレクトリ (`sora-/`) からの相対パスになります - 絶対パスの場合は指定したパスになります #### サイマルキャスト - [ADD] サイマルキャスト機能の `simulcast_encodings` パラメーターに `priority` を指定できるようになりました- `very-low` / `low` / `medium` / `high` - [ADD] サイマルキャスト機能の `simulcast_encodings` パラメーターに `networkPriority` を指定できるようになりました- `very-low` / `low` / `medium` / `high` #### スポットライト機能 - [ADD] [GetStatsConnection](API_STATS.html#e79b61) / [GetStatsClient](API_STATS.html#ef69ae) / [GetStatsAllConnections](API_STATS.html#ef695a) API の `spotlight` に、発話開始からフォーカス取得までの累積遅延 (マイクロ秒) を計測する `total_spotlight_audible_to_focus_delay_us` を追加しました - [ADD] [GetStatsConnection](API_STATS.html#e79b61) / [GetStatsClient](API_STATS.html#ef69ae) / [GetStatsAllConnections](API_STATS.html#ef695a) API の `spotlight` に、フォーカス取得成功回数を計測する `total_spotlight_focus_succeeded` を追加しました - [FIX] スポットライト機能で遅延フォーカス無効時に、発話からフォーカス取得まで最大 500 ms 遅延する問題を修正しました #### クラスター機能 クラスター利用時により安定的に負荷を各ノードに分散できるようになりました。 - [CHANGE] クラスターリレー機能でアフィニティ機能を有効にした際、今までは「空き接続数」が最も多いノードに接続していましたが、今後は「空き接続率」が最も高いノードに接続するようになりました- ノード単位での最大同時接続数制限を利用して最大同時接続数が異なる場合、より公平に接続先のノードを選択できるようになりました - [ADD] クラスター利用時に同一セッションに大量の接続が集中した場合でも接続が特定ノードに偏るのを防止する仕組みを追加しました - [FIX] クラスター利用時にテンポラリーノードが瞬断後復旧した場合に、まれにクラスターから除外されたままになる問題を修正しました #### クラスターリレー機能利用時の接続先ノード範囲指定機能 **これは実験的機能です。** クラスターリレー機能利用時に、接続先として利用するノードの範囲を限定できる [アフィニティ機能の接続先ノード範囲指定機能](CLUSTER.html#c6991a) を追加しました。この機能を利用することで、認証ウェブフックの認証成功時に払い出した `cluster_affinity_node_name_list` に指定した複数のノードをコネクション単位での接続先ノードとして限定することができます。 - [ADD] クラスターリレー機能利用時に、認証ウェブフックの認証成功時の払い出しで `cluster_affinity_node_name_list` に複数のノード名を指定することで、コネクション単位で接続先として利用するノードを限定できるようになりました- この機能は `cluster_affinity` が `true` と同時に払い出されている場合にのみ有効になります- [default_cluster_affinity](SORA_CONF.html#95466d) が `true` の場合でも、認証成功時の払い出しで `cluster_affinity` を `true` で払い出さない場合はこの機能は有効になりません - 利用には [最大ノード数ライセンス](LICENSE.html#aee259) が必要です - `cluster_affinity_node_name_list` 指定時のエラーを追加しました- `invalid_affinity_node_name_list` はノード名の不正や空リスト指定など、指定内容自体に問題がある場合に出力されます - `no_acceptable_node` は接続先として利用できるノードが指定した範囲に 1 つもない場合に出力されます #### OBS Studio WHIP サイマルキャスト対応 [OBS Studio 32.1](https://github.com/obsproject/obs-studio/releases/tag/32.1.0) で追加された WHIP のサイマルキャスト機能に対応しました。 > **警告** > > Sora の WHIP サイマルキャストは OBS Studio の WHIP サイマルキャストにのみ対応しています。 - [ADD] OBS Studio 32.1 以降で利用できる WHIP サイマルキャストに対応しました- サイマルキャストのエンコーディングに [simulcast_encodings_file](SORA_CONF.html#dead73) を設定しても、 OBS Studio 側の設定が採用されるため適用されません - 認証成功時に [simulcast_encodings の払い出し](AUTH_WEBHOOK_RETURN.html#eebbba) を指定しても、 OBS Studio 側の設定が採用されるため適用されません - OBS Studio の WHIP サイマルキャスト利用時には、認証ウェブフックで `whip` と `simulcast` が `true` で送られてきます - OBS Studio の WHIP サイマルキャスト利用時に認証成功時の払い出しで `simulcast` に `false` を指定すると、 Sora の接続に失敗します - OBS Studio の WHIP サイマルキャスト利用時に合計レイヤー数に 4 を指定すると、 Sora の接続に失敗します - [whip_simulcast](SORA_CONF.html#5a85ec) が `false` の場合、 OBS Studio の WHIP サイマルキャストを利用すると、 Sora の接続に失敗します - [ADD] OBS Studio で WHIP 利用時にサイマルキャストを利用するかどうかを指定する [whip_simulcast](SORA_CONF.html#5a85ec) を追加しました- デフォルトは `true` です # 用語集 ## クライアント クライアントは Sora と WebSocket や WebRTC で接続しているものを指し、各接続にはユニークな ID が与えられます。 1. **1 接続 1 クライアントの原則**:- Sora における各接続はそれぞれ別個のクライアントとして扱われます。つまり、1 つの接続は 1 つのクライアントとして扱われます 2. **ユニークな ID であるコネクション ID の割り当て**:- クライアントが Sora に接続すると、その接続には固有の ID (コネクション ID) が割り当てられます 3. **複数クライアントのサポート**:- SDK を利用することで、ユーザーは複数のクライアントを使用し、複数の接続を確立することができます 4. **同一ユーザーによる接続の統合**:- 同じユーザーが複数の接続を行う場合、これらの接続に同じクライアント ID を指定することで、ユーザーを一意に識別できます 5. **クライアント ID の自動割り当て**:- クライアント ID を指定しない場合、 Sora はコネクション ID をクライアント ID として自動的に割り当てます ## チャネル チャネルは Sora で使用される「ルーム」や「グループ」として機能する、独立したコミュニケーションのスペースです。 1. **コミュニケーションの制限**:- チャネルに接続したクライアントは、そのチャネル内でのみ音声、映像、データのやりとりができます。異なるチャネルのクライアント間での直接のコミュニケーションはできません 2. **複数チャネルへのアクセス**:- 一つのウェブブラウザを使用して、複数のクライアントが同時に複数のチャネルにアクセスすることができます 3. **チャネル ID**:- 利用者はチャネルに 255 バイトまでの値を ID として指定できます ## セッション セッションは実際にチャネルに参加しているクライアントの集まりを指し、各セッションにはユニークな ID が与えられます。 1. **セッションの存在**:- チャネルに 1 つ以上のクライアントが接続している状態を「セッションが存在する」と言い、逆にクライアントが 1 人も接続していない場合は「セッションが存在しない」と言います 2. **セッションの生成**:- セッションは、セッションがまだ存在しないチャネルにクライアントが接続した時に生成されます。 3. **セッションの破棄**:- 全てのクライアントがチャネルから切断した後、一定期間が経過するとセッションは破棄されます。 4. **セッション ID**:- セッションには Sora が自動で生成する一意の ID が割り当てられます ## コネクション コネクションはクライアントが接続している状態を指し、各コネクションにはユニークな ID が与えられます。 1. **コネクションの生成**:- クライアントが接続し、認証に成功した後、WebRTC が確立されるとコネクションが生成されます 2. **コネクションの破棄**:- クライアントが切断すると、そのコネクションは破棄されます 3. **コネクション ID の自動割り当て**:- コネクションには Sora が自動で生成する一意の ID が割り当てられます ## ロール Sora のロールは、クライアントが音声や映像をどのように取り扱うかを決定する役割を果たします。 1. **sendrecv (送受信)**:- sendrecv ロールを選択したクライアントは、音声および映像の送受信ができます。これは、クライアントが他のクライアントと音声や映像を交換する、双方向のコミュニケーションができる状態を意味します 2. **sendonly (送信のみ)**:- sendonly ロールを選択したクライアントは、音声および映像の送信のみができます。これは、自分の音声や映像を他のクライアントに送ることはできますが、他からの音声や映像を受け取ることはできない状態を意味します 3. **recvonly (受信のみ)**:- recvonly ロールを選択したクライアントは、音声および映像の受信のみができます。これは、他のクライアントからの音声や映像は受け取ることができますが、自分から送ることはできない状態を意味します 4. **ロールの選択タイミング**:- クライアントは接続時にのみロールを選択できます。一度選択されたロールは、その後の接続中に変更することはできません 5. **ロールとメッセージング機能の独立性**:- ロールの選択は Sora のメッセージング機能には影響しません。メッセージング機能の方向性(送信、受信、またはその両方)については、別の項目「direction」で管理されます # 動作環境 ## 対応 OS Sora は Ubuntu と Red Hat Enterprise Linux (RHEL) での動作をサポートしています。 ### Ubuntu x86_64 / arm64 - Ubuntu 26.04 LTS - Ubuntu 24.04 LTS - Ubuntu 22.04 LTS ### Red Hat Enterprise Linux x86_64 - Red Hat Enterprise Linux 10 x86_64 - Red Hat Enterprise Linux 9 x86_64 - Red Hat Enterprise Linux 8 x86_64 ## 対応 OS のサポートライフサイクル ### Ubuntu 26.04 LTS **スタンダードサポートまで対応** 2031 年 4 月 30 日にスタンダードサポートが終了するため、 2030 年 6 月リリース予定の Sora までがサポート対象となります。 ### Ubuntu 24.04 LTS **スタンダードサポートまで対応** 2029 年 4 月 30 日にスタンダードサポートが終了するため、 2028 年 6 月リリース予定の Sora までがサポート対象となります。 ### Ubuntu 22.04 LTS **スタンダードサポートまで対応** 2027 年 4 月 30 日にスタンダードサポートが終了するため、 2026 年 6 月リリース予定の Sora までがサポート対象となります。 ### Red Hat Enterprise Linux 10 **メンテナンスサポートまで対応** 2035 年 5 月 31 日にメンテナンスサポートが終了するため、 2034 年 6 月リリース予定の Sora までがサポート対象となります。 ### Red Hat Enterprise Linux 9 **メンテナンスサポートまで対応** 2032 年 5 月 31 日にメンテナンスサポートが終了するため、 2031 年 6 月リリース予定の Sora までがサポート対象となります。 ### Red Hat Enterprise Linux 8 **メンテナンスサポートまで対応** 2029 年 5 月 31 日にメンテナンスサポートが終了するため、 2028 年 6 月リリース予定の Sora までがサポート対象となります。 # 既知の問題 **既知の問題の詳細についてはサポートまでお問い合わせください** ## Chrome/Edge の不具合による録画機能利用時の音ズレ問題について Chrome/Edge の不具合により、音声トラックを削除し、その後音声トラックを追加した際に、 音声パケットやそれに関連するタイムスタンプが正しく処理されない場合があり、 これにより録画機能を利用する際に音ズレが発生する問題があります。 この Chrome/Edge の問題は残念ながら解決の見込みはありませんが、録画機能への影響があまりにも大きいため、 Sora 2024.1.0 でこの問題の改善を行いました。 しかし、この改善のための変更が Chrome の別の不具合の影響を受けて新たな問題が発生することが判明したため、 本変更をデフォルトで無効にすることにしました。 この問題への改善は今後も継続していく予定です。 この問題に関して不明点がありましたら、サポートまでご連絡ください。 > **警告** > > Safari および Safari Technology Preview でも音ズレが発生する問題を確認しています。 ### Sora 2024.1.3 での変更点 Sora 2024.1.0 で [rtp_hdrext_abs_capture_time](SORA_CONF.html#6cf562) のデフォルトを `true` へ変更し、 RTP ヘッダー拡張 `abs-capture-time` を利用することで録画機能利用時の音ズレを回避する仕組みを追加しました。 しかし、一部の端末では予期しない挙動が発生し、録画自体に問題が発生することが判明したため、 Sora 2024.1.3 で [rtp_hdrext_abs_capture_time](SORA_CONF.html#6cf562) の デフォルトを `false` へ変更しました。 この設定を `true` にする場合は、事前にサポートまでご連絡ください。 ## 署名アルゴリズムに SHA-1 が利用されている中間証明書をご利用されているお客様へ Sora 2023.2.x から、署名アルゴリズムが SHA-1 の中間証明書を利用した場合、 Bad Certificate エラーとして接続が拒否されます。 影響のある機能は下記の機能です。 - ウェブフック機能 - 音声ストリーミング機能 もし、このエラーがログに出力された場合はサポートまでご連絡ください。 ## マルチストリーム機能 - `"type": "sendrecv"` 利用時に音声のみや映像のみを指定した場合でも、音声と映像の両方が送られてきます- 転送フィルター機能を利用してください - 将来的に改善予定です ## OBS WHIP/WHEP 機能 ### スポットライト利用時に音声が自動で配信されない - OBS 側の WHIP に利用している WebRTC スタック実装で音量レベルを音声パケットに載せてこないため判断ができません- [FocusSpotlightFixed](API_SPOTLIGHT.html#beaf88) API を利用して OBS の接続にフォーカスをあてることで音声を配信できます - WHIP でのスポットライト有効時は音声を自動で配信する仕組みを導入するか、OBS 側の WHIP に利用している WebRTC スタックへ貢献することを検討しています ## 仕様としての制限 ### マルチトラック - 1 つのストリームに 1 オーディオトラック、1 ビデオトラックしか設定できません- マルチトラックへの対応は検討していますが未定です # 実験的機能 > **重要** > > 実験的機能を本番環境で利用する場合は **必ず** サポートまでご連絡ください。 ## 概要 実験的機能とは、正式リリースに向けて積極的に改善を行っている機能、および正式リリースを行うかについて決定を保留にしている機能であり、 今後、後方互換性のない仕様変更を行う可能性があります。 > **重要** > > 実験的機能は仕様の変更はあるものの、動作が不安定であることやバグを多く含んでいることを意味するものではなく、ご利用の場合はサポートの対象となります。 また、実験的機能に関するお客様からのお問い合わせやフィードバックを基に、今後の開発方針を決定することがあります。 ごく稀に、正式リリースを見合わせて削除する機能もありますので、具体的な機能については以下の一覧でご確認いただくとともに、 実際に本番環境でご利用いただく場合は事前にサポートまでご連絡いただきますようお願いします。 ## 実験的機能一覧 ### 正式リリースに向けて改善を進めている機能 - [視聴側の自動 rid ストリーム切り替え機能](SIMULCAST.html#0eb8c3)- 2026 年 12 月リリースの Sora にて正式リリースの予定です - [サイマルキャストマルチコーデック機能](SIMULCAST_MULTICODEC.html)- 2026 年 12 月リリースの Sora にて正式リリースの予定です - [OBS (WHEP) 対応](WHEP.html)- RFC が公開され次第正式リリースの予定です ### 正式リリースが未定の機能 - 映像コーデックパラメーター指定機能- [signaling_vp9_params](SORA_CONF.html#3261ea) - [signaling_av1_params](SORA_CONF.html#91f3b8) - [signaling_h264_params](SORA_CONF.html#b32e49) - [signaling_h265_params](SORA_CONF.html#8ed4e9) - [default_vp9_param_profile_id](SORA_CONF.html#ab0de9) - [default_av1_param_profile](SORA_CONF.html#319e30) - [default_h264_param_profile_level_id](SORA_CONF.html#1581db) - [default_h265_param_level_id](SORA_CONF.html#d15808) - [ビデオの VP9 設定指定](WEBSOCKET_SIGNALING.html#b7556a) - [ビデオの AV1 設定指定](WEBSOCKET_SIGNALING.html#48f92d) - [ビデオの H.264 設定指定](WEBSOCKET_SIGNALING.html#ffc4cb) - [ビデオの H.265 設定指定](WEBSOCKET_SIGNALING.html#bfe45b) - 音声コーデックパラメーター指定機能 - ウェブフック HTTP ヘッダー - [統計 API](EXPERIMENTAL_API_STATS.html) - [GetStatsReport](EXPERIMENTAL_API_STATS.html#bbbfca) API ### 正式リリースを行うかについて検討を保留にしている機能 - H.264/H.265 B-frame 対応- [h264_b_frame](SORA_CONF.html#f546aa) - [h265_b_frame](SORA_CONF.html#a9a8f8) - [RTP 転送 API](EXPERIMENTAL_API_RTP_FORWARDING.html) - [ListChannels](EXPERIMENTAL_API_SIGNALING.html#b27c42) API - 映像コーデックのビットレートを 15 Mbps より大きく指定した場合 # 非推奨機能 ここでは今後廃止される非推奨の機能について説明していきます。 不明点はサポートまでお問い合わせください。 ## サイマルキャスト視聴 rid 指定 `default_simulcast_rid` の非推奨化と廃止 > **注意** > > **2027 年 12 月リリース予定の Sora にて廃止** サイマルキャスト利用時に、視聴する rid を指定する設定である `sora.conf` の [default_simulcast_rid](SORA_CONF.html#d95788) を非推奨にしました。 今後は [default_simulcast_request_rid](SORA_CONF.html#9891c8) を利用してください。 2027 年 12 月リリース予定の Sora にて `sora.conf` の [default_simulcast_rid](SORA_CONF.html#d95788) を廃止します。 ## シグナリング接続時と認証成功時の `simulcast_rid` の非推奨化と廃止 > **注意** > > **2027 年 12 月リリース予定の Sora にて廃止** シグナリング接続時と認証成功時のサイマルキャスト視聴 rid 指定 `simulcast_rid` を非推奨にしました。 今後は `simulcast_request_rid` を利用してください。 2027 年 12 月リリース予定の Sora にて `simulcast_rid` を廃止します。 ## スポットライト機能 `spotlight_number` 項目の認証成功時の払い出しの非推奨化 > **重要** > > 現時点では廃止予定はありませんが、将来的に 1 年の移行期間をもうけて廃止する予定です。 セッションウェブフック [session.created](SESSION_WEBHOOK.html#1d1984) で `spotlight_number` の値を払い出すことができるようになりました。 そのためスポットライト機能の `spotlight_number` 項目を認証ウェブフック成功時の払い出しで利用するのは非推奨になります。 現時点では廃止予定はありませんが、将来的に 1 年以上の移行期間を経て廃止される予定です。 ## ウェブフックの HTTP ヘッダー `x-sora` prefix の非推奨化 > **重要** > > 現時点では廃止予定はありませんが、将来的に 1 年の移行期間をもうけて廃止する予定です。 `x-sora` prefix とは別に `sora` prefix の HTTP ヘッダーを追加しました。 これは [RFC 6648](https://datatracker.ietf.org/doc/html/rfc6648) による `x-` prefix の非推奨化に準拠するためです。 `x-sora` prefix は非推奨になります。現時点では廃止予定はありませんが、将来的に 1 年以上の移行期間を経て廃止される予定です。 - セッションウェブフックの `x-sora-session-webhook-type` ヘッダーは非推奨です、 `sora-session-webhook-type` ヘッダーを利用してください - イベントウェブフックの `x-sora-event-webhook-type` ヘッダーは非推奨です、 `sora-event-webhook-type` ヘッダーを利用してください ## API [非推奨 API](DEPRECATED_API.html) をご確認ください # 廃止機能 ## 概要 廃止機能とはすでに廃止された機能です。 API の廃止については [廃止 API](OBSOLETE_API.html) をご確認ください。 ## レガシー録画機能の廃止 > **注意** > > **2025 年 12 月リリースの Sora にて廃止** 今後は [録画機能 (セッション単位)](RECORDING.html) をご利用ください。 移行に関しては レガシー録画機能から新しい録画機能 (セッション単位) への移行 をご確認ください。 - 2024 年 12 月リリースの Sora にて `legacy_recording` のデフォルトを `false` に変更しました - 2025 年 12 月リリースの Sora にて `legacy_recording` の設定を廃止し、レガシーレコーディングを廃止しました。 ## ICE コネクションステートのタイムアウト指定設定の変更による非推奨と廃止 > **注意** > > **2025 年 12 月リリースの Sora にて廃止** ICE コネクションステートのタイムアウトを設定する `sora.conf` の `ice_connection_state_disconnected_timeout` と `ice_connection_state_failed_timeout` を非推奨にしました。 2025 年 12 月リリースの Sora にて `sora.conf` の `ice_connection_state_disconnected_timeout` と `ice_connection_state_failed_timeout` を廃止しました。 今後は `sora.conf` の [default_ice_connection_state_disconnected_timeout](SORA_CONF.html#420a1e) と [default_ice_connection_state_failed_timeout](SORA_CONF.html#d6f965) をご利用ください。 ## 組み込み TURN 機能無効の廃止 > **注意** > > **2025 年 12 月リリースの Sora にて廃止** TURN 機能を無効にする設定を廃止しました。それに伴い `sora.conf` の `turn` を `false` に設定することを廃止しました。 - 2025 年 6 月リリースの Sora にて組み込み TURN 機能を無効にする `turn` を `false` に設定することを非推奨にしました - 2025 年 12 月リリースの Sora にて `turn` を廃止し、組み込み TURN 機能を無効にすることができなくなりました ## WHIP/WHEP の TURN 機能無効の非推奨化と廃止 > **注意** > > **2025 年 12 月リリースの Sora にて廃止** WHIP/WHEP の TURN 機能を無効にする設定を非推奨にしました。それに伴い `sora.conf` の `whip_turn` と `whep_turn` を `false` に設定することを非推奨にしました。 - 2025 年 6 月リリースの Sora にて WHIP/WHEP の TURN 機能を無効にする `whip_turn` と `whep_turn` を `false` に設定することを非推奨化しました - 2025 年 12 月リリースの Sora にて `whip_turn` と `whep_turn` を廃止し、WHIP/WHEP の TURN 機能を無効にすることができなくなりました > **警告** > > 2024 年 7 月リリースの OBS 30.2 より前のバージョンの OBS は 2025 年 12 月リリースの Sora からは接続できなくなります。 ## ListForwardingFilters API の `channel_forwarding_filter` の廃止 > **注意** > > **2025 年 12 月リリースの Sora にて廃止** [ListForwardingFilters](API_FORWARDING_FILTER.html#a1dd75) API の戻り値 `channel_forwarding_filter` を廃止しました。 今後は `channel_forwarding_filters` をご利用ください。 ## 認証成功時とセッション生成時の `forwarding_filter` の廃止 > **注意** > > **2025 年 12 月リリースの Sora にて廃止** 認証成功時とセッション生成時の `forwarding_filter` を廃止しました。 今後は `forwarding_filters` をご利用ください。 ## RTP ストリーム停止/再開 API の廃止 > **注意** > > **2025 年 12 月リリースの Sora にて廃止** RTP 転送ストリーム停止/再開 API は [転送フィルター](FORWARDING_FILTER.html) により同等の機能が提供でき、 重複機能となるため廃止しました。 今後は [転送フィルター](FORWARDING_FILTER.html) をご利用ください。 ## レガシーネットワークシグナリング通知機能の非推奨化と廃止 > **注意** > > **2025 年 12 月リリースの Sora にて廃止** ネットワークシグナリング通知機能変更に伴い、レガシーなネットワークシグナリング通知機能を非推奨としました。 - 2025 年 6 月リリースの Sora にてレガシーなネットワークシグナリング通知機能を非推奨としました - 2025 年 12 月リリースの Sora にてレガシーなネットワークシグナリング通知機能を廃止しました ## AV1 無効の廃止 AV1 を試すために用意した `av1` ですが、 既にデフォルト有効になっており、AV1 を無効にする必要がないと判断したため、 `av1` を廃止しました。 - 2025 年 6 月リリースの Sora にて `av1` を非推奨としました - 2025 年 12 月リリースの Sora にて `av1` を廃止し、AV1 を無効にすることができなくなりました ## H.265 無効の廃止 H.265 を試すために用意した `h265` ですが、 既にデフォルト有効になっており、H.265 を無効にする必要がないと判断したため、 `h265` を廃止しました。 - 2025 年 6 月リリースの Sora にて `h265` を非推奨としました - 2025 年 12 月リリースの Sora にて `h265` を廃止し、H.265 を無効にすることができなくなりました ## Ubuntu 20.04 対応 Ubuntu 20.04 は 2025 年 4 月末でサポートが終了となるのにあわせて、Sora の Ubuntu 20.04 版については以下のとおりとなります。 **パッケージの提供**: 2024 年 6 月にリリースの 2024.1.0、およびその後リリースされる可能性のある 2024.1.x の提供をもって終了 **サポートの終了**: 2024.1.0 およびおよびその後リリースされる可能性のある 2024.1.x に対しては 2025 年 6 月末で終了 Ubuntu 20.04 版をご利用のお客様は、早めに OS の変更をご検討の上、移行先の OS をサポートまでご連絡下さい。 ## CentOS 7 対応 CentOS 7 は 2024 年 6 月末でサポートが終了となるのに合わせて、Sora の CentOS 7 版については以下のとおりとなります。 **パッケージの提供**: 2023 年 12 月にリリースの 2023.2.0、およびその後リリースされる可能性のある 2023.2.x の提供をもって終了 **サポートの終了**: 2023.2.0 およびおよびその後リリースされる可能性のある 2023.2.x に対しては 2024 年 12 月末で終了 - [EOL CentOS | End of Life (EOL) | Lifecycle](https://endoflife.software/operating-systems/linux/centos) CentOS 7 版をご利用のお客様は、早めに OS の変更をご検討の上、移行先の OS をサポートまでご連絡下さい。 ## 統計エクスポーター機能の廃止 > **重要** > > **2025 年 6 月リリースの Sora にて廃止** 実験的機能として提供している統計エクスポーター機能を廃止しました。 今後は [統計ウェブフック](STATS_WEBHOOK.html) をご利用ください。 ## ユーザーエージェント統計の廃止 > **重要** > > **2025 年 6 月リリースの Sora にて廃止** 統計エクスポーター機能廃止に伴い、ユーザーエージェント統計関連も廃止しました。 今後は RTC 統計を利用してください。 - 認証ウェブフック成功時の払い出しで利用する `user_agent_stats` を廃止しました- `rtc_stats` をご利用ください - `sora.conf` の `sora_conf-user_agent_stats` を廃止しました- [default_rtc_stats](SORA_CONF.html#558c2b) をご利用ください ## legacy_signaling_error の廃止 2024.1.x までのシグナリングエラー時のログ出力先やウェブフック [connection.failed](EVENT_WEBHOOK.html#5266b6) の通知タイミングを維持する `legacy_signaling_error` を廃止しました。 今後は以下の挙動になります。 - シグナリング時のエラーが `sora.jsonl` に出力しません - シグナリング時のエラーが `signaling_error.jsonl` に出力します - 認証失敗時のエラーが `sora.jsonl` に出力しません - 認証失敗時のエラーが `signaling_error.jsonl` に出力します - イベントウェブフック [connection.failed](EVENT_WEBHOOK.html#5266b6) が認証失敗時には通知しません - イベントウェブフック [connection.failed](EVENT_WEBHOOK.html#5266b6) が認証成功後に接続に失敗した時のみ通知します ### 認証失敗時のエラーログの出力 認証失敗時のログを `sora.jsonl` から `signaling_error.jsonl` に出力します。 認証時失敗時のエラーはシグナリングエラーと同等として扱います。 `sora.jsonl` に `ERROR` で出力されるシグナリング失敗のエラーメッセージは [connection.created](EVENT_WEBHOOK.html#eef06c) 以降に変更します。 ### イベントウェブフック connection.failed の挙動 [connection.failed](EVENT_WEBHOOK.html#5266b6) はシグナリング時にエラーが発生した場合通知する仕組みでしたが、 今後は認証が成功した後に接続が失敗した場合のみ通知されます。 これにより、認証が失敗した場合には [connection.failed](EVENT_WEBHOOK.html#5266b6) ウェブフックは通知されません。 ## mode_session_vanished の廃止 **2025 年 6 月リリースの Sora にて廃止** mode_session_vanished を廃止しました。 代わりに [GetStatsReport](EXPERIMENTAL_API_STATS.html#bbbfca) API の `total_ongoing_connections` をご利用ください。 また [Sora Exporter](SORA_EXPORTER.html) をご利用いただくことで、Sora の統計情報を OpenMetrics 形式で取得できますので、 こちらもご利用ください。 ## レガシーストリーム(非マルチストリーム)機能の廃止 **2025 年 6 月リリースの Sora にて廃止** レガシーストリーム(非マルチストリーム)機能を廃止しました。 今後はマルチストリームをご利用ください。 - 2024 年 6 月リリースの Sora にて `legacy_stream` の設定をデフォルト `false` にて追加しました - 2025 年 6 月リリースの Sora にて `legacy_stream` の設定を廃止し、レガシーストリームを廃止しました ## ListClusterNodes API の include_all_known_nodes の廃止 **2024 年 12 月リリースの Sora にて廃止** [ListClusterNodes](API_CLUSTER.html#a70901) API の `include_all_known_nodes` は廃止しました。 今後はそのクラスターへ登録されている全てのノード情報が常に含まれるようになります。 もし一時的に離脱しているノードを含めない場合は API の結果を `"connected": true` でフィルタリングしてください。 ## sora.conf の legacy_auth_webhook_log の廃止 **2024 年 12 月リリースの Sora にて廃止** 今まで認証ウェブフックが 200 番台を返さなかったり、 `"allowed"` 項目を含まなかったり、 `"allowed": false` なのに `"reason"` が含まれていなかったり、送信先から応答がなくタイムアウトしたなどで、 処理が正常に行えなかった場合は `auth_webhook.jsonl` に `res` 項目なしで出力していました。 この仕様を維持する `legacy_auth_webhook_log` 設定を廃止しました。 今後は `auth_webhook_error.jsonl` に `reason` 項目を追加して出力するように変更しました。 ## sora.conf の legacy_event_webhook_connection_destroyed_reason の廃止 **2024 年 12 月リリースの Sora にて廃止** Sora 2023.2.x まで `connection.destroyed` の `reason` には、 `disconnect_api_reason` と同じ値が含まれており、 コネクション切断系 API で `reason` が指定されていない場合は `null` が含めていました。 この仕様を維持する `legacy_event_webhook_connection_destroyed_reason` 設定を廃止しました。 今後は `connection.destroyed` の `reason` には以下のような値が入ります。 - `"normal"` は通常のコネクション破棄 - `"disconnected_api"` はコネクション切断系 API によるコネクション破棄 - `"session_destroyed"` はセッションライフタイム期限切れ、または API によるセッション破棄によるコネクション破棄 - `"lifetime_expired"` はライフタイム期限切れによるコネクション破棄 ## 認証成功時の払い出し h264_profile_level_id の廃止 **2024 年 6 月リリースの Sora にて廃止** 認証成功時の払い出しで H264 のプロファイルレベルの値を指定する `h264_profile_level_id` を廃止しました。 `"video_h264_params": {"profile_level_id": ...}` をご利用ください。 ## sora.conf の default_h264_profile_level_id の廃止 **2024 年 6 月リリースの Sora にて廃止** H264 のプロファイルレベルのデフォルト値を指定する `default_h264_profile_level_id` を廃止しました。 [default_h264_param_profile_level_id](SORA_CONF.html#1581db) をご利用ください。 ## Lyra コーデック対応の廃止 **2024 年 6 月リリースの Sora にて廃止** Lyra コーデック対応を廃止しました。 Opus 1.5 で Lyra 同様の低ビットレートが利用可能になったこと、Lyra が 2 年間更新がないことが廃止の理由です。 ## sora.conf の legacy_log_format の廃止 **2023 年 12 月リリースの Sora にて廃止** sora ログや internal ログをレガシーフォーマットで出力する `sora.conf` の `legacy_log_format` 設定を廃止しました。 ## sora.conf の legacy_log_extension の廃止 **2023 年 12 月リリースの Sora にて廃止** JSONL 形式で出力するログの拡張子を `.log` でファイル出力する `sora.conf` の `legacy_log_extension` 設定を廃止しました。 ## sora.conf の legacy_webhook_audio_video_json_structure の廃止 **2023 年 12 月リリースの Sora にて廃止** ウェブフックで利用する audio と video の JSON 構造を `{"audio": {"codec_type": "OPUS"}}` といった入れ子構造にする `sora.conf` の `legacy_webhook_audio_video_json_structure` 設定を廃止しました。 ## DataChannel で利用している SCTP 関連の実験的な設定の廃止 **2023 年 6 月リリースの Sora にて廃止** DataChannel で利用している SCTP 関連の実験的な設定である `dcsctp_heartbeat_interval` と `dcsctp_slow_start_tcp_style` の設定を廃止しました。 ## Ubuntu 18.04 サポートの終了 **サポート提供終了**: 2023 年 4 月末 [Ubuntu release cycle | Ubuntu](https://ubuntu.com/about/release-cycle) Ubuntu 18.04 は 2023 年 6 月末で通常サポートが終了しました。 Ubuntu 側から 4 月末での通常サポート終了が 6 月末まで延長されましたが、 Sora は当初の予定のまま 2023 年 4 月末をもって Ubuntu 18.04 版のサポートとパッケージの提供を終了しました。 Ubuntu 20.04 または Ubuntu 22.04 版への移行をお願いいたします。 Ubuntu 18.04 を利用しているお客様は、サポートまで切り替え先の OS をご連絡ください。 ## sora.conf の split_archive_legacy_prefix の廃止 **2023 年 6 月リリースの Sora にて廃止** `sora.conf` の `split_archive_legacy_prefix` 設定を廃止しました。 - 分割録画ファイル名 `archive-_.(json|webm)` が利用できなくなりました- `split-archive-_.(json|webm)` を利用するように変更してください - 分割録画時のイベントウェブフックタイプ `"type": "archive.split"` が利用できなくなりました- `"type": "split-archive.available"` を利用するように変更してください - 分割録画時のイベントウェブフックタイプ `"type": "archive.end"` が利用できなくなりました- `"type": "split-archive.end"` を利用するように変更してください ## sora.conf の default_multistream の廃止 **2023 年 6 月リリースの Sora にて廃止** `sora.conf` の `default_multistream` 設定を廃止しました。 今後は接続時に `multistream` を指定せずに接続した場合は常にマルチストリームが有効になります。 ## redact_archive_metadata_sensitive_data と redact_api_sensitive_data の廃止 **2022 年 12 月リリースの Sora にて廃止** 録画メタデータと API のセンシティブデータを **"REDACTED"** という文字列に書き換えを廃止しました。 今後はこれらのデータは書き換えを行いません。 ## recording.report の metadata_filename と metadata_file_path の廃止 **2022 年 12 月リリースの Sora にて廃止** 録画イベントウェブフックの `recording.report` に含まれる `metadata_filename` と `metadata_file_path` が `filename` と `file_path` に変更されます。 2021 年 12 月リリースの Sora にて `filename` と `file_path` が追加されていますので、そちらを利用するように変更してください。 ## シグナリング通知メタデータ metadata_list の廃止 **2022 年 6 月リリースの Sora にて廃止** `metadata_list` が `data` に変更されました。 ## `"type": "update"` の廃止 **2022 年 6 月リリースの Sora にて廃止** マルチストリーム機能利用時のシグナリングで利用する `"type": "update"` を廃止し、 `"type": "re-offer"` と `"type": "re-answer"` に変更しました。 ## sora.conf の demo の廃止 **2022 年 6 月リリースの Sora にて廃止** `sora.conf` の `demo` を廃止しました。今後は `devtools` を利用してください。 これは `デモ機能` が `開発ツール` へと名前を変更したことによる影響です。 ## sora.conf の remote_stats の廃止 **2022 年 6 月リリースの Sora にて廃止** `sora.conf` の `remote_stats` を廃止しました。今後は `user_agent_stats` を利用してください。 これは `リモート統計情報` が `ユーザーエージェント統計情報` へと名前を変更したことによる影響です。 ## StopRecording API の redirect の配信 **2022 年 6 月リリースの Sora にて廃止** 録画機能がクラスターで共有できるようになったことにより、 `redirect` 指定が不要になったため廃止しました。 ## CentOS 8 対応 **サポート提供終了**: 2021 年 12 月 - [CentOS Project shifts focus to CentOS Stream – Blog.CentOS.org](https://blog.centos.org/2020/12/future-is-centos-stream/?utm_source=rss&utm_medium=rss&utm_campaign=future-is-centos-stream) - [FAQ - CentOS Project shifts focus to CentOS Stream](https://centos.org/distro-faq/) - [FAQ: CentOS Stream Updates](https://www.redhat.com/ja/blog/faq-centos-stream-updates) CentOS 8 は 2021 年 12 月をもってサポートが終了しました。 それに伴い Sora は 2021 年 12 月末をもって CentOS 8 版のサポートとパッケージの提供を終了しました。 ## extmap_allow_mixed 設定のデフォルト有効化と廃止 **2021 年 12 月リリースの Sora にて廃止** Chrome M89 にて `a=extmap-allow-mixed` がデフォルトで設定されるようになり、 また Firefox 側でも動作に問題がなくなったことからこちらの設定が不要となりました。 2021 年 6 月リリースの Sora でデフォルト有効とし、2021 年 12 月リリースの Sora にて設定を廃止しました。 ## スポットライトレガシー機能の廃止 **2021 年 12 月リリースの Sora にて廃止** スポットライトレガシー機能は 2021 年 12 月リリースの Sora で廃止しました。 今後は [スポットライト機能](SPOTLIGHT.html) を利用してください。 ## `rtp` にある RTCP 関連統計情報を廃止 **2021 年 12 月リリースの Sora にて廃止** 統計 API の `rtp` 項目に入っている RTCP 関連統計情報を `rtcp` 項目として独立させました。 これに伴い `rtp` にある RTCP 関連統計情報を廃止しました。 ## `sora.conf` の `opus_param_clock_rate` を廃止 **2021 年 12 月リリースの Sora にて廃止** 実験的機能として提供していた `opus_param_clock_rate` を廃止しました。 ## `sora.conf` の `dcsctp_association_max_retrans` を廃止 **2021 年 12 月リリースの Sora にて廃止** 実験的機能として提供していた `dcsctp_association_max_retrans` を廃止しました。 今後は [ICE コネクションステート機能](ICE_CONNECTION_STATE.html) を利用してください。 ## role の upstream と downstream を廃止 **2021 年 6 月リリースの Sora にて廃止** `upstream` と `downstream` は 2021 年の 6 月リリースの Sora で廃止しました。 - マルチストリームの `upstream` は `sendrecv` をお使い下さい - マルチストリームの `downstream` は `recvonly` をお使い下さい - スポットライトの `upstream` は `sendrecv` をお使い下さい - スポットライトの `downstream` は `recvonly` をお使い下さい - 片方配信の `upstream` は `sendonly` をお使い下さい - 片方配信の `downstream` は `recvonly` をお使い下さい ### シグナリング接続 - シグナリング接続時に指定する `role` の `upstream` と `downstream` を廃止しました ### 認証ウェブフック - 認証ウェブフックの `channel_upstream_connections` を廃止しました- 今後は `channel_sendrecv_connections` または `channel_sendonly_connections` をご利用ください - 認証ウェブフックの `channel_downstream_connections` を廃止しました- 今後は `channel_recvonly_connections` をご利用ください ### イベントウェブフック - イベントウェブフック `*.connection` の `channel_upstream_connections` を廃止しました- 今後は `channel_sendrecv_connections` または `channel_sendonly_connections` をご利用ください - イベントウェブフック `*.connection` の `channel_downstream_connections` を廃止しました- 今後は `channel_recvonly_connections` をご利用ください ### シグナリング通知 - シグナリング通知 `*.connection` の `channel_upstream_connections` を廃止しました- 今後は `channel_sendrecv_connections` または `channel_sendonly_connections` をご利用ください - シグナリング通知 `*.connection` の `channel_downstream_connections` を廃止しました- 今後は `channel_recvonly_connections` をご利用ください ### API - `Sora_20151104.DisconnectChannelUpstream` API を廃止しました- 今後は [DisconnectChannelByRole](API_SIGNALING.html#39de6a) API をご利用ください - `Sora_20151104.DisconnectChannelDownstream` API を廃止しました- 今後は [DisconnectChannelByRole](API_SIGNALING.html#39de6a) API をご利用ください - `Sora_20160711.PushUpstream` API を廃止しました- 今後は [PushChannelByRole](API_PUSH.html#bc57a2) API をご利用ください - `Sora_20160711.PushDownStream` API を廃止しました- 今後は [PushChannelByRole](API_PUSH.html#bc57a2) API をご利用ください ## client_id を指定する設定の廃止 **2021 年 6 月リリースの Sora にて廃止** `sora.conf` の `allow_client_id_assignment` 設定を廃止し `client_id` はクライアント側で指定できるようにします。 ### sora.conf - `sora.conf` の `allow_client_id_assignment` を廃止しました ### API - `Sora_20170529.GetStats` API を廃止しました- `allow_client_id_assignment` 廃止に伴う廃止のため代替はありません - `Sora_20170814.StartForwardingRtp` API の `client_id` 指定を廃止しました- `allow_client_id_assignment` 廃止に伴う廃止のため代替はありません - `Sora_20170814.StopForwardingRtp` API の `client_id` 指定を廃止しました- `allow_client_id_assignment` 廃止に伴う廃止のため代替はありません - `Sora_20151104.ListConnections` API を廃止しました- 今後は [ListChannelConnections](API_SIGNALING.html#d388f3) API をご利用ください - `Sora_20151104.Disconnect` API を廃止しました- 今後は [DisconnectClient](API_SIGNALING.html#e91c0b) API をご利用ください ## 旧サイマルキャスト画質変更 API の廃止 **2021 年 6 月リリースの Sora にて廃止しました** - `Sora_20180820.ChangeSimulcastQuality`- 今後は [RequestRtpStream](DEPRECATED_API_SIMULCAST.html#6fe0b3) API をご利用ください この API の廃止に伴い、シグナリング接続時や認証成功時に指定するサイマルキャストの `quality` での `low` / `middle` / `high` 指定を廃止しました。 今後は `rid` と `r0` / `r1` / `r2` を利用してください。 ## bin/sora start の廃止 **2020 年 12 月リリースの Sora にて廃止しました** `bin/sora start` は 2020 年 12 月リリースの Sora 2020.3 で廃止しました。 今後は `bin/sora daemon` を利用してください。 systemd を利用されている方は `bin/sora foreground` を利用されていると思いますが、こちらに変更はありません。 ## Ubuntu 16.04 サポートの終了 **サポート提供終了**: 2021 年 4 月末 [Ubuntu release cycle | Ubuntu](https://ubuntu.com/about/release-cycle) Ubuntu 16.04 は 2021 年 4 月を持って通常サポートが終了しました。 それに伴い Sora は 2021 年 4 月末をもって Ubuntu 16.04 版のサポートとパッケージの提供を終了しました。 Ubuntu 18.04 または Ubuntu 20.04 版への移行をお願いいたします。 Ubuntu 16.04 を利用しているお客様は、サポートまで切り替え先の OS をご連絡ください。 # サポート ## Sora のクライアント SDK や専用ツールに関する問い合わせがある場合 Sora のクライアント SDK や専用ツールに関しては、サポートを提供していません。 もし不明点などがある場合は時雨堂の Discord サーバー () の `#sora-sdk-faq` や `#sora-tools-faq` チャンネルにてご相談ください。 ## Sora の仕様や使い方に関して問い合わせをする場合 Sora の仕様に関して質問がある場合は、ドキュメントに記載されている Sora の仕様や使い方に関して不明点がある場合は Sora のバージョンとドキュメントの URL を添えてお送りください。 もしドキュメントに記載されていない Sora の仕様に関して質問がある場合は、Sora のバージョンと質問内容を添えてお送りください。 ## Sora に問題が発生して問い合わせする場合 Sora で問題が発生した場合は [Sora に問題が発生した場合の問い合わせについて](SUPPORT_ISSUE.html) を確認いただき、必要な情報を送っていただけると、問題の解決がスムーズになります。 ## Sora のサポートライフサイクルポリシー Sora はリリース後 1 年間サポートを提供します。 詳細は [Sora のサポートライフサイクルポリシー](SUPPORT_LIFECYCLE.html) をご確認ください。 # Sora に問題が発生した場合の問い合わせについて Sora が期待どおりに動かない場合、 または動作に問題がある場合の問い合わせ時の事前確認と注意事項をまとめています。 ## 事前確認 問い合わせの前に、まずは以下の項目について事前に確認をお願いします。 ### サポートしている Sora のバージョン - Sora 2026.1.X- 2027 年 6 月 30 日までサポート - Sora 2025.2.X- 2026 年 12 月 31 日までサポート - Sora 2025.1.X- 2026 年 6 月 30 日までサポート - Sora 2024.2.X- **サポート終了** - 2025 年 12 月 31 日までサポート - Sora 2024.1.x- **サポート終了** - 2025 年 6 月 30 日までサポート - Sora 2023.2.x- **サポート終了** - 2024 年 12 月 31 日までサポート ### 利用している Sora のバージョンがサポート期限内かどうかを確認してください もし、サポートしているバージョンを利用していない場合は、 サポートしているバージョンへのアップデート後に問題が再現するかの確認をお願いします。 ### Sora の SDK サポートについては Sora サポート範囲外のため Discord サーバーの各チャンネルをご利用ください **時雨堂コミュニティサーバー**: SDK の質問や相談については `sora-sdk-faq` を利用してください。 - Sora JavaScript SDK- 投稿時に `sora-js-sdk` タグを指定してください - Sora iOS SDK- 投稿時に `sora-ios-sdk` タグを指定してください - Sora Android SDK- 投稿時に `sora-android-sdk` タグを指定してください - Sora Unity SDK- 投稿時に `sora-unity-sdk` タグを指定してください - Sora C++ SDK- 投稿時に `sora-cpp-sdk` タグを指定してください - Sora Python SDK- 投稿時に `sora-python-sdk` タグを指定してください - Sora Rust SDK- 投稿時に `sora-rust-sdk` タグを指定してください - Sora Flutter SDK- 投稿時に `sora-flutter-sdk` タグを指定してください ### 利用しているブラウザが安定版の最新版か確認してください ブラウザが古い場合、うまく接続できない可能性があります。 もし、ブラウザが古い場合は、最新版で再度問題が発生するかどうか確認をお願いします。 ### 開発ツールを有効にして開発ツールで問題が再現するか確認してください クライアント側の実装の問題もあるため、必ず確認をお願いしています。 もし、クライアント側の問題の場合は、 Sora のサポートでは対応することができません。ご了承下さい。 ### クライアントのシグナリング接続が WebSocket over TLS で接続しているかどうかを確認してください WebSocket over TLS ではない場合は、まずは WebSocket over TLS で接続するようにお願いいたします。 ### Sora のサポート範囲外の質問はご遠慮ください Sora の挙動や使い方以外はサポートの範囲外です。 - Sora を利用したサービスの設計や開発 - **NGINX 全般** - **WebRTC 全般** - Sora SDK 全般 - WebRTC Native Client Momo - WebRTC Load Testing Tool Zakuro - Recording Composition Tool Hisui - WebRTC Stats Collector Kohaku - Audio Streaming Gateway Suzu - Sora Archive Uploader - Sora Exporter - 各種クラウドサービス 上記はすべて Sora のサポート範囲外となります。 ## 問い合わせの場合、お送り頂く情報 > **重要** > > 前述の事前の確認後、以下の情報を **必ず** お送り下さい。 情報をお送り頂くときは `テキストファイル` でお送りください。 - サーバーやクライアントのスペック- わかれば機種名 - CPU - メモリ - ディスク - Linux Kernel のバージョン- `uname -a` の出力 - OS の種類、バージョン- Ubuntu と Red Hat Enterprise Linux のどちらを利用しているか - 利用している OS のバージョン - x86_64 または arm64 のどちらのアーキテクチャを利用しているのか - Sora のバージョン- 2024.2.2 など - クラスターを利用している場合はクラスターの構成 - Sora の **sora.conf 設定ファイル**- [環境変数による設定上書き機能](SORA_CONF.html#e551e8) を利用している場合は、環境変数で上書きしている設定内容もお送りください - Sora の log ディレクトリ以下すべてのログファイル- クラスターを利用している場合は全ノードのログ - tar.gz または zip などで圧縮し、パッケージ提供時にお送りしているログアップローダーを利用してお送りください - 評価中の場合は tar.gz または zip などで圧縮し、メールにてお送り下さい - 問題発生時の前後 1 週間分をめどにお送りください ### 詳細な問題発生状況 **何をどうすると問題が発生したのかの状況を可能な限り詳細にお教え下さい** > **重要** > > 以下の情報については **必ず** お送り下さい。 - 問題が発生したコネクションのシグナリング情報- チャネル ID - セッション ID - コネクション ID - 音声の有無- コーデック - ビットレート - 映像の有無- コーデック - ビットレート - 解像度 - サイマルキャスト機能の有無 - マルチストリーム機能の有無 - スポットライト機能の有無 - 問題が発生したブラウザバージョン- Chrome 124.0.6700.106 や Safari 17.5 など - SDK の種類とバージョン- Sora JavaScript SDK 2025.1.0 や Sora iOS SDK 2025.1.0 など - 問題が発生したブラウザまたは SDK を利用している OS の種類とバージョン- iOS 18.4 や macOS 15.4 や Windows 11 2304 など - 問題の発生状況- 発生時刻 (何度か発生している場合は複数) - 発生したタイミング (接続した直後、配信が10分以上継続した後、など) - 発生頻度 - 発生時の配信者数、視聴者数 - 発生の確率 (ある手順を踏むと必ず発生する、同じ手順でも5回に1回程度のみ発生する、など) ### 再現方法 **Sora 内蔵の開発ツールでの再現方法をお送りください** - 再現の手順- 開発ツールで問題が発生する場合、その手順をお送り下さい- 接続する開発ツールの URL- 開発ツールの copy URL を押すと現在の設定を反映した URL がコピーされます - 複数クライアントを接続したときに発生する場合は、その順序と接続間隔 (ほぼ同時、数分おいて接続、など) - 開発ツールでは発生しない場合、開発ツールに準じた情報をお送り下さい- シグナリングのパラメーター - 複数クライアントの接続の場合、その順序と接続間隔 (ほぼ同時、数分おいて接続、など) - 問題を再現するための独立したアプリケーションが作成できるようであれば、そちらをご用意いただくと解決までの距離が短くなります ## 録画関連の問い合わせについて **録画については以下の点をご注意ください** ### 録画ファイルの取り扱いについて > **重要** > > もし、何か録画に問題があった場合でも、録画ファイルを送ることは **絶対** にしないでください。 まずはどのような状況かをサポートまで連絡をお願いします。 ### 問題が起きた状況について - ブラウザで再生して問題が起きた場合は、ブラウザの種類とバージョン、プラットフォームをお教えください - VLC で再生して問題が起きた場合は、VLC のバージョンとプラットフォームをお教えください - 音声コーデックと映像コーデックをお教えください - 録画ファイルが MP4 か WebM かフォーマットをお教えください - 利用している SDK の種類とバージョンをお教えください - OBS を利用している場合は OBS のバージョンをお教えください ### HLS や MPEG-DASH の問い合わせについて HLS や MPEG-DASH といった Sora が録画したファイルを変換した状態で発生した問題についてはサポート対象外です。 # サポートライフサイクル ## 概要 Sora 2023.1.0 より、サポートの提供期間を変更しています。 ## 変更内容 これまでは Sora の最新バージョンの利用に対してのみサポートを提供していましたが、Sora 2023.1.0 以降はサポートの提供期間をより長く変更します。 また、合わせて Sora のアップデートを以下のとおりに区別します。 ### メジャーアップデート **サポート提供期間**: **メジャーアップデートがリリースされた日から 12 ヶ月後の月末最終日まで** - 原則として毎年 6 月と 12 月に、機能の追加や改善、廃止を目的として行うアップデートをメジャーアップデートといいます - このアップデートでは、以前のバージョンと後方互換性のない新機能が含まれたり、以前のバージョンの機能が廃止されたりする場合があります > **重要** > > - 2026 年 6 月 24 日にリリースされた Sora 2026.1.0 は、2027 年 6 月 30 日までサポートを提供します > - 2025 年 12 月 17 日にリリースされた Sora 2025.2.0 は、2026 年 12 月 31 日までサポートを提供します > - 2025 年 6 月 25 日にリリースされた Sora 2025.1.0 は、2026 年 6 月 30 日までサポートを提供します > - 2024 年 12 月 18 日にリリースされた Sora 2024.2.0 は、2025 年 12 月 31 日までサポートを提供します ### バグフィックスアップデート **サポート提供期間**: **修正の対象となるメジャーアップデートがリリースされた日から 12 ヶ月後の月末最終日まで** - メジャーアップデートをリリースして以降、次のメジャーアップデートまでの約 6 ヶ月の間に、問題の修正を目的として不定期に行うアップデートをバグフィックスアップデートといいます ### ホットフィックスアップデート **サポート提供期間**: **修正の対象となるメジャーアップデートがリリースされた日から 12 ヶ月後の月末最終日まで** - メジャーアップデート、バグフィックスアップデート以外に、ごく稀に緊急のアップデートが必要と判断する場合に行うアップデートをホットフィックスアップデートといいます - 最新バージョン以外にも、アップデートの必要があると判断する以前のバージョン、およびその両方に対してリリースを行う可能性があります ### Sora のバージョン表記 **YYYY.MAJOR.FIX** - `YYYY` はリリースした年を示します - `MAJOR` はその年のメジャーアップデートのリリース回数を示します- Sora 2024.1.0 は、2024 年の 1 回目のメジャーアップデートであることを示します - `FIX` は バグフィックスアップデートおよびホットフィックスアップデートのリリース回数を示します- Sora 2024.2.1 は、Sora 2024.2.0 に対する 1 回目のバグフィックスアップデートもしくはホットフィックスアップデートであることを示します - `FIX` のリリース回数は社内のみのリリースも含むことがあるため、公開時のリリース回数は飛ぶ可能性があります ## サポートライフサイクル例 ```mermaid supportLifeCycle title サポートライフサイクル例 dateFormat YYYY-MM-DD 2026.2.x : 2026-12-17, 2027-12-31, 2026.2.0 2026.1.x : 2026-06-24, 2027-06-30, 2026.1.0 2025.2.x : 2025-12-17, 2026-12-31, 2025.2.1 2025.1.x : 2025-06-25, 2026-06-30, 2025.1.0 2024.2.x : 2024-12-18, 2025-12-31, 2024.2.3 2024.1.x : 2024-06-26, 2025-06-30, 2024.1.3 2023.2.x : 2023-12-20, 2024-12-31, 2023.2.7 2023.1.x : 2023-06-28, 2024-06-30, 2023.1.3 2022.2.x : 2022-12-21, 2023-12-31, 2022.2.3 2022.1.x : 2022-06-29, 2023-06-30, 2022.1.4 ``` # FAQ ここでは WebRTC SFU Sora に関するよくある質問についてまとめています。 ## WebRTC 全般 ### 双方向配信には対応していますか? 対応しています。WebRTC のマルチストリームという技術を利用して実現しています。 クライアント側の負荷を考慮し、 1 チャネルに参加するクライアントは 12 までを推奨としています。 1 チャネルで 12 より多いクライアントで双方向の配信を行いたい場合は [スポットライト機能](SPOTLIGHT.html) を検討するかサポートまでお問い合わせください。 ### 片方向配信には対応していますか? 対応しています。 ### 片方向配信はどのくらいの接続数まで対応していますか? 1 つの Sora で、1 チャネルあたり 1 万接続程度まで対応しています。 クラスターリレー機能を利用することで、1 チャネルあたり数万〜数十万接続規模の配信もできます。 Sora では設計上 1 チャネルあたり 100 万接続程度の大規模な配信ができます。 ただし、使用するマシンスペックやネットワーク環境によっても大きく変わるため、 接続数が 1 万を超える規模の配信を検討している場合は、サポートまでお問い合わせください。 ### 音声検出による映像の切り替えには対応していますか? 対応しています。Sora 独自のスポットライト機能という名前で提供しています。 この機能は多人数で会議を行う場合に、クライアントやサーバーの負荷を減らせる技術です。 100 名以上が 1 チャネルに参加できます。 詳細は [スポットライト機能](SPOTLIGHT.html) をご確認ください。 ### スクリーンキャプチャ機能には対応していますか? 2026 年 6 月 の時点でスクリーンキャプチャ機能はブラウザでは Chrome と Firefox と Safari と Edge が対応しています。 getDisplayMedia を利用することで、実現できます。 [MediaDevices.getDisplayMedia() - Web APIs | MDN](https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getDisplayMedia) ### マルチストリームには対応していますか? > **ヒント** > > Sora はデフォルトでマルチストリームを利用します。 対応しています。ブラウザでは Chrome と Firefox と Safari と Edge で対応しています。 また、すべての SDK が対応しています。 ### マルチトラックには対応していますか? Sora はマルチトラックに対応していません。 Sora は 1 メディアストリームにつき 1 音声トラック、1 映像トラックしか対応していません。 マルチトラックへの対応は今のところ未定です。 ### 複数の音声や複数の映像を 1 つのコネクションで配信することはできますか? いいえ。 1 つのコネクションで複数ストリームを配信をすることはできません。 1 接続では 1 ストリーム (1 音声/1 映像) のみの配信ができます。 複数の配信を行いたい場合はマルチストリームの `sendonly` ロールを利用して複数接続してください。 ### 1 ユーザーで送受信と送信のみを利用している場合、送受信側で送信のみの音声や映像を受信しないことはできますか? はい、できます。接続時、または認証成功時に [bundle_id](WEBSOCKET_SIGNALING.html#b23b22) で同じ値を指定してください。 > **注釈** > > シグナリング時に `bundle_id` を指定する場合は `sora.conf` の [signaling_bundle_id](SORA_CONF.html#279311) を `true` にする必要があります。 `bundle_id` が同じ接続では送信のみの音声と映像を送受信側で受信しなくなります。 ### 映像コーデックは何がお勧めですか? すべてのブラウザ、さらにほぼすべての端末で動作する VP9 か H.264 がお勧めです。 ただし、端末に VP9 のハードウェアアクセラレータが搭載されていることはほとんどないため、 H.264 を採用した方が電池消費量は減ります。 ただしブラウザの場合はハードウェアアクセラレーターを利用するかどうかは実装次第です。 一方で、H.264 は一部の Android 端末で、 VP9 は一部の Intel GPU 搭載端末で正常に動作しないことがあります。 すべての環境が Chrome に統一できる場合は AV1 をお勧めします。 ### H.265 での映像配信に対応していますか? - Chrome は 136 から H.265 に対応しています - Safari は 18.0 から H.265 に対応しています 2026 年 6 月 の時点で、Firefox と Edge は H.265 に対応していません。 ### 主要ブラウザのコーデック対応を教えてください 2026 年 6 月 の時点で、主要ブラウザの対応コーデックは以下のとおりです。 - Chrome 150 は VP8、 VP9、 AV1、 H.264、 H.265 に対応しています - Edge 150 は VP8、 VP9、 AV1、 H.264 に対応しています- H.265 には対応していません - Safari 26.5 は VP8、 VP9、 H.264、 H.265 に対応しています- 実験的機能として AV1 に対応しています - Firefox 151 は VP8、 VP9、 H.264 に対応しています- AV1 には対応していません Sora は配信者がコーデックを選択できる仕組みを採用しています。 詳細は [シグナリング](SIGNALING.html) をご確認ください。 ### Safari は WebRTC に対応していますか? はい。 Safari 12 で WebRTC に対応しました。 詳細は [Apple Safari の WebRTC について](SAFARI.html) をご確認ください。 ### Chrome や Edge では HTTPS が必須ですか? はい。ローカルホスト以外からのアクセスでブラウザで getUserMedia を使用する場合は HTTPS が必須になります。 もし、開発中に HTTP でアクセスしたい場合は、以下を参考にしてください。 [http でのアクセスでカメラの映像を取得する - Qiita](https://qiita.com/Hexa/items/a5e5c3e06ba2a3e6bb41) ### Safari では HTTPS が必須ですか? はい。ただし、 開発者メニューから HTTP でも getUserMedia を使用できるようにするオプションが用意されています。 ### Edge は WebRTC に対応していますか? はい。 Chrome との違いは利用できるコーデックが違うくらいでそれ以外は基本的には同じです。 詳細は [Microsoft Edge の WebRTC について](EDGE.html) をご確認ください。 ### サーバー側からクライアントごとにコーデックや最大ビットレートを指定できますか? できます。 Sora からクライアントへ送信する Offer に含める SDP を、クライアントごとに指定できます。 詳細については [認証ウェブフック成功時の払い出し](AUTH_WEBHOOK_RETURN.html) をご確認ください。 ### コーデックが異なるクライアントでも同じチャネルでの双方向通信はできますか? できます。マルチストリームを利用することで接続ごとにコーデックを指定できます。 例えば、iOS の Safari は H.264、デスクトップの Chrome は VP8 という場合でも同じチャネルでの双方向通信が利用できます。 ただし、ブラウザが非対応の場合はもちろん送受信できませんのでご注意ください。 ### Firefox で複数タブで音声デバイスを利用できますか? いいえ。 Firefox 56 から複数タブで音声デバイスを利用できなくなりました。 ### Safari で音声が有効な場合、自動で視聴を開始できますか? いいえ。 Safari の仕様で、音声が含まれている映像を自動で再生することはできません。 ### 高いビットレートで配信することはできますか? できます。ただし、Sora では最大 50 Mbps での配信ができますが、 15 Mbps を超えるビットレートでの配信はサポート対象外です。 配信自体はできますが、クライアント、サーバーともに不安定になることがあるためです。 ### WebRTC で 4K 30 fps の映像配信はできますか? できます。ただし、クライアント側の負荷がとても高くなるため、ハードウェアアクセラレーターの利用が前提になります。 時雨堂が公開している SDK はハードウェアエンコーダーに対応していますので、 対応しているハードウェアをご用意ください。 ブラウザでも Safari での H.264/H.265 は確実にハードウェアアクセラレーターが利用できるため、4K 30 fps の配信が比較的安定して行えます。 また、時雨堂では [WebRTC Native Client Momo](https://momo.shiguredo.jp/) という、 様々なハードウェアエンコーダーに対応したクライアントをオープンソースで公開していますので、是非試してみてください。 [shiguredo/momo: WebRTC Native Client Momo](https://github.com/shiguredo/momo) ### 映像を 60 や 120 fps で配信することはできますか? Sora は映像を 60 や 120 fps で配信することはできます。 Sora は映像の fps には関与しません。 そのため、 fps はカメラが対応していること、 また、クライアントが対応していることが必要になります。 ### カメラで指定した解像度より低い解像度で配信されるのですが? カメラ映像の解像度と WebRTC でエンコードされて配信される解像度は一致しません。 カメラから入ってくる映像を WebRTC では圧縮して配信します。WebRTC は圧縮時に CPU 使用率が高い、ネットワーク帯域不足などの状況に応じ、自動で解像度やフレームレートを落として配信できる状態にして配信します。 ### WebRTC DataChannel には対応していますか? 対応しています。 2026 年 6 月 の時点では、シグナリング機能と [リアルタイムメッセージング機能](MESSAGING.html) と [RPC 機能](RPC.html) として [WebRTC DataChannel](https://developer.mozilla.org/en-US/docs/Web/API/RTCDataChannel) を利用できます。 詳細は [DataChannel 経由のシグナリング](DATA_CHANNEL_SIGNALING.html) や [リアルタイムメッセージング機能](MESSAGING.html) と [RPC 機能](RPC.html) をご確認ください。 ### 音声のステレオには対応していますか? Sora は音声のステレオに対応しています。 ただし、ステレオで音声をエンコード/デコードするかどうかはクライアント側に依存します。 例えばブラウザの場合はデフォルトでステレオに対応していますが、エコーキャンセルが有効な場合はステレオは利用できません。 エコーキャンセルを無効にすることでステレオが利用できるようになります。 エコーキャンセルの設定は以下を参考にしてください。 [Media Capture and Streams](https://www.w3.org/TR/mediacapture-streams/#dom-mediatracksupportedconstraints-echocancellation) ### MediaStreamTrack から connection_id は取得できますか? できます。 Sora では自分以外の MediaStreamTrack の ID に `{connection_id}-{audio | video}` という形式が含まれるようになっています。 そのため、MediaStreamTrack の ID から connection_id を取得することができます。 MediaStreamTrack の id や label 、getCapabilities の deviceId や getSettings の deviceId がこの形式になります。 - `"id": "CQE8KR2MAN1B1DD149NA2EX4MM-video"` - `"label": "CQE8KR2MAN1B1DD149NA2EX4MM-video"` - `"getCapabilities": {"deviceId": "CQE8KR2MAN1B1DD149NA2EX4MM-video", ...` - `"getSettings": {"deviceId": "CQE8KR2MAN1B1DD149NA2EX4MM-video", ...` > **危険** > > Firefox には対応していません ### WebRTC 統計情報 inbound-rtp から connection_id は取得できますか? できます。 Sora では WebRTC 統計情報 `inbound-rtp` の `trackIdentifier` に `{connection_id}-{audio | video}` という形式が含まれるようになっています。 そのため、 `trackIdentifier` から connection_id を取得することができます。 `"trackIdentifier": "CQE8KR2MAN1B1DD149NA2EX4MM-video"` のように含まれます。 > **危険** > > Firefox には対応していません ## シグナリング ### シグナリングは独自仕様ですか? 独自仕様です。 WebRTC の規格ではシグナリング部分は定義されていないため、 WebRTC で利用されるシグナリングは独自仕様が前提です。 Sora は `JSON over WebSocket` または `JSON over DataChannel` をシグナリングの仕様として採用しています。 Sora の SDK を利用すればシグナリングを意識する必要がありません。 Sora のシグナリングの詳細な仕様について確認したい場合は、[シグナリング](SIGNALING.html) をご確認ください。 > **注釈** > > OBS 向けのシグナリングは WHIP / WHEP という RFC で定義されているプロトコルに対応しています。 ### シグナリングに WebSocket (WS) ではなく WebSocket over TLS (WSS) を使うことはできますか? できます。 `getUserMedia` を使用する場合、ローカルホスト以外では HTTPS が必須です。 また、HTTPS のページから Sora に接続する場合、WebSocket は WSS が必須になります。 ただし、Sora は WS のみに対応しています。 これは、実運用を考慮して、前段にリバースプロキシサーバーを立てていることを前提としており、 リバースプロキシサーバーで TLS を終端する構成を想定しているためです。 そのため、もし WSS を使う場合は、 NGINX などのリバースプロキシサーバーを使用して TLS を終端してください。 > **注意** > > NGINX の設定などについてはサポート対象外となりますので、お問い合わせはご遠慮ください。 弊社では、TLS を終端するリバースプロキシサーバーには NGINX の使用を推奨しています。 詳細については [nginx](NGINX.html) をご確認ください。 ### OBS などで利用できる WHIP / WHEP 形式のシグナリングに対応していますか? Sora は OBS などで利用できる [WHIP](https://datatracker.ietf.org/doc/html/rfc9725) と [WHEP](https://datatracker.ietf.org/doc/html/draft-ietf-wish-whep) に対応しています。 詳細については [WHIP 機能](WHIP.html) や [WHEP 機能](WHEP.html) をご確認ください。 ### 接続単位で接続時間を知ることはできますか? Sora は接続単位で接続時間を知ることはできます。Sora は接続ごとにタイマーを保持しており、 デフォルトで接続後 1 分ごとに外部のアプリケーションサーバーに HTTP 経由で接続の状態を通知します。 この通知はクライアントごとに独立しており、通知にはクライアント ID やチャネル ID やアプリケーションサーバーが認証時に指定した event_metadata が含まれています。 これらの情報を使用して、例えば、ユーザーごとに接続から 10 分経過したら切断する等の処理が簡単に行えます。 ### シグナリングで利用している WebSocket や DataChannel を使ってクライアントにメッセージ送ることはできますか? できます。 [プッシュ API](API_PUSH.html) を利用することでシグナリングで利用している WebSocket や DataChannel 経由でクライアントにメッセージを送ることができます。 または [リアルタイムメッセージング機能](MESSAGING.html) を利用してクライアント間でメッセージがやりとりできます。 ### クライアントがシグナリング経由で他の人の接続を通知で受け取ることはできますか? できます、ただし同一チャネルのみに限ります。 [シグナリング通知](SIGNALING_NOTIFY.html) をご確認ください。 ### シグナリングに DataChannel を使うことはできますか? できます。ただし、WebRTC 接続確立までは WebSocket を利用する必要があります。 詳細は [DataChannel 経由のシグナリング](DATA_CHANNEL_SIGNALING.html) をご確認ください。 ## 認証 ### シグナリング時の認証はできますか? できます。ただし、Sora は認証機能を持っていますが、認証の判断をする仕組みを持っていません。 認証は外部のアプリケーションサーバーへウェブフックを送信し、その戻り値で判断を行います。 認証の判断材料として、 Sora のシグナリング開始時に任意の情報をクライアントに送ることができる `metadata` を指定できます。 これは外部のアプリケーションサーバー側で払い出して使用できます。 認証のフローを以下に簡単に書き出しておきます。 1. 外部のアプリケーションサーバーでアクセストークンをクライアントに払い出す 2. そのアクセストークンを `metadata` に入れて Sora に接続する 3. Sora はそのアクセストークンやコネクション ID を外部のアプリケーションサーバーに HTTP 経由で問い合わせる 4. 外部のアプリケーションサーバーはそのアクセストークンが正しいことを確認し、 `{"allowed": true}` を HTTP ステータスコード 200 番台で Sora に返す 5. Sora は Offer をクライアントに送る ```mermaid sequenceDiagram participant C as クライアント participant S as Sora participant A as アプリケーションサーバー C->>+S: "type": "connect" S->>+A: 認証ウェブフック A-->>-S: 200 OK
"allowed": true S-)-C: "type": "offer" C-)S: "type": "answer" note over C,S: WebRTC 確立 ``` 外部の HTTP サーバーに対してウェブフックを送信し、 `{"allowed": true}` と HTTP ステータスコード 200 番台 が返ってきたら認証を許可します。 詳細は [認証ウェブフック](AUTH_WEBHOOK.html) をご確認ください。 ### シグナリングの認証失敗時に失敗の理由をクライアントに返せますか? できます。外部のアプリケーションサーバーで Sora への認証ウェブフックの戻り値を返す場合、 `{"allowed": false, "reason": "最大 100 バイトまでの文字列"}` という値を返す必要があります。 この `reason` 部分はクライアントに通知されます。 詳細は [認証ウェブフック](AUTH_WEBHOOK.html) をご確認ください。 ## 通知 ### チャネルに参加中のクライアントが、別のクライアントの参加や離脱を知ることはできますか? できます。シグナリング通知機能を利用することにより、接続や切断のタイミングで、 シグナリングで利用している WebSocket または DataChannel 経由で通知されます。 詳細は [シグナリング通知](SIGNALING_NOTIFY.html) をご確認ください。 ### チャネルに参加中のクライアントが、自分の録画開始/終了を知ることはできますか? できます。シグナリング通知機能を利用することにより、録画の開始や終了のタイミングで、 シグナリングで利用している WebSocket または DataChannel 経由で通知されます。 詳細は [シグナリング通知](SIGNALING_NOTIFY.html) をご確認ください。 ### 参加者に Sora 側で変更できるメタデータをもたせることはできますか? できます。シグナリング通知メタデータ拡張機能を利用することで、 接続や切断のタイミングで API 経由で変更したメタデータを通知できます。 さらにメタデータの変更時に参加者全員にプッシュで通知することもできます。 詳細は [シグナリング通知メタデータ拡張](SIGNALING_NOTIFY_METADATA_EXT.html) をご確認ください。 ## HTTP API ### 指定したコネクションのみを切断することはできますか? できます。 Sora はチャネル ID とコネクション ID を指定して接続を切断できます。 詳細は [DisconnectConnection](API_SIGNALING.html#2ec3a0) をご確認ください。 ### 指定したコネクションを切断した際に切断理由を含めることはできますか? できます。 `reason` を指定することで、イベントウェブフック `connection.destroyed` の `disconnect_api_reason` として指定した値が入ってきます。 詳細は [DisconnectConnection](API_SIGNALING.html#2ec3a0) をご確認ください。 ### 指定したクライアントのみを切断することはできますか? できます。 Sora はチャネル ID とクライアント ID を指定して接続を切断できます。 詳細は [DisconnectClient](API_SIGNALING.html#e91c0b) をご確認ください。 ### 指定したチャネルの配信者や視聴者のみを切断することはできますか? できます。 Sora はチャネル ID を指定して配信者や視聴者のみを接続を切断できます。 詳細は [DisconnectChannelByRole](API_SIGNALING.html#39de6a) をご確認ください。 ### 指定した配信者の映像を、指定した視聴者が受信しないことはできますか? できます。Sora は配信者、視聴者のコネクション ID を指定して映像を Sora で一時的に止めることができます。 詳細は [転送フィルター 機能](FORWARDING_FILTER.html) をご確認ください。 ### API を直接クライアントから呼び出してもいいですか? Sora の HTTP API はクライアントから呼び出すことはできますが、 セキュリティの観点から推奨していません。 その代わり、特定の API を RPC 機能としてクライアントから呼び出すことができます。 詳細は [RPC 機能](RPC.html) をご確認ください。 ## RPC ### RPC 機能とは何ですか? Sora の RPC 機能は、クライアントから DataChannel 経由で Sora の特定の HTTP API を呼び出す仕組みです。 詳細は [RPC 機能](RPC.html) をご確認ください。 ## 録画 ### Sora で録画した場合に出力されるファイルの形式は何ですか? デフォルトは MP4 形式です。WebM 形式も選択できます。 詳細は [録画機能](RECORDING.html) をご確認ください。 ### Sora で録画した複数の WebM 形式のファイルを一つのファイルに出力することはできますか? できますが、サポートの範囲外になります。 録画ファイル合成ツールをオープンソースとして公開しています。 [Recording Composition Tool Hisui](https://github.com/shiguredo/hisui) ### 録画した MP4 形式のファイルはブラウザで閲覧できますか? できます。Chrome と Edge と Safari と Firefox で閲覧できます。 > **注釈** > > Firefox と Edge でも H.265 コーデックの MP4 形式のファイルは再生できます。 ### 録画した WebM 形式のファイルはブラウザで閲覧できますか? できます。Chrome と Firefox と Edge で閲覧できます。 Safari での視聴を検討している場合は MP4 形式での録画を利用してください。 ### 録画できるコーデックは何ですか? 音声コーデックは Opus 、映像コーデックは VP8 と VP9 と AV1 と H.264 と H.265 に対応しています。 録画ファイルはデフォルトで MP4 形式で保存されます。 フォーマット指定することで WebM 形式でも保存することができますが、 デファクトスタンダードである MP4 形式での保存をお勧めします。 > **注意** > > H.265 は MP4 形式でのみ録画できます。 ### 音声のみを録音できますか? できます。Opus コーデックで音声のみの録音が可能になります。 - MP4 形式の場合 `m4a` ファイルではなく `mp4` ファイルで出力されますので、ご注意ください - WebM 形式の場合 `webma` ファイルではなく `webm` ファイルで出力されますので、ご注意ください ### 録画した MP4 や WebM のサイズの例を教えてください 基本的には指定したビットレートで決まります。 例として Opus と VP8 の組み合わせの MP4 で、 Opus のビットレートが 64 kbps 、 VP8 の解像度が 640x480 でビットレートが 500 kbps で音声ありの場合、 1 分の映像で約 4.2 M バイトです。 ### 録画が開始するタイミングを教えてください 録画が開始するタイミングは 3 つあります。 1. 認証ウェブフックで録画を開始した場合 2. セッションウェブフックで録画を開始した場合 3. [StartRecording](API_RECORDING.html#c5b527) API が呼ばれた場合 詳細は [録画の開始方法](RECORDING.html#acb9d1) をご確認ください。 ### 録画が終了するタイミングを教えて下さい 1. セッションが破棄された場合 2. 録画開始時に指定した期限が来た場合 3. [StopRecording](API_RECORDING.html#fd0de5) API が呼ばれた場合 接続が切断しても他の接続が残っている場合は録画は終了しません。 詳細は [録画の終了方法](RECORDING.html#4c8592) をご確認ください。 ### 録画の開始と終了をクライアントへ通知することはできますか? 録画の開始と終了をクライアントへ通知することはできます。 シグナリング通知で `recording.started` と `recording.stopped` が送られます。 ### サイマルキャスト機能を利用した場合に録画はできますか? サイマルキャスト機能を利用した場合に録画はできます。 映像の優先度が一番低い映像(多くの場合で画質が高い映像)を録画します。 映像の優先度については [映像の優先度](SIMULCAST.html#36c708) をご確認ください。 ### スポットライト機能を利用した場合に録画はできますか? スポットライト機能を利用した場合に録画はできます。 映像の優先度が一番低い映像(多くの場合で画質が高い映像)を録画します。 映像の優先度については [映像の優先度](SIMULCAST.html#36c708) をご確認ください。 ### 録画関連ファイルをアップロードする仕組みはありますか? 録画関連ファイルをアップロードできますが、サポートの範囲外になります。 Sora が出力した録画関連ファイルを、 Amazon S3 や S3 互換オブジェクトストレージにアップロードするツールを GitHub に OSS として Apache-2.0 ライセンスで公開しています。 [Sora Archive Uploader](https://github.com/shiguredo/sora-archive-uploader) ### replaceTrack(null) を使うと、再生時に音声と映像がずれてしまいます Chrome には、特定の条件で RTP タイムスタンプが正しく進まないという問題があり、 そのため Sora が生成する WebM ファイルの再生時に音声と映像がずれてしまうことがあります。 発生条件は、音声ストリームに対して RTCRtpSender.replaceTrack(null) を実行した後に RTCRtpSender.replaceTrack(audioTrack) した場合です。 この問題は Chrome/WebRTC のバグトラッカー で管理されています。 ### 録画時のキーフレーム要求間隔は何秒ですか? 録画機能利用時の Sora からのキーフレーム要求間隔は 20 秒です。 MP4 形式では [default_recording_mp4_pli_interval](SORA_CONF.html#874e5b) で変更することができます。 WebM 形式は WebM の使用制限のため 20 秒固定です。 ## TURN ### TURN サーバーを立てる必要はありますか? Sora は TURN 機能を組み込んであり、 TURN サーバーを立てる必要はありません。 ### Sora の組み込み TURN サーバーは TURN-TCP や TURN-TLS に対応していますか? 対応しています。ただし、TURN-TLS 機能を使用するためには NGINX が必要となります。 - TURN-UDP- ポート変動 - TURN-TCP- ポート固定 - TURN-TLS- ポート固定 - NGINX 必須 詳細は [TURN 機能](TURN.html) をご確認ください ### HTTPS で利用される 443 番のポートを TURN 機能で利用することはできますか? できますが、nginx の利用が必須です。 詳細は [TURN-TLS、TURN-TCP、シグナリングで 443 番ポートを使用する](PRODUCTION.html#14258d) をご確認ください。 > **注意** > > NGINX の設定などについてはサポート対象外となりますので、お問い合わせはご遠慮ください。 ### TURN で UDP と TCP、TLS でどの経路が選択されるかはどう決められますか? クライアント側の実装に依存します。Sora はクライアントがどの経路を選択するかには関与しません。 ### TURN IPv6 に対応していますか? 対応しています。 ### TURN の FQDN 設定はどのようなときに設定が必要ですか? 基本的に設定して問題はありません。 また、NAT64/DNS64 ネットワーク環境に対しては TURN の FQDN を設定する必要があります。 ## ウェブフック ### ウェブフックのリクエスト送信先は複数登録できますか? ウェブフックのリクエスト送信先は複数登録できません。 もし、送信先を複数にしたい場合は、登録した送信先のアプリケーションサーバーなどで対応をお願いします。 ### ウェブフックにベーシック認証は利用できますか? ウェブフックにベーシック認証は利用できます。 `sora.conf` にて [webhook_basic_authn](SORA_CONF.html#081a9f) の設定を有効にしてください。 詳細については [ウェブフックリクエスト送信先のサーバーがベーシック認証を利用している場合](WEBHOOK.html#2a13ea) をご確認ください。 ### ウェブフックのタイムアウト値を設定できますか? できます。 `sora.conf` にて [webhook_response_timeout](SORA_CONF.html#e81d13) を設定することで、ウェブフックのレスポンスのタイムアウトが変更できます。 ### イベントウェブフックの session.updated の送信間隔を 1 分から変更できますか? できます。 `sora.conf` にて [session_updated_webhook_interval](SORA_CONF.html#4612dc) に `3 min` と設定することで、 session.updated のイベントウェブフックリクエストの送信間隔を 3 分に変更できます。 ### イベントウェブフックの session.updated を送らない設定はできますか? できます。 `sora.conf` にて [ignore_session_updated_webhook](SORA_CONF.html#0901a0) を `true` を設定することで、 session.updated のイベントウェブフックリクエストが送信されなくなります。 ### イベントウェブフックの connection.updated の戻り値を使用して切断などはできますか? できません。切断をする場合は Sora が持つ切断 API を使用してください。 ### イベントウェブフックの connection.updated の送信間隔を 1 分から変更できますか? できます。 `sora.conf` にて [connection_updated_webhook_interval](SORA_CONF.html#e67c3b) に `3 min` と設定することで、 connection.updated のイベントウェブフックリクエストの送信間隔を 3 分に変更できます。 ### イベントウェブフックの connection.updated を送らない設定はできますか? できます。 `sora.conf` にて [ignore_connection_updated_webhook](SORA_CONF.html#f3f12a) を `true` を設定することで、 connection.updated のイベントウェブフックリクエストが送信されなくなります。 ### イベントウェブフックのワーカー数を変更することはできますか? できます。同時接続数が増えた場合や、ウェブフックリクエスト送信先のサーバーの応答速度が遅い場合は、 `sora.conf` にて [event_webhook_worker_number](SORA_CONF.html#58523d) の値を変更してください。 イベントウェブフックのワーカー割り当てに利用している値は `channel_id` となります。 ワーカーが 10 の場合、 `channel_id` が 100 利用している場合、1 ワーカーに 10 の `channel_id` が割り当てられます。 ### イベントウェブフックの処理が遅くなった場合の挙動はどうなりますか? イベントウェブフックワーカーがキューを持っており、もしそのワーカーがリクエストを処理中の場合、キューに追加されます。 そのリクエストの処理が終わったらキューから取り出され処理されます。 ### 認証ウェブフックの同時接続数の項目を利用してセッション単位の接続数制限をかけることはできますか? ウェブフック送信先で接続制限をかけることはできますが、厳密な制限をすることはできません。 厳密な接続制限をする場合は [max_connections](SESSION_WEBHOOK.html#498be9) を利用してください。 ## DataChannel ### DataChannel でメッセージを送ることはできますか? できます。 Sora のメッセージング機能は DataChannel を利用しています。 詳細については [リアルタイムメッセージング機能](MESSAGING.html) をご確認ください。 ### role が recvonly で受信のみでもメッセージング機能を利用してメッセージを送ることはできますか? できます。メッセージング機能でメッセージを送ることができるかどうかは `direction` にのみ影響を受けます。 ### 送られてきたメッセージをどのクライアントが送ってきたかを判断することはできますか? できます。 メッセージング機能のヘッダー付与を利用してください。 詳細については [header](MESSAGING.html#717481) をご確認ください。 ### DataChannel でクライアントが `RTCPeerConnection.createDataChannel()` を利用することはできますか? できません。Sora 側で用意された DataChannel を利用してください。 ## 制限 ### 1 Sora に接続できる数を制限できますか? 1 Sora に接続できる数を制限できます。 [max_connections](SORA_CONF.html#498be9) を利用してください。 ### 1 チャネルに接続できる数を制限できますか? 1 チャネルに接続できる数を制限できます。 [max_connections](SESSION_WEBHOOK.html#498be9) を利用してください。 ### 同一クライアント ID が接続した際、既存の接続を追い出すことはできますか? 同一クライアント ID が接続した際、既存の接続を追い出すことはできます。 [duplicate_client_id](SESSION_WEBHOOK.html#f94372) を利用してください。 ## クラスター機能 ### クラスターには対応していますか? 対応しています。現在 1 クラスター最大 100 ノードまで対応しています。 詳細については [クラスター機能](CLUSTER.html) をご確認ください。 ### クラスター構築時に同一のライセンスを使う方法はありますか? あります。通常は同一のライセンスを複数のノードで利用することはできませんが [最大ノード数ライセンス](LICENSE.html#aee259) を利用することでできるようになります。 ### ロードバランスには対応していますか? 対応しています。 クラスター機能の一つとして、新規チャネルの接続は接続割合が少ない Sora ノードに割り振ります。 ### クラスターへの自動登録には対応していますか? 対応していません。 [RegisterClusterNode](API_CLUSTER.html#09ed96) API を利用してクラスターにノードを登録する必要があります。 ### クラスターの自動復旧には対応していますか? 対応しています。 ネットワーク障害やノード障害により、クラスターから離脱した場合 Sora は再度クラスターへの参加を自動で試みます。 ### ノード間通信は暗号化されていますか? されていません。そのためプライベートネットワークまたは暗号化されたネットワークを利用してください。 ### 2 ノードでもクラスターを構築できますか? できます。ただし推奨していません。 2 ノードの場合、どちらかのノードに障害が発生するとクラスター全体が止まってしまうため、 可用性は 1 ノードの場合よりも低くなります。 そのため 3 ノード以上でクラスターを組むことをお勧めします。 ### クラスターからノードを離脱させたい場合はどうすれば良いですか? Sora を終了することで離脱を行います。丁寧に離脱したい場合はモード切替で [新規コネクションブロックモード](MODE.html#0b67d3) を指定し、 すべての接続を切断してから終了してください。 もしそのノードが今後もクラスターに参加しない場合、 [PurgeClusterNode](API_CLUSTER.html#13b35a) API を利用してクラスターからそのノードの情報を完全消去してください。 なおノード情報を完全消去せずに、一度に過半数のノードを離脱させてしまうと、 残ったノードも接続を処理できなくなってしまうので注意が必要です。 詳細については [全ノードが半数以下のグループに所属した場合の挙動](CLUSTER_OPS.html#c1120e) をご確認ください。 ### クラスターのディザスタリカバリーには対応していますか? 対応していません。今後対応予定はありますが、リリース時期は未定です。 ### クラスターのリレーには対応していますか? 対応しています。 ### クラスターの最大ノード数はいくつですか? クラスターを構築するノードの最大数は 100 を想定しています。 これ以上のノード数でのクラスター構築を検討されている場合はサポートまでご連絡ください。 ## その他 ### IP アドレスは複数指定できますか? できますが、運用が複雑になるため、現時点ではドキュメントには記載していません。 もし、IP アドレスの複数指定を利用したい場合は、サポートまでお問い合わせください。 基本的には、クライアントごとに IP アドレスを変更したい場合は、認証時の戻り値を使用してください。 ### 配信者は音声と映像を配信し、視聴者は音声のみを受信することはできますか? できます。視聴者は配信者からの映像や音声のどちらかだけを受け取るよう指定できます。 詳細は [配信または視聴メディアの選択](WEBSOCKET_SIGNALING.html#7cd3d2) をご確認ください。 ### 複数のユーザーの中で、発言していないユーザーは低画質な映像のみを配信し、発言しているユーザーは音声と高画質な映像を配信することはできますか? スポットライト機能を利用すればできます。 詳細は [スポットライト機能](SPOTLIGHT.html) をご確認ください。 ### サイマルキャストに対応していますか? 対応しています。ブラウザは Chrome と Edge と Safari の最新バージョンに対応しています。 それ以外のブラウザでは配信はできませんが、視聴はできます。 映像コーデックは VP8、VP9、AV1、H.264、H.265 に対応しています。 - VP8 サイマルキャストは Chrome と Edge と Safari が対応しています - VP9 サイマルキャストは Chrome と Edge が対応しています - AV1 サイマルキャストは Chrome と Edge が対応しています - H.264 サイマルキャストは Chrome と Edge と Safari が対応しています - H.265 サイマルキャストは Chrome と Safari が対応しています ### サイマルキャスト視聴時に回線が不安定になったら自動的に低画質な映像に切り替えることはできますか? Sora は `sora.conf` の [default_simulcast_auto_rids](SORA_CONF.html#97a674) や認証成功時の払い出しで [simulcast_auto_rids の払い出し](AUTH_WEBHOOK_RETURN.html#3b4f6a) に自動で切り替えることができる `rid` を指定することで、回線が不安定になった際に、利用できる `rid` の範囲で自動的に低画質な映像に切り替えます。 > **重要** > > Sora 2025.2.0 では自動切り替えは「下げること」のみです。回線が安定した際に自動的に高画質な映像に戻すことはできません。この機能は 2026 年のリリース予定の Sora にて対応予定です。 ### 映像や音声を WebRTC 以外で出力する仕組みはありますか? [StartForwardingRtp](EXPERIMENTAL_API_RTP_FORWARDING.html#c734b8) API と [StopForwardingRtp](EXPERIMENTAL_API_RTP_FORWARDING.html#729828) API を利用することで、 外部のサーバーに対して WebRTC の DTLS (暗号部分) を除いた RTP パケットを送ることができます。 FFmpeg などを使用することで、 RTP から HLS や MPEG-DASH などに変換することもできます。 ### 音声や映像の配信を一時的に止めることはできますか? Sora は音声や映像の配信を一時的に止めることはできます。 [転送フィルター](FORWARDING_FILTER.html) をご確認ください。 ### HLS 配信はできますか? Sora 単体ではできません。ただし、Sora の [RTP 転送 API](EXPERIMENTAL_API_RTP_FORWARDING.html) を利用して FFmpeg などに転送することで、HLS での配信ができます。 ### 追いかけ再生はできますか? Sora 単体ではできません。 ただし、Sora の [RTP 転送 API](EXPERIMENTAL_API_RTP_FORWARDING.html) を利用して FFmpeg などに転送することで、HLS での配信ができます。 そのため、この HLS での配信を利用することで追いかけ再生を実現できます。 ### WebRTC が確立するまでにかかる時間は知ることができますか? [GetStatsReport](EXPERIMENTAL_API_STATS.html#bbbfca) API の `average_setup_time_msec` でシグナリング接続開始から WebRTC 接続が確立するまでにかかった平均時間が取得できます。 ## 性能 ### 負荷試験はどう行えばよいですか? サポートの範囲外になりますが、Sora 専用の負荷試験ツールをオープンソースとして公開しています。 [WebRTC Load Testing Tool Zakuro](https://github.com/shiguredo/zakuro) ### Sora は CPU をどの程度使用しますか? > **重要** > > WebRTC ではすべての通信が暗号化されているため、暗号化/復号処理で最も CPU リソースを消費します 通信環境やビットレートに影響するため一概には言えませんが、参考値を紹介します。 環境は AWS の C5n.4xlarge を利用しています。 以下の CPU の % は 1 コアを 100% とした場合です。 解像度が QVGA / 20fps / 1000kbps の映像と音声の送受信で 1 チャネル 8 クライアントを 12 ルーム (96 接続) で CPU 使用率を 200 % 程度利用します。 ### Sora はメモリをどの程度使用しますか? Sora は再送のキャッシュ用途にメモリを使用します。 100 接続であれば 4 GB 以上あれば十分です。 また、録画利用時にはフレーム組み立てのため一時的にメモリを使用します。こちらはビットレートに依存します。 ### Sora はディスクをどの程度使用しますか? 主に録画したファイルとログによりディスクが使用されます。 録画する映像の容量はコーデックやビットレートに依存するため一概には言えません。 ### マルチストリームは 1 チャネルで最大何クライアントまで対応していますか? 2026.1.0 時点で最大 12 クライアントまで対応しています。それ以上を接続することもできますが、お勧めはできません。 もし、大規模での会議を行いたい場合は、現在実験的機能として提供中の [スポットライト機能](SPOTLIGHT.html) の利用を検討してください。 ## 運用 ### Sora を利用する場合、インターネット接続が必要ですか? Sora を利用する場合、インターネット接続は必要ありません。 Sora はデフォルトでは外部アクセスをいっさい行わず、ライセンス確認も Sora 単体で行っています。 外部アクセスが発生するのは、ユーザーが sora.conf に明示的に設定を追加して、ウェブフック機能などを有効化した場合のみです。 その為、閉域網などのパブリックなネットワークへのアクセスができない環境でも利用頂けます。 ### WebSocket が通らないプロキシ環境がある場合はどうしたらよいですか? WebSocket は TLS を利用しているため、おそらくプロキシは TLS を一度終端するタイプかと思われます。 接続に対して中身の解析を行うプロキシであれば、 WebSocket だけでなく、TURN-UDP や TURN-TCP、TURN-TLS も通らない可能性が高いです。 結果として WebSocket が通らないプロキシを利用している場合は WebRTC 自体が利用できない可能性が高いため、プロキシの設定を変更してもらう以外の方法はありません。 ### Sora は Prometheus 形式に対応した監視情報を出力しますか? Sora は Prometheus 形式に対応した監視情報を出力しません。 その代わりに GitHub に OSS として Sora exporter を Apache-2.0 ライセンスで公開しています。 [Prometheus exporter for WebRTC SFU Sora metrics.](https://github.com/shiguredo/sora_exporter) ### Sora をデーモン化せずに起動することはできますか? Sora をデーモン化せずに起動することはできます。 Sora を起動する際、 `bin/sora foreground` で起動してください。 ### Sora を systemd で利用することはできますか? Sora を systemd で利用することはできます。 詳細は [systemd](SYSTEMD.html) をご確認ください。 ### Sora クラスターを利用せず、ロードバランサーを利用することはできますか? Sora クラスターを利用せず、ロードバランサーを利用することはできません。 Sora ではかならず同一チャネルの接続を同一 Sora に集約する必要があるためです。 もしロードバランサーを利用したい場合はクラスターを構築する必要があります。 ### Sora クラスターを利用して、ロードバランサーを利用することはできますか? Sora クラスターを利用して、ロードバランサーを利用することはできます。 ロードバランサーは WebSocket に対応している必要があります。 さらにロードバランサー側では 30 秒以上のタイムアウトを設定する必要があります。 これは Sora は WebSocket と DataChannel をシグナリングに併用した場合 30 秒間隔で Ping を Sora から送るためです。 また、ロードバランサーを経由しないシグナリング接続もできるようにする必要があります。 これは Sora 側でシグナリングのリダイレクトを行い別の Sora に直接接続させる仕組みがあるためです。 ### Sora はコンテナ上で利用できますか? Sora をコンテナで運用するのは推奨していませんが、利用できます。 サポートへ問い合わせする場合はコンテナに関係する問題を切り分けをして頂く必要があります。 ### Sora の WebSocket を利用したシグナリングのキープアライブの切断条件は何ですか? Sora はデフォルトの設定では WebSocket 経由で 5 秒間隔で `"type": "ping"` を送信し、 60 秒間で 1 回も `"type": "pong"` が返ってこなかった場合、 Sora はシグナリング接続を切断します。 これらの時間について `sora.conf` の設定 [websocket_signaling_ping_interval](SORA_CONF.html#27aae2) と [websocket_signaling_pong_timeout](SORA_CONF.html#140464) で変更できます。 ### Sora の DataChannel を利用したシグナリングの Sora 側からの切断条件は何ですか? Sora は定期的に接続状態を確認する仕組みを持っており、その仕組みで切断かどうかを判断しています。 詳細は [ICE コネクションステート](ICE_CONNECTION_STATE.html) をご確認ください。 ### Sora 1 起動あたりの最大同時接続数はいくつですか? 片方向配信の場合は、1 起動あたり 1 万同時接続程度まで対応しています。 双方向で大規模な配信を行う場合や、片方向で同時接続数が 1 万を超えるような配信を検討している場合は、 サポートまでお問い合わせください。 ### Sora が対応している OS は何ですか? 2026.1.0 の時点では以下の OS に対応しています。 - Ubuntu 26.04 LTS x86_64 - Ubuntu 26.04 LTS arm64 - Ubuntu 24.04 LTS x86_64 - Ubuntu 24.04 LTS arm64 - Ubuntu 22.04 LTS x86_64 - Ubuntu 22.04 LTS arm64 - Red Hat Enterprise Linux 10 x86_64- マイナーバージョンアップ版は全てサポート対象です - 可能な限り最新のバージョンをご利用ください - Red Hat Enterprise Linux 9 x86_64- マイナーバージョンアップ版は全てサポート対象です - 可能な限り最新のバージョンをご利用ください - Red Hat Enterprise Linux 8 x86_64- マイナーバージョンアップ版は全てサポート対象です - 可能な限り最新のバージョンをご利用ください ### Sora は Amazon Linux に対応していますか? 対応していません。 Sora が対応していると明記している OS 以外で動作させている場合は Sora はサポート対象外となります。 ### Sora のプロセス名は何になりますか? `bin/sora daemon` で起動した場合、Sora 本体は run_erl というプロセスになります。こちらの死活監視をお願いします。 ### Sora を終了しても epmd というプロセスが残りますが問題ありませんか? 問題ありません。 Sora と関係するプロセスですが独立しており、起動し続けていて構いません。 ### カーネルパラメーターの設定は何をすれば良いですか? まずはファイルディスクリプタ数をご確認ください。値は 65535 に設定しておくことをお勧めします。 その他のチューニング項目については [Linux カーネルチューニング](LINUX_KERNEL_TUNING.html) をご確認ください。 ### ログローテーションはどうすれば良いですか? sora.jsonl と connection.jsonl はローテーションされませんので必要な部分で mv コマンドなどで移動してください。 ファイルが無い場合、新しく作られます。 erlang.log については自動でログローテーションを行いますので気にする必要はありません。 ログの詳細については [ログファイル](LOG.html) をご確認ください。 ### ログのタイムゾーンを教えてください UTC です。 ### Sora が使用する UDP のポート範囲を教えてください Sora が使用する UDP ポートは Linux のエフェメラルポートを使用しています。 エフェメラルポートの範囲は sysctl などで確認してください。 実行例: ``` $ sysctl -n net.ipv4.ip_local_port_range 32768 60999 ``` ### Sora が使用する UDP のポート範囲を制限できますか? できます。Sora が使用する UDP ポートの範囲はエフェメラルポートの範囲です。 Linux 側でエフェメラルポートの範囲を設定してください。 sysctl にて net.ipv4.ip_local_port_range の範囲を指定してください。 ### ブラウザで WebRTC の詳細情報を取得することはできますか? できます。 - Chrome であれば URL に `chrome://webrtc-internals` を入力してみてください - Firefox であれば URL に `about:webrtc` を入力してみてください - Edge であれば URL に `edge://webrtc-internals` を入力してみてください - Safari であれば JavaScript コンソールの設定の一般から WebRTC を設定できます ![image](https://i.gyazo.com/cbcc400253e213c4d5e311377ea5a613.png) ### SELinux を利用する際の注意点はありますか? Sora の log ディレクトリ以下にログを書き込めるようにする必要があります。 以下を参考にしてみてください。 - [logging - logrotate cron job not rotating certain logs - Stack Overflow](https://stackoverflow.com/questions/15652654/logrotate-cron-job-not-rotating-certain-logs) - [linux - Configuring SELINUX to allow logging to a file that's outside /var/log - Unix & Linux Stack Exchange](https://unix.stackexchange.com/questions/79311/configuring-selinux-to-allow-logging-to-a-file-thats-outside-var-log) ### 映像が乱れたり止まったりする場合は何を確認するのが良いですか? 映像が乱れたり止まったりする場合はネットワーク回線が不安定なことがほとんどです。 この場合は切断時に生成される `connection.jsonl` を確認してみてください。 このログで映像の送信側と受信側の統計情報が確認できますので、 映像が乱れたり止まったりした接続の `connection_id` を記録しておいてください。 - `total_received_rtcp_rtpfb_generic_nack` - `total_sent_rtcp_rtpfb_generic_nack` この値が多ければ多いほど「再送要求」の回数が多く、回線が不安定だったことが把握できます。 `connection.jsonl` の詳細については [connection ログ](LOG.html#f2e264) をご確認ください。 ### Sora が突然終了しました Sora は何か問題があり Sora が終了した場合 `erl_crash.dump` というログを出力します。 このログが出力された場合はサポート問い合わせの手順に従ってサポートまでご連絡ください。 もし `erl_crash.dump` が出力されずに Sora が終了した場合はカーネル側から停止された可能性があります。 まずは OOM Killer で殺されていないかどうかを確認してみてください。 ### Sora で利用している Erlang VM のフラグを指定することはできますか? > **重要** > > この設定を利用する場合はサポートまでお問い合わせください できます。環境変数 `SORA_ADDITIONAL_ERL_ARGS` を利用してください。 ### クライアントごとに Sora への経路を変更することはできますか? できます。認証成功時にクライアントに `ipv4_address` または `ipv6_address` を払い出すことで、 クライアントはその IP アドレスを利用して Sora へ接続を試みるようになります。 例えばインターネット経由とプライベートネットワーク経由で接続先を変えることができます。 - パブリックネットワーク経由の場合は `ipv4_address` または `ipv6_address` に Sora が利用しているサーバーのパブリック IP アドレスを設定してください - プライベートネットワーク経由の場合は `ipv4_address` または `ipv6_address` に Sora が利用しているサーバーのプライベート IP アドレスを設定してください ## SDK Sora の SDK は基本的にシグナリング処理のための SDK です。 WebRTC 部分は [webrtc.org](https://webrtc.org/?hl=ja) が提供しているライブラリを利用しています。 ### Sora の SDK へのサポートはありますか? Sora の SDK サポートは提供していません。有償のサポートも提供していません。 もしアドバイスが必要だったり、問題が起きたりした場合は Discord へお願いします。バグ対応は最優先で行います。 ### Discord サーバーの招待 URL SDK の質問や相談については `sora-sdk-faq` を利用してください。 - Sora JavaScript SDK- 投稿時に `sora-js-sdk` タグを指定してください - Sora iOS SDK- 投稿時に `sora-ios-sdk` タグを指定してください - Sora Android SDK- 投稿時に `sora-android-sdk` タグを指定してください - Sora Unity SDK- 投稿時に `sora-unity-sdk` タグを指定してください - Sora C++ SDK- 投稿時に `sora-cpp-sdk` タグを指定してください - Sora Python SDK- 投稿時に `sora-python-sdk` タグを指定してください ### JavaScript SDK はありますか? Sora の JavaScript SDK に関しては以下をご確認ください。 - [Sora JavaScript SDK ドキュメント — Sora JavaScript SDK](https://sora-js-sdk.shiguredo.jp/) - [WebRTC SFU Sora JavaScript SDK](https://github.com/shiguredo/sora-js-sdk) - [WebRTC SFU Sora JavaScript SDK サンプル集](https://github.com/shiguredo/sora-js-sdk-examples) ### iOS SDK はありますか? Sora の iOS SDK に関しては以下をご確認ください。 Swift で書かれています。 - [Sora iOS SDK ドキュメント — Sora iOS SDK](https://sora-ios-sdk.shiguredo.jp/) - [WebRTC SFU Sora iOS SDK](https://github.com/shiguredo/sora-ios-sdk) - [WebRTC SFU Sora iOS SDK クイックスタート](https://github.com/shiguredo/sora-ios-sdk-quickstart) - [WebRTC SFU Sora iOS SDK サンプル集](https://github.com/shiguredo/sora-ios-sdk-samples) ### Android SDK はありますか? Sora の Android SDK に関しては以下をご確認ください。 Kotlin で書かれています。 - [Sora Android SDK ドキュメント — Sora Android SDK](https://sora-android-sdk.shiguredo.jp/) - [WebRTC SFU Sora Android SDK](https://github.com/shiguredo/sora-android-sdk) - [WebRTC SFU Sora Android SDK クイックスタート](https://github.com/shiguredo/sora-android-sdk-quickstart) - [WebRTC SFU Sora Android SDK サンプルアプリケーション](https://github.com/shiguredo/sora-android-sdk-samples) ### C++ SDK はありますか? Sora の C++ SDK に関しては以下をご確認ください。 C++ で書かれています。 - [WebRTC SFU Sora C++ SDK](https://github.com/shiguredo/sora-cpp-sdk) ### Unity SDK はありますか? Sora の Unity SDK に関しては以下をご確認ください。 C++ SDK をベースにしています。 - [Sora Unity SDK ドキュメント — Sora Unity SDK ドキュメント](https://sora-unity-sdk.shiguredo.jp/) - [WebRTC SFU Sora Unity SDK](https://github.com/shiguredo/sora-unity-sdk) ### Python SDK はありますか? Sora の Python SDK に関しては以下をご確認ください。 C++ SDK をベースにしています。 - [Sora Python SDK ドキュメント — Sora Python SDK](https://sora-python-sdk.shiguredo.jp/) - [WebRTC SFU Sora Python SDK](https://github.com/shiguredo/sora-python-sdk) - [Sora Python SDK サンプル集](https://github.com/shiguredo/sora-python-sdk-examples) ### JavaScript SDK は認証付き HTTP Proxy に対応していますか? JavaScript SDK はブラウザで動作するため、ブラウザが WebRTC での HTTP Proxy に対応している必要があります。 主要なブラウザは HTTP Proxy に対応済みです。利用する場合はブラウザで HTTP Proxy の設定をしてください。 ### iOS / Android / Unity / C++ SDK / Python SDK は認証付き HTTP Proxy に対応していますか? 対応しています。ただし Basic 認証のみの対応で、 **OS の設定や PAC ファイルへの対応は未定です** 。 - iOS SDK- 最新版で対応済みです - Android SDK- 最新版で対応済みです - C++ SDK- 最新版で対応済みです - Unity SDK- 最新版で対応済みです - Python SDK- 最新版で対応済みです ### ブラウザレスな WebRTC クライアントアプリケーションはありますか? OSS として WebRTC Native Client Momo を公開しています。 - [WebRTC Native Client Momo](https://momo.shiguredo.jp/) - [shiguredo/momo: WebRTC Native Client Momo](https://github.com/shiguredo/momo) また OBS が WHIP という WebRTC シグナリング仕様を実装しています。 詳しくは [WHIP](WHIP.html) をご確認ください。 ## ライセンス ### 同時接続とは具体的に何を指していますか? シグナリングの同時接続数を指しています。1 シグナリング接続で 1 同時接続です。 ### ライセンスの同時接続数を超えた時はどうなりますか? もし、最大同時 100 接続のライセンスファイルを利用している場合で 101 本目の接続がきた場合、 Sora は 101 本目の接続を拒否します。 その際、クライアントには `SERVICE-UNAVAILABLE` というエラーメッセージを通知します。 Sora 側では `sora.jsonl` ログに `EXCEED-MAX-CONNECTIONS` というエラーログを出力します。 ### ライセンスの同時接続数の最小の値はいくつですか? ライセンスの同時接続数の最小は 100 となります。 10 や 50 といったライセンスは提供しておりません。 ### ライセンスの同時接続数は 100 単位ですか? ライセンスの同時接続数は 100 単位です。 100 の次は 200 となり、100 同時接続単位となります。 110 や 150 といったライセンスは提供しておりません。 ### ライセンスの最大同時接続とは別に最大同時接続数を設定できますか? Sora は `sora.conf` の [max_connections](SORA_CONF.html#498be9) で最大同時接続数を設定できます。 この値はライセンスの最大同時接続数以下に設定する必要があります。 ### ライセンスの期限を過ぎた場合はどうなりますか? 動作上、既存の接続に対しては特に何もありませんが、新規の接続を受け付けなくなります。 ### Sora の現在の同時接続数を確認する方法はありますか? [GetStatsReport](EXPERIMENTAL_API_STATS.html#bbbfca) API の `total_ongoing_connections` で現在 Sora に接続している同時接続数が確認できます。 また、 [Sora Exporter](SORA_EXPORTER.html) を利用することで、現在の同時接続数を監視することができます。 ### ライセンス期限のタイムゾーンを教えてください ライセンス期限のタイムゾーンは UTC です。 ### クラスター利用時に同一のライセンスを利用する方法はありますか? あります。 `最大ノード数ライセンス` を契約することで、 1 つのクラスター構築時に同一のライセンスを利用できるようになります。 `最大ノード数ライセンス` では、 1 クラスターで同一のライセンスを最大いくつのノードに適用できるかがあらかじめ定義されています。 クラスターを構築する際に、その最大ノード数までは同一ライセンスを利用できます。 詳細は [最大ノード数ライセンス](LICENSE.html#aee259) をご確認ください。 ### 最大ノード数ライセンスで契約できる最大ノード数はいくつですか? 最大ノード数は 1000 を想定しています。 ## アップデート ### アップデートは有償ですか? ライセンスをご契約いただいている期間は、無償でアップデートを提供させていただきます。 ### アップデートのタイミングは決まっていますか? 原則として毎年 6 月と 12 月に、機能の追加や改善、削除を目的としたアップデートを行います。 その他、必要に合わせて不定期に修正のアップデートを行うことがあります。 詳細は [サポートライフサイクル](SUPPORT_LIFECYCLE.html) をご確認ください。 ### Sora のバージョン表記 バージョン表記: ``` YYYY.MAJOR.FIX ``` - `YYYY` はリリースした年を示します - `MAJOR` はその年のメジャーアップデートのリリース回数を示します - `FIX` はバグフィックスアップデートおよびホットフィックスアップデートのリリース回数を示します 詳細は [サポートライフサイクル](SUPPORT_LIFECYCLE.html) をご確認ください。 ## サポート ### 古いバージョンの Sora のサポートは提供していますか? 以前は最新バージョンの利用に対してのみサポートを提供していましたが、Sora 2023.1.0 以降はサポート提供期間を約 12 ヶ月間に変更しました。 詳細は [サポートライフサイクル](SUPPORT_LIFECYCLE.html) をご確認ください。 ### Sora のサポートは電話で受け付けていますか? いいえ。サポートはサポート専用のメールでのみ、受け付けています。 ### Sora のサポートは 24 時間 365 日ですか? いいえ。サポートは弊社営業日の 10:00-17:00 のみ、対応しています。 ### SDK の有償サポートは受け付けていますか? いいえ。Sora SDK の有償サポートは行っていません。 ただし GitHub 上ですべてのコードを公開しています。 もし何か問題が起きた場合は時雨堂コミュニティの Discord にてご相談ください。 バグ対応は最優先で行います。 ### Zakuro や Hisui など関連ツールの有償サポートは受け付けていますか? いいえ。関連ツールの有償サポートは行っていません。 ただし GitHub 上ですべてのコードを公開しています。 もし何か問題が起きた場合は時雨堂コミュニティの Discord にてご相談ください。 バグ対応は最優先で行います。 # トラブルシューティング ## 突然切断された ### sora ログに `PONG-TIMEOUT-ERROR | reason=<<"WebSocket">>` が出力されている場合 Sora からデフォルトの設定で 5 秒間隔で送っている `{"type": "ping"}` に対して、 クライアントが `{"type": "pong"}` を 60 秒間返してこない場合に発生します。 また、これらの時間設定は `sora.conf` の設定 [websocket_signaling_ping_interval](SORA_CONF.html#27aae2) と [websocket_signaling_pong_timeout](SORA_CONF.html#140464) で変更できます。 これは Sora がクライアントが疎通不能だと判断して切断した、正常な終了です。 まずはクライアントのネットワーク状況を確認してみてください。 WebSocket が詰まることを回避する方法としては、 [DataChannel 経由のシグナリング](DATA_CHANNEL_SIGNALING.html) の利用を検討してください。 ### sora ログに `tcp_closed` という文字列が含まれている場合 この場合、通信に TURN-TCP が採用されており、OS 側で TCP の切断を検知し、接続を終了しています。 connection ログの `turn_transport_type` で `tcp` になっているかどうかを確認してみてください。 OS による TCP の切断に関しては Sora 側で対処できることは基本的にはありません。 ## Intel GPU を利用した端末で VP9 で配信または視聴した際に視聴している映像が乱れる Windows で Intel の GPU (内蔵 GPU を含みます) を利用している場合に、VP9 のハードウェアアクセラレーターが正常に動作しないことがあります。 この問題は Intel 特有のチップセットでのみ発生することが確認されています。これは Chrome または Intel のドライバーの不具合である可能性が高いため、 Sora 側の対応で解決することはできません。そのため、他のコーデックを利用することで回避してください。 ただし Chrome 側で VP9 のハードウェアアクセレーターの利用を停止することで回避することもできます。 ### ハードウェアアクセラレーターを停止する方法 VP9 のハードウェアアクセラレーターを停止する場合、 映像が乱れる原因がエンコーダーかデコーダーかがわからないため、まずはデコーダーを停止してみてください。 ハードウェアアクセラレーターのデコーダーを停止すると `libvpx` を利用したソフトウェアデコードに切り替わります。多くの場合はこれで解決する可能性が高いです。 ただし、状況が改善しない場合はハードウェアアクセラレーターのエンコーダー側も停止してみてください。 エンコーダー側の停止で解決した場合、エンコーダーが壊れている映像を送信している可能性が高くなります。 Chrome のハードウェアアクセラレーターを停止するには、 `chrome://flags/#disable-accelerated-video-decode` と `chrome://flags/#disable-accelerated-video-encode` を `停止中` に変更することで、 ハードウェアアクセラレーターの利用を停止できます。 > **重要** > > chrome://flags の設定変更後はブラウザの再起動が必要になります。 ### 有効(デフォルト) ハードウェアアクセラレーターが **有効** になっている状態です。 ![image](https://i.gyazo.com/45f650d456a2215b19aaf8f47e159d02.png) `chrome://gpu` にてハードウェアアクセラレーターが有効になっているか確認できます。 `Video Decode: Hardware accelerated` と `Video Encode: Hardware accelerated` のように表示されていればハードウェアアクセレーターが有効になっています。 ![image](https://i.gyazo.com/ef94a4ef1bfffccc82f193a8d6294883.png) ### 停止中 ハードウェアアクセラレーターが **停止中** になっている状態です。 ![image](https://i.gyazo.com/708aca89e11a6f988ba13b8d1a641c6b.png) `停止中` に設定変更した場合 `chrome://gpu` にてハードウェアアクセラレーターが停止しているかを確認することができます。 `Video Decode: Software only. Hardware acceleration disabled` と `Video Encode: Software only. Hardware acceleration disabled` のように表示されていればハードウェアアクセラレーターが停止しています。 ![image](https://i.gyazo.com/bf78bfb5bc3f12e51e8670811a0f8bdd.png) この状態では `libvpx` を利用したソフトウェアエンコード/デコードが利用されます。 ### 問題が発生した場合の Intel のハードウェアアクセラレーターが利用されているかどうかの確認方法 Intel の GPU または内蔵 GPU を利用している端末で配信側と視聴側の両方を確認してください。 #### 配信側の確認方法 `chrome://webrtc-internals` の `kind` が `video` の `outbound-rtp` を見ていただき、 `[codec]` と `encoderImplementation` を確認してみてください。 ここで `VP9` と `ExternalEncoder` となっている場合、 `VP9` のエンコードにハードウェアアクセラレーターが利用されていることが確認できます。 ソフトウェアエンコーダーが利用されている場合は `encoderImplementation` には `libvpx` と表示されます。 #### 視聴側の確認方法 `chrome://webrtc-internals` の `kind` が `video` の `inbound-rtp` を見ていただき、 `[codec]` と `decoderImplementation` を確認してみてください。 ここで `VP9` と `ExternalDecoder` となっている場合、 `VP9` のデコードにハードウェアアクセラレーターが利用されていることが確認できます。 ソフトウェアエンコーダーが利用されている場合は `decoderImplementation` には `libvpx` と表示されます。 # ワークアラウンド ## 概要 Sora 以外の要因で発生している問題に対するワークアラウンドを提供しています。 ## Safari タイムスタンプバグに対するワークアラウンド *バージョン 2024.2.3 で追加。* > **重要** > > このワークアラウンドは 2026 年 12 月リリース予定の Sora にて廃止します。 > **注釈** > > このワークアラウンドは Safari 18.6 以降で不要になりました。 Safari の問題により、 2025 年 8 月 1 日 時点で Safari 18.4-18.5 において、 H.264 または H.265 の録画が正常に行えない問題が発生することに対するワークアラウンド機能です。 > **重要** > > H.264 や H.265 を利用せず VP8 や VP9 を利用することでこのワークアラウンドは不要になります。 > このワークアラウンドは H.264 や H.265 で録画を必ず利用しなければいけない場合にのみ有効にしてください。 > **危険** > > ワークアラウンドを有効にすることで、今まで正常に録画できていた H.264 や H.265 を利用した録画が正常に行えなくなるリスクもあります。 > それを踏まえた上で有効にしてください。 この問題は macOS / iOS / iPadOS 全てのプラットフォームで発生することを確認しています。 また、iOS 版 Chrome や Firefox でも同様の問題が発生することを確認しています。 > **警告** > > この問題の修正が確認されている Safari Technology Preview 219 でもこのワークアラウンドが有効になってしまう問題があります。これは Safari Technology Preview のバージョンが 18.4 となっており、Safari 18.4 との区別ができないためです。 弊社ではこの問題が確認できているバージョンの Safari は以下になります。 - Safari 18.4 - Safari 18.4.1 - Safari 18.5 ### 設定 このワークアラウンドを有効にする場合、 `sora.conf` に `workaround_20250515 = 18.4,18.4.1,18.5` のように、ワークアラウンドに対応させる Safari のバージョンを `,` で区切って指定してください。 デフォルトは **未指定** で、指定しなければワークアラウンドは有効になりません。 ```ini workaround_20250515 = 18.4,18.4.1,18.5 ``` ### Safari 18.5.1 Safari 18.5.1 で修正された際、Sora 側で Safari 18.5.1 と Safari 18.5 のバージョンを区別できない可能性があります。 その場合は、もし修正されていたとしてもワークアラウンドが有効になってしまい、録画が正常に行えないかもしれません。 その場合はワークアラウンドを無効にしていただき、Safari 18.5.1 へアップデートして利用していただくようお願いします。 ### iOS/iPadOS Safari 18.3.2 Safari 18.3.1 では問題が発生しないことを確認していますが、 Safari 18.3.2 で問題が発生するかどうかを確認できていません。 ただし、iOS / iPadOS 向けの Safari 18.3.2 は iOS 18.3.1 同様、セキュリティフィックスのための更新となっているため、18.3.1 同様に問題が発生しないと考えられます。 [iOS 18.3.2およびiPadOS 18.3.2のセキュリティコンテンツについて - Apple サポート (日本)](https://support.apple.com/ja-jp/122281) ### ワークアラウンド適用の判定について HTTP ヘッダーに含まれる User-Agent 値のチェックと、映像コーデックが H.264 または H.265 であるかどうかで判定しています。 - `Version/18.5 Safari` - `iPhone; CPU iPhone OS 18_5_0 like Mac OS X` - `iPad; CPU OS 18_5_0 like Mac OS X` > **注釈** > > - 18_4_1 は 18.4.1 として扱われます > - 18_5_0 は 18.5 として扱われます > - 18_5 は 18.5 として扱われます Safari や iOS 版 Chrome 以外でも `User-Agent` に `iPhone` や `iPad` が含まれ、OS のバージョンが指定した Safari のバージョンに含まれる場合はワークアラウンドが有効になります。 例えばワークアラウンドの設定に 18.5 を含んでいた場合、 iOS 版の Chrome では `iPhone; CPU iPhone OS 18_5_0 like Mac OS X` という文字列が含まれるため、ワークアラウンドが有効になります。 ### 問題の詳細 Safari が依存している WebRTC ライブラリである libwebrtc を M128 から M132 へとアップデートする際、 廃止になった `VideoFrame::timestamp()` の代わりに、本来利用すべき `VideoFrame::rtp_timestamp()` ではなく、 `VideoFrame::timestamp_us()` を利用してしまったことで発生した問題になります。 `VideoFrame::timestamp()` が非推奨になったコミット `VideoFrame::timestamp()` が削除されたコミット Safari のベースである WebKit の libwebrtc を M132 に更新した際に、 `VideoFrame::rtp_timestamp` ではなく `VideoFrame::timestamp_us` を利用してしまったコード この間違った修正により、ハードウェアアクセラレーターを利用するコーデック H.264 と H.265 は、 送信するパケットのタイムスタンプがおかしくなってしまい、Sora の録画機能が正しく機能しなくなっています。 この問題については WebKit では既に解決済みになっており、 修正コミットがマージされています。 問題のバグ 修正されたコミット Safari Technology Preview 219 ではこの問題が修正されていることを確認済みのため、この修正コミットは含まれているようです。 2025 年 7 月 30 日にリリースされた Safari 18.6 にて本問題が修正されていることを確認しており、ワークアラウンドは不要です。 # 開発ツール ## 概要 [Sora DevTools](https://github.com/shiguredo/sora-devtools) は時雨堂が開発し Apache-2.0 ライセンスとしてオープンソースで GitHub に公開している Sora の開発者向けのツールです。 Sora DevTools は、Sora の機能を試したり、アプリケーションの開発中に機能を確認したり、Sora で何か問題が発生した場合に再現を行うために利用できます。 Sora DevTools はオンライン版とオフライン版の 2 種類があります。 オンライン版はブラウザから直接アクセスして利用できます。 オフライン版は閉鎖ネットワーク環境下などで、オンライン版にアクセスできない場合に、 ローカルに NGINX でホスティングして利用できます。 ## Sora DevTools オンライン版を利用する Sora DevTools のオンライン版は、 `https://sora-devtools.shiguredo.app` へアクセスし、 `signalingUrlCandidates` に Sora のシグナリング URL を指定することで利用できます。 ## Sora DevTools オンライン版を NGINX でリバースプロキシして利用する > **警告** > > 商用環境ではこの設定は利用せず、開発環境でのみ有効にしてください。 NGINX の `location` `/` ディレクティブで `https://sora-devtools.shiguredo.app` へリバースプロキシしてください。 ```nginx location / { proxy_http_version 1.1; proxy_pass https://sora-devtools.shiguredo.app; proxy_set_header Host sora-devtools.shiguredo.app; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_ssl_server_name on; proxy_ssl_name sora-devtools.shiguredo.app; proxy_ssl_protocols TLSv1.2 TLSv1.3; } ``` ## Sora DevTools オフライン版を NGINX でホスティングして利用する > **警告** > > 商用環境ではこの設定は利用せず、開発環境でのみ有効にしてください。 から `sora-devtools-.tar.gz` をダウンロードして解凍してください。 解凍したディレクトリを NGINX の `root` ディレクティブに指定してください。 ```nginx location / { root /path/to/sora-devtools-; index index.html; try_files $uri $uri/ /index.html; } ``` ## Sora DevTools オフライン版を Python3 でホスティングして利用する ローカルで簡単に動かしたい場合はこの方法がおすすめです。 から `sora-devtools-.tar.gz` をダウンロードして解凍してください。 ```bash cd /path/to/sora-devtools- python3 -m http.server 8000 ``` ブラウザから `http://localhost:8000` にアクセスすることで利用できます。 `signalingUrlCandidates` に Sora のシグナリング URL を指定することで利用できます。 ## サポート - Sora DevTools の正式版については、 Sora のサポート対象です - Sora DevTools の開発版については、 Sora のサポート対象外です ### Discord Discord にてコミュニティを運営しています。 なにか質問したい場合は Discord サーバーへ参加してください。 開発ツールの開発版についての質問やバグ報告は Discord の `#sora-tool-faq` チャンネルにお願いします。 # チュートリアル ## 概要 このチュートリアルでは、Sora に組み込まれている開発ツールを動かして、ひととおり使ってみるところまでを説明します。 ## チュートリアルの注意点 > **注意** > > 繋がらないという問い合わせのほとんどは UDP のポート開放忘れです。必ずポートを開放してください。 - このチュートリアルでは、リバースプロキシとしての NGINX や HTTPS の知識を必要とします - Sora は TCP と UDP の両方を利用します- TCP はデフォルトであれば 3000 番と 5000 番を利用します - UDP はデフォルトであればエフェメラルポートの範囲を利用します - Sora のシグナリングは WebSocket over TLS 非対応のため、nginx をリバースプロキシとして利用して、 TLS 終端を行い Sora のシグナリングへ繋ぐ必要があります ## Sora の展開 tar.gz で圧縮されていますので、展開して下さい。 ```console $ tar xfz sora---.tar.gz ``` ## ライセンスファイルの配置 ライセンスファイルを etc/ において、cp コマンドを利用して `license.json` に変更して下さい。 ## 起動 設定が終わったらサーバーを起動します。 ```bash $ sora-/bin/sora daemon ``` ### 停止 以下で停止できます。 ```bash $ sora-/bin/sora stop ``` ## シグナリングへの HTTPS の適用 **HTTPS (WebSocket over TLS を含む) の適用は必ず行ってください。HTTPS への接続以外はサポート対象外となります** ブラウザで WebRTC の機能の一つである getUserMedia を利用する場合は HTTPS が必須となります。 ただし、Sora 自体は HTTPS 非対応のため、Sora の前段にリバースプロキシとして NGINX を設置して TLS 終端を行ってください。 NGINX の location ディレクティブの設定については [nginx](NGINX.html) を参考にして設定をお願いします。 > **注意** > > NGINX の設定に関する質問については Sora のサポート範囲外となりますのでご了承下さい。 証明書については [Let's Encrypt - Free SSL/TLS Certificates](https://letsencrypt.org/) の利用をおすすめします。 > **注意** > > Let's Encrypt に関する質問については Sora のサポート範囲外となりますのでご了承下さい。 リバースプロキシとしての NGINX の役割: ``` // 開発者ツールの静的ファイルの場合 クライアント -> -> NGINX -> -> Sora // シグナリングの場合 クライアント -> -> NGINX -> -> Sora ``` ## 開発者ツールを利用してみる Sora では開発ツールを利用して、Sora の機能を試すことができます。まずはオンライン版の利用をお勧めします。 ### オンライン版を利用する オンライン版の開発ツールは から利用することができます。 Sora のシグナリング URL を指定する必要があります。 Sora のシグナリング URL を `signalingUrlCandidates` に指定してください。 シグナリング URL は `wss://sora.example.com/signaling` のように `wss://` で始まる WebSocket over TLS の URL を指定してください。 ![image](https://i.gyazo.com/a97220d4ec14bc1107041a45a0a78bb0.png) ### オンライン版を NGINX でリバースプロキシ経由で利用する オンライン版の開発ツールに対してリバースプロキシを設定することで、Sora のシグナリング URL を指定せずに利用することができます。 NGINX の `location` `/` ディレクティブで `https://sora-devtools.shiguredo.app` へリバースプロキシしてください。 ```nginx location / { proxy_http_version 1.1; proxy_pass https://sora-devtools.shiguredo.app; proxy_set_header Host sora-devtools.shiguredo.app; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_ssl_server_name on; proxy_ssl_name sora-devtools.shiguredo.app; proxy_ssl_protocols TLSv1.2 TLSv1.3; } ``` `https://example.com/` のように NGINX のホスト名でアクセスしてください。 ### オフライン版を NGINX で利用する 開発ツールのオフライン版を NGINX でホストして利用することができます。 から Latest の `sora-devtools-.tar.gz` をダウンロードして展開してください。 展開したディレクトリを NGINX の `root` ディレクティブに指定してください。 ```nginx location / { root /path/to/sora-devtools-; index index.html; try_files $uri $uri/ /index.html; } ``` `https://example.com/` のように NGINX のホスト名でアクセスしてください。 ### 開発者ツールが動作するブラウザ一覧 以下の最新のブラウザで動作します。 - Google Chrome - Mozilla Firefox - Apple Safari - Microsoft Edge ただし一部の機能は特定のブラウザでのみ動作します。 ### 動作確認 > **警告** > > ハウリングする可能性があります。 ビデオ会議システムなどで利用されるような双方向での配信機能です。 受信だけ、送信だけでの利用もできます。 `connect` を押して、その後、別のブラウザやタブで同じ URL を開いて、 `connect` を押して下さい。 ![image](https://i.gyazo.com/b79590e2493ec49fed8f9dc0e0470a26.png) 追加でタブを開いて `connect` していけば参加者を増やせます。 開発ツールでは気軽にいろいろな設定を試せるようになっています。触ってみてください。 ## 次のステップ [本番稼働に向けて](PRODUCTION.html) で Sora の本番稼働向けの設定を行ってください。 Sora はいろいろな機能を持っていますので、一通りドキュメントをご確認下さい。 ドキュメントで不明な点がありましたら、お気軽にお問い合わせください。 > **注釈** > > [アプリケーション連携チュートリアル](APP_INTEGRATE_TUTORIAL.html) は Sora を利用したアプリケーション連携用のチュートリアルを Python にて説明しています。 ## トラブルシューティング ### タイムアウトが起きてつながらない場合 > **重要** > > OS の設定やファイアウォールで UDP の通信ができない場合は接続に失敗します。 Sora が利用する UDP のポートの範囲は通常 32768 から 60999 です。この範囲の通信を許可にしてみてください。 ### それでもうまく繫がらない場合 サーバーの IPv4 アドレスを `ipv4_address` に指定して、 `ipv6` を `false` にしてみてください。 ```ini ## https://sora-doc.shiguredo.jp/SORA_CONF#sora-conf-ipv4-address ipv4_address = 192.0.2.10 ``` > **注釈** > > Amazon EC2 インスタンス等のようなパブリック IP アドレスとプライベート IP アドレスが異なる環境では > ブラウザからアクセスできる IP アドレス(パブリック IP アドレス)を ipv4_address に設定してください。 ### よくある問題 ここでは利用しているドメインを仮に `example.com` としています。 - `https://example.com/` にアクセスできない- NGINX の設定が間違っている可能性があります。nginx の設定を見直して下さい - `https://example.com/` にアクセスしても 404 になる- Sora の組み込みの開発者ツールが有効になっていない可能性があります- `sora.conf` の設定で開発者ツールが有効になっているか確認して下さい - `http://example.com:5000/` にアクセスして開発者ツールが有効になっているかを確認して下さい - Sora が利用するポートを他のプロセスが利用していないかを確認してください- Sora が利用したいポートを他のプロセスが既に利用しているために、Sora が起動していない可能性があります ### それでも繋がらない場合 **お問い合わせ前に以下を確認してください** - チュートリアル以外のことはやっていないかどうかを確認して下さい - **ファイアウォールの設定をすべて無効にして確認してください** - IPv6 アドレスを無効にして確認してください - Sora では基本的にロードバランサーを利用することはできませんので、ロードバランサーなしで確認してください すべてを確認しても繋がらない場合はお問い合わせください。 その際に以下の情報を **必ず** お送りください。 - どんな環境でチュートリアルを実行しているか - Sora のバージョン - Sora の設定ファイルである `sora.conf` - log ディレクトリ以下すべてを tar.gz にて圧縮してお送りください- 容量が 1 メガバイトを超える場合は事前にご連絡ください。アップローダーをご提供します - 繋がらなかった開発者ツール- たとえば `sendonly` など - 繋がらなかったブラウザを利用している OS とバージョン- たとえば `macOS Sonoma 14.5` や `Windows 10 2004` など - 繋がらなかったブラウザの種類とバージョン- たとえば `Chrome 125.0.6422.142` など それ以外にも可能な限り、こちらがサポートをするために必要そうな情報をお送りください。 # 本番稼働に向けて この資料はチュートリアルで Sora をなんとなく体験したあとに、 本番環境に向けてどのような準備が必要なのか、どの機能を使っていけばいいのかをまとめたものです。 > **重要** > > 不明点などはサポートまでお問い合わせください。 ## 優先順位 Sora で外部から指定する値には優先順位があります。 上から順に優先度が高く、同じ優先度の場合は後から指定した値が優先されます。 1. セッション生成時の払い出しで指定した値 2. 認証成功時の払い出しで指定した値 3. シグナリング接続時に指定した値 4. sora.conf で設定した値 - sora.conf で設定した値は、シグナリング接続時の値で上書きできます - シグナリング接続時の値は、認証成功時の払い出しで上書きできます - 認証成功時の払い出しは、セッション生成時の払い出しで上書きできます 本番環境ではシグナリング接続時の値を利用するのは避けて、 認証成功時やセッション生成時の値を利用するようにしてください。 ## IPv4 アドレスの固定 `sora.conf` の [ipv4_address](SORA_CONF.html#04becc) にサーバーの IP アドレスを指定してください。 ```ini ipv4_address = 192.0.2.10 ``` ## IPv6 アドレスの利用について Safari は IPv6 環境での動作が不安定なため、 Safari をターゲットデバイスに含んでいる場合は `sora.conf` の IPv6 設定を無効にする `ipv6 = false` を推奨しています。 ファイアーウォールを利用される場合は IPv6 向け設定もご確認ください。 ## sora.conf の turn_fqdn を設定する iOS の場合は TURN は FQDN を利用しないと接続ができない場合があるため、 TURN-UDP / TURN-TCP で利用するドメインを指定してください。 `sora.conf` の `ipv4_address` に指定した IP アドレスを設定してある FQDN を指定してください。 ```ini turn_fqdn = sora-turn.example.com ``` ## ウェブフックなどで利用する CA 証明書のインストール もしウェブフックなどで HTTPS サーバへのアクセスを行う場合に、 自前で CA 証明書を設定しない場合、信頼された CA 証明書のインストールを行ってください。 - Ubuntu は `apt install ca-certificates` でインストールされる証明書を利用します - RHEL (または CentOS) は `dnf install ca-certificates` でインストールされる証明書を利用します ### 影響を受ける機能 - 認証ウェブフック - セッションウェブフック - イベントウェブフック - 統計ウェブフック - 音声ストリーミング機能 ただし、以下の設定で自前で CA 証明書を指定している場合は、この影響を受けません。 - [webhook_tls_verify_cacert_file](SORA_CONF.html#7036dc) - [audio_streaming_tls_verify_cacert_file](SORA_CONF.html#feef99) ## HTTP API のループバックアドレスからのみのアクセス > **重要** > > この設定を導入することを強く推奨します Sora の HTTP API は TLS を利用したセキュアな通信機能や認証機能を持ち合わせていません。 そのため、本番環境では `sora.conf` の [api_loopback_address_only](SORA_CONF.html#9d6140) の値を `true` にしてください。 こうすることでループバックアドレスからのみ HTTP API が叩けるようになります。 アプリケーションからの HTTP API へのアクセスは Nginx などのリバースプロキシ経由で利用してください。 ## シグナリングのループバックアドレスからのみのアクセス > **重要** > > この設定を導入することを強く推奨します Sora の WebSocket は TLS を利用したセキュアな通信機能を持ち合わせていません。 そのため、本番環境では `sora.conf` の [signaling_loopback_address_only](SORA_CONF.html#e22105) の値を `true` にしてください。 こうすることでループバックアドレスからのみシグナリングが叩けるようになります。 WebRTC クライアントからシグナリングへのアクセスは Nginx などのリバースプロキシ経由で利用してください。 ## ファイルディスクリプタ数の設定 Sora は 1 接続で少なくとも 2 つ以上のファイルディスクリプタを利用します。 また、ウェブフックやログの書き込みでも追加でファイルディスクリプタを利用します。 同時接続数が 100 の場合は Linux のデフォルト値である 1024 でも足りるとは思いますが、 ある程度大きめのファイルディスクリプタ数に変更してください。 ## systemd の適用 > **重要** > > この仕組みを導入することを強く推奨します Sora の起動/停止に `bin/sora daemon` を利用するのではなく systemd を適用してください。 デーモン化せずに Sora を動かすには `bin/sora foreground` を利用します。 詳細は [systemd](SYSTEMD.html) をご確認ください。 ## TURN-TLS、TURN-TCP、シグナリングで 443 番ポートを使用する > **重要** > > この仕組みを導入することを強く推奨します。 > この設定は Sora 2021.1 以降に最適化されています。 > **注意** > > NGINX および systemd の設定に関する質問については Sora のサポート範囲外となります。 **この設定はある程度の NGINX や証明書の知識が必要になります** NGINX のバージョンは 1.11.5 以降が必須です。 TURN-TLS、TURN-TCP、シグナリング(HTTPS)を 443 番ポートのみで受信する場合は次の設定を追加してください。 > **注意** > > NGINX の停止に QUIT シグナルを使用している場合は、nginx 起動時に作成された UNIX domain socket のソケットファイルは削除されないため、nginx の再起動に失敗します。 > そのため、サービス停止を QUIT シグナルではなく TERM シグナルを使用するように変更するか、または、daemon off で起動することをお勧めします。 > systemd を使用している場合も、ドロップインファイル等を作成して、nginx 停止時のシグナルを QUIT シグナルから TERM シグナルへ変更するか、daemon off による管理へ変更することをお勧めします。 ### NGINX のストリーム機能と ssl_preread 機能を利用する > **ヒント** > > Ubuntu 24.04 では NGINX のストリーム機能は `apt install libnginx-mod-stream` で明示的にインストールする必要があります。 NGINX の機能を利用して、同一ポートの待受で複数のプロトコルを扱えるようにします。 その機能を利用した NGINX の参考設定です。証明書には Let's Encrypt を利用している想定です。 利用する証明書はマルチドメイン (SANs) またはワイルドカード証明書が前提となります。 - sora.example.com- シグナリングの WebSocket over TLS で利用するドメイン - sora-turn.example.com- TURN-TLS で利用するドメイン ```nginx stream { # SNI のサーバー名が取得できない場合、または、該当するサーバー名が指定されていない場合は TURN-TCP へ # 該当するサーバー名が指定されている場合は TURN-TLS または シグナリングへ map $ssl_preread_server_name $upstream { default sora-turn.example.com; "sora-turn.example.com" unix:/tmp/tls.sock; "sora.example.com" unix:/tmp/https.sock; } # Sora の TURN-TCP へ転送 upstream sora-turn.example.com { # Sora の TURN-TCP へ # ここの IP アドレスは Sora の ipv4_address に指定した値を指定してください # ここを 127.0.0.1 にすると Firefox で繋がらなくなることを確認しています server 192.0.2.1:3478; } # TURN-TCP, TURN-TLS, シグナリングを TCP で待ち受け server { listen 443; # IPv6 を利用している場合は下記を有効にしてください # listen [::]:443; proxy_pass $upstream; proxy_protocol on; ssl_preread on; } # TURN-TLS, シグナリングの TLS 終端し TURN-TCP へ転送 server { listen unix:/tmp/tls.sock ssl proxy_protocol; # SNI を見て TURN-TLS の場合は TURN-TCP へ転送 # シグナリング(HTTPS)の場合は HTTP へ転送 proxy_pass $ssl_server_name; proxy_protocol on; ssl_certificate /etc/letsencrypt/live/sora.example.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/sora.example.com/privkey.pem; ssl_protocols TLSv1.2; ssl_prefer_server_ciphers on; ssl_handshake_timeout 10s; ssl_session_cache off; ssl_session_tickets off; } } http { include mime.types; default_type application/octet-stream; sendfile on; keepalive_timeout 65; gzip on; # $proxy_protocol_addr を利用することでクライアントの IP が保持できるようになる log_format proxy '$proxy_protocol_addr - $remote_user [$time_local] ' '"$request" $status $body_bytes_sent ' '"$http_referer" "$http_user_agent"'; # 定義した proxy を利用する access_log /var/log/nginx/access.log proxy; server { listen unix:/tmp/https.sock ssl proxy_protocol; root /var/www/html; index index.html index.htm; ssl_certificate /etc/letsencrypt/live/sora.example.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/sora.example.com/privkey.pem; ssl_protocols TLSv1.2; ssl_prefer_server_ciphers on; ssl_session_cache off; ssl_session_tickets off; real_ip_header proxy_protocol; server_name sora.example.com; # シグナリングを Sora に Proxy します location = /signaling { proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_pass http://127.0.0.1:5000/signaling; proxy_set_header X-Real-IP $proxy_protocol_addr; proxy_set_header X-Forwarded-For $proxy_protocol_addr; } # Sora の HTTP API に Proxy します # 本番環境では認証などの機能を利用してください location /api { proxy_http_version 1.1; proxy_pass http://127.0.0.1:3000/; } # OBS (WHIP/WHEP) 向けのシグナリングを Sora に Proxy します location ~ ^/(whip|whip-session|whep|whep-session)/ { proxy_pass http://127.0.0.1:5000; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Authorization $http_authorization; } # Sora のヘルスチェックに Proxy します # 公開するかどうかは検討してください location /.ok { proxy_http_version 1.1; proxy_pass http://127.0.0.1:5000; } } } ``` TURN-TCP、 TURN-TLS、シグナリングを 443 番で使用する場合の sora.conf の設定は以下になります。 turn_tcp_port, turn_tls_port を 443 に変更します。 ```ini ## TURN 機能を有効にするかどうかを指定してください turn = true ## TURN 機能で利用するレルムを指定してください turn_realm = sora-turn.example.com ## TURN 機能で TURN URL 払い出し機能で利用する FQDN (最後の . なし)を指定してください turn_fqdn = sora-turn.example.com ## TURN 機能で TURN-TCP を有効にするかどうかを指定してください turn_tcp = true ## TURN 機能で TURN-TCP を有効にした際に利用するポート番号を指定してください turn_tcp_listen_port = 3478 ## TURN 機能で TURN-TCP URL 払い出し時のポート番号を指定してください turn_tcp_port = 443 ## TURN 機能で TURN-TLS URL 払い出し機能を有効にするかどうかを指定してください ## オプションでデフォルトは false です turn_tls = true ## TURN 機能で TURN-TLS URL 払い出し機能で利用する FQDN (最後の . なし)を指定してください ## turn_tls_fqdn は turn_fqdn の値を上書きします turn_tls_fqdn = sora-turn.example.com ## TURN 機能で TURN-TLS URL 払い出し機能を有効にした際に利用するポート番号を指定してください turn_tls_port = 443 ``` ### Ubuntu の Nginx で Unix Domain Socket を利用する際の注意点 - SIGTERM を利用するようにしないと、リスタートすることができません - セキュリティアップデートで強制的に apt upgrade が行われた際、 Unix Domain Socket ファイルが残って Nginx が再起動でき無くなる場合があります ```console $ sudo systemctl edit nginx.service ``` ```ini [Service] ExecStartPre= # 起動前に /tmp/tls.sock を削除する設定を追加 ExecStartPre=/bin/rm -f /tmp/tls.sock # 起動前に /tmp/https.sock を削除する設定を追加 ExecStartPre=/bin/rm -f /tmp/https.sock ExecStartPre=/usr/sbin/nginx -t -q -g 'daemon on; master_process on;' ExecStop= ExecStop=-/sbin/start-stop-daemon --quiet --stop --signal TERM --pidfile /run/nginx.pid ``` - `ExecStartPre=` を追加して、 既存の `ExecStartPre=` の設定をクリアしてください - `ExecStartPre=/bin/rm -f /tmp/tls.sock` を設定してください - `ExecStartPre=/bin/rm -f /tmp/https.sock` を設定してください - `ExecStop=` を追加して、既存の `ExecStop=` の設定をクリアしてください - `ExecStop=-/sbin/start-stop-daemon --quiet --stop --signal TERM --pidfile /run/nginx.pid` を設定してください。 その後、以下のコマンドを実行してください。 ```console $ sudo systemctl daemon-reload $ sudo systemctl restart nginx ``` ## ウェブフックを NGINX 経由で送信する Sora からウェブフックを送信する際、NGINX をリバースプロキシとして利用することを推奨しています。 > **注意** > > NGINX はフォワードプロキシサーバーを経由したリクエスト送信には対応していません。 > そのため、ウェブフックサーバーへのリクエストをフォワードプロキシサーバー経由で送信する場合は、NGINX 経由の送信は利用せず、sora.conf の webhook_proxy_url 設定を使用してください。 ### NGINX の設定例 Sora からのウェブフックサーバーへのアクセスに、NGINX を使用したリバースプロキシを使用する場合の設定例です。 この設定は `/etc/nginx/conf.d/webhook.conf` に保存することを想定しています。 `/etc/nginx/nginx.conf` の `http` ディレクティブに、 `include /etc/nginx/conf.d/*.conf;` がない場合や、 コメントアウトされていて `/etc/nginx/conf.d/webhook.conf` が読み込まれない場合は、 `include` ディレクティブを追加、または、コメントアウトを外して `/etc/nginx/conf.d/webhook.conf` が読み込まれるようにしてください。 Sora からのウェブフックサーバーへのリクエストを NGINX で HTTP で受信して、HTTPS でウェブフックサーバーに転送します Sora と NGINX 間の通信は HTTP のため、下記の設定例は Sora と同じサーバーに NGINX をインストールしてある前提です この設定を使用する場合は、 `nginx.conf` の `listen` ディレクティブのポート番号は、 `sora.conf` の `auth_webhook_url`, `event_webhook_url`, `session_webhook_url`, `stats_webhook_url` の設定と合わせてください。 ```nginx server { # 外からのリクエストは受信しない # ポート番号は sora.conf の auth_webhook_url, event_webhook_url, session_webhook_url, stats_webhook_url の設定と合わせてください listen 127.0.0.1:18080; # 名前解決に使用するリゾルバの設定 # 転送先ウェブフックサーバーへのリクエスト時にホスト名の名前解決が必要な場合は、 # resolver ディレクティブに、/etc/resolv.conf で利用している DNS サーバー、 # または、環境標準の DNS サーバーの IP アドレスを設定してください # また、resolver ディレクティブを使用しない場合には、location ディレクティブの proxy_pass への # 転送先 URI 指定には変数を使用しないでください resolver 127.0.0.53 valid=30s; access_log /var/log/nginx/upstream_access.log; error_log /var/log/nginx/upstream_error.log warn; # HTTP の HOST ヘッダーと TLS の SNI、proxy_pass での転送先指定で使用するホスト名の設定 # 転送先ウェブフックサーバーのホスト名を設定してください set $upstream_host "webhook.example.com"; proxy_http_version 1.1; proxy_set_header Host $upstream_host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto http; # Basic 認証をパススルーする場合は下記のコメントアウトを外します # proxy_set_header Authorization $http_authorization; # プロキシタイムアウト設定 proxy_connect_timeout 5s; proxy_send_timeout 30s; proxy_read_timeout 30s; # リクエストサイズ制限 client_max_body_size 1m; # リトライ抑制:POST の二重送信を避ける proxy_next_upstream off; # レスポンスの Location 書き換えを無効化 proxy_redirect off; proxy_ssl_server_name on; proxy_ssl_name $upstream_host; proxy_ssl_verify on; # TLS の証明書検証で使用する CA 証明書の指定 # 下記以外に、自己発行証明書を使用する場合や他のパスに設置した CA 証明書を使用する場合は、 # その CA 証明書のパスを proxy_ssl_trusted_certificate ディレクティブに設定してください ## Ubuntu の場合 # proxy_ssl_trusted_certificate /etc/ssl/certs/ca-certificates.crt; ## RHEL の場合 # proxy_ssl_trusted_certificate /etc/pki/tls/certs/ca-bundle.crt; # Upstream TLS 証明書の検証時に許可する証明書チェーンの深さの指定 # # 利用者環境によっては異なる証明書チェーンが使用されるため、 # 以下のような証明書検証エラーが発生した場合は、 # 転送先の証明書チェーンおよび CA 設定を確認し、 # 必要に応じて proxy_ssl_verify_depth の値を調整を試みてください # # unable to get local issuer certificate # certificate verify error # proxy_ssl_verify_depth 3; # sora.conf の auth_webhook_url に設定した URI のパスと合わせてください location = /sora/webhook/auth { # POST 以外を拒否 limit_except POST { deny all; } # 認証ウェブフックの転送先 URI を指定してください proxy_pass https://$upstream_host:28080/sora/webhook/auth; } # sora.conf の event_webhook_url に設定した URI のパスと合わせてください location = /sora/webhook/event { # POST 以外を拒否 limit_except POST { deny all; } # イベントウェブフックの転送先 URI を指定してください proxy_pass https://$upstream_host:28080/sora/webhook/event; } # sora.conf の session_webhook_url に設定した URI のパスと合わせてください location = /sora/webhook/session { # POST 以外を拒否 limit_except POST { deny all; } # セッションウェブフックの転送先 URI を指定してください proxy_pass https://$upstream_host:28080/sora/webhook/session; } # sora.conf の stats_webhook_url に設定した URI のパスと合わせてください location = /sora/webhook/stats { # POST 以外を拒否 limit_except POST { deny all; } # 統計ウェブフックの転送先 URI を指定してください proxy_pass https://$upstream_host:28080/sora/webhook/stats; } # location で設定されていないパスは 404 location / { return 404; } } ``` ## カーネルパラメーターの適用 Sora は UDP を利用します。音声や映像の配信では大量の UDP を処理するため Linux のデフォルトの設定だと厳しい場合があります。 そのため、パラメーターの変更を推奨しています。 詳細は [Linux カーネルチューニング](LINUX_KERNEL_TUNING.html) をご確認ください。 ## コンテナ環境での利用する場合 ### 認識するコア数と利用できるコア数に矛盾がないかの確認 Sora をコンテナ環境で利用する場合、 コンテナが認識するコア数と実際にコンテナが利用できるなコア数が異なる環境があります。 Sora は **コンテナが認識するコア数を想定した挙動** をするため、 Sora の性能劣化が発生する場合があります。 コンテナが認識するコア数とコンテナが利用できるコア数が異なる場合は **必ずサポートまでご連絡ください** 。 コンテナが認識するコア数は以下のコマンドで確認できます。 ```bash $ grep processor /proc/cpuinfo | wc -l ``` - AWS ECS on EC2 利用時にコンテナが認識するコア数と利用できるコア数が異なることを確認しています ## SDK の利用 Sora へ接続する場合は、弊社がオープンソースとして公開している SDK を利用してください。 これらのライブラリは弊社によって最新版の Sora で動作するようにメンテナンスされています。 導入もとても簡単になっているので、是非利用してください。 > **重要** > > SDK に関する質問・要望・バグなどの報告は Discord の利用をお願いします。 > Sora のライセンス契約の有無に関わらず、 > 応答時間と問題の解決を保証しませんのでご了承ください。 > > ただし、明らかなバグについては優先的に対応しますので、ご安心ください。 SDK の質問や相談については `sora-sdk-faq` を利用してください。 - Sora JavaScript SDK- 投稿時に `sora-js-sdk` タグを指定してください - Sora iOS SDK- 投稿時に `sora-ios-sdk` タグを指定してください - Sora Android SDK- 投稿時に `sora-android-sdk` タグを指定してください - Sora Unity SDK- 投稿時に `sora-unity-sdk` タグを指定してください - Sora C++ SDK- 投稿時に `sora-cpp-sdk` タグを指定してください - Sora Python SDK- 投稿時に `sora-python-sdk` タグを指定してください - Sora Rust SDK- 投稿時に `sora-rust-sdk` タグを指定してください - Sora Flutter SDK- 投稿時に `sora-flutter-sdk` タグを指定してください ## やりたいことが 1:1 の双方向配信の場合 配信が 1:1 の双方向の場合はマルチストリーム機能を利用してください。 詳細は [マルチストリーム機能](MULTISTREAM.html) をご確認ください。 ## やりたいことが複数人での双方向配信の場合 複数人で双方向の配信を行いたい場合はスポットライト機能を検討してください。 スポットライト機能を利用することで、クライアントとサーバー側の負荷をかなり抑えられるようになります。 詳細は [スポットライト機能](SPOTLIGHT.html) をご確認ください。 ## やりたいことが 1:多 の双方向配信の場合 配信が 1:多 の片方向の場合でもマルチストリーム機能を利用してください。 `role` に `sendonly` と `recvonly` を利用してください。 詳細は [マルチストリーム機能](MULTISTREAM.html) をご確認ください。 ## やりたいことが 1:多 の片方向配信で、大規模の場合 配信が 1:多 の片方向で大規模な場合は、クラスターリレー機能を利用してください。 クラスターリレー機能を利用することで、1 チャネルで大規模な配信を行うことができます。 詳細は [リレー機能](CLUSTER.html#4b3bf1) をご確認ください。 ## やりたいことが OBS からの配信の場合 OBS からの配信を行いたい場合は OBS (WHIP) 対応機能を利用してください。 詳細は [WHIP 機能](WHIP.html) をご確認ください。 ## やりたいことが OBS での取り込みの場合 OBS へ取り込みを行いたい場合は OBS (WHEP) 対応機能を利用してください。 詳細は [WHEP 機能](WHEP.html) をご確認ください。 ## Edge が機能要件に含まれている場合 最新の Edge であれば、ほとんど Chrome と同じ動きをしますので安心してお使いください。 ## Firefox が機能要件に含まれている場合 Firefox の WebRTC 実装はかなり中途半端なため、 できるだけ Firefox は機能要件から外すことをお勧めします。 ## 認証を外部の指定した HTTP サーバーで判断したい場合 認証ウェブフック機能を利用してください。この機能は外部の指定した HTTP サーバーで認証を判断できるようになります。 外部の HTTP サーバーの URL 指定は `sora.conf` の [auth_webhook_url](SORA_CONF.html#36a99a) に設定してください。 そうすることで、外部に認証を移譲できます。 詳細は [認証ウェブフック](AUTH_WEBHOOK.html) をご確認ください。 ## 接続、切断の検知を外部の指定した HTTP サーバーで利用したい場合 イベントウェブフック機能を利用してください。この機能は外部の指定した HTTP サーバーでクライアント単位での接続、切断を検知できるようになります。 外部の HTTP サーバーの URL 指定は `sora.conf` の [event_webhook_url](SORA_CONF.html#e1a4d2) に設定してください。 そうすることで、外部にイベントをリクエスト送信できます。 詳細は [イベントウェブフック](EVENT_WEBHOOK.html) をご確認ください。 ## 配信されている音声や映像を記録したい場合 Sora には録画機能があります。もし利用を検討されている場合はいくつか注意事項があります。 - 録画を終了させる、またはクライアントが切断するまで、録画ファイルは生成されない - 複数人数が参加する会議の録画ファイルはクライアントごとに生成される- 5 人が会議に参加していれば 5 個ファイルが生成されます これらを踏まえて録画機能の利用を検討してください。 録画機能の詳細は [録画機能](RECORDING.html) をご確認ください。 ## クライアント側で参加してきたユーザーの情報を通知したい場合 Sora では「〜さんが会議に参加しました」や「〜さんが会議から退席しました」というメッセージをクライアント側で流すことができます。 これにはシグナリング通知を利用します。 シグナリング通知機能はシグナリングで利用している WebSocket もしくは DataChannel を経由して、 参加しているチャネルに新しく参加、または退席した状態を通知する機能です。自分が参加したときも自身に参加通知は飛びます。 ただシグナリング通知に含まれる標準の情報はあくまでコネクション ID のみになるため、 そのコネクション ID が誰なのかはどこからか取得する必要があります。 そのコネクション ID が誰なのかを問い合わせる処理が毎回走ってしまうのは無駄なため、 認証ウェブフックの戻り値で、 `signaling_notify_metadata` (シグナリング通知メタデータ)にそのコネクション ID の値のユーザー名を含めてください。 そうすることで、Sora がその参加者のユーザー名を `signaling_notify_metadata` に含めて返すようになります。 この `signaling_notify_metadata` は新しく参加した人には `data` として、 既存の参加している人の `signaling_notify_metadata` が含まれたリストが参加時に通知されるようになっています。 さらに、新しく参加者がいた場合はその参加者の `metadata` が通知されます。もちろん退席者の場合でもその退席者の `metadata` が含まれて通知されます。 `metadata` にユーザー名が含まれるため、サーバーへ問い合わせをしなくても参加者や退席者のユーザー名を取得できます。 シグナリング通知の詳細は [シグナリング通知](SIGNALING_NOTIFY.html) をご確認ください。 シグナリング通知メタデータの詳細は [シグナリング通知メタデータ](SIGNALING_NOTIFY_METADATA.html) をご確認ください。 # ライセンス Sora はライセンスファイルを読み込ませることで起動します。 ## ライセンスファイルのパス設定と配置 ライセンスファイルのパスは `sora.conf` の [license_file](SORA_CONF.html#77d4d5) で設定できます。 Sora を起動する前に設定し、ライセンスファイルを配置してください。 デフォルト設定のまま使う場合は、ライセンスファイルを sora ディレクトリ以下の etc/license.json にコピーしてください。 ```console $ cp 123ABC-SRA-E001-202301-100.json sora/etc/license.json ``` ## ライセンスの更新 ライセンスを更新する場合は `sora.conf` の [license_file](SORA_CONF.html#77d4d5) で指定しているファイルを cp コマンドで上書きしてください。 デフォルト設定では sora ディレクトリ以下にある `etc/license.json` です。 ```console $ cp 123ABC-SRA-E002-201901-100.json sora/etc/license.json ``` その後、ライセンス更新 API である [UpdateLicense](API_LICENSE.html#9e2217) API を実行することで更新されます。 Sora の再起動は不要です。 192.0.2.1 の部分には実際に利用している IP アドレスかドメインを指定してください ```console $ curl -sS \ -X POST \ http://192.0.2.1:3000/ \ -H "x-sora-target: Sora_20171218.UpdateLicense" \ | jq . ``` 正常に反映されているかを [GetLicense](API_LICENSE.html#be3ee8) API を実行して `serial_code` を確認してください。 ```console $ curl -sS \ -X POST \ http://192.0.2.1:3000/ \ -H "x-sora-target: Sora_20171218.GetLicense" \ | jq . ``` ### ライセンスの更新に失敗した場合 もし、誤って壊れているライセンスファイル等を使用して更新に失敗しても、既存のライセンス情報は上書きされません。 ### ライセンスの更新時のライセンス適用について ライセンスが更新される際に新しい接続が発生したとしても、 更新前または更新後のいずれかのライセンスが適用され、最大同時接続数の確認が行われます。 ライセンスの状態が一時的に空白になることはありません。 ## 同時接続数制限を超えて接続しようとした場合 > **重要** > > 最大同時接続数を超過したとしても既に接続しているクライアントには影響がありません。 ライセンスファイルには最大同時接続数が定義してあり、その最大同時接続数を超えて接続することはできません。 ### sora.jsonl への出力 既存の接続は継続されますが、新規接続ができなくなります。 `sora.jsonl` に `EXCEED-MAX-CONNECTIONS` というエラーログが出力します。 ### クライアントへの通知 最大同時接続数を超えて接続ができなかったクライアントには、 `SERVICE-UNAVAILABLE` というエラーメッセージが通知されます。 ### 同時接続数が +1 されるタイミング 認証が成功し、セッションへ参加し、その後 WebRTC での接続が確立したタイミングで初めて同時接続数が +1 されます。 認証が成功しただけでは同時接続数は増えません。 ### 同時接続数が -1 されるタイミング コネクションが切断したタイミングで同時接続数から -1 カウントします。 ### エラーメッセージを通知するタイミング シグナリング開始で WebSocket で `"type": "connect"` 送信後に、 最大同時接続数を超えた場合にエラーメッセージが通知され、シグナリングの WebSocket が切断されます。 ## ライセンス期限が過ぎている場合 > **重要** > > ライセンスの期限が過ぎていても Sora を起動することはできます。 ### sora.jsonl への出力 既存の接続は継続されますが、新規接続ができなくなります。 `sora.jsonl` に `EXPIRED-LICENSE` というエラーログが出力します。 ### ライセンスの期限時刻 ライセンスの期限が `2022-01` の場合は UTC で 2022 年 2 月 1 日の 0 時から新規接続ができなくなります。 ### クライアントへ通知するエラーメッセージについて ライセンス期限が過ぎているため接続ができなかったクライアントには、 `SERVICE-UNAVAILABLE` というエラメッセージが通知されます。 ## ライセンスファイルのパスの更新 ライセンスファイルのパスの更新は、一度 Sora を停止し、 `sora.conf` の [license_file](SORA_CONF.html#77d4d5) のパスを変更して Sora を起動する必要があります。 ## 最大ノード数ライセンス 2022 年 6 月から `最大ノード数ライセンス` という形式のライセンスを提供しています。 通常の Sora のライセンスは Sora 1 起動 1 ライセンスと固定されており、 同一のライセンスを複数の Sora で利用することはできません。 `最大ノード数ライセンス` は、クラスター構築時に、あらかじめライセンスに定義されている最大ノード数までは同一のライセンスを利用できます。 > **危険** > > 最大ノード数に対応していないライセンスで複数の Sora を起動することはできません。 最大ノード数に対応したライセンスファイルの中身の例 ```javascript { "expired_at": "2013-03", "max_connections": 100, "max_nodes": 3, "product_name": "Sora", "serial_code": "DOC123-SRA-E002-201303-N3-100", "signature": "****", "type": "Experimental" } ``` ファイルの中身に `"max_nodes": 3` と書かれているライセンスでは、クラスターを組む際に最大 3 ノードまで同一のライセンスが利用できます。 > **注釈** > > max_nodes 1 につき 1 ライセンス分の料金が必要になります。例えば max_nodes が 3 の場合は 3 ライセンス分の料金となります。 > **危険** > > 最大ノード数に対応しているライセンスを利用した場合に構築できるクラスターは 1 つのみです。複数のクラスターを構築することはできません。 `最大ノード数ライセンス` について不明な部分がある場合はサポートにお問い合わせください。 ### 最大ノード数ライセンスの非クラスター利用について > **注意** > > 契約済みの最大ノード数ライセンスを非クラスターで利用したい場合はサポートまでご連絡ください。 最大ノード数ライセンスはクラスターを利用しない場合は通常のライセンスと同じように利用できます。 ただし、 その場合は 1 ライセンスとして扱うため、1 ノードでしか利用できません。 もし `"max_nodes": 3` と記載されていても、クラスターを利用しない場合は 1 ノードでしか利用できません。 ### 最大ノード数ライセンスへの切り替えについて 通常のライセンスから最大ノード数ライセンスへの切り替えができます。詳細はサポートまでご連絡ください。 ### 最大ノード数ライセンスと通常ライセンスの混在について 最大ノード数ライセンスと通常ライセンスを混在して利用することはできません。 ### 最大ノード数ライセンスでのみ利用できる機能 - [クラスターリレー機能](CLUSTER.html#4b3bf1) - [クラスターリレー利用時のアフィニティ機能](CLUSTER.html#6f4bfb) - [クラスター利用時のテンポラリーノード機能](CLUSTER.html#3cb6c8) - [クラスター利用時のライセンスで決められた最大同時接続数の合計を維持する機能](CLUSTER.html#7bc873) ### 最大ノード数ライセンス利用時のノード数超過について #### InitCluster API で新規に登録する場合のノード数超過 [InitCluster](API_CLUSTER.html#621990) API で新規に登録する場合、 `node_name_list` に指定したノード数が `"max_nodes"` で指定された最大ノード数を超える場合、 `EXCEED-MAX-NODES` というエラーメッセージが通知され、クラスターの初期化に失敗します。 #### RegisterClusterNode API で新規に登録する場合のノード数超過 [RegisterClusterNode](API_CLUSTER.html#09ed96) API で新規に登録する場合、 既にクラスターが最大ノード数ライセンスの `"max_nodes"` で指定された最大ノード数に達している場合、 `EXCEED-MAX-NODES` というエラーメッセージが通知され、ノードの登録に失敗します。 ## ライセンスエラー時の動作確認用ライセンスの提供について ライセンス期限が過ぎたり、最大同時接続数を超過した際の動作確認を行うためのライセンスを提供しています。 動作確認用ライセンスが必要なお客様はサポートまでご連絡ください。 ライセンスエラー時の動作確認用ライセンスはクラスターでも確認できるよう、最大ノード数ライセンスでの提供となります。 最大ノード数ライセンスはクラスターを利用しない場合は通常のライセンスと同じように利用できます。 ### ライセンス期限が古く、最大同時接続数が 1 のライセンス ライセンス期限が過ぎたテストにご利用ください。 ### ライセンス期限が新しく、最大同時接続数が 0 のライセンス 同時接続数が超過したテストにご利用ください。 # sora.conf リファレンス Sora の設定ファイルは `key = value` 形式です。 文字列であっても `""` で囲わないでください。 ## 単位指定 `sora.conf` では一部の設定に単位の指定が必須です。 - 利用できる単位- ミリ秒 `ms` - 秒 `s` - 分 `min` - 時 `h` - 数値と単位の間にはスペースを入れてください ```ini webhook_response_timeout = 30 s ``` > **注釈** > > 利用できる単位が制限されている設定項目も存在します。 ## 範囲表記 - `2..10` と書いてある場合 2 以上、10 以下の値を指定できることを表しています - `2..10 s` と書いてある場合は 2 秒以上、10 秒以下の値を指定できることを表しています ## 環境変数による設定上書き機能 *バージョン 2025.2.0 で追加。* Sora の設定ファイル `sora.conf` の設定は環境変数で上書きすることができます。 `SORA_` に続けて設定項目名を大文字にし、アンダースコア `_` に置き換えた名前を環境変数として指定することで、設定を上書きできます。 例えば `sora.conf` の `api_port` を環境変数で上書きする場合は、以下のように指定します。 ```bash export SORA_API_PORT=18000 ``` `connection_created_wait_timeout` のように値に単位が含まれる設定項目も同様に指定できます。 `sora.conf` と同様に値の後ろにスペースを入れて指定してください。 ```bash export SORA_CONNECTION_CREATED_WAIT_TIMEOUT="60 s" ``` ### 注意点 - Sora 起動後に環境変数を変更しても設定は反映されません - Sora 起動後に環境変数を削除しても設定は反映されません ## api_cors_origin **デフォルト**: 指定なし API の戻りのヘッダーに CORS (Cross-Origin Resource Sharing) を含める際のドメインを指定してください。 http から始めて、パスの / は含まないでください。 ```ini api_cors_origin = http://127.0.0.1:5000 ``` ## api_loopback_address_only **デフォルト**: false API へのアクセスをループバックアドレスからのみに制限します。できる限り有効にしてください。 ```ini api_loopback_address_only = true ``` ## api_port **デフォルト**: 3000 API に使用するポート番号を指定してください。 ```ini api_port = 3000 ``` ## archive_dir **デフォルト**: archive 録画ファイルが保存されるディレクトリを指定してください。できる限り **絶対パス** で指定してください。 ```ini archive_dir = /path/to/archive ``` > **注意** > > `archive_dir` と `archive_tmp_dir` は違うディレクトリを指定してください ## archive_tmp_dir **デフォルト**: tmp/archive 録画に使用する一時ファイルを保存するディレクトリを指定してください。できる限り **絶対パス** で指定してください。 > **重要** > > 録画が失敗した場合には、このディレクトリに保存されたファイルは自動的に削除されません。 > そのため録画失敗時には一時ファイルが残り続けます。 ```ini archive_tmp_dir = /path/to/tmp/archive ``` > **注意** > > `archive_dir` と `archive_tmp_dir` は違うディレクトリを指定してください ## audio_red > **注意** > > この設定を有効にする場合は事前にサポートまでご連絡ください **デフォルト**: false 音声冗長化を有効にするかどうかを指定してください。デフォルトでは無効になっています。 現時点では Chrome M95 以降で使用できます。非対応ブラウザが混在していても利用できます。 ```ini audio_red = true ``` ## audio_streaming_header **デフォルト**: false 音声ストリーミングヘッダーを有効にするかどうかを指定してください。 ```ini audio_streaming_header = true ``` ## audio_streaming_max_retries **デフォルト**: 0 音声ストリーミングゲートウェイへの接続が失敗した場合の最大リトライ回数を指定してください。 リトライが発生するのは、 この値と [audio_streaming_retry_interval](SORA_CONF.html#15f73d) が `0` 以外が指定されており、 音声ストリーミングゲートウェイへの接続確立が失敗、または音声ストリーミングゲートウェイが 5xx 系でエラーを返した場合です。 ```ini audio_streaming_max_retries = 3 ``` ## audio_streaming_retry_interval **デフォルト**: 5 s 音声ストリーミングゲートウェイへの接続が失敗した場合のリトライ間隔を指定してください。 ```ini audio_streaming_retry_interval = 10 s ``` ## audio_streaming_tls_fullchain_file > **注意** > > この設定を利用する場合は事前にサポートまでご連絡ください **デフォルト**: 指定なし 音声ストリーミングゲートウェイとの通信に HTTPS で mTLS を利用するための設定で、 中間証明書を含むクライアント証明書を PEM 形式で設定してください。 ```ini audio_streaming_tls_fullchain_file = /path/to/fullchain.pem ``` ## audio_streaming_tls_privkey_file > **注意** > > この設定を利用する場合は事前にサポートまでご連絡ください **デフォルト**: 指定なし 音声ストリーミングゲートウェイとの通信に HTTPS で mTLS を利用するための設定で、 クライアント証明書の秘密鍵を PEM 形式で設定してください。 > **重要** > > 秘密鍵にはパスフレーズが設定されている場合エラーとなります ```ini audio_streaming_tls_privkey_file = /path/to/privkey.pem ``` ## audio_streaming_tls_verify_cacert_file > **注意** > > この設定を利用する場合は事前にサポートまでご連絡ください **デフォルト**: 指定なし 音声ストリーミングゲートウェイとの通信に HTTPS を利用した際、サーバー証明書のチェックを行う CA ファイルを PEM 形式で設定してください。 ```ini audio_streaming_tls_verify_cacert_file = /path/to/server_cacert.pem ``` > **重要** > > この設定がない場合、 OS 組み込みのルート CA 証明書を利用してサーバー証明書をチェックします。 > OS 組み込みのルート CA 証明書については [ウェブフックリクエストなどの送信先サーバー証明書の検証に利用する OS 組み込みのルート CA 証明書について](WEBHOOK.html#e8a845) をご確認ください。 ## audio_streaming_url **デフォルト**: 指定なし 音声ストリーミングゲートウェイの URL を指定してください。 http を指定した場合は HTTP/2 (h2c) で送られます。 https の場合は HTTP/2 (h2) で送られます。 音声ストリーミングゲートウェイは HTTP/2 に対応している必要があります。 ```ini audio_streaming_url = http://192.0.2.10:48080/speech ``` ```ini audio_streaming_url = https://suzu.example.com/speech ``` ## auth_webhook_log **デフォルト**: true 認証ウェブフックをすべてログファイルに出力します。詳細は [認証ウェブフックログ](AUTH_WEBHOOK.html#d4693f) をご確認ください。 ```ini auth_webhook_log = true ``` ## auth_webhook_recording **デフォルト**: false 認証ウェブフックの戻り値で録画を開始できるかどうかを指定してください。 ```ini auth_webhook_recording = true ``` ## auth_webhook_url **デフォルト**: 指定なし 認証機能を有効にしたときに、問い合わせに行く HTTP URL を指定してください。その戻り値に含まれる値によって認証の可否を判定します。 ```ini auth_webhook_url = https://example.com/sora/webhook/auth ``` ## cluster **デフォルト**: false クラスター機能を利用するかどうかを指定してください。 ```ini cluster = true ``` ## cluster_affinity_threshold > **注意** > > この設定を利用する場合は事前にサポートまでご連絡ください **デフォルト**: 10 **範囲**: 1..10000 クラスターのリレー機能とアフィニティ機能が有効な場合、 別ノードにセッションを作成するノード単位の同一セッションに対する同時接続数の基準値を指定してください。 ```ini cluster_affinity_threshold = 50 ``` ## cluster_listen_max_port > **注意** > > この設定を利用する場合は事前にサポートまでご連絡ください **デフォルト**: 49020 `sora.conf` にクラスター利用時のノード間通信に使用するポート番号範囲の最大値を指定してください。 ```ini cluster_listen_max_port = 49020 ``` ## cluster_listen_min_port > **注意** > > この設定を利用する場合は事前にサポートまでご連絡ください **デフォルト**: 49010 `sora.conf` にクラスター利用時のノード間通信に使用するポート番号範囲の最小値を指定してください。 ```ini cluster_listen_min_port = 49010 ``` ## cluster_relay > **注意** > > この機能を利用するには [最大ノード数ライセンス](LICENSE.html#aee259) が必要です。 **デフォルト**: true クラスターリレー機能を利用するかどうかを指定してください。 ```ini cluster_relay = true ``` ## cluster_temporary_node **デフォルト**: false テンポラリーノードとして利用するかどうかを指定してください。 ```ini cluster_temporary_node = true ``` ## connection_created_wait_timeout **単位指定必須** **デフォルト**: 30 s **範囲**: 0..600 s WebRTC SFU と WebRTC の接続が確立するまでの許容時間を指定してください。 基本的に WebRTC SFU との接続確立は数百ミリ秒で終わります。 ただし iOS などでカメラの使用などを許可するといった設定が入る場合を考慮しデフォルトは 30 秒としています。 ```ini connection_created_wait_timeout = 30 s ``` > **注釈** > > 値を 0 s にすることで、意図的に connection_created_wait_timeout のエラーを発生させることができます。 ## connection_updated_webhook_interval **デフォルト**: 1 min **範囲**: 1..10 min **単位**: min のみ 接続更新時のイベントウェブフック `connection.updated` の間隔を指定してください。 時間単位には 分 `min` のみ指定できます。 ```ini connection_updated_webhook_interval = 1 min ``` ## copy_websocket_signaling_header_names **デフォルト**: 未指定 ウェブフックやログにコピーしたい WebSocket シグナリングの HTTP ヘッダー名を指定してください。 ヘッダー名は複数指定することができます。ヘッダー名はカンマ区切りで指定してください。 ウェブフックの場合は **HTTP ヘッダー** にコピーされます。ログの場合は **copy_headers** 項目にコピーされます。 ```ini copy_websocket_signaling_header_names = X-Forwarded-For, X-Real-IP, Tracestate ``` ### ヘッダーがコピーされるウェブフック - 認証ウェブフック ### copy_headers が出力されるログ - `auth_webhook.jsonl` - `auth_webhook_error.jsonl` - `rtc_stats.jsonl` - `connection.jsonl` ## data_channel_messaging **デフォルト**: false DataChannel を使用したメッセージング機能を利用するかどうかを指定してください。 ```ini data_channel_messaging = false ``` ## data_channel_messaging_only **デフォルト**: false DataChannel メッセージングの利用時に、音声と映像を `false` にした場合でも接続できるようにするかどうかを指定してください。 ```ini data_channel_messaging_only = false ``` ## data_channel_packet_loss_simulator_incoming > **危険** > > この機能はあくまで検証時のみ有効にしてください **デフォルト**: 0 **範囲**: 0..100 Sora が受信する DataChannel パケットを指定したパーセント分ドロップさせます。 値を 0 より大きくした場合、クライアントが接続するたびに warning が発生します。 ### Sora が受信する DataChannel パケットを 10 % パケロスさせる場合 ```ini data_channel_packet_loss_simulator_incoming = 10 ``` ## data_channel_packet_loss_simulator_outgoing > **危険** > > この機能はあくまで検証時のみ有効にしてください **デフォルト**: 0 **範囲**: 0..100 Sora が送信する DataChannel パケットを指定したパーセント分ドロップさせます。 値を 0 より大きくした場合、クライアントが接続するたびに warning が発生します。 ### Sora が送信する DataChannel パケットを 10 % パケロスさせる場合 ```ini data_channel_packet_loss_simulator_outgoing = 10 ``` ## data_channel_rpc **デフォルト**: true DataChannel を使用した RPC 機能を利用するかどうかを指定してください。 この機能を利用する場合は必ず認証成功時に [rpc_methods の払い出し](AUTH_WEBHOOK_RETURN.html#a2e307) で利用できる RPC メソッド名一覧を払い出す必要があります。 ```ini data_channel_rpc = true ``` ## data_channel_signaling_close_message **デフォルト**: false Sora から DataChannel シグナリングを切断する際に `"type": "close"` メッセージを送信するかどうかを指定してください。 ```ini data_channel_signaling_close_message = true ``` ## data_channel_stats_max_retransmits > **注意** > > この設定を利用する場合は事前にサポートまでご連絡ください **デフォルト**: 指定なし **範囲**: 0..8 シグナリング経路を DataChannel に切り替えた際にクライアントが統計情報を送信するときのメッセージの再送回数を指定してください。 ```ini data_channel_stats_max_retransmits = 1 ``` ## data_channel_stats_timer_interval **単位指定必須** **デフォルト**: 60 s **範囲**: 5..600 s シグナリング経路を DataChannel に切り替えた際にクライアントへの統計情報を要求する間隔を指定してください。 ```ini data_channel_stats_timer_interval = 60 s ``` ## data_dir > **注意** > > この設定を利用する場合は事前にサポートまでご連絡ください **デフォルト**: data Sora 内部で利用する情報を書き出すディレクトリを指定してください。できる限り **絶対パス** で指定してください。 ```ini data_dir = /path/to/data ``` ## default_audio_bit_rate **設定しないことをおすすめします** **単位**: k(キロ)bps **範囲**: 6..510 **デフォルト**: 指定なし 音声が使用できるビットレートを指定してください。デフォルトの場合はクライアント側の挙動に依存します。 ```ini default_audio_bit_rate = 192 ``` ## default_audio_streaming_language_code **デフォルト**: 指定なし 音声ストリーミングゲートウェイ接続時に HTTP ヘッダー `sora-audio-streaming-language-code` にデフォルトで含める文字列を指定してください。 この設定がない場合、接続時に `audio_streaming_language_code` で文字列が指定されていない場合、 音声ストリーミングが有効になっても Sora は接続の音声ストリーミングを開始しません。 ```ini default_audio_streaming_language_code = ja-JP ``` ## default_audio_streaming_result_push **デフォルト**: true 音声ストリーミングゲートウェイからのレスポンスをシグナリングプッシュ通知で送ることをデフォルトで行うかを指定してください。 ```ini default_audio_streaming_result_push = true ``` ## default_av1_param_profile **デフォルト**: 0 **範囲**: 0..2 AV1 で利用するプロファイルのデフォルト値を指定してください。 ```ini default_av1_param_profile = 0 ``` ## default_cluster_affinity > **注意** > > この機能を利用するには [最大ノード数ライセンス](LICENSE.html#aee259) が必要です。 **デフォルト**: true クラスターリレー機能利用時にアフィニティ機能を利用するかどうかのデフォルト値を指定してください。 ```ini default_cluster_affinity = true ``` ## default_connection_lifetime **デフォルト**: 未指定 **範囲**: 0..720 h デフォルトのコネクションライフタイムを指定してください。デフォルトは未指定です。 ```ini default_connection_lifetime = 1 h ``` ## default_data_channel_signaling **デフォルト**: false シグナリング経路を WebSocket から DataChannel に切り替えるかどうかを指定してください。 ```ini default_data_channel_signaling = false ``` ## default_duplicate_client_id **デフォルト**: allow **範囲**: allow, evict クライアント ID の重複による既存コネクションを破棄するかどうかを指定してください。 ```ini default_duplicate_client_id = evict ``` ## default_forwarding_pli_interval > **注意** > > この設定を利用する場合は事前にサポートまでご連絡ください **単位指定必須** **デフォルト**: 10 s **範囲**: 1..90 s RTP 転送 API 利用時に、クライアントに対して PLI を送る間隔を指定してください。 ```ini default_forwarding_pli_interval = 10 s ``` 録画機能併用時には、 `20 s` より大きな値を指定したとしても、録画機能の PLI 送信間隔 `20 s` が適用されます。 もし `default_forwarding_pli_interval` に `20 s` より小さな値を指定した場合は、 PLI 送信間隔には `default_forwarding_pli_interval` の値が適用されます。 録画機能の利用を継続し、RTP 転送機能を停止したタイミングで、 録画機能の PLI 送信間隔 `20 s` が適用されます。 ## default_h264_param_profile_level_id **デフォルト**: 42e02a H.264 で利用するプロファイルレベル ID のデフォルト値を文字列で指定してください。 ```ini default_h264_param_profile_level_id = 42e02a ``` ## default_h265_param_level_id **デフォルト**: 93 **範囲**: 0..255 H.265 で利用するレベル ID のデフォルト値を数値で指定してください。 ```ini default_h265_param_level_id = 93 ``` ## default_ice_connection_state_disconnected_timeout > **注意** > > この設定を利用する場合は事前にサポートまでご連絡ください **デフォルト**: 5 s **範囲**: 1..300 s ICE コネクションステートが `checking` から `disconnected` の状態に移行するまでの時間を指定してください。 ```ini default_ice_connection_state_disconnected_timeout = 5 s ``` ## default_ice_connection_state_failed_timeout > **注意** > > この設定を利用する場合は事前にサポートまでご連絡ください **デフォルト**: 10 s **範囲**: 1..300 s ICE コネクションステートが `disconnected` から `failed` の状態に移行するまでの時間を指定してください。 ```ini default_ice_connection_state_failed_timeout = 10 s ``` ## default_ignore_disconnect_websocket **デフォルト**: false シグナリング経路を DataChannel に切り替えた際に WebSocket が切断されても接続の切断と判断しないかどうかを指定してください。 ```ini default_ignore_disconnect_websocket = false ``` ## default_playout_delay_max_delay **デフォルト**: 未指定 **単位**: ms のみ **範囲**: 0..40950 プレイアウト遅延機能を利用する際の最大値(ミリ秒)を指定してください。 ```ini default_playout_delay_min_delay = 0 ms default_playout_delay_max_delay = 100 ms ``` ## default_playout_delay_min_delay **デフォルト**: 未指定 **単位**: ms のみ **範囲**: 0..40950 プレイアウト遅延機能を利用する際の最小値(ミリ秒)を指定してください。 ```ini default_playout_delay_min_delay = 0 ms default_playout_delay_max_delay = 100 ms ``` ## default_recording_format > **重要** > > Sora 2025.2.0 から録画機能(セッション単位)のデフォルト出力フォーマットを `webm` から `mp4` に変更しました。 **デフォルト**: mp4 録画ファイルのデフォルトのフォーマットを指定してください。 `mp4` と `webm` が指定できます。 ```ini default_recording_format = mp4 ``` ## default_recording_mp4_pli_interval **デフォルト**: 20 s **範囲**: 1..240 s 録画機能(セッション単位) 利用時に MP4 形式を利用した場合、クライアントへ送るキーフレーム要求 (PLI) の間隔を指定してください。 ```ini default_recording_mp4_pli_interval = 100 s ``` ## default_rtc_stats **デフォルト**: true Sora から SDK やクライアントへ RTC 統計情報を要求するかどうかを指定してください。 SDK やクライアント側がシグナリングの `"type": "stats"` に対応している必要があります。 ```ini default_rtc_stats = true ``` ## default_sdp_setup_role_passive > **注意** > > この設定を利用する場合は事前にサポートまでご連絡ください。 **デフォルト**: false SDP の `setup` 属性のデフォルト値を `passive` にするかどうかを指定してください。 ```ini default_sdp_setup_role_passive = true ``` ## default_simulcast_auto_rids *バージョン Sora 2025.2.0 で追加。* **デフォルト**: 未指定 サイマルキャスト利用時に、視聴側の環境に合わせて rid を自動で切り替える場合に、利用する rid のリストを指定してください。 未指定の場合は自動で切り替わりません。 > **重要** > > `simulcast_rid_auto` が `true` の場合、 Sora 2025.2.0 ではまだ「視聴環境が悪化した場合に、ビットレートが低い映像に自動的に下げる」機能のみになります。「視聴環境が改善した場合にビットレートが高い映像に自動的に上げる」機能は 2026 年リース予定の Sora にて対応予定です。 ```ini default_simulcast_auto_rids = "r0", "r1" ``` ## default_simulcast_request_rid *バージョン Sora 2025.2.0 で追加。* **デフォルト**: r0 **範囲**: auto / r0 / r1 / r2 / none サイマルキャスト利用時に、視聴する rid を指定せずに接続した場合に採用される rid の値を指定してください。 デフォルトでは r0 になっています。 ```ini default_simulcast_request_rid = r2 ``` ## default_simulcast_rid > **警告** > > この設定では Sora 2025.2.0 に新しく追加された `auto` や `none` を指定することはできません。 > [default_simulcast_request_rid](SORA_CONF.html#9891c8) をご利用ください。 > **注意** > > この設定は 2027 年 12 月リリース予定の Sora にて廃止しします。 > 今後は [default_simulcast_request_rid](SORA_CONF.html#9891c8) をご利用ください。 **デフォルト**: r0 **範囲**: r0 / r1 / r2 サイマルキャスト利用時に、視聴する rid を指定せずに接続した場合に採用される rid の値を指定してください。 デフォルトでは r0 になっています。 ```ini default_simulcast_rid = r2 ``` ## default_spotlight_auto_unfocus **デフォルト**: true スポットライト機能利用時の自動アンフォーカスの有無を指定してください。 ```ini default_spotlight_auto_unfocus = true ``` ## default_spotlight_auto_unfocus_interval **デフォルト**: 10 s **範囲**: 1 ms .. 30 s スポットライト機能の自動アンフォーカスの時間間隔を指定してください。 ```ini default_spotlight_auto_unfocus_interval = 10 s ``` ## default_spotlight_delayed_focus **デフォルト**: true スポットライト機能利用時に、遅延フォーカスの有無を指定してください。 遅延フォーカスは音声が有効になってもすぐにフォーカスせず、一定時間音声が有効な際に初めてフォーカスする仕組みです。 ```ini default_spotlight_delayed_focus = true ``` ## default_spotlight_delayed_focus_interval **デフォルト**: 2000 ms **範囲**: 1..60000 ms スポットライト機能利用時に、遅延フォーカスが有効な際に、どの程度遅延をさせるか指定してください。 ```ini default_spotlight_delayed_focus_interval = 2000 ms ``` ## default_spotlight_focus_min_interval **デフォルト**: 2000 ms **範囲**: 0 ms .. 60 s スポットライト機能でフォーカスしてからアンフォーカスされるまでの最低時間間隔を指定してください。 ```ini default_spotlight_focus_min_interval = 2000 ms ``` ## default_spotlight_focus_rid **デフォルト**: r1 **指定できる rid**: none / r0 / r1 / r2 スポットライト機能利用時に、フォーカスした際に利用する rid を指定してください。 none は映像自体を配信しません。 ```ini default_spotlight_focus_rid = r1 ``` ## default_spotlight_number **デフォルト**: 1 **範囲**: 1..8 スポットライトで同時にフォーカスされるデフォルトの数を指定してください。 ```ini default_spotlight_number = 2 ``` ## default_spotlight_unfocus_audio **デフォルト**: true スポットライト機能利用時に、フォーカスなしでの音声配信を指定してください。 ```ini default_spotlight_unfocus_audio = false ``` ## default_spotlight_unfocus_audio_rate_limit **デフォルト**: 5 **範囲**: 0..20 スポットライト機能利用時に、フォーカスなしの音声転送の上限レートを指定してください。 単位は 1 音声ストリーム = 50 packets / s となります。 ```ini default_spotlight_unfocus_audio_rate_limit = 5 ``` ## default_spotlight_unfocus_rid **デフォルト**: r0 **範囲**: none, r0, r1, r2 スポットライト機能利用時に、フォーカスなしで利用する rid を指定してください。 none は映像自体を配信しません。 ```ini default_spotlight_unfocus_rid = none ``` ## default_video_bit_rate **デフォルト**: 500 **単位**: k(キロ)bps **範囲**: 1..50000 映像が使用できるビットレートを指定してください。デフォルトでは 500kbps です。この値を少なく指定すると解像度が不安定になります。 基本は 500 で余裕があるのであれば 800 などに設定することをお勧めします。 15000 より大きい値はまだ十分に検証ができていないため、現時点ではサポート外となります。ご了承ください。 ```ini default_video_bit_rate = 500 ``` ## default_vp9_param_profile_id **デフォルト**: 0 **範囲**: 0..3 VP9 で利用するプロファイル ID のデフォルト値を指定してください。 ```ini default_vp9_param_profile_id = 0 ``` ## event_webhook_connection_updated_log **デフォルト**: true `event_webhook.jsonl` に `connection.updated` を出力するかどうかを指定してください。デフォルトでは出力します。 ```ini event_webhook_connection_updated_log = false ``` ## event_webhook_url **デフォルト**: 指定なし クライアントの接続や切断、録画ファイル生成の終了などのイベントを通知する HTTP URL を指定してください。 ```ini event_webhook_url = https://example.com/sora/webhook/event ``` ## event_webhook_worker_key *バージョン 2025.1.0 で追加。* **デフォルト**: channel_id **範囲**: channel_id または connection_id イベントウェブフックのワーカー割り当てに利用する値を指定してください。 ```ini event_webhook_worker_key = connection_id ``` ## event_webhook_worker_number **デフォルト**: 100 **範囲**: 5..5000 イベントウェブフックのワーカー数を指定してください。 イベントウェブフックのワーカー割り当てに利用する値は [event_webhook_worker_key](SORA_CONF.html#d73d7a) で指定した値です。 ```ini event_webhook_worker_number = 100 ``` ## external_api_url **デフォルト**: 指定なし ノードに対する Sora API の URL を指定してください。クラスター機能のリダイレクト時に用います。 ```ini external_api_url = http://127.0.0.1:3000/ ``` ## external_signaling_url **デフォルト**: 指定なし ノードに対するシグナリング URL を指定してください。クラスター機能のリダイレクト時に用います。 ```ini external_signaling_url = ws://127.0.0.1:5000/signaling ``` ## forwarding_simulcast > **注意** > > この設定を利用する場合は事前にサポートまでご連絡ください **単位指定必須** **デフォルト**: single RTP 転送 API 利用時にサイマルキャストの転送オプションを指定してください。 - `single` は最も優先度の低いストリームのみを転送します - `all` はすべてのストリームを転送します ```ini forwarding_simulcast = all ``` ## generic_nack > **注意** > > この設定を無効にする場合は事前にサポートまでご連絡ください **デフォルト**: true Generic NACK を有効にするかどうかを指定してください。一つのチャネルに対して、 視聴者がかなり多い場合などはこの設定を無効にすることで、サーバー側の負荷を抑えることができるようになります。 ```ini generic_nack = true ``` ## h264_b_frame > **重要** > > 2026 年 6 月 時点で Sora SDK では B-frame を利用することはできません。 **デフォルト**: false H.264 で B-frame が利用できるようになります。 ```ini h264_b_frame = true ``` ## h265_b_frame > **重要** > > 2026 年 6 月 時点で Sora SDK では B-frame を利用することはできません。 **デフォルト**: false H.265 で B-frame が利用できるようになります。 ```ini h265_b_frame = true ``` ## hide_origin_username **デフォルト**: false 有効にした場合は SDP の Offer 時に送られる o= の username の部分を `shiguredo...SORA-` から `_` に変更します。 ```ini hide_origin_username = false ``` ## ignore_archive_available_webhook **デフォルト**: false 録画機能で、分割録画を含む場合に分割した録画ファイルが利用可能になった際、 イベントウェブフック `split-archive.available` リクエストを `event_webhook_url` に登録された URL に送信するかどうかを指定してください。 ```ini ignore_archive_available_webhook = true ``` ## ignore_archive_failed_webhook **デフォルト**: false 録画機能で、録画が失敗した場合に、 `event_webhook_url` に登録された URL に `archive.failed` リクエストを送るかどうかを指定してください。 ```ini ignore_archive_failed_webhook = true ``` ## ignore_archive_started_webhook **デフォルト**: false 録画機能で、コネクションのアーカイブを開始した場合に、 イベントウェブフック `event_webhook_url` に登録された URL に `archive.started` リクエストを送信するかどうかを指定してください。 デフォルトではリクエストの送信を行います。 この設定が `true` の場合でも、 `event_webhook.jsonl` には `archive.started` のログが出力されます。 ```ini ignore_archive_started_webhook = true ``` ## ignore_audio_streaming_failed_webhook **デフォルト**: true 音声ストリーミング機能利用時に、音声ストリーミング送り先から `"type": "error"` が送られてきたなどで、 正常に処理が行えなくなった場合に、 `event_webhook_url` に指定された URL に `audio_streaming.failed` リクエストを送るかどうかを指定してください。 この設定が `true` の場合でも、 `event_webhook.jsonl` には `audio_streaming.failed` のログが出力されます。 ```ini ignore_audio_streaming_failed_webhook = false ``` ## ignore_audio_streaming_webhook **デフォルト**: true 音声ストリーミング機能で音声が送信された場合に、 `session_webhook_url` に登録された URL に `audio_streaming.started` と `audio_streaming.stopped` リクエストを送るかどうかを指定してください。 デフォルトではリクエストの送信を行いません。 この設定が `true` の場合でも、 `session_webhook.jsonl` には `audio_streaming.started` と `audio_streaming.stopped` のログが出力されます。 ```ini ignore_audio_streaming_webhook = false ``` ## ignore_connection_failed_webhook **デフォルト**: true 接続が失敗時に `event_webhook_url` に指定された URL へ `connection.failed` リクエストを送るかどうかを指定してください。 デフォルトではリクエストの送信を行いません。 この設定が `true` の場合でも、 `event_webhook.jsonl` には `connection.failed` のログが出力されます。 ```ini ignore_connection_failed_webhook = false ``` ## ignore_connection_rtc_webhook **デフォルト**: false クライアントから RTC 統計情報が送られてきた際、 統計ウェブフック `connection.rtc` リクエストを `stats_webhook_url` に登録された URL に送信するかどうか指定してください。 デフォルトではリクエストの送信を行います。 ログの出力は [stats_webhook_url](SORA_CONF.html#1f750f) をご確認ください。 ```ini ignore_connection_rtc_webhook = true ``` ## ignore_connection_updated_webhook **デフォルト**: false イベントウェブフックの接続の更新時に `event_webhook_url` に指定された URL へ `connection.updated` を送るかどうかを指定してください。 デフォルトではリクエストの送信を行います。 この設定が `true` の場合でも、 `event_webhook.jsonl` には `connection.updated` のログが出力されます。 ```ini ignore_connection_updated_webhook = false ``` ## ignore_recording_report_webhook **デフォルト**: false 録画レポートが送信された場合に、 `event_webhook_url` に登録された URL に `recording.report` リクエストを送るかどうかを指定してください。 ```ini ignore_recording_report_webhook = true ``` ## ignore_recording_started_webhook **デフォルト**: false 録画機能で、録画を開始した場合に、 `event_webhook_url` または `session_webhook_url` に登録された URL に `recording.started` リクエストを送るかどうかを指定してください。 デフォルトではリクエストの送信を行います。 この設定が `true` の場合でも、 `event_webhook.jsonl` または `session_webhook.jsonl` には `recording.started` のログが出力されます。 ```ini ignore_recording_started_webhook = true ``` ## ignore_session_destroyed_webhook **デフォルト**: false セッションが破棄された場合に、 `session_webhook_url` に登録された URL に `session.destroyed` リクエストを送るかどうかを指定してください。 ```ini ignore_session_destroyed_webhook = true ``` ## ignore_session_updated_webhook **デフォルト**: false セッションウェブフックのセッションの更新時に `session_webhook_url` に指定された URL へ `session.updated` を送るかどうかを指定してください。 デフォルトではリクエストの送信を行います。 この設定が `true` の場合でも、 `session_webhook.jsonl` には `session.updated` のログが出力されます。 ```ini ignore_session_updated_webhook = false ``` ## ignore_split_archive_available_webhook **デフォルト**: false 録画機能で、分割録画を含む場合に分割した録画ファイルが利用可能になった際、 イベントウェブフック `split-archive.available` リクエストを送信するかどうかを指定してください。 デフォルトではリクエストの送信を行います。 この設定が `true` の場合でも、 `event_webhook.jsonl` には `split-archive.available` のログが出力されます。 ```ini ignore_split_archive_available_webhook = true ``` ## ignore_split_archive_end_webhook **デフォルト**: false 録画機能で、分割録画を含む場合に分割した録画ファイルが利用可能になった際、 イベントウェブフック `split-archive.available` リクエストを `event_webhook_url` に登録された URL に送信するかどうかを指定してください。 ```ini ignore_split_archive_end_webhook = true ``` ## ignore_spotlight_changed_webhook **デフォルト**: true スポットライト機能で発言者が切り替わった場合に、 `event_webhook_url` に登録された URL に `spotlight.focused` と `spotlight.unfocused` リクエストを送るかどうかを指定してください。 デフォルトではリクエストの送信を行いません。 この設定が `true` の場合でも、 `event_webhook.jsonl` には `spotlight.focused` と `spotlight.unfocused` のログが **出力されません** 。 ```ini ignore_spotlight_changed_webhook = true ``` ## ignore_turn_five_tuple > **注意** > > この設定を利用する場合は事前にサポートまでご連絡ください **デフォルト**: false TURN 利用時に送られてくるパケットの 5-TUPLE を無視するかどうかを指定してください。 ```ini ignore_turn_five_tuple = true ``` ## ipv4_address **デフォルト**: 未指定 この値を有効にしなくても自動で IPv4 アドレスを収集しますが、 固定された IPv4 アドレスがサーバーに割り当てられている場合は指定することを推奨しています。 IPv4 アドレスを指定してください。 `192.0.2.10` のように指定してください。 ```ini ipv4_address = 192.0.2.10 ``` ## ipv6 **デフォルト**: false IPv6 機能を有効にするかどうか指定してください。デフォルトでは無効になっています。 この機能を有効にすると以下の機能が有効になります - ipv6_address が指定されていない場合は自動で IPv6 アドレスが収集される - ipv6_address で指定された値が使用される - IPv6 アドレスが使用できる場合、 TURN サーバーの URL が IPv6 でも払い出される この機能はシグナリングや API を IPv6 有効にする機能ではありません。シグナリングや API は IPv6 非対応です。 ```ini ipv6 = false ``` ## ipv6_address **デフォルト**: 未指定 この値を有効にしなくても ipv6 が true の場合は、自動で IPv6 アドレスを収集しますが、 固定された IPv6 アドレスがサーバーに割り当てられている場合は指定することを推奨しています。 IPv6 アドレスを指定してください。 `2001:0DB8::10` のように指定してください。 ```ini ipv6_address = 2001:0DB8::10 ``` ## ipv6_only **デフォルト**: false IPv6 アドレスのみを利用するようになります。この設定はシグナリングや API には影響しません。 ```ini ipv6_only = true ``` ## label **デフォルト**: "WebRTC SFU Sora" 認証やイベントウェブフックリクエスト送信時に送られる、サーバー固有の値を指定してください。 ```ini label = sora-node-001.example.com ``` ## legacy_cluster_relay > **注意** > > この設定を利用する場合は事前にサポートまでご連絡ください。 **デフォルト**: false クラスタリングリレー機能のレガシーモードを有効にするかどうかを指定してください。 ```ini legacy_cluster_relay = true ``` ## license_file **デフォルト**: "etc/license.json" ライセンスファイルのパスを指定してください。できる限り **絶対パス** を指定してください。 ```ini license_file = etc/license.json ``` ## log_dir **デフォルト**: log ログファイルの出力先ディレクトリを指定してください。デフォルトではパッケージディレクトリ以下の `log` ディレクトリに出力されます。 - 相対パスで指定した場合は Sora のパッケージディレクトリ (`sora-/`) からの相対パスになります - 絶対パスで指定した場合は指定したパスになります ```ini log_dir = /var/log/sora ``` ## max_connections **デフォルト**: ライセンスで許可された最大同時接続数 この Sora で許可する最大同時接続数を指定してください。 ```ini max_connections = 50 ``` ## media_publish_worker_autoscale_threshold *バージョン 2025.1.0 で追加。* **デフォルト**: 50 **範囲**: 1..1000 音声や映像の 1 配信ワーカーが担当する視聴者数を指定してください。ただし、デフォルトで十分なことがほとんどです。 ```ini media_publish_worker_autoscale_threshold = 20 ``` ## multistream_auto_sharing_video_bit_rate **デフォルト**: false マルチストリームで配信者が利用する映像ビットレートを自動で共有する機能です。 映像のビットレートに 1000kbps を指定した場合 4 人の配信者がいる場合はそれぞれの配信者のビットレートは 250kbps になります。 ```ini multistream_auto_sharing_video_bit_rate = true ``` ## node_name **デフォルト**: 指定なし クラスター機能で利用するノード名を指定してください。 ノード名の @ の前には、正規表現 `[0-9A-Za-z_\\-]+` にマッチする文字列を指定してください。 また @ の後ろには、サーバーのドメイン名(FQDN)や、IP アドレスを指定してください。 ```ini node_name = sora@192.0.2.10 ``` ## opus_param_channels > **注意** > > この設定を利用する場合は事前にサポートまでご連絡ください **デフォルト**: 2 **範囲**: 1..8 ## opus_param_maxplaybackrate > **注意** > > この設定を利用する場合は事前にサポートまでご連絡ください **デフォルト**: 48000 **範囲**: 8000..48000 ## opus_param_minptime > **注意** > > この設定を利用する場合は事前にサポートまでご連絡ください **デフォルト**: 10 **範囲**: 3..120 ## opus_param_ptime > **注意** > > この設定を利用する場合は事前にサポートまでご連絡ください **デフォルト**: 20 **範囲**: 3..120 ## opus_param_sprop_stereo > **注意** > > この設定を利用する場合は事前にサポートまでご連絡ください **デフォルト**: true ## opus_param_stereo > **注意** > > この設定を利用する場合は事前にサポートまでご連絡ください **デフォルト**: true ## opus_param_usedtx > **注意** > > この設定を利用する場合は事前にサポートまでご連絡ください **デフォルト**: false ## opus_param_useinbandfec > **注意** > > この設定を利用する場合は事前にサポートまでご連絡ください **デフォルト**: true ## recording_dual_output **デフォルト**: true 録画で一括&分割録画を利用できるようにするかどうかを指定してください。 > **重要** > > この設定が false になっている際に一括&分割録画をしようとするとエラーになります ```ini recording_dual_output = false ``` ## recording_expire_time_required **デフォルト**: false > **重要** > > この設定は一括録画時に録画ファイルが大きくなりすぎるのを防ぐための設定です。 録画で一括または一括&分割録画時に `expire_time` の指定を必須にするかどうかを指定してください。 ```ini recording_expire_time_required = true ``` ## recording_max_expire_time **デフォルト**: 86400 s **範囲**: 1..86400 s 録画時に指定する `expire_time` の最大値を指定してください。 ```ini recording_max_expire_time = 10 min ``` ## recording_max_split_duration **デフォルト**: 86400 s **範囲**: 1..86400 s 録画で分割または一括&分割録画時に `split_duration` の最大値を指定してください。 ```ini recording_max_split_duration = 10 min ``` ## recycle_media_section **デフォルト**: true SDP でアクティブではなくなったメディアセクション (m=) を再利用する機能を有効化するかどうかを指定してください。 ```ini recycle_media_section = false ``` ## rtc_stats_log **デフォルト**: false SDK やクライアントから送られてきた RTC 統計情報をログとして保存するかどうかを指定してください。 デフォルトではログは保存されません。 > **警告** > > ログはかなりの量になるため、利用する際は注意してください ```ini rtc_stats_log = true ``` ## rtp_hdrext_abs_capture_time **デフォルト**: false RTP ヘッダー拡張 [http://www.webrtc.org/experiments/rtp-hdrext/abs-capture-time](https://webrtc.googlesource.com/src/+/refs/heads/main/docs/native-code/rtp-hdrext/abs-capture-time) を利用するかどうかを指定してください。 ```ini rtp_hdrext_abs_capture_time = true ``` ## rtp_hdrext_color_space > **注意** > > この設定を利用する場合は事前にサポートまでご連絡ください **デフォルト**: false RTP ヘッダー拡張 [http://www.webrtc.org/experiments/rtp-hdrext/color-space](https://webrtc.googlesource.com/src/+/refs/heads/main/docs/native-code/rtp-hdrext/color-space) を利用するかどうかを指定してください。 ```ini rtp_hdrext_color_space = true ``` ## rtp_hdrext_dependency_descriptor_vp9 > **警告** > > この設定を `true` にした場合、 Firefox で VP9 が利用できなくなります。 **デフォルト**: false RTP ヘッダー拡張 [https://aomediacodec.github.io/av1-rtp-spec/#dependency-descriptor-rtp-header-extension](https://aomediacodec.github.io/av1-rtp-spec/#dependency-descriptor-rtp-header-extension) を VP9 で利用するかどうかを指定してください。 ```ini rtp_hdrext_dependency_descriptor_vp9 = true ``` ## rtp_hdrext_playout_delay **デフォルト**: true RTP ヘッダー拡張 [http://www.webrtc.org/experiments/rtp-hdrext/playout-delay](https://webrtc.googlesource.com/src/+/refs/heads/main/docs/native-code/rtp-hdrext/playout-delay) を利用するかどうかを指定してください。 ```ini rtp_hdrext_playout_delay = false ``` ## rtp_hdrext_sdes_mid > **注意** > > この設定を利用する場合は事前にサポートまでご連絡ください **デフォルト**: false RTP ヘッダー拡張 [urn:ietf:params:rtp-hdrext:sdes:mid](https://www.rfc-editor.org/rfc/rfc9143.html) を利用するかどうかを指定してください。 ```ini rtp_hdrext_sdes_mid = true ``` ## rtp_hdrext_video_content_type > **注意** > > この設定を利用する場合は事前にサポートまでご連絡ください **デフォルト**: false RTP ヘッダー拡張 [http://www.webrtc.org/experiments/rtp-hdrext/video-content-type](https://webrtc.googlesource.com/src/+/refs/heads/main/docs/native-code/rtp-hdrext/video-content-type) を利用するかどうかを指定してください。 ```ini rtp_hdrext_video_content_type = true ``` ## rtp_hdrext_video_orientation > **注意** > > この設定を利用する場合は事前にサポートまでご連絡ください **デフォルト**: false RTP ヘッダー拡張 `urn:3gpp:video-orientation` を利用するかどうかを指定してください。 ```ini rtp_hdrext_video_orientation = true ``` ## rtp_hdrext_video_timing > **注意** > > この設定を利用する場合は事前にサポートまでご連絡ください **デフォルト**: false RTP ヘッダー拡張 [http://www.webrtc.org/experiments/rtp-hdrext/video-timing](https://webrtc.googlesource.com/src/+/refs/heads/main/docs/native-code/rtp-hdrext/video-timing) を利用するかどうかを指定してください。 ```ini rtp_hdrext_video_timing = true ``` ## rtp_packet_loss_simulator_incoming > **危険** > > この機能はあくまで検証時のみ有効にしてください **デフォルト**: 0 **範囲**: 0..100 Sora が受信する RTP パケットを指定したパーセント分ドロップさせます。 値を 0 より大きくした場合、クライアントが接続するたびに warning が発生します。 ### Sora が受信する RTP パケットを 10 % パケロスさせる場合 ```ini rtp_packet_loss_simulator_incoming = 10 ``` ## rtp_packet_loss_simulator_outgoing > **危険** > > この機能はあくまで検証時のみ有効にしてください **デフォルト**: 0 **範囲**: 0..100 Sora が送信する RTP パケットを指定したパーセント分ドロップさせます。 値を 0 より大きくした場合、クライアントが接続するたびに warning が発生します。 ### Sora が送信する RTP パケットを 10 % パケロスさせる場合 ```ini rtp_packet_loss_simulator_outgoing = 10 ``` ## rtx > **注意** > > この設定を無効にする場合は事前にサポートまでご連絡ください **デフォルト**: true RTX を有効にするかどうかを指定してください。デフォルトでは true で有効になっています。 現時点では Chrome / Safari / Edge / Firefox が使用できます。 iOS / Android / Unity は libwebrtc の最新版を利用している場合は対応しています。 ```ini rtx = false ``` ## session_created_response_validate_warning_as_error > **注意** > > この設定を利用する場合は事前にサポートまでご連絡ください **デフォルト**: false セッションウェブフック [session.created](SESSION_WEBHOOK.html#1d1984) の戻り値が正常でない場合にエラーとし、セッションを破棄するかどうかを指定してください。 > **注釈** > > この設定が false の場合、戻り値が正常でない場合は sora ログに警告が出力され、デフォルトの戻り値が設定されます。 > セッションも破棄されません。 ```ini session_created_response_validate_warning_as_error = true ``` ## session_created_timeout **デフォルト**: 5 s **範囲**: 0..300 s セッションが存在しない状態で、新規接続が来た際にセッション生成に利用できる時間を指定してください。 この時間はセッションウェブフックにかかる時間も含まれます。 ```ini session_created_timeout = 5 s ``` ## session_destroyed_timeout **デフォルト**: 15 s **範囲**: 0..300 s セッションに同時接続数が 0 になった場合、セッション破棄する時間を指定してください。 ```ini session_destroyed_timeout = 15 s ``` ## session_updated_webhook_interval **デフォルト**: 1 min **範囲**: 1..10 min **単位**: min のみ セッション更新時のセッションウェブフック `session.updated` の間隔を指定してください。 時間単位には 分 `min` のみ指定できます。 ```ini session_updated_webhook_interval = 1 min ``` ## session_webhook_session_updated_log **デフォルト**: true `session_webhook.jsonl` に `session.updated` を出力するかどうかを指定してください。デフォルトでは出力します。 ```ini session_webhook_session_updated_log = false ``` ## session_webhook_url **デフォルト**: 指定なし セッションに関連するウェブフックリクエスト送信先の HTTP URL を指定してください。 ```ini session_webhook_url = https://example.com/sora/webhook/session ``` ## signaling_av1_params **デフォルト**: false シグナリングで AV1 のパラメーターを指定できるようにするかを指定してください。 ```ini signaling_av1_params = true ``` ## signaling_bundle_id **デフォルト**: false シグナリングでバンドル ID を指定できるようにするかを指定してください。 ```ini signaling_bundle_id = true ``` ## signaling_forwarding_filters **デフォルト**: false 転送フィルターをシグナリング接続時に設定できるかどうかを指定してください。 ```ini signaling_forwarding_filters = true ``` ## signaling_h264_params **デフォルト**: false シグナリングで H.264 のパラメーターを指定できるようにするかを指定してください。 ```ini signaling_h264_params = true ``` ## signaling_h265_params **デフォルト**: false シグナリングで H.265 のパラメーターを指定できるようにするかを指定してください。 ```ini signaling_h265_params = true ``` ## signaling_loopback_address_only **デフォルト**: false シグナリングへのアクセスをループバックアドレスからのみに制限します。できる限り有効にしてください。 ```ini signaling_loopback_address_only = true ``` ## signaling_normal_close_reason **デフォルト**: true 正常切断時の `reason` に切断理由を含むかどうかを指定してください。 `false` を指定した場合は空文字 `""` が含まれるようになります。 ```ini signaling_normal_close_reason = false ``` ## signaling_notify **デフォルト**: true シグナリング経由で接続や切断、更新の通知を受け取るかどうか指定してください。この設定はすべての設定に影響します。 個別の設定の場合は認証ウェブフックのレスポンス時で指定してください。 シグナリング経由での通知機能の詳細は [シグナリング通知機能](SIGNALING_NOTIFY.html) をご確認ください 認証の戻り値に関しては [認証ウェブフックの戻り値での指定](SIGNALING_NOTIFY.html#28d39f) を確認してください。 ```ini signaling_notify = true ``` ## signaling_notify_audio_streaming_failed **デフォルト**: false シグナリング通知機能が有効な際、音声ストリーミングサーバーへの接続が失敗した際にチャネル参加者全員に通知をするかどうかを指定してください。 ```ini signaling_notify_audio_streaming_failed = true ``` ## signaling_notify_authn_metadata_max_size **デフォルト**: 64512 **範囲**: 0..1048576 > **注釈** > > この設定を 0 にすることでクライアントからシグナリング通知メタデータを指定できなくなります。 クライアントから接続時に送られてくるシグナリング通知メタデータの最大サイズをバイト単位で指定してください。 ```ini signaling_notify_authn_metadata_max_size = 64512 ``` ## signaling_notify_bundle_id **デフォルト**: true シグナリング通知機能が有効な際、通知にバンドル ID を含むかどうかを指定してください。 ```ini signaling_notify_bundle_id = true ``` ## signaling_notify_client_id **デフォルト**: true シグナリング通知機能が有効な際、通知にクライアント ID を含むかどうかを指定してください。 ```ini signaling_notify_client_id = true ``` ## signaling_notify_connection_created_timestamp **デフォルト**: true シグナリング通知機能が有効な際、 `"event_type": "connection.created"` に `timestamp` を含むかどうかを指定してください。 ```ini signaling_notify_connection_created_timestamp = true ``` ## signaling_notify_connection_id **デフォルト**: true シグナリング通知機能が有効な際、通知にコネクション ID を含むかどうかを指定してください。 ```ini signaling_notify_connection_id = true ``` ## signaling_notify_forwarding_filter **デフォルト**: true シグナリング通知機能が有効な際、 転送フィルターのブロック開始とブロック解除の通知をするかどうかを指定してください。 ```ini signaling_notify_forwarding_filter = true ``` ## signaling_notify_ice_connection_state **デフォルト**: false シグナリング通知機能が有効な際、 ICE 接続の状態を自分を含む同一セッションに参加しているクライアント全員に通知するかどうかを指定してください。 ```ini signaling_notify_ice_connection_state = true ``` ## signaling_notify_media **デフォルト**: true シグナリング通知機能が有効な際、通知に音声や映像が有効かどうかを含むかどうかを指定してください。 ```ini signaling_notify_media = true ``` ## signaling_notify_metadata **デフォルト**: true シグナリング通知機能が有効な際、 `"type": "connect"` の `signaling_notify_metadata` で指定した値、 または認証ウェブフックの戻り値の `signaling_notify_metadata` で指定した値を通知するかどうかを指定してください。 ```ini signaling_notify_metadata = true ``` ## signaling_notify_metadata_ext **デフォルト**: false シグナリング通知メタデータ拡張機能を有効にするかどうかを指定してください。 シグナリング通知機能が無効でも通知されないだけで API は利用できます。 詳細は [シグナリング通知メタデータ拡張機能](SIGNALING_NOTIFY_METADATA_EXT.html) をご確認ください。 ```ini signaling_notify_metadata_ext = true ``` ## signaling_notify_network **デフォルト**: true シグナリング通知機能が有効な際、ネットワークの状態を通知するかどうかを指定してください。 ```ini signaling_notify_network = true ``` ## signaling_notify_network_status_interval **デフォルト**: 10 s **範囲**: `20 ms` .. `10 min` シグナリング通知が有効な際、ネットワーク状態の通知間隔を指定してください。 ```ini signaling_notify_network_status_interval = 30 s ``` ## signaling_notify_recording **デフォルト**: true シグナリング通知機能が有効な際、 録画の開始と停止の状態を通知するかどうかを指定してください。 ```ini signaling_notify_recording = true ``` ## signaling_notify_session_id **デフォルト**: true シグナリング通知機能が有効な際、通知にセッション ID を含むかどうかを指定してください。 ```ini signaling_notify_session_id = true ``` ## signaling_notify_simulcast_switched **デフォルト**: true シグナリング通知機能が有効な際、サイマルキャストの rid の切り替わりを通知するかどうかを指定してください。 ```ini signaling_notify_simulcast_switched = true ``` ## signaling_notify_spotlight **デフォルト**: true シグナリング通知が有効な際、スポットライトがフォーカス/アンフォーカスに切り替わったことを通知するかどうかを指定してください。 ```ini signaling_notify_spotlight = false ``` ## signaling_port **デフォルト**: 5000 シグナリングに使用するポート番号を指定してください。 ```ini signaling_port = 5000 ``` ## signaling_vp9_params **デフォルト**: false シグナリングで VP9 のパラメーターを指定できるようにするかを指定してください。 ```ini signaling_vp9_params = true ``` ## simulcast_auto_min_switch_interval **デフォルト**: 5 s **範囲**: 1..300 s サイマルキャスト機能利用時に、 `simulcast_auto_rids` を指定した際、自動で切り替わる最小の間隔を秒数で指定してください。 ```ini simulcast_auto_min_switch_interval = 10 s ``` ## simulcast_codecs_file > **注意** > > この設定を利用する場合は事前にサポートまでご連絡ください **デフォルト**: なし サイマルキャストマルチコーデックで利用するコーデックパラメーターのカスタマイズを JSON 形式のファイルで指定してください。 詳細は [サイマルキャストマルチコーデックのデフォルト値を変更する](SIMULCAST_MULTICODEC.html#48a6a7) をご確認ください。 ```ini simulcast_codecs_file = etc/simulcast_codecs.json ``` ## simulcast_encodings_file **デフォルト**: なし サイマルキャストで利用するエンコーディングパラメーターのカスタマイズを JSON 形式のファイルで指定してください。 詳細は [映像のエンコーディングパラメーターのカスタマイズ](SIMULCAST.html#6c680e) をご確認ください。 ```ini simulcast_encodings_file = etc/simulcast_encodings.json ``` ## simulcast_multicodec > **注意** > > この設定を利用する場合は事前にサポートまでご連絡ください **デフォルト**: false サイマルキャストマルチコーデックを有効にするかどうかを指定してください。 ```ini simulcast_multicodec = true ``` ## skip_redact_sensitive_data **デフォルト**: false ログファイル中のセンシティブなデータを **"REDACTED"** という文字列に書き換えて出力する処理をスキップします。 ```ini skip_redact_sensitive_data = true ``` センシティブなデータを書き換える対象は以下のとおりです。 - `auth_webhook.jsonl` の `event_metadata` を **"REDACTED"** に書き換えます - `session_webhook.jsonl` の `session_metadata` と `event_metadata` を **"REDACTED"** に書き換えます - `event_webhook.jsonl` の `event_metadata` を **"REDACTED"** に書き換えます ## spotlight_encodings_file **デフォルト**: なし スポットライトで利用するエンコーディングパラメーターのカスタマイズを JSON 形式のファイルで指定してください。 詳細は [スポットライト利用時の映像のエンコーディングパラメーターのカスタマイズ](SPOTLIGHT.html#bd05eb) をご確認ください。 ```ini spotlight_encodings_file = etc/spotlight_encodings.json ``` ## stats_webhook_log **デフォルト**: false 統計ウェブフックのログをファイルに出力します。 ```ini stats_webhook_log = true ``` ## stats_webhook_url **デフォルト**: 指定なし 統計情報を通知する HTTP URL を指定してください。 ```ini stats_webhook_url = https://example.com/sora/webhook/stats ``` ## stats_webhook_worker_number **デフォルト**: 5 **範囲**: 5..5000 統計ウェブフックのワーカー数を指定してください。 統計ウェブフックのワーカー割り当てに利用する値は `channel_id` です。 ```ini stats_webhook_worker_number = 5 ``` ## switched_websocket_signaling_ping_interval **デフォルト**: 15 s **範囲**: 5..300 s シグナリングが DataChannel に切り替わった後、サーバーからクライアントへ WebSocket 経由でネットワーク死活監視のために `"type": "ping"` を送信する間隔を指定してください。 ```ini switched_websocket_signaling_ping_interval = 15 s ``` > **重要** > > デフォルト値を 15 秒にしているのは、一部の Apple iPad Safari で `"type": "switched"` 後に `"type": "ping"` の送信間隔が 30 秒だと WebSocket が切断されてしまう問題が発生したためです。 ## test_api **デフォルト**: false テスト用 API 機能を有効にするかどうかを指定してください。デフォルトでは無効になっています。 ```ini test_api = true ``` ## turn_fqdn **デフォルト**: なし TURN 機能の URL で使用する FQDN (最後の . なし) を指定してください。 指定した場合は TURN-UDP, TURN-TCP, TURN-TLS に共通で採用されます。 TURN-TLS の FQDN は `turn_tls_fqdn` 設定で上書きできます。 ### ドメイン名が sora-turn.example.com の場合 ```ini turn_fqdn = sora-turn.example.com ``` ## turn_realm **デフォルト**: "sora-turn.example.com" TURN 機能で使用するレルムを指定してください。 文字列であれば何でも良いのですが、会社のドメインなどを指定することをおすすめします。 ```ini turn_realm = sora-turn.example.com ``` ## turn_tcp **デフォルト**: true TURN 機能で TURN-TCP を使用するかどうかを指定してください。使用しない場合は false を指定してください。 ### 使用しない場合の設定 ```ini turn_tcp = false ``` ## turn_tcp_allocate_success_delay_time **デフォルト**: 100 ms **範囲**: 0..1 s TURN 機能で TURN-TCP 時の Allocate-Success を返す時間を遅らせます。 ```ini turn_tcp_allocate_success_delay_time = 100 ms ``` ## turn_tcp_listen_port **デフォルト**: 3478 TURN 機能で TURN-TCP を有効にした際に使用するポート番号を指定してください。デフォルトでは 3478 番ポートが使用されます。 ```ini turn_tcp_listen_port = 3478 ``` ## turn_tcp_only **デフォルト**: false > **危険** > > この機能はあくまで検証時のみ有効にしてください TURN-TCP を強制的に利用するようになります。この機能を有効にした場合 warning ログが出力されます。 ### 検証する場合 ```ini turn_tcp_only = true ``` ## turn_tcp_port **デフォルト**: turn_tcp_listen_port の値を利用 TURN 機能で TURN-TCP URL 払い出し時のポート番号を指定してください。デフォルトでは turn_tcp_listen_port の値が利用されます。 ```ini turn_tcp_port = 3478 ``` ## turn_tls **デフォルト**: false TURN 機能で TURN-TLS の URL 払い出し機能を使用するかどうかを指定してください。使用しない場合は false を指定してください。 ```ini turn_tls = true ``` ## turn_tls_fqdn TURN 機能で TURN-TLS の URL で使用する FQDN (最後の . なし) を指定してください。 指定しない場合は `turn_fqdn` の値が採用されます。 どちらも設定されていない場合 TURN-TLS を利用することはできません。 ### ドメイン名が sora.example.com の場合 ```ini turn_tls_fqdn = sora-turn.example.com ``` ## turn_tls_only **デフォルト**: false > **危険** > > この機能はあくまで検証時のみ有効にしてください TURN-TLS を強制的に利用するようになります。この機能を有効にした場合 warning ログが出力されます。 ### 検証する場合 ```ini turn_tls_only = true ``` ## turn_tls_port **デフォルト**: 5349 TURN 機能で TURN-TLS の URL 払い出し機能を有効にした際に使用するポート番号を指定してください。デフォルトでは 5349 番ポートが使用されます。 ```ini turn_tls_port = 443 ``` ## turn_udp_allocate_request_401_rate_limit_count **デフォルト**: 60 **範囲**: 0..300 TURN-UDP 利用時の認証エラーを返すレートリミット回数を指定してください。 60 の場合は [turn_udp_allocate_request_401_rate_limit_window](SORA_CONF.html#56ea52) で指定した秒数の間に 60 回を超えた場合、 サイレントディスカードします。 ```ini turn_udp_allocate_request_401_rate_limit_count = 60 ``` ## turn_udp_allocate_request_401_rate_limit_window **デフォルト**: 60 s **範囲**: 1..300 s TURN-UDP 利用時の認証エラーを返すレートリミットウィンドウを指定してください。 60 s の場合は 60 秒の間に [turn_udp_allocate_request_401_rate_limit_count](SORA_CONF.html#5deefa) で指定した回数を超えた場合、 サイレントディスカードします。 ```ini turn_udp_allocate_request_401_rate_limit_window = 60 s ``` ## ulpfec > **注意** > > この設定を有効にする場合は事前にサポートまでご連絡ください **デフォルト**: false ULPFEC を有効にするかどうかを指定してください。デフォルトでは無効になっています。 現時点では Chrome と Safari が使用でき、 Firefox は対応しておりません。 iOS/Android は libwebrtc を使用した場合は対応しています。 ```ini ulpfec = false ``` ## webhook_basic_authn **デフォルト**: false ウェブフックで HTTP ベーシック認証を利用するかどうかを指定してください。 ```ini webhook_basic_authn = true ``` ## webhook_basic_authn_password **デフォルト**: 指定なし ウェブフックで HTTP ベーシック認証を利用する際のパスワードを指定してください。 `basic-authn-password` のように文字列で指定してください。 ```ini webhook_basic_authn_password = basic-authn-password ``` ## webhook_basic_authn_user_id **デフォルト**: 指定なし ウェブフックで HTTP ベーシック認証を利用する際のユーザー ID を指定してください。 `basic-authn-user-id` のように文字列で指定してください。 ```ini webhook_basic_authn_user_id = basic-authn-user-id ``` ## webhook_connect_timeout **デフォルト**: 30 s **範囲**: 1..600 s ウェブフックの接続確立までのタイムアウト時間を指定してください。 ```ini webhook_connect_timeout = 120 s ``` ## webhook_insecure > **注意** > > この設定を利用する場合は事前にサポートまでご連絡ください **デフォルト**: false ウェブフックで HTTPS を利用する際に証明書のチェックを行わない場合はこの設定を有効にしてください。 ```ini webhook_insecure = true ``` ## webhook_ipv6 **デフォルト**: false ウェブフックで IPv6 を利用するかどうかを指定してください。 この設定を `true` にしない限り、ウェブフックでは IPv4 が利用されます。 ```ini webhook_ipv6 = true ``` ## webhook_proxy_auth_password **指定しない場合はコメントアウトしたままにしてください** **デフォルト**: 指定なし ウェブフックで利用する HTTP Proxy の認証パスワードを指定してください。 `proxy-auth-password` のように文字列で指定してください。 ```ini webhook_proxy_auth_password = proxy-auth-password ``` ## webhook_proxy_auth_user **指定しない場合はコメントアウトしたままにしてください** **デフォルト**: 指定なし ウェブフックで利用する HTTP Proxy の認証ユーザーを指定してください。 `proxy-auth-user` のように文字列で指定してください。 ```ini webhook_proxy_auth_user = proxy-auth-user ``` ## webhook_proxy_url **指定しない場合はコメントアウトしたままにしてください** **デフォルト**: 指定なし ウェブフックで利用する HTTP Proxy の URL を指定してください。 `http://proxy.example.com:8080` のように URL を指定してください。 ```ini webhook_proxy_url = http://proxy.example.com:8080 ``` ## webhook_response_timeout **デフォルト**: 5 s **範囲**: 1..600 s ウェブフックのレスポンス受信までのタイムアウト時間を指定してください。 ```ini webhook_response_timeout = 5 s ``` ## webhook_tls_fullchain_file **デフォルト**: 指定なし ウェブフックリクエスト送信先との通信に HTTPS で mTLS を利用するための設定で、 中間証明書を含むクライアント証明書を PEM 形式で設定してください。 ```ini webhook_tls_fullchain_file = /path/to/fullchain.pem ``` ## webhook_tls_privkey_file **デフォルト**: 指定なし ウェブフックリクエスト送信先との通信に HTTPS で mTLS を利用するための設定で、 クライアント証明書の秘密鍵を PEM 形式で設定してください。 > **危険** > > 秘密鍵にパスフレーズが設定されている場合エラーとなります ```ini webhook_tls_privkey_file = /path/to/privkey.pem ``` ## webhook_tls_verify_cacert_file **指定しない場合はコメントアウトしたままにしてください** **デフォルト**: 指定なし ウェブフックリクエスト送信先との通信に HTTPS を利用した際、サーバー証明書のチェックを行う CA ファイルを PEM 形式で設定してください。 ```ini webhook_tls_verify_cacert_file = /path/to/server_cacert.pem ``` > **重要** > > この設定がない場合、 OS 組み込みのルート CA 証明書を利用してサーバー証明書をチェックします。 > OS 組み込みのルート CA 証明書については [ウェブフックリクエストなどの送信先サーバー証明書の検証に利用する OS 組み込みのルート CA 証明書について](WEBHOOK.html#e8a845) をご確認ください。 ## websocket_signaling_ping_interval **デフォルト**: 5 s **範囲**: 5..300 s WebSocket 経由のシグナリングの場合に、サーバーからクライアントへネットワーク死活監視のために `"type": "ping"` を送信する間隔を指定してください。 > **重要** > > ここで指定する値は [websocket_signaling_pong_timeout](SORA_CONF.html#140464) より短くしてください。 ```ini websocket_signaling_ping_interval = 5 s ``` ## websocket_signaling_pong_timeout **デフォルト**: 60 s **範囲**: 60..600 s WebSocket 経由のシグナリングの場合に、クライアントから返却される `"type": "pong"` のタイムアウト時間を指定してください。 この時間内に `"type": "pong"` が返却されない場合はサーバーから接続を切断します。 > **重要** > > ここで指定する値は [websocket_signaling_ping_interval](SORA_CONF.html#27aae2) より長くしてください。 ```ini websocket_signaling_pong_timeout = 60 s ``` ## websocket_stats_timer_interval **デフォルト**: 60 s **範囲**: 5..600 s WebSocket 経由のシグナリングの場合に、サーバーからクライアントに統計情報の送信を要求する `"stats": true` を設定する間隔を指定してください。 ```ini websocket_stats_timer_interval = 60 s ``` ## whep > **注意** > > この設定を利用する場合は事前にサポートまでご連絡ください **デフォルト**: false OBS の WHEP 形式のシグナリングを有効にするかどうか指定してください。 ```ini whep = true ``` ## whep_bearer_token_metadata_key > **注意** > > この設定を利用する場合は事前にサポートまでご連絡ください **デフォルト**: 指定なし OBS の WHEP 形式のシグナリング時の Authentication ヘッダーに含まれるトークンを、メタデータとして送信する際のキーを指定してください。 ```ini whep_bearer_token_metadata_key = access_token ``` ## whip **デフォルト**: false OBS の WHIP 形式のシグナリングを有効にするかどうか指定してください。 ```ini whip = true ``` ## whip_bearer_token_metadata_key **デフォルト**: 指定なし OBS の WHIP 形式のシグナリング時の Authentication ヘッダーに含まれるトークンを、メタデータとして送信する際のキーを指定してください。 ```ini whip_bearer_token_metadata_key = access_token ``` ## whip_simulcast **デフォルト**: true WHIP 利用時にサイマルキャストを受け付けるかどうかを指定してください。 詳細は [WHIP](WHIP.html) をご確認ください。 ```ini whip_simulcast = true ``` ## workaround_20250515 **デフォルト**: 未指定 この設定項目については [Safari タイムスタンプバグに対するワークアラウンド](WORKAROUND.html#e73b7a) をご確認ください。 ```ini workaround_20250515 = 18.4,18.4.1,18.5 ``` # systemd `bin/sora foreground` はデーモン化せずに Sora を起動するコマンドです。 ## 設定 ### ユニットファイル `/etc/systemd/system/` に `sora.service` のユニットファイルを作成します。 ユニットファイルの例: ``` [Unit] Description=WebRTC SFU Sora Service After=network.target [Service] Environment="HOME=/home/shiguredo" ExecStart=/home/shiguredo/sora/bin/sora foreground Type=simple Restart=always RestartSec=60s User=shiguredo KillMode=process [Install] WantedBy=multi-user.target ``` `[Service]` セクションの `Environment`、 `User` はそれぞれ、実際に Sora サービスを開始するユーザーの `$HOME`、 `$USER` に置き換えてください。 また、 `ExecStart` は Sora のインストール先に応じた実行コマンドのパスに置き換えてください。 ### Sora サービスの有効化と開始 sora.service の有効化: ``` $ sudo systemctl enable sora.service ``` sora.service の開始: ``` $ sudo systemctl start sora.service ``` ### Sora サービスの停止 sora.service の停止: ``` $ sudo systemctl stop sora.service ``` # Linux カーネルチューニング Sora は UDP に対して大きな負荷がかかるシステムです。そのためカーネルをチューニングする必要があります。 ## 確認方法 netstat コマンドで Errors が出ていた場合はバッファが足りない可能性が高いです。 ```console $ netstat -su ``` ## Ubuntu ### sysctl sysctl にて、以下の値を設定することを推奨します。 このあたりの値はサーバースペックによりますので、こちらは推奨値となります。 ``` sudo sysctl -w net.core.rmem_default=33554432 sudo sysctl -w net.core.rmem_max=33554432 sudo sysctl -w net.core.wmem_default=33554432 sudo sysctl -w net.core.wmem_max=33554432 sudo sysctl -w net.core.somaxconn=65535 sudo sysctl -w net.core.optmem_max=25165824 sudo sysctl -w net.core.netdev_max_backlog=65536 sudo sysctl -w net.ipv4.tcp_mem='786432 1048576 26777216' sudo sysctl -w net.ipv4.tcp_rmem='8192 87380 33554432' sudo sysctl -w net.ipv4.tcp_wmem='8192 65536 33554432' sudo sysctl -w net.ipv4.udp_mem='65536 131072 262144' sudo sysctl -w net.ipv4.udp_rmem_min=16384 sudo sysctl -w net.ipv4.udp_wmem_min=16384 ``` # IPv6 での動作について ## 概要 Sora は WebRTC とウェブフックが IPv6 での動作に対応しています。ただし、ブラウザ側やサーバー側が非対応な場合があります。 特に、IPv6 での TURN 機能にクライアントが対応していない場合は接続できないことがあります。 ## お問い合わせの際の情報について IPv6 環境は様々な組み合わせがあるため、問題を解析するには多くの情報が必要になります。 お問い合わせの際は以下の情報をお送りください。 - クライアント側の IPv6 の有無について - Sora 側の IPv6 の設定の有無について - Sora が動作しているサーバーの A または AAAA レコードの有無について - クライアントが IPv4 または IPv6 または IPv4 と IPv6 どの環境かについて 他にも何か気づいた点などがありましたらそちらも合わせてお問い合わせください。 ## IPv6 のみ Sora の WebRTC を IPv6 のみの通信のみでの動作させます。 `sora.conf` にて [ipv6_only](SORA_CONF.html#5e9e68) を `true` にすることで、 WebRTC の接続を IPv6 のみに制限することができます。 シグナリングや API 部分を IPv6 のみにしたい場合は Nginx 側の設定を変更してください。 ## ウェブフックの IPv6 対応 Sora のウェブフックは IPv6 での動作に対応しています。 `sora.conf` にて [webhook_ipv6](SORA_CONF.html#6c895b) を `true` にすることで、 ウェブフックの接続で IPv6 を利用することができます。 # メタデータ ## 概要 Sora では様々なメタデータを扱っているため、それぞれのメタデータの説明をしています。 ## 接続時の認証メタデータ指定 クライアントが Sora へ接続する際に、認証に利用する `metadata` を指定できます。 これは認証ウェブフックに `metadata` として含まれます。 ```javascript { "type": "connect", "role": "sendrecv", "channel_id": "sora", "metadata": {"spam": "egg"} } ``` この値はクライアントと Sora だけで共有される値です。他のクライアントには一切共有されません。 ## 認証ウェブフック成功時のメタデータ払い出し 認証ウェブフック成功時に `metadata` を払い出すことができます。 この値は Sora が `"type": "offer"` をクライアントへ送る際に `metadata` として送られます。 ```javascript { "allowed": true, "metadata": {"spam": "egg"} } ``` ```javascript { "type": "offer", "sdp": "...", "metadata": {"spam": "egg"} } ``` この値は Sora とクライアントだけで共有される値です。他のクライアントには一切共有されません。 ## 認証ウェブフック成功時のイベントメタデータ払い出し 認証ウェブフック成功時に `event_metadata` を払い出すことができます。 この値は Sora がイベントウェブフックリクエストを送信する際に `event_metadata` として含まれます。 ```javascript { "allowed": true, "event_metadata": {"spam": "egg"} } ``` ```javascript { "type": "connection.created", "event_metadata": {"spam": "egg"} } ``` この値は Sora と認証ウェブフックとイベントウェブフック先のサーバーとのみで共有されます。 クライアントには通知されません。 ## 接続時のシグナリング通知メタデータ指定 シグナリング接続時の `"type": "connect"` で `signaling_notify_metadata` が指定できます。 ここで指定した値は同じチャネルに参加しているクライアントと新しく参加するクライアントに通知されます。 ```javascript { "type": "connect", "signaling_notify_metadata": {"spam": "egg"} } ``` ```javascript { "type": "connection.created", "authn_metadata": {"spam": "egg"} "metadata": {"spam": "egg"} } ``` ### シグナリング通知メタデータ拡張が有効な場合 シグナリング通知メタデータ拡張有効になっている場合は以下のように `authn_metadata` のみに値が含まれます。 ```javascript { "type": "connection.created", "authn_metadata": {"spam": "egg"} "metadata": {} } ``` もしこのシグナリング通知メタデータを接続時にしていさせたくない場合、 [signaling_notify_authn_metadata_max_size](SORA_CONF.html#a8c147) を `0` に設定してください。 ## 認証ウェブフック成功時のシグナリング通知メタデータ払い出し 認証ウェブフック成功時に `signaling_notify_metadata` を払い出すことができます。 この値は同じチャネルに参加しているクライアントと新しく参加するクライアントに通知されます。 もし接続時に `signaling_notify_metadata` が指定されていた場合は、 認証成功時のシグナリング通知メタデータ払い出しで **上書き** されます。 ```javascript { "allowed": true, "signaling_notify_metadata": {"spam": "egg"} } ``` ```javascript { "type": "connection.created", "authz_metadata": {"spam": "egg"} "metadata": {"spam": "egg"} } ``` ### シグナリング通知メタデータ拡張が有効な場合 シグナリング通知メタデータ拡張が有効になっている場合は以下のように `authz_metadata` のみに値が含まれます。 ```javascript { "type": "connection.created", "authz_metadata": {"spam": "egg"} "metadata": {} } ``` ## シグナリング通知メタデータ拡張 **[シグナリング通知メタデータ拡張](SIGNALING_NOTIFY_METADATA_EXT.html) を利用すると接続ごとに状態を持てるようになり、** : API でそのメタデータを変更し、通知することができるようになります。 本来、シグナリング通知メタデータは接続時か認証成功払い出し時にしか指定できず一度指定したら変更できません。 シグナリング通知メタデータ拡張を利用した場合は HTTP API を利用して途中でメタデータの値を変更できます。 この機能を有効にするとシグナリング時の通知メタデータに指定した値は `metadata` に含まれなくなります。 ## セッション生成時のセッションメタデータ払い出し セッション生成時に送信される [session.created](SESSION_WEBHOOK.html#1d1984) の戻り値に指定することで `session_metadata` を払い出すことができます。 この値は一定間隔で送られる [session.updated](SESSION_WEBHOOK.html#2a5b1b) と、 このセッションが破棄された時に送られる [session.destroyed](SESSION_WEBHOOK.html#ccb165) に含まれます。 ```javascript { "session_metadata": "" } ``` ## 一括録画ファイルメタデータ archive-.json 録画機能で一括録画を指定した際に `archive//` 以下に生成されるファイルです。 かならず `archive-.webm` ファイルとペアになります。 ## 分割録画ファイルメタデータ split-archive-_.json 録画機能で分割録画を指定した際に `archive//` 以下に生成されるファイルです。 かならず `split-archive-_.webm` ファイルとペアになります。 ## 録画(セッション単位) の StartRecording API で指定するメタデータ [StartRecording](API_RECORDING.html#c5b527) API では `metadata` を指定できます。 この値は以下のセッションウェブフックに `recording_metadata` として含まれます。 - [recording.started](SESSION_WEBHOOK.html#9b5c58) - [recording.report](SESSION_WEBHOOK.html#920a02) - [session.updated](SESSION_WEBHOOK.html#2a5b1b) また、 `report-.json` ファイルにも記録されます。 ## 録画(セッション単位) のセッションウェブフック `session.created` で指定するメタデータ 録画(セッション単位) ではセッションウェブフック `session.created` の戻り値として、 `recording_metadata` を払い出すことができます。 ``` { "recording": true, "recording_metadata": "" } ``` この値は以下のセッションウェブフックに `recording_metadata` として含まれます。 - [recording.started](SESSION_WEBHOOK.html#9b5c58) - [recording.report](SESSION_WEBHOOK.html#920a02) - [session.updated](SESSION_WEBHOOK.html#2a5b1b) また、 `report-.json` ファイルにも記録されます。 # センシティブデータ ## 概要 Sora ではログに出力されるセンシティブデータを **"REDACTED"** という文字列に書き換えます。 ## 対象ログと項目 Sora のログは以下の内容のセンシティブデータを **"REDACTED"** に書き換えて出力します。 - `auth_webhook.jsonl` の `event_metadata` を **"REDACTED"** に書き換えて出力します。 - `session_webhook.jsonl` の `session_metadata` と `event_metadata` を **"REDACTED"** に書き換えて出力します。 - `event_webhook.jsonl` の `event_metadata` を **"REDACTED"** に書き換えて出力します。 ### event_webhook_error ログ > **重要** > > `event_webhook_error.jsonl` の `event_metadata` については **"REDACTED"** の書き換えは行いません ### session_webhook_error ログ > **重要** > > `session_webhook_error.jsonl` の `session_metadata` と `event_metadata` については **"REDACTED"** の書き換えは行いません ## 書き換えをスキップする > **重要** > > この書き換えを無効にすることは推奨していません。 センシティブなデータを利用している場合は、 **"REDACTED"** への書き換えをスキップする設定を提供しています。 `sora.conf` の [skip_redact_sensitive_data](SORA_CONF.html#00d209) を `true` にすることでセンシティブなデータの **"REDACTED"** への書き換えをスキップします。 ## 録画メタデータの扱いについて StartRecording API やセッションウェブフックの戻り値で指定できる録画メタデータについてはセンシティブなデータとして扱っていません。 これは録画ファイル出力時の録画メタデータファイルに含まれ、映像合成時に利用することを想定しているためです。 # ログファイル **サポート問い合わせの場合は log/ ディレクトリ以下をすべて圧縮して送ってください** ## ログファイル Sora はデフォルトで log/ ディレクトリ以下にログファイルを出力します。 [log_dir](SORA_CONF.html#ddcdf0) を設定することでログファイルの出力先を変更できます。 ### Sora の運用に関係するログ - sora.jsonl- Sora の開始、終了や問題があった場合に出力されますので、まずはこの監視をお願いします - ログローテーションされませんので、ログローテーションをお願いします - 週次ログローテーションを推奨します - cluster.jsonl- Sora クラスターに関するログが出力されます - **Sora クラスターを利用していない場合も出力されます** - ログローテーションされませんので、ログローテーションをお願いします - 週次ログローテーションを推奨します - auth_webhook.jsonl- 認証ウェブフックの送信が **正常に動作した** 処理を書き込みます - ログローテーションされませんので、ログローテーションをお願いします - 週次ログローテーションを推奨します - auth_webhook_error.jsonl- 認証ウェブフックの送信が失敗した処理を書き込みます- レスポンスがステータスコードが 200 番台以外であった場合 - レスポンスの JSON に `"allowed"` 項目が含まれていない場合 - レスポンスの JSON が `"allowed": false` にもかかわらず `"reason"` 項目が含まれていない場合 - 送信先からの応答がなく、タイムアウトした場合 - ログローテーションされませんので、ログローテーションをお願いします - 週次ログローテーションを推奨します - session_webhook.jsonl- セッションウェブフックの送信が **正常に動作した** 処理を書き込みます - ログローテーションされませんので、ログローテーションをお願いします - 週次ログローテーションを推奨します - session_webhook_error.jsonl- セッションウェブフックの送信が失敗した処理を書き込みます- レスポンスがステータスコードが 200 番台以外であった場合 - 送信先からの応答がなく、タイムアウトした場合 - ログローテーションされませんので、ログローテーションをお願いします - 週次ログローテーションを推奨します - event_webhook.jsonl- イベントウェブフックで送信した **すべて** の処理を書き込みます - ログローテーションされませんので、ログローテーションをお願いします - 週次ログローテーションを推奨します - event_webhook_error.jsonl- イベントウェブフックの送信が失敗した処理を書き込みます- レスポンスがステータスコードが 200 番台以外であった場合 - 送信先からの応答がなく、タイムアウトした場合 - ログローテーションされませんので、ログローテーションをお願いします - 週次ログローテーションを推奨します - stats_webhook.jsonl- このログは [stats_webhook_log](SORA_CONF.html#2fa540) を `true` に設定した場合に出力されます - 統計ウェブフックで送信した **すべて** の処理を書き込みます - ログローテーションされませんので、ログローテーションをお願いします - 週次ログローテーションを推奨します - stats_webhook_error.jsonl- このログは [stats_webhook_log](SORA_CONF.html#2fa540) を `true` に設定した場合に出力されます - 統計ウェブフックの送信が失敗した処理を書き込みます- レスポンスがステータスコードが 200 番台以外であった場合 - 送信先からの応答がなく、タイムアウトした場合 - ログローテーションされませんので、ログローテーションをお願いします - 週次ログローテーションを推奨します - rtc_stats.jsonl- このログは [rtc_stats_log](SORA_CONF.html#2fc848) を `true` に設定した場合に出力されます - クライアントの RTC 統計情報を出力します - ログローテーションされませんので、ログローテーションをお願いします - 週次ログローテーションを推奨します ### Sora のサポートに関係するログ - connection.jsonl- 接続が切断した際にクライアントとサーバーの統計情報を出力するログです - ログローテーションされませんので、ログローテーションをお願いします - 週次ログローテーションを推奨します - signaling.jsonl- シグナリングでやりとりされている offer / answer / candidate / re-offer / re-answer と接続終了 (close) を記録したログです - OBS WHIP/WHEP 用の whip-offer / whip-answer / whep-offer / whep-answer も出力します - ログローテーションされませんので、ログローテーションをお願いします - 週次ログローテーションを推奨します - signaling_error.jsonl- シグナリングでエラーが発生した際にエラー情報を出力します - ログローテーションされませんので、ログローテーションをお願いします - 週次ログローテーションを推奨します - api.jsonl- 一部の API 操作に関するログを出力します - ログローテーションされませんので、ログローテーションをお願いします - 週次ログローテーションを推奨します - internal.jsonl- Sora が予定外の動作をしたときに出力されるログです。問題解決に必須のログです - ログローテーションされませんので、ログローテーションをお願いします - 週次ログローテーションを推奨します - crash.log- Sora が予定外の動作をしたときに出力されるログです。問題解決に必須のログです - ログローテーションされませんので、ログローテーションをお願いします - 週次ログローテーションを推奨します - erlang.log.<1..5>- サポート時に必要となるログですので、気にする必要はありません - 自動でログローテーションされますので、ログローテーションは不要です - `bin/sora foreground` コマンドで起動する場合には出力されません - sysctl.log- 起動時に取得するログで、毎回上書きされます - sysctl -a の実行結果を記録します - ログローテーションは不要です - ulimit.log- 起動時に取得するログで、毎回上書きされます - ulimit -n の実行結果を記録します - ログローテーションは不要です - run_erl.log- 起動時に出力されるログのため、ほとんどログが出力されることはありません - ログローテーションは不要です - `bin/sora foreground` コマンドで起動する場合には出力されません ## 特別なログ Sora が異常終了した際 `erl_crash.dump` というファイルが log/ ディレクトリに生成されます。 こちらは **必ず** 保存し、送っていただけるようお願いいたします。 ### 監視用確認目的で erl_crash.dump ログを強制的に出力させる方法 監視を行う際に実際に `erl_crash.dump` を生成したい場合には、 `bin/sora daemon` で起動した上で、 `kill -SIGUSR1` を使用して `run_erl` プロセスを落としてください。 ```bash $ kill -SIGUSR1 <プロセス ID> ``` この方法で log/ ディレクトリに `erl_crash.dump` が生成されます。 ## JSONL (JSON Lines) 形式 Sora は一部のログを除いて JSONL 形式でログを出力します。 JSONL の仕様は [JSON Lines](https://jsonlines.org/) に記載されているものに準拠します。 - UTF-8 エンコード - 改行は `\n` - 各行は JSON 値 - ファイル拡張子は `jsonl` ### JSONL 形式で出力されるログ - sora ログ - cluster ログ - internal ログ - api ログ - signaling ログ - connection ログ - auth_webhook ログ - auth_webhook_error ログ - session_webhook ログ - session_webhook_error ログ - event_webhook ログ - event_webhook_error ログ - stats_webhook ログ - stats_webhook_error ログ ### id Sora が出力する全ての JSONL 形式のログには UUIDv4 を Base32 でエンコードした `"id"` が含まれます。 `"id": "JKBYVZA3KN6QH249B6QTKDCX8M"` ## auth_webhook ログ **出力ファイル名**: auth_webhook.jsonl ```javascript { "timestamp": "2024-01-19T02:44:22.799941Z", "id": "7N7RTNSEVN43ZB7NVXGAYPETJ4", "req": { "timestamp": "2024-01-19T02:44:22.793747Z", "id": "1EYTQSFVZ56MZ2BRZC12GQYQKW", "x_forwarded_for": "49.97.11.19", "version": "2024.1.0", "label": "WebRTC SFU Sora", "node_name": "sora@127.0.0.1", "role": "sendrecv", "channel_id": "sora", "connection_id": "9SRMRSDWA959XFN74DCV3Z6XA0", "simulcast": false, "spotlight": false, "audio": true, "audio_codec_type": "OPUS", "video": true, "video_codec_type": "VP9", "video_bit_rate": 500, "video_vp9_params": { "profile_id": 0 }, "data_channel_signaling": true, "ignore_disconnect_websocket": false, "channel_connections": 0, "channel_sendrecv_connections": 0, "channel_sendonly_connections": 0, "channel_recvonly_connections": 0, "sora_client": { "raw": "Sora JavaScript SDK 2024.1.0", "type": "Sora JavaScript SDK", "version": "2024.1.0", "environment": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36" }, "e2ee": false }, "res": { "allowed": true, "client_id": "client-01" }, "url": "http://192.0.2.1:9000/webhook/auth" } ``` ## auth_webhook_error ログ **出力ファイル名**: auth_webhook_error.jsonl 認証ウェブフックが正常に動作しなかった場合に出力します。 `auth_webhook` ログとは異なり `res` ではなく `reason` が出力されます。 ## session_webhook ログ **出力ファイル名**: session_webhook.jsonl レスポンスが返却されない場合、 `res` は出力されません。 ```javascript { "id": "XJ227VDDFH60BAB833C1R2HDBW", "timestamp": "2024-04-19T05:32:25.583312Z", "req": { "id": "D5PAF0ZHDX00B4VAWMZAR866MR", "label": "WebRTC SFU Sora", "timestamp": "2024-04-19T05:32:24.280641Z", "type": "session.created", "version": "2024.1.0", "node_name": "sora@127.0.0.1", "session_id": "NAA3DGPJQH2J7FDV698RZ9X6R0", "channel_id": "sora", "spotlight": false, "created_time": 1713504744, "created_timestamp": "2024-04-19T05:32:24.277809Z" }, "url": "http://192.0.2.1/webhook/session", "res": { "recording": true } } ``` ## connection ログ **出力ファイル名**: connection.jsonl Sora は接続単位で統計情報を保持しています。クライアント側の統計情報とサーバー側の統計情報の両方をログとして出力します。 クライアント側の統計情報は RTC 統計情報機能を利用しているため、 SDK 側が RTC 統計機能に対応している必要があります。 こちらのログはログローテーションしないため、ローテーションが必要となります。 ## sora ログ **出力ファイル名**: sora.jsonl sora ログは主にサポートで利用するためのログを出力します。そのためエラーメッセージがかなり技術的な表現になっています。 - sora ログは何かあって大量のログが出たとしてもうまい具合にスキップする機能が入っています ### UTC に固定 sora ログのタイムスタンプは RFC 3339 UTC (マイクロ秒) 形式に固定されています。 `timestamp` という項目でタイムスタンプが出力されます。 ```javascript { "id": "QGJMC1AF3552V448N8F53CZBJ4", "level": "debug", "channel_id": "sora", "role": "sendonly", "simulcast": false, "spotlight": false, "node_name": "sora@127.0.0.1", "connection_id": "NXHKH46FP93571ZM4PZBSFD4Z4", "timestamp": "2022-08-02T04:43:02.828358Z" } ``` ### クラスター利用時 ```javascript { "id": "QR6YX8VW8H76N6S3B7HBCXJ4PM", "level": "debug", "channel_id": "sora", "role": "sendonly", "simulcast": false, "spotlight": false, "node_name": "sora@127.0.0.1", "connection_id": "NXHKH46FP93571ZM4PZBSFD4Z4", "timestamp": "2022-08-02T04:43:02.828358Z" } ``` ### オプション情報 ```javascript { "level": "debug", "channel_id": "sora", "role": "sendonly", "simulcast": false, "spotlight": false, "node_name": "sora@127.0.0.1", "connection_id": "NXHKH46FP93571ZM4PZBSFD4Z4", "timestamp": "2022-08-02T04:43:02.828358Z" } ``` ### 出力例 ライセンスの同時接続数を超えて接続しようとした際に出力される `EXCEED-MAX-CONNECTIONS` の出力例は次の通りです。 ```javascript { "id": "JKBYVZA3KN6QH249B6QTKDCX8M", "timestamp": "2024-01-19T02:44:22.799941Z", "node": "sora@127.0.0.1", "level": "error", "msg": "EXCEED-MAX-CONNECTIONS | connections=101", "domain": [ "sora", "signaling" ], "channel_id": "sora", "role": "recvonly", "connection_id": "J9RQEB074S2EB9SFBCN9AH7ASM", "simulcast": false, "spotlight": false, "sora_version": "2024.1.0" } ``` 認証ウェブフック成功時に認証サーバーから払い出された値が不正な場合に出力される `INVALID-AUTHZ-VALUE` の出力例は次の通りです。 ```javascript { "id": "7N7RTNSEVN43ZB7NVXGAYPETJ4", "timestamp": "2024-01-19T02:44:22.799941Z", "node": "sora@127.0.0.1", "level": "warning", "msg": "INVALID-AUTHZ-VALUE | client_id=12345", "domain": [ "sora", "signaling" ], "channel_id": "sora", "role": "sendrecv", "connection_id": "9SRMRSDWA959XFN74DCV3Z6XA0", "simulcast": false, "spotlight": false, "sora_version": "2024.1.0" } ``` DataChannel シグナリングで `ignore_disconnect_websocket: true` の際に WebSocket が想定外の終了をした場合に出力される `WEBSOCKET-TERMINATE` の出力例は次の通りです。 ```javascript { "id": "XJ227VDDFH60BAB833C1R2HDBW", "timestamp": "2024-04-19T05:32:25.583312Z", "node": "sora@127.0.0.1", "level": "warning", "msg": "WEBSOCKET-TERMINATE | reason={error,closed}, connected=true", "domain": [ "sora", "signaling" ], "channel_id": "sora", "role": "sendrecv", "connection_id": "174QEZP34D45B6S7665Y32MSQ0", "simulcast": false, "spotlight": false, "sora_version": "2024.1.0" } ``` ### warning ログレベル `warning` は「接続自体は維持できる問題」の際に出力します。 このログが出力された場合でも Sora 側から切断は行いません。 - 一般- WEBSOCKET-TERMINATE- DataChannel シグナリングで ignore_disconnect_websocket: true の際に WebSocket が想定外の終了をした場合に出力します - MULTISTREAM-RE-ANSWER-NO-ICE-UFRAG- マルチストリーム利用時 `type: re-answer` を受信した際に ICE に必要な SDP が含まれていない場合に出力します - MULTISTREAM-INTERNAL-ERROR - ウェブフック- INVALID-AUTHZ-VALUE- 認証ウェブフック成功時に認証サーバーからの払い出した値がおかしい場合に出力します - TERMINATE-EVENT-WORKER- イベントウェブフックのワーカーが何らかの理由で終了した場合に出力します - MISSING-WEBHOOK-BASIC-AUTH-USER-ID- ウェブフック利用時にベーシック認証のユーザー ID が見つからない場合に出力します - MISSING-WEBHOOK-BASIC-AUTH-PASSWORD- ウェブフック利用時にベーシック認証のパスワードが見つからない場合に出力します - MISSING-WEBHOOK-PROXY-AUTH-PASSWORD- ウェブフック利用時にプロキシのパスワードが見つからない場合に出力します - 録画- ARCHIVE-FINAL-SPLIT-ERROR- 録画ファイルの分割がエラーになった場合に出力します、ただし全体出力に向けて処理は継続します - プロトコル- DTLS-ALERT- DTLS でレベルが WARNING のアラートメッセージがクライアントから送られてきた場合に出力します - TURN-SEND-INDICATION-BINDING-ERROR- TURN 利用時に STUN-Binding-Error over STUN-Send-Indication を受信した場合に出力します - TURN-CHANNEL-DATA-BINDING-ERROR- TURN 利用時に STUN-Binding-Error over TURN-Channel-Data を受信した場合に出力します - SIMULCAST-DUPLICATED-RID- クライアントから複数の SSRC から同一の RID が送られてきた場合に出力します - UNKNOWN-RTP- `role: recvonly` にもかかわらず RTP パケットが送られてきた場合に出力します - Sora の内部エラーでも出力される場合があります - UNKNOWN-RTCP- 見知らぬ RTCP を受信した場合に出力します - ULPFEC-RECOVER-ERROR- ULPFEC を利用している場合にリカバーを試みて失敗した場合に出力します - RTP-PACKET-LOSS-SIMULATOR-INCOMING-ENABLED- 受信パケロスシュミレーターを有効にしている場合に出力します - RTP-PACKET-LOSS-SIMULATOR-OUTGOING-ENABLED- 送信パケロスシュミレーターを有効にしている場合に出力します ### error ログレベル `error` は「接続自体を維持できない問題」の際に出力します。 このログが出力された場合、Sora 側から切断を行います。 - 一般- UNEXPECTED-EXIT - シグナリング- INTERNAL-ERROR- Sora の内部エラーです - SIGNALING-INTERNAL-ERROR- シグナリングでの内部エラーが発生した場合に出力します - ライセンス- EXPIRED-LICENSE- ライセンスが切れている場合に出力されます - EXCEED-MAX-CONNECTIONS- ライセンスの同時接続数を超えて接続をしようとしたクライアントがいた場合に出力されます - イベントウェブフック- EVENT-WEBHOOK-ERROR- イベントウェブフックリクエストが正常に送信できなかった場合に出力します - DataChannel- INVALID-DATA-CHANNEL-USER-DATA- 片方向でしか利用していない DataChannel にメッセージが送られてきた場合に出力します - 録画- ARCHIVE-FAILED- 録画ファイルの生成に失敗した際に出力します - プロトコル- TURN-UDP-INTERNAL-ERROR- TURN UDP で内部エラーが発生した場合に出力します - DTLS-ALERT- DTLS でレベルが FATAL のアラートメッセージが送られてきたとき出力します ### emergency ログレベル `emergency` は「Sora の起動を維持できない問題」の際に出力します。 このログが出力された場合、Sora を終了します。 - SORA-NODE-DUPLICATED- 同一ノード名の Sora が既に起動している場合に出力します - `src/` 以下の Erlang コードではなく、起動前スクリプト `rel/pkg/pre_start` から `sora.jsonl` に直接書き込まれます - BOOT-FAILED- Sora が正常に起動できない場合に出力します - 設定- SORA-CONF-ERROR- sora.conf が正常に読み込めない場合に出力します # ログの型定義 ここではログの型について説明します。型の表記は TypeScript で記述します。 [ウェブフックの型定義](WEBHOOK_TYPE.html) も利用しています。 ## 基本的な型 ```typescript // @ts-check // JSON 値を表します。 // 仕様は RFC 8259 に従います。 type JSONValue = | null | boolean | number | string | JSONValue[] | { [key: string]: JSONValue | undefined }; // UnixTime // 例: 1704067199 type UnixTime = number; // RFC3339 UTC (マイクロ秒) // 例: 2023-12-31T23:59:59.999999Z type Timestamp = string; // ストリームの種別 type Role = "sendrecv" | "sendonly" | "recvonly"; // 最大 255 バイト type ChannelId = string; type SessionId = string; type ClientId = string; type BundleId = string; // Base32(UUIDv4) 26 文字の文字列 type ConnectionId = string; // サイマルキャストで視聴する映像の種類 type SimulcastRid = "none" | "r0" | "r1" | "r2"; type OpusParams = { channels?: number; maxplaybackrate?: number; // 6000..510000 maxaveragebitrate?: number; minptime?: number; ptime?: number; stereo?: boolean; sprop_stereo?: boolean; useinbandfec?: boolean; usedtx?: boolean; }; // 音声の設定 type Audio = | boolean | { codec_type?: AudioCodecType; bit_rate?: number; opus_params?: OpusParams; }; type VideoVP9Params = { // 0..3 profile_id?: number; }; type VideoAV1Params = { // 0..2 profile?: number; // 0..15 level_idx?: number; // 0..1 tier?: number; }; type VideoH264Params = { profile_level_id?: string; // 0..2 packetization_mode?: number; // 0..1 level_asymmetry_allowed?: number; // sora.conf で h264_b_frame = true を設定する必要があります b_frame?: boolean; }; type VideoH265Params = { level_id?: number; // 0..31 profile_id?: number; // 0..1 tier_flag?: number; // "SRST" | "MRST" | "MRMT" tx_mode?: H265TxMode; // sora.conf で h265_b_frame = true を設定する必要があります b_frame?: boolean; }; // 映像の設定 type Video = | boolean | { codec_type?: VideoCodecType; bit_rate?: number; // 利用するには sora.conf で signaling_vp9_params = true を設定する必要があります vp9_params?: VideoVP9Params; // 利用するには sora.conf で signaling_av1_params = true を設定する必要があります av1_params?: VideoAV1Params; // 利用するには sora.conf で signaling_h264_params = true を設定する必要があります h264_params?: VideoH264Params; // 利用するには sora.conf で signaling_h265_params = true を設定する必要があります h265_params?: VideoH265Params; }; // 音声コーデックの種類 type AudioCodecType = "OPUS"; // 映像コーデックの種類 type VideoCodecType = "VP9" | "VP8" | "AV1" | "H264" | "H265"; type H265TxMode = "SRST" | "MRST" | "MRMT"; // DataChannel の方向 type Direction = "sendrecv" | "sendonly" | "recvonly"; type DataChannelMessagingHeaderFieldType = "sender_connection_id"; type DataChannelMessagingHeaderField = { type: DataChannelMessagingHeaderFieldType; // * length は "type": "offer" 時の data_channels にのみ含まれる // * length は"type": "connect" 時には指定できない // * length は認証成功時の払い出し時には指定できない length?: number; }; // DataChannels type DataChannel = { label: string; direction: Direction; ordered: boolean; max_packet_life_time?: number; max_retransmits?: number; protocol?: string; compress: boolean; header?: DataChannelMessagingHeaderField[]; }; type TurnTransportType = "udp" | "tcp"; type ForwardingFilterRuleField = "connection_id" | "client_id" | "kind"; type ForwardingFilterRuleOperator = "is_in" | "is_not_in"; type ForwardingFilterRuleKindValue = "audio" | "video"; type ForwardingFilterRule = { field: ForwardingFilterRuleField; operator: ForwardingFilterRuleOperator; values: string[]; }; type ForwardingFilterAction = "block" | "allow"; type ForwardingFilter = { version?: string; metadata?: JSONValue; name?: string; priority?: number; action?: ForwardingFilterAction; rules: ForwardingFilterRule[][]; }; type SoraClientType = | "Sora JavaScript SDK" | "Sora iOS SDK" | "Sora Android SDK" | "Sora Unity SDK" | "Sora C++ SDK" | "Sora Python SDK" | "Sora C SDK" | "Sora Flutter SDK" | "OBS-Studio" | "OBS-Studio-WHIP" | "OBS-Studio-WHEP" | "WebRTC Native Client Momo" | "WebRTC Load Testing Tool Zakuro"; // SoraClient type SoraClient = { environment?: string; raw?: string; type?: SoraClientType; version?: string; commit_short?: string; libwebrtc?: string; }; // RTCRtpCodecParameters // https://www.w3.org/TR/webrtc/#dom-rtcrtpcodecparameters type SimulcastCodec = { // payloadType や channels は省略 mimeType: string; clockRate: number; sdpFmtpLine?: string; }; // RTCRtpEncodingParameters // https://w3c.github.io/webrtc-pc/#dom-rtcrtpencodingparameters type SimulcastEncoding = { // https://www.w3.org/TR/webrtc/#dom-rtcrtpcodingparameters-rid rid: SimulcastRid; // https://www.w3.org/TR/webrtc/#dom-rtcrtpencodingparameters-active active?: boolean; // https://www.w3.org/TR/webrtc/#dom-rtcrtpencodingparameters-maxframerate maxFramerate?: number; // https://www.w3.org/TR/webrtc/#dom-rtcrtpencodingparameters-maxbitrate maxBitrate?: number; // https://www.w3.org/TR/webrtc/#dom-rtcrtpencodingparameters-scaleresolutiondownby scaleResolutionDownBy?: number; // https://www.w3.org/TR/webrtc/#dom-rtcrtpcodec codec?: SimulcastCodec; // https://w3c.github.io/webrtc-extensions/#dom-rtcrtpencodingparameters-scaleresolutiondownto // @ts-expect-error RTCResolutionRestriction は typed で未定義のため型チェックを無視(型定義が追加され次第削除) scaleResolutionDownTo?: RTCResolutionRestriction; // https://w3c.github.io/webrtc-extensions/#dom-rtcrtpencodingparameters-adaptiveptime adaptivePtime?: boolean; // https://www.w3.org/TR/webrtc-svc/#dom-rtcrtpencodingparameters-scalabilitymode scalabilityMode?: string; }; ``` ## 型定義 ### ウェブフックログ ```typescript // @ts-check // Base32 化した UUIDv4 type WebhookID = string; // ウェブフック URL で HTTP または HTTPS type WebhookURL = string; // WebSocket シグナリング HTTP ヘッダーのコピー type CopyHeaders = Record; // 認証ウェブフックログ (auth_webhook.jsonl) type AuthWebhookLog = { id: WebhookID; timestamp: Timestamp; req: AuthWebhookLogRequest; res: AuthWebhookResponse; // ウェブフック URL url?: WebhookURL; // ウェブフック応答時間 (ミリ秒) // auth_webhook_url が未指定の場合はウェブフックを送信しないためキー自体を含めない response_time_ms?: number; copy_headers?: CopyHeaders; }; // 認証ウェブフックエラーログ (auth_webhook_error.jsonl) type AuthWebhookErrorLog = { id: WebhookID; timestamp: Timestamp; req: AuthWebhookLogRequest; // ウェブフック URL url: WebhookURL; // エラー理由 reason: string; // ウェブフック応答時間 (ミリ秒) response_time_ms?: number; copy_headers?: CopyHeaders; }; // 認証ウェブフックログ req 項目 type AuthWebhookLogRequest = AuthWebhookRequest & { x_forwarded_for?: string[]; }; // 認証ウェブフックログ res 項目 type AuthWebhookResponse = AuthWebhookAcceptResponse | AuthWebhookRejectResponse; // セッションウェブフックログ (session_webhook.jsonl) type SessionWebhookLog = { id: WebhookID; timestamp: Timestamp; req: SessionWebhookRequest; res?: SessionWebhookResponse; // ウェブフック URL url?: WebhookURL; // ウェブフック応答時間 (ミリ秒) // session_webhook_url が未指定、 もしくは ignore_*_webhook で無視するように指定したウェブフックの場合はウェブフックを送信しないためキー自体を含めない response_time_ms?: number; }; // セッションウェブフックエラーログ (session_webhook_error.jsonl) type SessionWebhookErrorLog = { id: WebhookID; timestamp: Timestamp; req: SessionWebhookRequest; // ウェブフック URL url?: WebhookURL; // エラー理由 reason: string; // ウェブフック応答時間 (ミリ秒) response_time_ms?: number; }; // イベントウェブフックログ (event_webhook.jsonl) type EventWebhookLog = EventWebhookRequest; // イベントウェブフックエラーログ (event_webhook_error.jsonl) type EventWebhookErrorLog = EventWebhookRequest; // 統計ウェブフックログ (stats_webhook.jsonl) type StatsWebhookLog = StatsWebhookConnectionRtcRequest; // 統計ウェブフックエラーログ (stats_webhook_error.jsonl) type StatsWebhookErrorLog = StatsWebhookConnectionRtcRequest; ``` ### コネクションログ ```typescript // @ts-check // コネクションログ (connection.jsonl) type ConnectionLog = { id: WebhookID; timestamp: Timestamp; node_name: string; label: string; version: string; created_timestamp: Timestamp; destroyed_timestamp: Timestamp; data_channel_signaling: boolean; ignore_disconnect_websocket: boolean; ignore_max_connections: boolean; role: Role; simulcast: boolean; simulcast_multicodec: boolean; // role が sendrecv または sendonly、simulcast が true、spotlight が false の場合のみ含まれます simulcast_encodings?: SimulcastEncoding[]; simulcast_codecs?: ConnectionLogSimulcastCodec[]; spotlight: boolean; // role が sendrecv または sendonly、simulcast が true、spotlight が true の場合のみ含まれます spotlight_encodings?: SimulcastEncoding[]; channel_id: ChannelId; group_id: SessionId; session_id: SessionId; client_id: ClientId; bundle_id: BundleId; connection_id: ConnectionId; audio: boolean; // audio が true の場合のみ含まれます audio_codec_type?: AudioCodecType; audio_bit_rate?: number; video: boolean; // video が true の場合のみ含まれます video_codec_type?: VideoCodecType; video_bit_rate?: number; video_width?: number; video_height?: number; video_vp9_params?: VideoVP9Params; video_av1_params?: VideoAV1Params; video_h264_params?: VideoH264Params; video_h265_params?: VideoH265Params; recording_block: boolean; turn_transport_type: TurnTransportType; turn_transport_src_ip_address?: string; turn_transport_src_port?: number; sora_client: SoraClient; copy_headers: CopyHeaders; local_stats: ConnectionLogLocalStats; destroyed_reason: ConnectionLogDestroyedReason; disconnect_api_reason?: JSONValue; type_disconnect_reason?: JSONValue; shutdown_reason?: string; websocket_terminated_reason?: string; data_channel_exit_reason?: string; signaling_terminate_reason?: string; rpc_methods: string[]; // クライアント側 RTC 統計情報 rtc_stats?: RTCStatsReport[]; }; type ConnectionLogDestroyedReason = | "normal" | "disconnected_api" | "session_destroyed" | "lifetime_expired" | "duplicate_client_id" | "abort" | "signaling_re_answer_timeout"; type ConnectionLogSimulcastCodec = { rid?: SimulcastRid; codec_type?: VideoCodecType; codec_params?: VideoVP9Params | VideoAV1Params | VideoH264Params | VideoH265Params; }; type ConnectionLogLocalStats = { rtp: ConnectionLogRtpStats; rtp_hdrext: ConnectionLogStatsCounters; rtcp: ConnectionLogStatsCounters; signaling: ConnectionLogSignalingStats; simulcast: Partial>; sctp: ConnectionLogStatsCounters; data_channel: Record; turn: ConnectionLogStatsCounters; dtls: ConnectionLogDtlsStats; packet_loss_simulator: ConnectionLogStatsCounters; spotlight: ConnectionLogStatsCounters; cc: ConnectionLogStatsCounters; ice_connection_state: ConnectionLogIceConnectionStateStats; media_publish_worker: ConnectionLogMediaPublishWorkerStats; }; type ConnectionLogStatsCounters = Record; type ConnectionLogRtpStats = { total_received_key_frame: number; total_ulpfec_recovered: number; total_sent: number; total_sent_byte_size: number; total_received: number; total_received_byte_size: number; total_sent_rtp_byte_size: number; total_sent_rtp_sfu_delay_us: number; total_sent_rtp: number; total_received_rtp_byte_size: number; total_received_rtp: number; total_received_sounding_rtp: number; total_received_rtp_payload_invalid: number; total_received_rtp_padding: number; total_received_rtp_padding_size: number; total_received_rtp_rtx: number; total_received_rtp_red: number; total_received_rtp_red_ulpfec: number; total_received_rtp_red_rtx: number; total_decrypt_skipped_srtp: number; total_decrypt_skipped_video_srtp: number; total_decrypt_skipped_audio_srtp: number; total_received_srtp_invalid: number; }; type ConnectionLogSignalingStats = { total_received_signaling_pong: number; total_sent_signaling_ping: number; }; type ConnectionLogSimulcastRidStats = { rtp: ConnectionLogSimulcastRidRtpStats; rtp_hdrext: ConnectionLogStatsCounters; }; type ConnectionLogSimulcastRidRtpStats = { total_decrypt_skipped_srtp: number; total_received_rtp: number; total_received_rtp_byte_size: number; total_received_rtp_padding: number; total_received_rtp_padding_size: number; total_received_rtp_red: number; total_received_rtp_red_rtx: number; total_received_rtp_red_ulpfec: number; total_received_rtp_rtx: number; }; type ConnectionLogDtlsStats = { total_received_dtls: number; total_sent_dtls: number; }; type ConnectionLogIceConnectionStateStats = { total_connected_req: number; total_connected_ack: number; total_checking_req: number; total_checking_ack: number; total_disconnected_req: number; total_disconnected_ack: number; total_connected_to_checking: number; total_checking_to_disconnected: number; total_disconnected_to_failed: number; total_checking_to_connected: number; total_disconnected_to_checking: number; total_checking_duration_ms: number; total_disconnected_duration_ms: number; }; type ConnectionLogMediaPublishWorkerStats = { peak_count: number; total_started: number; total_stopped: number; total_unknown_subscriber: number; }; type ConnectionLogDataChannelStats = { ordered: boolean; max_packet_life_time?: number; max_retransmits?: number; protocol: string; direction: string; compress: boolean; total_data_channel_abandon_message: number; total_data_channel_retransmit_message: number; total_data_channel_open_message: number; total_data_channel_ack_message: number; total_received_data_channel_message: number; total_received_data_channel_message_byte_size: number; total_sent_data_channel_message: number; total_sent_data_channel_message_byte_size: number; }; ``` ### シグナリングログ ```typescript // @ts-check // シグナリングログ (signaling.jsonl) type SignalingLog = | SignalingLogConnect | SignalingLogRedirect | SignalingLogOffer | SignalingLogAnswer | SignalingLogCandidate | SignalingLogReOffer | SignalingLogReAnswer | SignalingLogDisconnect | SignalingLogSwitched | SignalingLogWebsocketTerminate | SignalingLogUnknownType | SignalingLogWhipOffer | SignalingLogWhipAnswer | SignalingLogWhipRedirect | SignalingLogWhepOffer | SignalingLogWhepAnswer | SignalingLogWhepRedirect; type SignalingLogBase = { id: WebhookID; channel_id: ChannelId; connection_id: ConnectionId; timestamp: Timestamp; // role が未確定の場合は "-" が出力されます role: Role | "-"; }; // type: "connect" type SignalingLogConnect = SignalingLogBase & { type: "connect"; // type: connect メッセージの内容をそのまま記録します json: SignalingConnectMessage; }; // type: "redirect" type SignalingLogRedirect = SignalingLogBase & { type: "redirect"; json: SignalingRedirectMessage; }; // type: "offer" type SignalingLogOffer = SignalingLogBase & { type: "offer"; sdp: string; json: SignalingOfferMessage; }; // type: "answer" type SignalingLogAnswer = SignalingLogBase & { type: "answer"; sdp: string; }; // type: "candidate" type SignalingLogCandidate = SignalingLogBase & { type: "candidate"; sdp: string; }; // type: "re-offer" type SignalingLogReOffer = SignalingLogBase & { type: "re-offer"; sdp: string; }; // type: "re-answer" type SignalingLogReAnswer = SignalingLogBase & { type: "re-answer"; sdp: string; }; // type: "disconnect" type SignalingLogDisconnect = SignalingLogBase & { type: "disconnect"; type_disconnect_reason?: JSONValue; }; // type: "switched" type SignalingLogSwitched = SignalingLogBase & { type: "switched"; ignore_disconnect_websocket: boolean; }; // type: "websocket-terminate" type SignalingLogWebsocketTerminate = SignalingLogBase & { type: "websocket-terminate"; reason: SignalingLogWebsocketTerminateReason; connected: boolean; data_channel_signaling: boolean; ignore_disconnect_websocket: boolean; // reason が "remote-closed" かつ Cowboy から close コード付きで終了した場合のみ含まれます close_code?: number; // reason が "other-error" の場合のみ含まれます cause?: string; }; type SignalingLogWebsocketTerminateReason = | "remote-closed" | "self-closed" | "error-closed" | "other-error"; // type: "unknown-type" type SignalingLogUnknownType = SignalingLogBase & { type: "unknown-type"; json: JSONValue; }; // type: "whip-offer" type SignalingLogWhipOffer = SignalingLogBase & { type: "whip-offer"; sdp: string; }; // type: "whip-answer" type SignalingLogWhipAnswer = SignalingLogBase & { type: "whip-answer"; sdp: string; }; // type: "whip-redirect" type SignalingLogWhipRedirect = SignalingLogBase & { type: "whip-redirect"; node: string; }; // type: "whep-offer" type SignalingLogWhepOffer = SignalingLogBase & { type: "whep-offer"; sdp: string; }; // type: "whep-answer" type SignalingLogWhepAnswer = SignalingLogBase & { type: "whep-answer"; sdp: string; }; // type: "whep-redirect" type SignalingLogWhepRedirect = SignalingLogBase & { type: "whep-redirect"; node: string; }; // シグナリングエラーログ (signaling_error.jsonl) type SignalingErrorLog = { id: WebhookID; timestamp: Timestamp; version: string; label: string; node_name: string; connection_id: ConnectionId; simulcast: boolean; spotlight: boolean; message: SignalingErrorMessage; accepted: boolean; sdp_negotiation_state: SignalingErrorLogSdpNegotiationState; ipv4_address_list: string[]; ipv6_address_list: string[]; data: SignalingErrorLogData; // エラー内容に応じて異なる JSON オブジェクトが出力されます details: JSONValue; config: SignalingErrorLogConfig; }; type SignalingErrorMessage = | "UNAUTHORIZED" | "INTERNAL-ERROR" | "SERVICE-UNAVAILABLE" | "TIMEOUT" | "INVALID-MESSAGE"; type SignalingErrorLogSdpNegotiationState = | "waiting_connect" | "offer_sent" | "waiting_answer" | "waiting_dtls_ack" | "maybe_re_offer" | "waiting_re_answer"; type SignalingErrorLogData = { role?: Role; channel_id?: ChannelId; group_id?: SessionId; session_id?: SessionId; client_id?: ClientId; bundle_id?: BundleId; audio?: boolean; video?: boolean; sora_client?: SoraClient; // channel_id が不明な場合は含まれません stats?: SignalingErrorLogConnectionStats; }; type SignalingErrorLogConnectionStats = { timestamp: Timestamp; group_id: SessionId; session_id: SessionId; channel_id: ChannelId; client_id: ClientId; bundle_id: BundleId; connection_id: ConnectionId; signaling: ConnectionLogSignalingStats; rtp: ConnectionLogRtpStats; rtp_hdrext: ConnectionLogStatsCounters; rtcp: ConnectionLogStatsCounters; simulcast: Partial>; sctp: ConnectionLogStatsCounters; data_channel: Record; turn: ConnectionLogStatsCounters; dtls: ConnectionLogDtlsStats; packet_loss_simulator: ConnectionLogStatsCounters; spotlight: ConnectionLogStatsCounters; cc: ConnectionLogStatsCounters; simulcast_auto: ConnectionLogStatsCounters; ice_connection_state: ConnectionLogIceConnectionStateStats; media_publish_worker: ConnectionLogMediaPublishWorkerStats; }; type SignalingErrorLogConfig = { turn: boolean; turn_realm: string; turn_fqdn: string; turn_tcp: boolean; turn_tcp_listen_port: number; turn_tcp_port: number; turn_tls: boolean; turn_tls_fqdn: string; turn_tls_port: number; rtx: boolean; ulpfec: boolean; connection_created_wait_timeout: number; ipv6: boolean; }; ``` ### その他のログ ```typescript // @ts-check // JSON Lines 形式ではないログは定義していません。 // RTC 統計ログ type RtcStatsLog = { id: WebhookID; timestamp: Timestamp; node_name: string; label: string; version: string; type: string; role: string; channel_id: ChannelId; group_id: SessionId; session_id: SessionId; client_id: ClientId; bundle_id: BundleId; connection_id: ConnectionId; simulcast: boolean; spotlight: boolean; rtc_timestamp: DOMHighResTimeStamp; rtc_type: RTCStatsType; rtc_id: string; // https://www.w3.org/TR/webrtc/#dom-rtcstatsreport rtc_data: Record; copy_headers?: CopyHeaders; log_written: boolean; }; // API ログの操作種別 type ApiLogOperation = | "ChangeMode" | "DisconnectChannel" | "DisconnectChannelByRole" | "DisconnectClient" | "DisconnectConnection" | "InitCluster" | "PurgeClusterNode" | "RegisterClusterNode" | "StartForwardingRtp" | "StartRecording" | "StopForwardingRtp" | "StopRecording"; // API ログ type ApiLog = { id: WebhookID; timestamp: Timestamp; // 操作 operation: ApiLogOperation; // JSON データ json: string; }; ``` # アプリケーション連携チュートリアル > **重要** > > このドキュメントについては Sora サポートの対象外です。 このドキュメントは Sora のウェブフックと API を利用したアプリケーションサーバー開発者向けです。 ## 概要 Sora はウェブフックと API を利用して、アプリケーションサーバーと連携することができます。 ### ウェブフック ウェブフックは認証と払い出し、そしてコネクションやセッション、録画などの状況の取得です。 Sora から一定間隔で送られてくるウェブフックを利用することで定期的な状態を取得することができます。 どのコネクションが何分繫いでいたかの把握や、そのセッションは何分で終了させるといったことも実現できます。 ウェブフックは Sora からアプリケーションサーバーへ `HTTP/1.1` でリクエストで送信します。 ### API ウェブフックはコネクションの切断、セッションの破棄、統計情報の取得などアプリケーションサーバーが必要とするタイミングで送信することができます。 API はアプリケーションサーバーから Sora へ `HTTP/1.1` でリクエストを送信する必要があります。 ## JSON Sora がアプリケーションに送信するウェブフックの JSON は `snake_case` を採用しています。 `camelCase` ではないことに注意してください。 `snake_case` の JSON はシグナリング、ウェブフック、 API で利用します。 ## ウェブフックのローカル開発 Sora をサーバーに立て、ウェブフックの送信先をローカルにしたい場合には [ngrok](https://ngrok.com/) がお勧めです。 ### ngrok の利用方法 **URL**: ngrok は無料プランでも、静的ドメインを一つ利用することができるため、 この静的ドメインを Sora 側に指定することにより、ローカルのウェブフックを利用することができます。 ngrok は Windows / Linux / macOS で利用できます。 また ngrok が HTTPS を終端し、HTTP でアプリケーションサーバーにリクエストを送信するため、 アプリケーションサーバー側を HTTPS にする必要はありません。 ### シーケンス図 ngrok を利用した場合のシーケンス図です。 `--domain` には example ではなく ngrok のダッシュボードに表示されているドメインを指定してください。 ```mermaid sequenceDiagram participant C as クライアント participant S as Sora participant NS as Ngrok Server
https://example.ngrok-free.app box ローカル環境 participant NC as Ngrok Client
$ ngrok http --domain=example.ngrok-free.app 8080 participant A as ローカルアプリケーション
http://localhost:8080 end C ->>+ S: "type": "connect" S ->>+ NS: 認証ウェブフック NS ->>+ NC: 認証ウェブフック NC ->>+ A: 認証ウェブフック A -->>- NC: 200 OK
"allowed": true NC -->>- NS: 200 OK
"allowed": true NS -->>- S: 200 OK
"allowed": true S ->>- C: "type": "offer" ``` ## サンプルコードについて アプリケーションサーバーのサンプルコードでは Python を利用しています。 あくまで例であり、実際のアプリケーションでの利用は想定しておりません。 現在は [OpenAI ChatGPT](https://openai.com/chatgpt/) や [GitHub Copilot](https://github.com/features/copilot/) を利用することで、 他の言語への変換がとても簡単に行えるようになったこともあり、 サンプルコードに利用するプログラミング言語を Python に統一しています。 Python 3.14 で動作確認をしています。 ## aiohttp サンプルコードでは Python の非同期 HTTP ライブラリである `aiohttp` を利用しています。 `$ pip install aiohttp` や `$ uv add aiohttp` でインストールして利用してください。 ### Django 風 ウェブフックの処理を行うコードです。 このドキュメントではこちらの書き方を利用します。 ```python from aiohttp import web async def auth_webhook(request: web.Request) -> web.Response: return web.json_response({"allowed": True}) app = web.Application() app.router.add_routes( [ web.post("/auth", auth_webhook), ] ) if __name__ == "__main__": web.run_app(app, port=8000) ``` ### Flask 風 デコレーターを利用して、ウェブフックの処理を行うコードです。 Django 風と Flask 風、どちらを利用するかは好みの問題ですので、 好きな方を利用してください。 ```python from aiohttp import web routes = web.RouteTableDef() @routes.post("/auth") async def auth_webhook(request: web.Request) -> web.Response: return web.json_response({"allowed": True}) app = web.Application() app.router.add_routes(routes) if __name__ == "__main__": web.run_app(app, port=8000) ``` ## ウェブフック HTTP 実装 ウェブフックを処理するコードです。 `sora.conf` の以下の設定に URL を指定してください。 - [auth_webhook_url](SORA_CONF.html#36a99a) - [session_webhook_url](SORA_CONF.html#76fa79) - [event_webhook_url](SORA_CONF.html#e1a4d2) 例として ngrok を利用している URL を指定しています。 ```ini auth_webhook_url = https://example.ngrok-free.app/auth session_webhook_url = https://example.ngrok-free.app/session event_webhook_url = https://example.ngrok-free.app/event ``` 認証が常に成功するようなコードになっています。 ```python from aiohttp import web async def auth_webhook(request: web.Request) -> web.Response: return web.json_response({"allowed": True}) async def session_webhook(request: web.Request) -> web.Response: return web.Response(status=204) async def event_webhook(request: web.Request) -> web.Response: return web.Response(status=204) app = web.Application() app.router.add_routes( [ web.post("/auth", auth_webhook), web.post("/session", session_webhook), web.post("/event", event_webhook), ] ) if __name__ == "__main__": web.run_app(app, port=8000) ``` ## ウェブフック HTTPS 対応 Sora のウェブフックは HTTPS にも対応しています。 Sora の HTTPS はサーバ証明書のチェックをデフォルトで OS に組み込まれた証明書を利用して行います。 自前で用意した証明書などを利用したい場合は [webhook_tls_verify_cacert_file](SORA_CONF.html#7036dc) を利用してください。 詳細は [ウェブフックリクエストなどの送信先サーバー証明書の検証に利用する OS 組み込みのルート CA 証明書について](WEBHOOK.html#e8a845) をご確認ください。 ```python import ssl from aiohttp import web async def auth_webhook(request: web.Request) -> web.Response: return web.json_response({"allowed": True}) async def session_webhook(request: web.Request) -> web.Response: return web.Response(status=204) async def event_webhook(request: web.Request) -> web.Response: return web.Response(status=204) app = web.Application() app.router.add_routes( [ web.post("/auth", auth_webhook), web.post("/session", session_webhook), web.post("/event", event_webhook), ] ) # サーバー証明書 certfile: str = "192.0.2.1.pem" # サーバー証明書のプライベートキー keyfile: str = "192.0.2.1-key.pem" if __name__ == "__main__": # SSL コンテキストの作成 ssl_context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH) ssl_context.load_cert_chain(certfile, keyfile) # HTTPS サーバーとして起動 web.run_app(app, port=4433, ssl_context=ssl_context) ``` ## ウェブフック mTLS (mutual-TLS またはクライアント認証) 対応 Sora のウェブフックは mTLS にも対応しています。 その場合、アプリケーションサーバー側に、Sora に設定した証明書の CA 証明書を指定する必要があります。 ```python import ssl from aiohttp import web async def auth_webhook(request: web.Request) -> web.Response: return web.json_response({"allowed": True}) async def session_webhook(request: web.Request) -> web.Response: return web.Response(status=204) async def event_webhook(request: web.Request) -> web.Response: return web.Response(status=204) app = web.Application() app.router.add_routes( [ web.post("/auth", auth_webhook), web.post("/session", session_webhook), web.post("/event", event_webhook), ] ) # サーバー証明書 certfile: str = "192.0.2.1.pem" # サーバー証明書のプライベートキー keyfile: str = "192.0.2.1-key.pem" # クライアント証明書のCA証明書 cafile: str = "ca.pem" if __name__ == "__main__": # SSL コンテキストの作成 ssl_context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH) ssl_context.load_cert_chain(certfile, keyfile) ssl_context.load_verify_locations(cafile) # クライアント証明書の検証を要求 ssl_context.verify_mode = ssl.CERT_REQUIRED # HTTPS サーバーとして起動 web.run_app(app, port=4433, ssl_context=ssl_context) ``` ## ウェブフック IPv6 対応 Sora は昨今の IPv4 事情を考慮して IPv6 にも対応しています。 `sora.conf` の `webhook_ipv6` を `true` にすることで、 IPv6 のみのウェブフックエンドポイントと通信をすることができます。 ## 認証ウェブフック Sora 自体は認証処理を持っていません。 そのため、アプリケーションサーバー側で認証の仕組みを開発する必要があります。 Sora は [auth_webhook_url](SORA_CONF.html#36a99a) に指定した URL にクライアントから送られてきた情報などを、 アプリケーションサーバに対して HTTP (または HTTPS) リクエストとして送信します。 ### 認証メタデータ 認証ウェブフックにはクライアントが送ってくる `metadata` が含まれます。 これはクライアントが自由に値を含められる場所で、ここの値を使って認証を行うことを推奨しています。 ```python from aiohttp import web async def auth_webhook(request: web.Request) -> web.Response: data = await request.json() # metadata がない場合は None が返る metadata = data.get("metadata") if not metadata: # metadata がない場合は認証を許可しない # 認証を拒否する場合は 'allowed': False と 'reason': '認証失敗理由' を返す # この認証失敗理由はクライアントまで通知されるので注意すること return web.json_response({"allowed": False, "reason": "metadata not found"}) # 認証を許可する JSON を返す return web.json_response({"allowed": True}) ``` ### 認証メタデータに JWT 認証メタデータの中に `access_token` として JWT が入ってきた場合の処理です。 [PyJWT](https://github.com/jpadilla/pyjwt) を利用して、JWT をデコードして認証を行います。 ```python import os import jwt from aiohttp import web async def auth_webhook(request: web.Request) -> web.Response: data = await request.json() metadata = data.get("metadata") if not metadata: return web.json_response({"allowed": False, "reason": "metadata not found"}) access_token = metadata.get("access_token") if not access_token: return web.json_response({"allowed": False, "reason": "access_token not found"}) # 環境変数からシークレットキーを取得 secret = os.environ.get("JWT_SECRET_KEY") if not secret: return web.json_response({"allowed": False, "reason": "secret key not found"}) try: # PyJWT を利用して JWT をデコードし、署名を検証する jwt.decode(access_token, secret, algorithms=["HS256"]) except jwt.InvalidTokenError: # トークンが無効の場合は認証を拒否 return web.json_response({"allowed": False, "reason": "invalid token"}) # 認証を許可する JSON を返す return web.json_response({"allowed": True}) ``` ### イベントメタデータ 認証ウェブフックで、認証成功時にイベントメタデータを払い出すことができます。 イベントメタデータはイベントウェブフックの `connection.{created, updated, destroyed}` に含まれます。 このイベントメタデータは Sora とアプリケーションサーバー間だけでやり取りされ、クライアントには送られません。 そのためデータベースの `Primary Key` などを入れておいたりすることができます。 ```python from aiohttp import web async def auth_webhook(request: web.Request) -> web.Response: # ここでデータベースなどの値を引っ張る account_pk = 1 # イベントメタデータ event_metadata = { "account_pk": account_pk, } # 認証を許可する JSON を返す return web.json_response({"allowed": True, "event_metadata": event_metadata}) ``` イベントメタデータはウェブフックログには `REDACTED` として記録されます。 これはセンシティブデータを含んでいる可能性があるためです。 `REDACTED` については [センシティブデータ](SENSITIVE_DATA.html) をご確認ください。 ```mermaid sequenceDiagram participant C as クライアント participant S as Sora participant A as アプリケーション C ->>+ S: "type": "connect" S ->>+ A: 認証ウェブフック A -->>- S: 200 OK
"allowed": true
"event_metadata": {"account_pk": 1} S ->>+ A: セッションウェブフック
session.created A -->>- S: 200 OK S ->>- C: "type": "offer" note over C,S: WebRTC 確立 S ->>+ A: イベントウェブフック
connection.created
"event_metadata": {"account_pk": 1} A -->>- S: 200 OK S ->>+ A: イベントウェブフック
connection.updated
"event_metadata": {"account_pk": 1} A -->>- S: 200 OK note over S,A: connection.updated は一定間隔で送信 C -) S: "type": "disconnect" S -) C: "Close" note over C,S: WebRTC 切断 S ->>+ A: イベントウェブフック
connection.destroyed
"event_metadata": {"account_pk": 1} A -->>- S: 200 OK ``` ## セッションウェブフック セッションウェブフックはセッション単位の変化を通知するためのウェブフックです。 Sora は `session_webhook_url` に指定した URL にセッションの変化を HTTP リクエストとして送信します。 ### セッション セッションはチャネルで少なくとも 1 つのクライアントが接続しているチャネルの状態を指します。 ### セッションメタデータ ```python from aiohttp import web async def session_webhook(request: web.Request) -> web.Response: # ここでデータベースなどの値を引っ張る room_pk = 2 return web.json_response({"session_metadata": {"room_pk": room_pk}}) ``` ### セッション録画開始 セッションウェブフックの `session.created` の戻り値に `recording: true` を含めることで、 そのセッションが開始したタイミングから録画を開始することができます。 ```python from aiohttp import web async def session_webhook(request: web.Request) -> web.Response: # このセッションで録画を有効にする return web.json_response({"recording": True}) ``` ## イベントウェブフック イベントウェブフックはコネクション単位での変化を通知するためのウェブフックです。 - コネクションが接続したら、コネクション接続のイベントが送信されます - コネクションが接続している間は、コネクション更新のイベントが一定間隔で送信されます- デフォルトでは 1 分間隔で送信されますが、 [connection_updated_webhook_interval](SORA_CONF.html#e67c3b) で変更できます - コネクションが切断したら、コネクション切断のイベントが送信されます ### connection.{created,updated,destroyed} ```python from aiohttp import web async def event_webhook(request: web.Request) -> web.Response: data = await request.json() match data.get("type"): case "connection.created": # connection.created イベントの処理 # データベースに保存したりする pass case "connection.updated": # connection.updated イベントの処理 # データベースに保存したりする pass case "connection.destroyed": # connection.destroyed イベントの処理 # データベースに保存したりする pass case _: # 未対応のイベントの処理 pass return web.Response(status=204) ``` ## API Sora の API は、パスを利用せず、ヘッダーを利用して判定する方式を採用しています。 - **メソッドは常に POST を利用します** - **パスは常に / を利用します** - `x-sora-target` ヘッダーを利用して、どの API にアクセスするかを判定します ## 指定したチャネルのコネクションを切断する ```python import asyncio import aiohttp async def main(): url = "https://sora.example.com" headers = { "X-Sora-Target": "Sora_20151104.DisconnectConnection", } data = { "channel_id": "sora", "connection_id": "T34CDBMRJS1B5BVPF17RTBQA3C", } async with aiohttp.ClientSession() as session: # Nginx で api の prefix を /api に設定している場合は以下のように変更 # response = await session.post(f"{url}/api", json=data, headers=headers) response = await session.post(url, json=data, headers=headers) print(response.status) response_data = await response.text() print(response_data) if __name__ == "__main__": asyncio.run(main()) ``` ## 接続してから 3 分経過したコネクションを切断する イベントウェブフック [connection.updated](EVENT_WEBHOOK.html#5430cd) と、 コネクション切断 [DisconnectConnection](API_SIGNALING.html#2ec3a0) API を利用して、 接続してから 3 分経過したコネクションを切断します。 ```python import aiohttp from aiohttp import web async def auth_webhook(request: web.Request) -> web.Response: return web.json_response({"allowed": True}) async def session_webhook(request: web.Request) -> web.Response: return web.Response(status=204) async def event_webhook(request: web.Request) -> web.Response: data = await request.json() match data.get("type"): case "connection.updated": if data.get("minutes", 0) >= 3: channel_id = data.get("channel_id") connection_id = data.get("connection_id") url = "https://sora.example.com/api" headers = { "X-Sora-Target": "Sora_20151104.DisconnectConnection", } data = { "channel_id": channel_id, "connection_id": connection_id, } async with aiohttp.ClientSession() as session: async with session.post( url, headers=headers, json=data, ) as response: if response.status != 200: # エラー処理 pass case _: # 見知らぬイベントの処理 pass return web.Response(status=204) app = web.Application() app.router.add_routes( [ web.post("/auth", auth_webhook), web.post("/session", session_webhook), web.post("/event", event_webhook), ] ) if __name__ == "__main__": web.run_app(app, port=8000) ``` ### シーケンス図 ```mermaid sequenceDiagram participant C as クライアント participant S as Sora participant A as アプリケーション C ->>+ S: "type": "connect" S ->>+ A: 認証ウェブフック A -->>- S: 200 OK
"allowed": true S ->>+ A: セッションウェブフック
session.created A -->>- S: 200 OK S ->>- C: "type": "offer" note over C,S: WebRTC 確立 S ->>+ A: イベントウェブフック
connection.created
"minutes": 0 A -->>- S: 200 OK S ->>+ A: イベントウェブフック
connection.updated
"minutes": 1 A -->>- S: 200 OK S ->>+ A: イベントウェブフック
connection.updated
"minutes": 2 A -->>- S: 200 OK note over C,A: WebRTC 確立してから 10 分経過 S ->>+ A: イベントウェブフック
connection.updated
"minutes": 10 A -->>- S: 200 OK A ->>+ S: DisconnectConnection API S -->>- A: 200 OK S -) C: "Close" note over C,S: WebRTC 切断 S ->>+ A: イベントウェブフック
connection.destroyed
"minutes": 10 A -->>- S: 200 OK ``` # シグナリング ## 概要 Sora では、 WebRTC 接続に必要な情報を交換する **シグナリング** に WebSocket と DataChannel を利用します。 - 利用するコーデックなどを決めるための情報を交換するため - 新しくクライアントが参加した際に、既存のクライアントに新しいクライアントの情報を伝えるため - クライアントが退出した際に、既存のクライアントに退出したクライアントの情報を伝えるため ## Sora のシグナリング方式について Sora ではシグナリングの方法として WebSocket と DataChannel を提供しています。 ここでは WebSocket と DataChannel を使用したシグナリングについて説明します。 ### WebSocket を使用したシグナリング Sora は最初に WebSocket でシグナリングを行います。 そのため、 WebSocket 経由のシグナリングは必須です。 メッセージの形式は JSON を採用しています。 詳細は [WebSocket 経由のシグナリング](WEBSOCKET_SIGNALING.html) をご確認ください。 ### DataChannel を使用したシグナリング Sora では WebSocket での接続確立までシグナリングが完了した後、その後のシグナリングを DataChannel に切り替えることができます。 詳細は [DataChannel 経由のシグナリング](DATA_CHANNEL_SIGNALING.html) をご確認ください。 ## WHIP / WHEP のシグナリング方式について Sora は RFC で定義されている WHIP / WHEP のシグナリング方式もサポートしています。 WHIP / WHEP のシグナリング方式は、HTTP を利用してシグナリングを行う方式です。 ### WHIP **RFC**: 詳細は [WHIP](WHIP.html) をご確認ください。 ### WHEP **RFC ドラフト**: 詳細は [WHEP](WHEP.html) をご確認ください。 ## シグナリングの型定義 Sora では TypeScript を利用した型定義情報を提供しています。 詳細は [シグナリングの型定義](SIGNALING_TYPE.html) をご確認ください。 ## シグナリング通知 Sora ではシグナリングに利用する WebSocket や DataChannel を利用して、 Sora 側からクライアントに対して通知をする仕組みがあり、これがシグナリング通知です。 詳細は [シグナリング通知](SIGNALING_NOTIFY.html) をご確認ください。 # WebSocket 経由のシグナリング ## 概要 > **重要** > > Sora の SDK を利用する場合は、ここに書かれているシグナリングの細かい仕様を把握する必要は基本的にありません。 Sora のシグナリングにはデフォルトでは WebSocket を使用します。 ## 用語 ### channel_id 接続のグルーピングに利用する ID です。 接続時に任意の文字列、最大 255 バイトまでを自由に指定できます。 ### session_id channel_id への接続が 0 から 1 に切り替わったタイミングで生成される id です。 1 から 0 になり、一定期間が経過したタイミングでセッションは破棄されます。 セッションが破棄された後、 再度同一 channel_id で接続が 0 から 1 になった場合、新しい session_id が生成されます。 セッションごとのユニークな値です。 UUIDv4 で生成した値を Base32 でエンコードした値で、Sora が払い出します。指定はできません。 ### client_id 接続時やサーバー認証成功時に任意の文字列を最大 255 バイトまで指定できる値です。 指定しない場合は connection_id が入ります。自由に指定できます。重複が可能な ID です。 > **注釈** > > `sora.conf` の [default_duplicate_client_id](SORA_CONF.html#c8b57b) を `evict` 、 > または [session.created](SESSION_WEBHOOK.html#1d1984) の払い出しに `duplicate_client_id` を `evict` に指定した場合はセッション単位でクライアント ID が重複するクライアントが接続してきた場合、 > 最初に接続していたクライアントが追い出されます。 ### bundle_id `bundle_id` を指定した場合、マルチストリーム利用時に `bundle_id` が等しい接続からの音声や映像、メッセージング、シグナリング通知を受信しなくなります。 接続時やサーバー認証成功時に任意の文字列を最大 255 バイトまで指定できる値です。指定しない場合は connection_id が入ります。 シグナリングでの bundle_id の指定はデフォルトでは無効になっているため、有効にする場合には `sora.conf` にて `signaling_bundle_id` を `true` にする必要があります。 ### connection_id 接続ごとのユニークな値です。 UUIDv4 で生成した値を Base32 でエンコードした値で、Sora が払い出します。指定はできません。 **connection_id の例** : "FW0CJSHETX0RXAGX8WWEXNBQN8" ## 仕組み Sora のシグナリングは、Sora からクライアントへ Offer (SDP) を送ります。 シグナリングの処理の流れは、[認証ウェブフックなし](WEBSOCKET_SIGNALING.html#cea9ce) のシーケンス図をご確認ください。 シグナリングの型の正確な仕様は [シグナリングの型定義](SIGNALING_TYPE.html) をご確認ください。 ### URL デフォルトの設定では、シグナリングは `0.0.0.0:5000` でリッスンするため、 シグナリング URL は `http://<サーバーのアドレス>:5000/signaling` となります。 **パス部分は /signaling 固定で変更できません** 。 ### DataChannel 経由への切り替え 詳細は [DataChannel 経由のシグナリング](DATA_CHANNEL_SIGNALING.html) をご確認ください。 ## 注意 シグナリングが完了しても WebSocket の接続は切断しないでください。WebSocket の接続が切れると Sora は WebRTC 接続を終了します。 - 30 秒以内に `"type": "answer"` を受信しなかった場合、 Sora は接続を終了します - 30 秒以内に `"type": "re-answer"` を受信しなかった場合、 Sora は接続を終了します ## 設定 ### signaling_loopback_address_only `sora.conf` にて [signaling_loopback_address_only](WEBSOCKET_SIGNALING.html#e22105) を `true` にすることで、 ループバックアドレスからのみアクセスできるようにします。 NGINX などを前段に利用している場合は可能な限り有効にしてください。 ## シグナリングのタイプ Sora のシグナリングは、タイプごとの JSON でクライアントとメッセージをやりとりします。 ### "type": "connect" クライアントは Sora に接続の意思を伝える JSON を送ります。以下は最小の JSON です。 ```javascript { "type": "connect", "role": "sendonly", "channel_id": "Spam" } ``` #### role そのクライアントの役割を指定します。この設定は必須です。 `role` には `sendrecv` / `sendonly` / `recvonly` のどれかを指定してください。 - sendrecv- 送信及び受信を行います - sendonly- 送信のみを行い、受信を行いません - recvonly- 受信のみを行い、送信を行いません #### channel_id `channel_id` は 1-255 バイトまでの文字列であればどのような文字列でも指定できます。 #### 配信または視聴メディアの選択 **この項目はオプションです** `audio` と `video` を指定することにより配信、または視聴するメディアを選択することができます。 `role` に `sendrecv` または `sendonly` を指定した場合は配信するメディア、 `recvonly` を指定したときは視聴するメディアについての指定となります。 この設定が未指定の場合は、 `true` がデフォルトで指定され、映像と音声両方の配信、または映像と音声両方の受信が行われます。 以下の例では `role` に `sendrecv` が指定されており、音声のみが配信されます。 ```javascript { "type": "connect", "role": "sendrecv", "channel_id": "Spam", "video": false } ``` > **注釈** > > `role` に `sendrecv` が指定された場合は常に映像と音声両方を受信します。 > もし特定のストリームを受信したくないなどある場合は [転送フィルター機能](FORWARDING_FILTER.html) を利用してください。 以下の例では `role` に `sendonly` が指定されており、映像のみが配信されます。 ```javascript { "type": "connect", "role": "sendonly", "channel_id": "Spam", "audio": false } ``` 以下の例では `role` に `recvonly` が指定されており、音声のみが受信されます。 ```javascript { "type": "connect", "role": "recvonly", "channel_id": "Spam", "video": false } ``` #### オーディオコーデック指定 **この項目はオプションです** `role` が `sendrecv` または `sendonly` の場合はオーディオコーデックを指定できます。 この設定はオプションです。 この設定が指定されない場合は、 `OPUS` がデフォルトで設定されます。 - Opus- "OPUS" ```javascript { "type": "connect", "role": "sendonly", "channel_id": "Spam", "audio": { "codec_type":"OPUS" } } ``` #### オーディオビットレート指定 **この項目はオプションです** > **重要** > > オーディオビットレートは指定しないことをおすすめします。指定しないことで最適なビットレートが採用されます。 `role` が `sendrecv` または `sendonly` の場合はオーディオビットレートの最大値を指定できます。 このビットレート指定は Opus にのみ有効です。 - bit_rate- 6-510 ```javascript { "type": "connect", "role": "sendonly", "channel_id": "Spam", "audio": { "codec_type": "OPUS", "bit_rate": 64 } } ``` 指定できる値は 6 から 510 です。32 を指定した場合は、32kbps がビットレートの最大値です。 指定しない場合は `sora.conf` の `default_audio_bit_rate` に指定した値が採用されます。 `default_audio_bit_rate` も指定していない場合、ビットレートはクライアント側に依存します。 #### オーディオの Opus 設定指定 > **注意** > > この機能は実験的機能です。この機能を利用される場合は必ず事前にサポートまでご連絡ください `role` が `sendrecv` または `sendonly` の場合は Opus の設定を指定できます。 - opus_params- channels- 1-8 - maxplaybackrate- 8000-48000 - stereo- boolean - sprop_stereo- boolean - minptime- integer 3-120 - useinbandfec- boolean - usedtx- boolean - **この機能を有効にした場合は録画がおかしくなります** ```javascript { "type": "connect", "role": "sendonly", "channel_id": "Spam", "audio": { "codec_type": "OPUS", "opus_params": { "stereo": false, "useinbandfec": false } } } ``` #### ビデオコーデック指定 **この項目はオプションです** `role` が `sendrecv` または `sendonly` の場合はビデオコーデックを指定できます。 この設定はオプションです。 この設定が指定されない場合は、VP9 がデフォルトで設定されます。 - VP8- `"VP8"` - VP9- "`VP9"` - AV1- `"AV1"` - Chrome M96 以降で利用できます - Safari では機能フラグを有効にすることで利用できます - Sora SDK で利用できます - H.264- `"H264"` - H.265- `"H265"` - Chrome M137 以降で利用できます - Safari で利用できます - Sora SDK で利用できます ```javascript { "type": "connect", "role": "sendonly", "channel_id": "Spam", "video": { "codec_type":"VP9" } } ``` #### ビデオビットレート指定 **この項目はオプションです** `role` が `sendrecv` または `sendonly` の場合はビデオビットレートの最大値を指定できます。単位は **kbps** です。 - bit_rate- 1-50000 ```javascript { "type": "connect", "role": "sendonly", "channel_id": "Spam", "video": { "codec_type": "VP9", "bit_rate": 500 } } ``` 指定できる値は 1 から 50000 です。500 を指定した場合は、500 kbps がビットレートの最大値です。 10 Mbps を最大値としたい場合は 10000 を指定してください。ただし 15 Mbps より大きい値は現時点ではサポート外となります。 指定しない場合は `sora.conf` の `default_video_bit_rate` に指定した値が採用されます。 #### ビデオの VP9 設定指定 `role` が `sendrecv` または `sendonly` の場合は VP9 のプロファイル ID を指定できます。 VP9 のプロファイル ID を指定をする場合は、あわせて `codec_type` に `VP9` を指定する必要があります。 - vp9_params- profile_id- integer - 0-3 この値を指定するには `sora.conf` にて [signaling_vp9_params](SORA_CONF.html#3261ea) を `true` に設定する必要があります。 ```javascript { "type": "connect", "role": "sendonly", "channel_id": "Spam", "video": { "codec_type": "VP9", "vp9_params": { "profile_id": 2 } } } ``` #### ビデオの AV1 設定指定 `role` が `sendrecv` または `sendonly` の場合は AV1 のプロファイル を指定できます。 AV1 のプロファイル を指定をする場合は、あわせて `codec_type` に `AV1` を指定する必要があります。 - av1_params- profile- integer - 0-2 - level_idx- integer - 0-31 - tier- integer - 0-1 この値を指定するには `sora.conf` にて [signaling_av1_params](SORA_CONF.html#91f3b8) を `true` に設定する必要があります。 ```javascript { "type": "connect", "role": "sendonly", "channel_id": "Spam", "video": { "codec_type": "AV1", "av1_params": { "profile": 0, "level_idx": 5, "tier": 0 } } } ``` #### ビデオの H.264 設定指定 `role` が `sendrecv` または `sendonly` の場合は H.264 のプロファイルレベル ID を指定できます。 H.264 のプロファイルレベル ID を指定をする場合は、あわせて `codec_type` に `H264` を指定する必要があります。 - h264_params- profile_level_id- string - "42e02a" など - b_frame- boolean - `sora.conf` にて [h264_b_frame](SORA_CONF.html#f546aa) が `true` に指定されているときに指定できます この値を指定するには `sora.conf` にて [signaling_h264_params](SORA_CONF.html#b32e49) を `true` に設定する必要があります。 ```javascript { "type": "connect", "role": "sendonly", "channel_id": "Spam", "video": { "codec_type": "H264", "h264_params": { "profile_level_id": "42e02a" } } } ``` #### ビデオの H.265 設定指定 > **注意** > > この機能は実験的機能です。この機能を本番環境で利用される場合は必ず事前にサポートまでご連絡ください > **警告** > > この機能はまだ対応しているライブラリが存在しません。 `role` が `sendrecv` または `sendonly` の場合は H.265 のプロファイルレベル ID を指定できます。 H.265 のプロファイルレベル ID を指定をする場合は、あわせて `codec_type` に `H265` を指定する必要があります。 - h265_params- level_id- integer - 93 など - profile_id- integer - 0-31 - tier_flag- integer - 0-1 - tx_mode- string - "SRST" または "MRST" または "MRMT" - b_frame- boolean - `sora.conf` にて [h265_b_frame](SORA_CONF.html#a9a8f8) が `true` に指定されているときに指定できます この値を指定するには `sora.conf` にて [signaling_h265_params](SORA_CONF.html#8ed4e9) を `true` に設定する必要があります。 ```javascript { "type": "connect", "role": "sendonly", "channel_id": "Spam", "video": { "codec_type": "H265", "h265_params": { "level_id": 93, "profile_id": 1, "tier_flag": 0, "tx_mode": "SRST" } } } ``` #### 認証メタデータ **この項目はオプションです** 認証するための判断材料としてメタデータを使用できます。 認証メタデータは必須ではありません。 ```javascript { "type": "connect", "role": "sendonly", "channel_id": "Spam", "metadata": "1234abcd" } ``` 認証メタデータは、そのまま認証サーバーに送られます。詳細は [認証ウェブフック](AUTH_WEBHOOK.html) をご確認ください。 #### client_id の指定 **この項目はオプションです** > **重要** > > `client_id` の値は重複することができます。 1-255 バイトまでの文字列であれば、どのような文字列でも指定できます。 ```javascript { "type": "connect", "role": "sendonly", "channel_id": "Spam", "client_id": "egg-ham" } ``` #### bundle_id の指定 **この項目はオプションです** > **重要** > > `bundle_id` の値は重複することができます。 1-255 バイトまでの文字列であれば、どのような文字列でも指定できます。 マルチストリーム利用時に `bundle_id` が同じ接続からの音声や映像、メッセージングを受信しなくなります。 この値を指定するには `sora.conf` にて [signaling_bundle_id](SORA_CONF.html#279311) を `true` に設定する必要があります。 ```javascript { "type": "connect", "role": "sendonly", "channel_id": "Spam", "bundle_id": "spam_egg" } ``` #### サイマルキャスト **この項目はオプションです** 自分が配信する映像のストリームを複数本にすることで、 受信側にどのストリームを受信するかを選択させることができるようになります。 ```javascript { "type": "connect", "role": "sendrecv", "channel_id": "spam", "simulcast": true } ``` 詳細は [サイマルキャスト機能](SIMULCAST.html) をご確認ください。 #### サイマルキャストマルチコーデック **この項目はオプションです** 自分が配信する映像のストリームを複数本かつ、複数コーデックにすることができます。 サイマルキャストマルチコーデック機能を利用する場合、 `sora.conf` にて [simulcast_multicodec](SORA_CONF.html#a8cf0f) を `true` に設定する必要があります。 ```javascript { "type": "connect", "role": "sendrecv", "channel_id": "spam", "simulcast": true, "simulcast_multicodec": true } ``` 詳細は [サイマルキャストマルチコーデック機能](SIMULCAST_MULTICODEC.html) をご確認ください。 #### スポットライト **この項目はオプションです** 話をした人にフォーカスを当てて、フォーカスが当たっている人は高画質な映像と音声で配信、 フォーカスが当たっていない人は低画質な映像で配信するという、クライアントの負荷を下げる仕組みです。 ```javascript { "type": "connect", "role": "sendrecv", "channel_id": "spam", "simulcast": true, "spotlight": true } ``` 詳細は [スポットライト機能](SPOTLIGHT.html) をご確認ください。 #### 転送フィルター **この項目はオプションです** 接続時に転送フィルターを指定することで、条件に該当する他のチャネル参加者の音声や映像の受信をブロックする仕組みです。 - forwarding_filters- 受信をブロックする条件をリストで指定します - 接続後は [転送フィルター API](API_FORWARDING_FILTER.html) を利用してフィルターの変更、削除ができます - この機能を利用するには [signaling_forwarding_filters](SORA_CONF.html#bf0e30) を `true` に設定する必要があります ```javascript { "type": "connect", "role": "sendrecv", "channel_id": "spam", "forwarding_filters": [ { "action": "block", "rules": [ [ {"field": "kind", "operator": "is_in", "values": ["audio"]} ] ] } ] } ``` 詳細は [転送フィルター機能](FORWARDING_FILTER.html) をご確認ください。 #### sdp **この項目はオプションです** Sora SDK や Sora クライアントで生成した offer SDP を Sora のログに記録します。 この項目は、ログの記録にのみ利用します。 ```javascript { "type": "connect", "role": "sendrecv", "channel_id": "spam", "sdp": "..." } ``` #### sora_client **この項目はオプションです** Sora SDK や Sora クライアントの情報を文字列で送ることができます。 これはログに記録されたり、認証ウェブフックリクエストで送信されたりします。 ```javascript { "type": "connect", "role": "sendrecv", "channel_id": "sora", "sora_client": "Sora JavaScript SDK 2021.1.0" } ``` #### environment **この項目はオプションです** Sora SDK や Sora クライアントの利用環境を文字列で送ることができます。 これはログに記録されたり、認証ウェブフックリクエストで送信されたりします。 Sora JavaScript SDK では userAgent の情報が入ります。 ```javascript { "type": "connect", "role": "sendrecv", "channel_id": "sora", "environment": "Mozilla\/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit\/537.36 (KHTML, like Gecko) Chrome\/93.0.4522.0 Safari\/537.36" } ``` #### libwebrtc **この項目はオプションです** Sora SDK や Sora クライアントの libwebrtc のバージョンを文字列で送ることができます。 これはログに記録されたり、認証ウェブフックリクエストで送信されたりします。 ```javascript { "type": "connect", "role": "sendrecv", "channel_id": "sora", "libwebrtc": "Shiguredo-Build M90.4430@{#3} (90.4430.3.1 dee77cf2)" } ``` #### redirect クラスター利用時に、接続先の Sora から `"type": "redirect"` を受け取って、 再度 Sora へ接続する際に、この値に `true` を指定する必要があります。 ### "type": "offer" 認証ウェブフックが認証成功を返すと、Sora は以下のような JSON をクライアントに送ります。 SDK を利用している場合は、この仕様を意識する必要はありません。 ```javascript { "type": "offer", "sdp": "", "channel_id": "sora", "session_id": "05JTBDGM1H3GB7FK0B1CJ45JE0", "connection_id": "ECF3W1RGMD02DETH30CDZTHNRW", "client_id": "ECF3W1RGMD02DETH30CDZTHNRW", "bundle_id": "ECF3W1RGMD02DETH30CDZTHNRW", "simulcast": false, "spotlight": false, "version": "2024.2.0", "metadata": "1234abcd", "audio": true, "audio_codec_type": "OPUS", "video": true, "video_codec_type": "VP9", "video_bit_rate": 500, "config": { "iceServers": [ { "credential": "ClDTPB4DjgFLrclpSBxjTiXg7K8kYsGf", "urls": [ "turn:192.0.2.1:443?transport=tcp" ], "username": "sYL5WdMt" } ], "iceTransportPolicy": "relay" }, "mid": { "audio": "audio_aDScYe", "video": "video_i2sNRq" }, "data_channels": [ { "compress": true, "label": "stats", "ordered": true, "direction": "sendrecv" }, { "compress": true, "label": "push", "ordered": true, "direction": "recvonly" }, { "compress": true, "label": "notify", "ordered": true, "direction": "recvonly" }, { "compress": true, "label": "signaling", "ordered": true, "direction": "sendrecv" }, { "compress": true, "label": "rpc", "ordered": true, "direction": "sendrecv" } ], "rpc_methods": [ "2025.2.0/PutSignalingNotifyMetadata", "2025.2.0/PutSignalingNotifyMetadataItem" ] } ``` - channel_id- `"type": "connect"` の `channel_id` で指定した値が入ります - session_id- UUIDv4 を Base32 でエンコードしたユニークな ID が入ります - connection_id- UUIDv4 を Base32 でエンコードしたユニークな ID が入ります - client_id- クライアントや認証サーバーが指定した値、または、Sora が生成した connection_id が入ります - bundle_id- クライアントや認証サーバーが指定した値、または、Sora が生成した connection_id が入ります - config- RTCPeerConnection に渡す設定が入ります - 主に TURN の情報です - mid- audio と video の MediaStream Id が入ります - audio- 音声の配信を行うかどうかが入ります - audio_codec_type- これはオプションです - `audio` が `true` かつ `role` が `sendrecv` または `sendonly` の場合に含まれます - 音声のコーデックが入ります - audio_bit_rate- これはオプションです - `audio` が `true` かつ `role` が `sendrecv` または `sendonly` で `audio_bit_rate` が指定された場合に含まれます - 音声のビットレートが入ります - video- 映像の配信を行うかどうかが入ります - video_codec_type- これはオプションです - `video` が `true` かつ `role` が `sendrecv` または `sendonly` の場合に含まれます - 映像のコーデックが入ります - video_bit_rate- これはオプションです - `video` が `true` かつ `role` が `sendrecv` または `sendonly` の場合に含まれます - 映像のビットレートが入ります - version- Sora のバージョンが入ります - metadata- これはオプションです - 認証サーバーから払い出された metadata が入ります - data_channels- これは DataChannel 経由のシグナリングを有効にしている場合にのみ利用されます - 詳細は [DataChannel への切り替え要否の判断](DATA_CHANNEL_SIGNALING.html#1abf7f) をご確認ください - rpc_methods- これは RPC 機能を有効にしている場合にのみ利用されます - 詳細は [RPC 機能を利用する条件](RPC.html#167a95) をご確認ください ### "type": "answer" クライアントは offer を受け取りしだい、answer 用の SDP を生成します。 ```javascript { "type": "answer", "sdp": "" } ``` その後、必要があればクライアントは取得した candidate を送ります。 ```javascript { "type": "candidate", "candidate": "candidate:3179889176 1 tcp 1518214911 192.168.1.10 0 typ host tcptype active generation 0" } ``` ### "type": "disconnect" クライアントからこのメッセージを送ると、Sora は WebSocket を切断します。また、WebRTC 側も終了します。 クライアントから切断する際には、このメッセージを送るようにしてください。 ```javascript { "type": "disconnect" } ``` オプションとして `reason` を指定することもできます。 この値は [connection.destroyed](EVENT_WEBHOOK.html#6c02d0) の `type_disconnect_reason` として含まれます。 `reason` は最大 128 バイトまで指定することができます。 ```javascript { "type": "disconnect", "reason": "NO-ERROR" } ``` ### "type": "ping" サーバーからクライアント側に定期的に送られる通知です。この値をクライアントが受け取った場合は、すぐに以下の JSON を Sora に送信してください。 ```javascript { "type": "pong" } ``` `"type": "ping"` を送ってから指定時間の間に一度も `"type": "pong"` が返ってこない場合、 Sora は正常な通信が行えていないと判断して、Sora からシグナリングの接続を切断します。 指定時間はデフォルトでは 60 秒に設定されており、この値は `sora.conf` の設定 [websocket_signaling_pong_timeout](SORA_CONF.html#140464) で変更できます。 #### stats > **注意** > > この機能は WebSocket 経由でのシグナリングの時のみ有効です `sora.conf` にて `rtc_stats` を `true` にしている場合は、 `"type": "ping"` 時に `"stats": true` が送られてきます。 ```javascript { "type": "ping", "stats": true } ``` この値を受け取った場合は、WebRTC の統計情報を取得して `"type": "pong"` 送信時に `stats` をキーにして値を含んで応答してください。 ```javascript { "type": "pong", "stats": [{"type": "..."}, {"type": "..."}] } ``` ### "type": "notify" サーバーからクライアントに対して、参加しているチャネルの情報が通知されるようになります。 詳細は [シグナリング通知機能](SIGNALING_NOTIFY.html) をご確認ください。 ### "type": "push" Sora の [プッシュ API](API_PUSH.html) や [シグナリング通知メタデータ拡張機能](SIGNALING_NOTIFY_METADATA_EXT.html) 、 [音声ストリーミング機能](AUDIO_STREAMING.html) 利用時にクライアントに送信されるプッシュ通知です。 `data` 内に各機能に応じた情報が設定されます。 ```javascript { "type": "push", "data": { : , : , ... } } ``` ## シグナリングエラー 切断時の reason を利用してハンドリングできます。 - Sora のシグナリング失敗時には必ず WebSocket が切断されます。 - どのようなエラーでも、ステータスコードは固定で 4490 が返ってきます。 - reason にはエラーメッセージが入ります ### クライアントに返されるエラーの種類 - `INTERNAL-ERROR` - `SERVICE-UNAVAILABLE` - `TIMEOUT` - `INVALID-MESSAGE` > **重要** > > Sora はライセンスの期限が切れていたとしても、クライアントには **SERVICE-UNAVAILABLE** というエラーを返します。 ### `signaling_error.jsonl` に出力される `message` 一覧 - `UNAUTHORIZED`- このエラーはクライアントに通知されることはなく、ログにしか出力されません - `INTERNAL-ERROR` - `SERVICE-UNAVAILABLE` - `TIMEOUT` - `INVALID-MESSAGE` ### `signaling_error.jsonl` に出力される `details.reason` の一部 * - details.reason - 解説 * - connection_created_wait_timeout - シグナリングを実行してから Sora と WebRTC の接続が成功するまでの許容時間を超えた場合に出力されるエラー * - answer_timeout - 30 秒以内に "type": "answer" を返さなかった場合のエラー * - pong_timeout - Ping の応答が返ってこなかった場合のエラー * - duplicated_channel_id - 同一の channel_id をすでに使用中の場合のエラー * - connect_wait_timeout - Open したあと一定時間以内に "type": "connect" のメッセージを送信しなかった場合のエラー * - missing_type - type: が JSON に含まれていなかった場合のエラー * - invalid_json - JSON 形式が間違っていた場合のエラー * - no_media - 音声も映像も有効にせずに "type": "connect" を送ってきた場合のエラー * - unexpected_type - シグナリングのフローとして許されない type を受信した場合のエラー * - unknown_type - 未知の type を受信した場合のエラー * - validate_error - シグナリングメッセージのバリデーションに失敗した場合のエラー * - exceed_max_connections - ライセンスの接続数を超えた接続が来た、またはライセンスの期限が切れている場合のエラー * - bad_fingerprint - 証明書検証が失敗した場合のエラー * - missing_sdp_fingerprint - SDP に fingerprint が含まれていない場合のエラー * - too_many_candidate - 多くの "type": "candidate" が送られてきた場合のエラー * - no_acceptable_node - クラスターのどのノードも受け入れられない場合のエラー * - invalid_signaling_params - セッションが残っている状態かつ、接続数が 0 ではない際にシグナリング項目が一致しない接続がきた場合のエラー * - block_new_connection - モードが ``block_new_connection`` のノードに、接続がきた場合のエラー * - block_new_session - ノードのモードが ``block_new_session`` かつ、そのノードが担当していないセッションに対しての接続がきた場合のエラー * - internal_error - 内部エラー ### connection_created_wait_timeout シグナリングを実行してから Sora と WebRTC の接続が成功するまでの許容時間を超えた場合に出力されるエラーです。 多くの場合はシグナリングの WebSocket は確立したものの、WebRTC の接続が失敗している場合に出力されます。 この許容時間はデフォルトでは 30 秒に設定されており、この値は `sora.conf` の設定 [connection_created_wait_timeout](SORA_CONF.html#0509af) で変更できます。 ```ini // これは 10 秒待っても、シグナリングが成功しない場合は接続を切断する設定です connection_created_wait_timeout = 10 s ``` > **注釈** > > [connection_created_wait_timeout](SORA_CONF.html#0509af) の値を 0 s にすることで、 > 意図的に connection_created_wait_timeout のエラーを発生させることができます。 ## シーケンス図 ### 認証ウェブフックなし ```mermaid sequenceDiagram autonumber participant C as クライアント participant S as WebRTC SFU Sora participant A as アプリケーションサーバー C->>+S: "type": "connect" S->>-C: "type": "offer" C->>S: "type": "answer" C->>S: "type": "candidate" note over C,A: WebRTC 確立 S->>+A: イベントウェブフック
"type": "connection.created" A-->-S: 200 OK C->>S: "type": "disconnect" S->>+A: イベントウェブフック
"type": "connection.destroyed" A-->>-S: 200 OK S->>C: Websocket Close ``` ### 認証ウェブフックあり ```mermaid sequenceDiagram autonumber participant C as クライアント participant S as WebRTC SFU Sora participant A as アプリケーションサーバー C->>+S: "type": "connect" S->>+A: 認証ウェブフック A-->>-S: 200 OK
{"allowed": "true"} S->>-C: "type": "offer" C->>S: "type": "answer" C->>S: "type": "candidate" note over C,A: WebRTC 確立 S->>+A: イベントウェブフック
"type": "connection.created" A-->-S: 200 OK C->>S: "type": "disconnect" S->>+A: イベントウェブフック
"type": "connection.destroyed" A-->>-S: 200 OK S->>C: Websocket Close ``` # DataChannel 経由のシグナリング ## 概要 DataChannel は WebRTC の機能の一つで文字列やバイナリといったデータの送受信を行える機能です。 Sora では WebRTC 接続確立後に、シグナリングを WebSocket 経由から DataChannel 経由に切り替えることができます。 ## 目的 WebSocket は TCP ベースのため Head of Line Blocking が存在し、不安定な回線などでパケットが詰まってしまうことがあります。 DataChannel は WebSocket とは異なり、パケットを並列でやりとりできるため、不安定な回線などでもパケットが詰まることが少なくなります。 シグナリングを WebSocket 経由から DataChannel 経由へ切り替える機能を提供することでより安定した接続が維持できます。 > **警告** > > DataChannel 経由のシグナリングを利用した場合でも、 > TURN-TCP や TURN-TLS を利用している場合は、 > TCP ベースとなるため Head of Line Blocking が存在します。 > そのため、 WebSocket 経由のシグナリングと同じ問題が発生します。 ## SDK 対応状況 - 最新版の JavaScript SDK- 対応済みです - 最新版の iOS SDK- 対応済みです - 最新版の Android SDK- 対応済みです - 最新版の Unity SDK- 対応済みです - 最新版の C++ SDK- 対応済みです - 最新版の Python SDK- 対応済みです ## 注意 DataChannel 経由のシグナリングを有効にした場合、ラベルが違うメッセージは並列に処理されます。 そのため、ラベルをまたいだメッセージ間の順序は保証されなくなります。 例えば、WebSocket 経由のシグナリングを利用する場合は、マルチストリーム時の SDP 再交換メッセージ `"type": "re-offer"` によって発火する `ontrack` イベントが、 参加通知である `"type": "notify", "event_type": "connection.created"` イベントより先に発火することが多くなります。 DataChannel 経由のシグナリングでは `ontrack` と `"type": "notify", "event_type": "connection.created"` 順序は不定となります。 不明点がある場合はサポートまでお問い合わせください。 ## 制限 - Sora の DataChannel 機能では、クライアント側から DataChannel を作成することはできません。- Sora 側で用意した DataChannel の Label のみを利用できます - Sora の DataChannel 機能では、クライアント側からデータを送信する際には特定の条件を満たす必要があります。 ## 推奨メッセージサイズ DataChannel で利用している SCTP というプロトコルはもともと小さなメッセージを送るために設計されたため、 大きなメッセージを送るのには向いていません。そのため 1 メッセージサイズは 64 KiB 以内を推奨しています。 64 KiB 以上のメッセージを送る場合は、大きくても 64 KiB 以下のメッセージなるように分割して送るようにしてください。 > **注釈** > > Sora は Chrome の仕様に合わせてメッセージサイズの最大値を 256 KiB にしていますが、 > 64 KiB 以下のメッセージを送ることを推奨しています。 ### 今後 libwebrtc が DataChannel の SCTP の I-DATA チャンクを実装することで、 より大きなメッセージに対応できるようになる予定です。 - [5696 - Support ndata for SCTP - webrtc](https://bugs.chromium.org/p/webrtc/issues/detail?id=5696&sort=-modified) - [RFC 8260 - Stream Schedulers and User Message Interleaving for the Stream Control Transmission Protocol](https://datatracker.ietf.org/doc/html/rfc8260) ### 参考資料 ## シグナリング切り替え DTLS が確立したタイミングで、シグナリングのやりとりを WebSocket 経由から DataChannel 経由に切り替える仕組みです。 > **重要** > > 切り替えが完了した場合でも、Sora 側からは WebSocket を切断しません。 シグナリングの切り替えを含めた DataChannel 経由のシグナリングの処理の流れは、[DataChannel シグナリング](DATA_CHANNEL_SIGNALING.html#5626ed) のシーケンス図をご確認ください。 ### シグナリングの切り替えを有効にする シグナリングの切り替えを有効にするには、次の 3 つの方法があります。 - `"type": "connect"` 時に `data_channel_signaling` を `true` にする - 認証成功時に `data_channel_signaling` を `true` で払い出す - `sora.conf` の [default_data_channel_signaling](SORA_CONF.html#adceef) を `true` にする Sora SDK を利用している限りは、これらの設定のみで、シグナリングの WebSocket 経由から DataChannel 経由への切り替えを利用できます。 ### "type": "switched" DataChannel へ完全に切り替わるタイミングで、 Sora は `"type": "switched"` を WebSocket 経由でクライアントへ送ります。 DataChannel に切り替わる前に WebSocket が閉じた場合、Sora はその接続が無効と判断して、接続を終了します。 ### DataChannel へ切り替わった後("type": "switched" 後)の WebSocket での "type": "ping" / "type": "pong" について WebSocket から DataChannel に切り替わると、 WebSocket の `"type": "ping"` を送る間隔が 5 秒から 15 秒に引き延ばされます。 さらに Sora が `"type": "pong"` を期待しなくなります。 `"type": "switched"` 後の `"type": "ping"` の送信間隔は `sora.conf` の [switched_websocket_signaling_ping_interval](SORA_CONF.html#6c5676) で変更できます。デフォルト値は 15 秒です。 ## WebSocket が閉じたことを無視する Sora は、デフォルトでは接続の切断判定に WebSocket を利用しています。WebSocket が閉じると、Sora は接続が切断したと判断します。 ただし、WebSocket が閉じた場合でも、接続が切断したと判断しないようにしたい場面もあるため、 `ignore_disconnect_websocket` という設定を用意しています。 この設定は `sora.conf` 、 `"type": "connect"` または認証成功時の払い出しで指定できます。 この設定を `true` にすることで、Sora は WebSocket が閉じてもその接続が切断したとは判断せずに、 WebRTC のやりとりを継続します。 > **注意** > > `"type": "disconnect"` を送らずに終了した場合、 DataChannel が切断に気付くまでには早くても 10 秒はかかります。 ### クライアント側の切断タイミング もし、 `ignore_disconnect_websocket` を `true` にして WebSocket を切断したい場合は、 必ず Sora から `"type": "switched"` を受け取った後にしてください。 `ignore_disconnect_websocket` が `true` の場合でも、 `"type": "switched"` を受け取る前に WebSocket を切断すると、 Sora はその接続が無効と判断して接続を終了します。 ## DataChannel への切り替え要否の判断 `"type": "offer"` に `"data_channels"` が含まれることを確認することで、DataChannel への切り替えが必要と判断できます。 切り替えが不要な場合は `"data_channels"` は送られてきません。 `data_channels` の各要素は `ordered` と `compress` を常に含み、 `max_packet_life_time` / `max_retransmits` / `protocol` は指定されている場合のみ含みます。 ```javascript { "type": "offer", "data_channels": [ { "compress": true, "label": "stats", "ordered": true, "direction": "sendrecv" }, { "compress": true, "label": "push", "ordered": true, "direction": "recvonly" }, { "compress": true, "label": "notify", "ordered": true, "direction": "recvonly" }, { "compress": true, "label": "signaling", "ordered": true, "direction": "sendrecv" }, { "compress": true, "label": "rpc", "ordered": true, "direction": "sendrecv" } ] } ``` ## label 単位の圧縮 Sora は、DataChannel 経由のメッセージを `zlib/deflate` で圧縮した送受信を要求する場合があります。 メッセージの圧縮や展開は Label ごとに要求します。 メッセージの圧縮や展開を要求する Label の情報は、 `"type": "offer"` 時に `data_channels` で `compress` を `true` に指定してクライアントに送ります。 - Sora は圧縮時に zlib ヘッダーを付けて送ってきます - Sora は展開時に zlib ヘッダーを必要とします - Sora は圧縮レベルは `default` を利用します ### 圧縮されるデフォルト Label - signaling - notify - push - stats - rpc ## 設定 ### default_data_channel_signaling シグナリングを WebSocket から DataChannel 経由に切り替えるかどうかの設定です。 デフォルトは `false` です。 ### default_ignore_disconnect_websocket シグナリングを DataChannel 経由に切り替えた際に、 WebSocket が閉じても、接続が切断したとみなさない設定です。 デフォルトは `false` です。 ### data_channel_signaling_close_message シグナリングを DataChannel 経由かつ `ignore_disconnect_websocket` が `true` の場合に、 `signaling` ラベルに `"type": "close"` メッセージを送るかどうかの設定です。 デフォルトは `false` です。 ## label とシグナリングのタイプ > **重要** > > これらの DataChannel 経由のシグナリングで Sora が利用するラベルは `data_channels` で指定することはできません。 `data_channels` で指定するラベルは [リアルタイムメッセージング機能](MESSAGING.html) 用で、必ず先頭に `#` を付ける必要があります。 各 label とシグナリングのタイプについては、[DataChannel シグナリング](DATA_CHANNEL_SIGNALING.html#5626ed) の図も下記の説明と合わせてご確認ください。 ### "label": "signaling" **順番**: あり **信頼性**: あり **圧縮**: あり WebRTC が確立する前の type: connect/offer/answer/candiate については、DataChannel 経由のシグナリングでは利用できません。 `"type": "re-offer"` は `"label": "signaling"` に送られてきます。 `"type": "re-answer"` 、 `"type": "disconnect"` は `"label": "signaling"` に送ります。 `"type": "ping"` と `"type": "pong"` は DataChannel では利用しません。 #### "type": "re-offer" > **重要** > > "type": "update" の代わりに Sora からは "type": "re-offer" が送られてきます。 マルチストリーム利用時に SDP 再交換を行う際に、 Sora から送られてきます。 #### "type": "re-answer" > **重要** > > "type": "update" の代わりに Sora へ "type": "re-answer" を送ります。 マルチストリーム利用時に SDP 再交換を行う際に、 Sora へ送ります。 #### "type": "disconnect" 接続を切断することを通知するために Sora へ送ります。 #### "type": "close" **DataChannel シグナリングで新しく追加されたタイプです** Sora から切断する場合に送ります。ただし、 `"type": "disconnect"` が送られてきた時は送りません。 `data_channel_signaling_close_message` が `true` かつ、 `ignore_disconnect_websocket` が `true` の場合に送ります。 ### "label": "notify" **順番**: あり **信頼性**: あり **圧縮**: あり `"type": "notify"` は `"label": "notify"` に送られてきます。 中身は WebSocket 経由の値と変わりません。 ### "label": "push" **順番**: あり **信頼性**: あり **圧縮**: あり `"type": "push"` は `"label": "push"` に送られてきます。 中身は WebSocket 経由の値と変わりません。 ### "label": "stats" **順番**: あり **信頼性**: あり **圧縮**: あり 今まで `"type": "ping"` と `"type": "pong"` 内部でやりとりしていた `stats` は DataChannel 経由では独立しました。 Sora から `{"type": "req-stats"}` が送られてきたら、 `{"type": "stats", "reports": [{"id": "...", ...}, ...]}` で `reports` の中に、 WebSocket 経由時には `"type": "pong"` で入れていた統計情報を入れて送り返してください。 #### "type": "req-stats" **DataChannel シグナリングで新しく追加されたタイプです** Sora からクライアントに stats 情報を要求します。 #### "type": "stats" クライアントから Sora に stats 情報を送ります。 ### "label": "rpc" **順番**: あり **信頼性**: あり **圧縮**: あり DataChannel 経由で一部の API を実行する [RPC 機能](RPC.html) で利用します。 ## DataChannel 関連の設定 ### data_channel_stats_timer_interval シグナリングを DataChannel 経由に切り替えた際に、 Sora からクライアントへ統計情報の要求を送る間隔の設定です。 デフォルトは `60 s` です。 ## シーケンス図 ### 認証ウェブフックあり ```mermaid sequenceDiagram autonumber participant C as クライアント participant S as Sora participant A as アプリケーションサーバー C->>+S: "type": "connect" S->>+A: 認証ウェブフック A-->>-S: 200 OK
{"allowed": "true"} S->>-C: "type": "offer" C->>S: "type": "answer" C->>S: "type": "candidate" note over C,A: WebRTC 確立 S->>+A: イベントウェブフック
"type": "connection.created" A-->-S: 200 OK note over C,A: DataChannel 確立 S->>C: "type": "switched" note over C,A: これ以降は DataChannel が利用される ``` ### DataChannel シグナリング ```mermaid sequenceDiagram autonumber participant C as クライアント participant S as Sora note over C,S: WebRTC 確立 note over C,S: DataChannel 確立 S->>C: "type": "switched" note over C,S: これ以降は DataChannel が利用される S->>C: "type": "re-offer" note right of S: label: signaling C->>S: "type": "re-answer" note left of C: label: signaling S->>C: "type": "notify" note right of S: label: notify S->>C: "type": "push" note right of S: label: push S->>C: "type": "req-stats" note right of S: label: stats C->>S: "type": "stats" note left of C: label: stats ``` # シグナリングの型定義 この章ではシグナリングの型について説明します。 シグナリングの仕様については [シグナリング](SIGNALING.html) を参照ください。 型の表記は TypeScript で記述します。 ## 基本的な型 ```typescript // @ts-check // JSON 値を表します。 // 仕様は RFC 8259 に従います。 type JSONValue = | null | boolean | number | string | JSONValue[] | { [key: string]: JSONValue | undefined }; // UnixTime // 例: 1704067199 type UnixTime = number; // RFC3339 UTC (マイクロ秒) // 例: 2023-12-31T23:59:59.999999Z type Timestamp = string; // ストリームの種別 type Role = "sendrecv" | "sendonly" | "recvonly"; // 最大 255 バイト type ChannelId = string; type SessionId = string; type ClientId = string; type BundleId = string; // Base32(UUIDv4) 26 文字の文字列 type ConnectionId = string; // サイマルキャストで視聴する映像の種類 type SimulcastRid = "none" | "r0" | "r1" | "r2"; type OpusParams = { channels?: number; maxplaybackrate?: number; // 6000..510000 maxaveragebitrate?: number; minptime?: number; ptime?: number; stereo?: boolean; sprop_stereo?: boolean; useinbandfec?: boolean; usedtx?: boolean; }; // 音声の設定 type Audio = | boolean | { codec_type?: AudioCodecType; bit_rate?: number; opus_params?: OpusParams; }; type VideoVP9Params = { // 0..3 profile_id?: number; }; type VideoAV1Params = { // 0..2 profile?: number; // 0..15 level_idx?: number; // 0..1 tier?: number; }; type VideoH264Params = { profile_level_id?: string; // 0..2 packetization_mode?: number; // 0..1 level_asymmetry_allowed?: number; // sora.conf で h264_b_frame = true を設定する必要があります b_frame?: boolean; }; type VideoH265Params = { level_id?: number; // 0..31 profile_id?: number; // 0..1 tier_flag?: number; // "SRST" | "MRST" | "MRMT" tx_mode?: H265TxMode; // sora.conf で h265_b_frame = true を設定する必要があります b_frame?: boolean; }; // 映像の設定 type Video = | boolean | { codec_type?: VideoCodecType; bit_rate?: number; // 利用するには sora.conf で signaling_vp9_params = true を設定する必要があります vp9_params?: VideoVP9Params; // 利用するには sora.conf で signaling_av1_params = true を設定する必要があります av1_params?: VideoAV1Params; // 利用するには sora.conf で signaling_h264_params = true を設定する必要があります h264_params?: VideoH264Params; // 利用するには sora.conf で signaling_h265_params = true を設定する必要があります h265_params?: VideoH265Params; }; // 音声コーデックの種類 type AudioCodecType = "OPUS"; // 映像コーデックの種類 type VideoCodecType = "VP9" | "VP8" | "AV1" | "H264" | "H265"; type H265TxMode = "SRST" | "MRST" | "MRMT"; // DataChannel の方向 type Direction = "sendrecv" | "sendonly" | "recvonly"; type DataChannelMessagingHeaderFieldType = "sender_connection_id"; type DataChannelMessagingHeaderField = { type: DataChannelMessagingHeaderFieldType; // * length は "type": "offer" 時の data_channels にのみ含まれる // * length は"type": "connect" 時には指定できない // * length は認証成功時の払い出し時には指定できない length?: number; }; // DataChannels type DataChannel = { label: string; direction: Direction; ordered: boolean; max_packet_life_time?: number; max_retransmits?: number; protocol?: string; compress: boolean; header?: DataChannelMessagingHeaderField[]; }; type TurnTransportType = "udp" | "tcp"; type ForwardingFilterRuleField = "connection_id" | "client_id" | "kind"; type ForwardingFilterRuleOperator = "is_in" | "is_not_in"; type ForwardingFilterRuleKindValue = "audio" | "video"; type ForwardingFilterRule = { field: ForwardingFilterRuleField; operator: ForwardingFilterRuleOperator; values: string[]; }; type ForwardingFilterAction = "block" | "allow"; type ForwardingFilter = { version?: string; metadata?: JSONValue; name?: string; priority?: number; action?: ForwardingFilterAction; rules: ForwardingFilterRule[][]; }; type SoraClientType = | "Sora JavaScript SDK" | "Sora iOS SDK" | "Sora Android SDK" | "Sora Unity SDK" | "Sora C++ SDK" | "Sora Python SDK" | "Sora C SDK" | "Sora Flutter SDK" | "OBS-Studio" | "OBS-Studio-WHIP" | "OBS-Studio-WHEP" | "WebRTC Native Client Momo" | "WebRTC Load Testing Tool Zakuro"; // SoraClient type SoraClient = { environment?: string; raw?: string; type?: SoraClientType; version?: string; commit_short?: string; libwebrtc?: string; }; // RTCRtpCodecParameters // https://www.w3.org/TR/webrtc/#dom-rtcrtpcodecparameters type SimulcastCodec = { // payloadType や channels は省略 mimeType: string; clockRate: number; sdpFmtpLine?: string; }; // RTCRtpEncodingParameters // https://w3c.github.io/webrtc-pc/#dom-rtcrtpencodingparameters type SimulcastEncoding = { // https://www.w3.org/TR/webrtc/#dom-rtcrtpcodingparameters-rid rid: SimulcastRid; // https://www.w3.org/TR/webrtc/#dom-rtcrtpencodingparameters-active active?: boolean; // https://www.w3.org/TR/webrtc/#dom-rtcrtpencodingparameters-maxframerate maxFramerate?: number; // https://www.w3.org/TR/webrtc/#dom-rtcrtpencodingparameters-maxbitrate maxBitrate?: number; // https://www.w3.org/TR/webrtc/#dom-rtcrtpencodingparameters-scaleresolutiondownby scaleResolutionDownBy?: number; // https://www.w3.org/TR/webrtc/#dom-rtcrtpcodec codec?: SimulcastCodec; // https://w3c.github.io/webrtc-extensions/#dom-rtcrtpencodingparameters-scaleresolutiondownto // @ts-expect-error RTCResolutionRestriction は typed で未定義のため型チェックを無視(型定義が追加され次第削除) scaleResolutionDownTo?: RTCResolutionRestriction; // https://w3c.github.io/webrtc-extensions/#dom-rtcrtpencodingparameters-adaptiveptime adaptivePtime?: boolean; // https://www.w3.org/TR/webrtc-svc/#dom-rtcrtpencodingparameters-scalabilitymode scalabilityMode?: string; }; ``` ## シグナリング シグナリングは「クライアントからサーバー (Sora) に送信される」メッセージと「サーバー (Sora) からクライアントに送信される」メッセージに分かれます。 ### クライアントからサーバーに送信されるメッセージ - connect - answer - candidate - re-answer - pong- WebSocket 経路利用時のみ - disconnect - stats- DataChannel 経路利用時のみ ### Server からクライアントに送信されるメッセージ - offer - re-offer - ping- WebSocket 経路利用時のみ - push - notify - req-stats- DataChannel 経路利用時のみ ## 型定義 ```typescript // @ts-check // シグナリング type SignalingMessage = SendSignalingMessage | ReceiveSignalingMessage; // クライアントから Sora に送信されるメッセージ type SendSignalingMessage = | SignalingConnectMessage | SignalingAnswerMessage | SignalingReAnswerMessage | SignalingCandidateMessage | SignalingPongMessage | SignalingDisconnectMessage | SignalingStatsMessage; // Sora からクライアントに送信されるメッセージ type ReceiveSignalingMessage = | SignalingRedirectMessage | SignalingOfferMessage | SignalingReOfferMessage | SignalingPingMessage | SignalingPushMessage | SignalingNotifyMessage | SignalingReqStatsMessage | SignalingSwitchedMessage | SignalingCloseMessage; // type: "connect" type SignalingConnectMessage = { type: "connect"; role: Role; channel_id: ChannelId; client_id?: ClientId; bundle_id?: BundleId; audio?: Audio; video?: Video; // 未指定の場合は false として扱われます simulcast?: boolean; // simulcast_rid は 2027 年 12 月リリース予定の Sora にて廃止します // 今後は simulcast_request_rid をご利用ください simulcast_rid?: "r0" | "r1" | "r2"; simulcast_request_rid?: SimulcastRid; // sora.conf にて simulcast_multicodec = true を有効にする必要があります simulcast_multicodec?: boolean; // 未指定の場合は false として扱われます spotlight?: boolean; // 非推奨です // session.created の戻り値をご利用ください spotlight_number?: number; spotlight_focus_rid?: "none" | SimulcastRid; spotlight_unfocus_rid?: "none" | SimulcastRid; metadata?: JSONValue; signaling_notify_metadata?: JSONValue; data_channel_signaling?: boolean; data_channels?: DataChannel[]; ignore_disconnect_websocket?: boolean; forwarding_filters?: ForwardingFilter[]; // type: redirect で戻されて再度 type: connect で接続するときに有効にする必要があります redirect?: boolean; audio_streaming_language_code?: string; sdp?: string; sora_client?: string; environment?: string; libwebrtc?: string; }; // type: "redirect" type SignalingRedirectMessage = { type: "redirect"; location: string; }; type Mid = { audio?: string; video?: string; }; // type: "offer" type SignalingOfferMessage = { type: "offer"; sdp: string; mid: Mid; version: string; simulcast: boolean; simulcast_multicodec: boolean; spotlight: boolean; channel_id: ChannelId; session_id: SessionId; client_id: ClientId; bundle_id: BundleId; connection_id: ConnectionId; rpc_methods: rpcMethod[]; audio: boolean; // audio が false または role が recvonly の際は含まれません audio_codec_type?: AudioCodecType; // audio が false または role が recvonly の際は含まれません audio_bit_rate?: number; video: boolean; // audio が false または role が recvonly の際は含まれません video_codec_type?: VideoCodecType; // audio が false または role が recvonly の際は含まれません video_bit_rate?: number; metadata?: JSONValue; config?: RTCConfiguration; encodings?: SimulcastEncoding[]; data_channels?: DataChannel[]; }; // type: "answer" type SignalingAnswerMessage = { type: "answer"; sdp: string; }; // type: "candidate" type SignalingCandidateMessage = { type: "candidate"; candidate: string; }; // type: "switched" type SignalingSwitchedMessage = { type: "switched"; ignore_disconnect_websocket: boolean; }; // type: "re-offer" type SignalingReOfferMessage = { type: "re-offer"; sdp: string; }; // type: "re-answer" type SignalingReAnswerMessage = { type: "re-answer"; sdp: string; }; // type: "close" // サーバー側からの切断を通知するためのメッセージ // data_channel_signaling = true かつ ignore_disconnect_websocket = true の場合のみ // sora.conf にて data_channel_signaling_close_message = true を有効にする必要がある type SignalingCloseMessage = { type: "close"; code: number; reason: string; }; // type: "ping" // WebSocket シグナリング type SignalingPingMessage = { type: "ping"; stats?: boolean; }; // type: "pong" // WebSocket シグナリング type SignalingPongMessage = { type: "pong"; stats?: RTCStatsReport[]; }; // type: "push" type SignalingPushMessage = { type: "push"; data: Record; }; // type: "disconnect" type SignalingDisconnectMessage = { type: "disconnect"; reason: string; }; // type: "req-stats" // DataChannel シグナリング type SignalingReqStatsMessage = { type: "req-stats"; }; // type: "stats" // DataChannel シグナリング type SignalingStatsMessage = { type: "stats"; reports: RTCStatsReport[]; }; ``` ### シグナリング通知 ```typescript // @ts-check // シグナリング通知 // type: "notify" type SignalingNotifyMessage = | SignalingNotifyConnectionCreated | SignalingNotifyConnectionUpdated | SignalingNotifyConnectionDestroyed | SignalingNotifySpotlightFocused | SignalingNotifySpotlightUnfocused | SignalingNotifyRecordingStarted | SignalingNotifyRecordingStopped | SignalingNotifyForwardingBlocked | SignalingNotifyForwardingAllowed | SignalingNotifyNetworkStatus | SignalingNotifyIceConnectionStateChanged | SignalingNotifySimulcastSwitched; // 接続中のクライアントの情報 type SignalingNotifyMetadata = { client_id?: ClientId; bundle_id?: BundleId; connection_id?: ConnectionId; ice_connection_state?: SignalingNotifyIceConnectionState; authn_metadata?: JSONValue; authz_metadata?: JSONValue; metadata?: JSONValue; timestamp?: Timestamp; }; // "connection.created", type SignalingNotifyConnectionCreated = { type: "notify"; event_type: "connection.created"; timestamp?: Timestamp; role: Role; session_id?: SessionId; client_id?: ClientId; bundle_id?: BundleId; connection_id?: ConnectionId; audio?: boolean; video?: boolean; authn_metadata?: JSONValue; authz_metadata?: JSONValue; metadata?: JSONValue; data?: SignalingNotifyMetadata[]; minutes: number; channel_connections: number; channel_sendrecv_connections: number; channel_sendonly_connections: number; channel_recvonly_connections: number; turn_transport_type: TurnTransportType; }; // "connection.updated" type SignalingNotifyConnectionUpdated = { type: "notify"; event_type: "connection.updated"; role: Role; session_id?: SessionId; client_id?: ClientId; bundle_id?: BundleId; connection_id?: ConnectionId; audio?: boolean; video?: boolean; authn_metadata?: JSONValue; authz_metadata?: JSONValue; metadata?: JSONValue; minutes: number; channel_connections: number; channel_sendrecv_connections: number; channel_sendonly_connections: number; channel_recvonly_connections: number; turn_transport_type: TurnTransportType; }; // "connection.destroyed" type SignalingNotifyConnectionDestroyed = { type: "notify"; event_type: "connection.destroyed"; role: Role; session_id?: SessionId; client_id?: ClientId; bundle_id?: BundleId; connection_id?: ConnectionId; audio?: boolean; video?: boolean; minutes: number; authn_metadata?: JSONValue; authz_metadata?: JSONValue; metadata?: JSONValue; channel_connections: number; channel_sendrecv_connections: number; channel_sendonly_connections: number; channel_recvonly_connections: number; turn_transport_type: "udp" | "tcp"; }; // "spotlight.focused" type SignalingNotifySpotlightFocused = { type: "notify"; event_type: "spotlight.focused"; client_id: ClientId | null; bundle_id: BundleId | null; connection_id: ConnectionId; audio: boolean; video: boolean; fixed: boolean; spotlight_number: number; }; // "spotlight.unfocused" type SignalingNotifySpotlightUnfocused = { type: "notify"; event_type: "spotlight.unfocused"; client_id: ClientId | null; bundle_id: BundleId | null; connection_id: ConnectionId; audio: boolean; video: boolean; spotlight_number: number; }; // "recording.started" type SignalingNotifyRecordingStarted = { type: "notify"; event_type: "recording.started"; client_id: ClientId | null; bundle_id: BundleId | null; connection_id: ConnectionId; }; // "recording.stopped" type SignalingNotifyRecordingStopped = { type: "notify"; event_type: "recording.stopped"; client_id: ClientId | null; bundle_id: BundleId | null; connection_id: ConnectionId; }; // "forwarding.blocked" type SignalingNotifyForwardingBlocked = { type: "notify"; event_type: "forwarding.blocked"; kind: ForwardingFilterRuleKindValue; destination_connection_id: ConnectionId; source_connection_id: ConnectionId; }; // "forwarding.allowed" type SignalingNotifyForwardingAllowed = { type: "notify"; event_type: "forwarding.allowed"; kind: ForwardingFilterRuleKindValue; destination_connection_id: ConnectionId; source_connection_id: ConnectionId; }; // "audio-streaming.failed" type SignalingNotifyAudioStreamingFailed = { type: "notify"; event_type: "audio-streaming.failed"; failed_connection_id: ConnectionId; }; // "network.status" type SignalingNotifyNetworkStatus = { type: "notify"; event_type: "network.status"; timestamp: Timestamp; unix_timestamp_ms: number; previous_unix_timestamp_ms: number; total_sent_rtp_byte_size: number; previous_total_sent_rtp_byte_size: number; estimated_bandwidth: number; previous_estimated_bandwidth: number; }; type SignalingNotifyIceConnectionState = "connected" | "checking" | "disconnected"; // "ice_connection_state.changed" type SignalingNotifyIceConnectionStateChanged = { type: "notify"; event_type: "ice-connection-state.changed"; timestamp: Timestamp; connection_id: ConnectionId; current_state: SignalingNotifyIceConnectionState; previous_state: SignalingNotifyIceConnectionState; }; // "simulcast.switched" type SignalingNotifySimulcastSwitched = { type: "notify"; event_type: "simulcast.switched"; timestamp: Timestamp; sender_connection_id: ConnectionId; priority: "higher" | "lower"; trigger: "api" | "rpc" | "sender" | "receiver"; rpc_rids: SimulcastRid[]; auto_rids: SimulcastRid[]; request_rid: SimulcastRid; current_rid: SimulcastRid; previous_rid: SimulcastRid; }; ``` # シグナリング通知 ## 概要 シグナリング通知は、Sora がシグナリングの接続で利用する WebSocket やデータチャネルを利用して、 自身の状態や、他のコネクションの状態をリアルタイムに通知する機能です ## シグナリング通知を利用することで実現できること - 配信されているストリームに対してユーザー名を表示する - 新しくチャネルに参加したクライアントのユーザー名を通知する - 現在のネットワークの状態をクライアント画面に表示する - 離脱したユーザーの名前を表示する - 録画の開始や停止をクライアントに通知する - スポットライト機能を利用した場合に、配信が切り替わったことをクライアントに通知する ## シグナリング通知の利用が向いていないこと - 片方向配信で視聴者が多い ## シグナリング通知の有効 / 無効について シグナリング通知はデフォルトで有効になっています。 シグナリング通知を無効にした場合はシグナリング通知が送られてこなくなります。 無効にするには、 `sora.conf` でシグナリング通知の無効を指定するか、または、認証ウェブフックの戻り値で無効を指定する必要があります。 ### sora.conf での指定 `sora.conf` でシグナリング通知の有無を指定する方法です。 `sora.conf` で `signaling_notify = false` を指定することで、シグナリング通知が無効になります。 ただし、この値は認証ウェブフックの戻り値で上書きできます。 ### 認証ウェブフックの戻り値での指定 認証ウェブフックの戻り値を利用して、クライアントごとに signaling_notify の true / false を指定する方法です。 認証ウェブフックの戻り値に `{"signaling_notify": false}` を指定することで、そのクライアントに対して signaling_notify を無効にできます。 ```javascript { "allowed": true, "signaling_notify": false } ``` 認証ウェブフックの戻り値に signaling_notify の指定が無い場合は、sora.conf の signaling_notify の値が採用されます。 **表 1. sora.conf と認証ウェブフックの戻り値の signaling_notify の組み合わせによるクライアントの signaling_notify の採用値** * - sora.conf の signaling_notify - 認証ウェブフックの戻り値の signaling_notify - クライアントの signaling_notify の採用値 * - true - 指定なし - true * - true - false - false * - true - true - true * - false - 指定なし - false * - false - false - false * - false - true - true ## sora.conf によるシグナリング通知関連の共通設定 ### signaling_notify_client_id **デフォルト**: true `sora.conf` で `signaling_notify_client_id = false` を指定することで、シグナリング通知時にクライアント ID を含まなくなります。 ただし [スポットライト機能のシグナリング通知](SIGNALING_NOTIFY.html#dcfbb9) には常にクライアント ID が含まれます。 ### signaling_notify_bundle_id **デフォルト**: true `sora.conf` で `signaling_notify_bundle_id = false` を指定することで、シグナリング通知時にバンドル ID を含まなくなります。 ただし [スポットライト機能のシグナリング通知](SIGNALING_NOTIFY.html#dcfbb9) には常にバンドル ID が含まれます。 ### signaling_notify_connection_id **デフォルト**: true `sora.conf` で `signaling_notify_connection_id = false` を指定することで、シグナリング通知時にコネクション ID を含まなくなります。 ただし [サイマルキャスト機能のシグナリング通知](SIGNALING_NOTIFY.html#3807dd) 、 [スポットライト機能のシグナリング通知](SIGNALING_NOTIFY.html#dcfbb9) 、 [転送フィルターのシグナリング通知](SIGNALING_NOTIFY.html#efa550) には常にコネクション ID が含まれます。 ### signaling_notify_connection_created_timestamp **デフォルト**: true これは `event_type` が `connection.created` の時のみ有効になります。 `sora.conf` で `signaling_notify_connection_created_timestamp = false` を指定することで、シグナリング通知時にコネクション生成時刻を含まなくなります。 ### signaling_notify_media **デフォルト**: true `sora.conf` で `signaling_notify_media = false` を指定することで、シグナリング通知時に音声や映像の情報を含まなくなります。 ただし [スポットライト機能のシグナリング通知](SIGNALING_NOTIFY.html#dcfbb9) には常に音声や映像の情報が含まれます。 ### signaling_notify_metadata **デフォルト**: true `signaling_notify_metadata` は、ユーザーが参加や離脱したときに送られるシグナリング通知に含まれるメタデータです。 シグナリング通知メタデータの詳細は [シグナリング通知メタデータ](SIGNALING_NOTIFY_METADATA.html) をご確認ください。 `sora.conf` で `signaling_notify_metadata = false` を指定すると [コネクションのシグナリング通知](SIGNALING_NOTIFY.html#5b6b0a) でシグナリング通知メタデータおよびシグナリング通知メタデータ拡張の情報を含まなくなります。 ### signaling_notify_metadata_ext **デフォルト**: false `signaling_notify_metadata_ext` は、ユーザーが参加や離脱したときに送られるシグナリング通知に含まれるメタデータを、API 経由で自由に変更できるようにします。 シグナリング通知メタデータ拡張の詳細は [シグナリング通知メタデータ拡張機能](SIGNALING_NOTIFY_METADATA_EXT.html) をご確認ください。 ### signaling_notify_ice_connection_state **デフォルト**: false `signaling_notify_ice_connection_state` は、ICE 接続の状態が変化したときに送られるシグナリング通知に含まれるメタデータです。 自分を含むセッション参加者全員に通知されます。 ICE コネクションステートの詳細は [ICE コネクションステート機能](ICE_CONNECTION_STATE.html) をご確認ください。 ## コネクションのシグナリング通知 ### クライアントに送信される JSON の仕様 - event_type- string - `connection.created` 、 `connection.updated` 、 `connection.destroyed` の 3 つの内のいずれかが入ります - `connection.created` と `connection.destroyed` は、全員に通知されます - `connection.updated` は、自身に通知されます - timestamp- string - RFC3339 (マイクロ秒) - `connection.created` の時に、コネクション生成時間が含まれます - role- string - `sendrecv` / `sendonly` / `recvonly` が入ります - minutes- integer - その接続の接続経過時間 (分) が入ります - channel_connections- integer - そのチャネルの接続数が入ります - channel_sendonly_connections- integer - そのチャネルの sendonly 接続数が入ります - channel_recvonly_connections- integer - そのチャネルの recvonly 接続数が入ります - channel_sendrecv_connections- integer - そのチャネルの sendrecv 接続数が入ります - client_id- string - `connection.created` の場合は、参加してきたクライアントのクライアント ID が入ります - `connection.destroyed` の場合は、離脱したクライアントのクライアント ID が入ります - `connection.updated` の場合は、自身のクライアント ID が入ります - `sora.conf` で、 `signaling_notify_client_id` を `false` にすることでこの値は含まれなくなります - bundle_id- string - `connection.created` の場合は、参加してきたクライアントのバンドル ID が入ります - `connection.destroyed` の場合は、離脱したクライアントのバンドル ID が入ります - `connection.updated` の場合は、自身のバンドル ID が入ります - `sora.conf` で、 `signaling_notify_bundle_id` を `false` にすることでこの値は含まれなくなります - connection_id- string - `connection.created` の場合は、参加してきたクライアントのコネクション ID が入ります - `connection.destroyed` の場合は、離脱したクライアントのコネクション ID が入ります - `connection.updated` の場合は、自身のコネクション ID が入ります - `sora.conf` で、 `signaling_notify_connection_id` を `false` にすることでこの値は含まれなくなります - audio- boolean - `connection.created` の場合は、参加してきたクライアントの audio が有効かどうかが入ります - `connection.destroyed` の場合は、離脱したクライアントの audio が有効かどうかが入ります - `connection.updated` の場合は、自身の audio が有効かどうかが入ります - `sora.conf` で、 `signaling_notify_media` を `false` にすることでこの値は含まれなくなります - video- boolean - `connection.created` の場合は、参加してきたクライアントの video が有効かどうかが入ります - `connection.destroyed` の場合は、離脱したクライアントの video が有効かどうかが入ります - `connection.updated` の場合は、自身の video が有効かどうかが入ります - `sora.conf` で、 `signaling_notify_media` を `false` にすることでこの値は含まれなくなります - metadata, authz_metadata, authn_metadata- json - [シグナリング通知メタデータ](SIGNALING_NOTIFY_METADATA.html) で利用する項目です。 - `sora.conf` で、 `signaling_notify_metadata` を `false` にすることでこの値は含まれなくなります - data- json 型のリスト- json 型の中身は、以下の sora.conf の設定により変化します- [signaling_notify_client_id](SORA_CONF.html#fc78ca) - [signaling_notify_bundle_id](SORA_CONF.html#f2a58f) - [signaling_notify_connection_id](SORA_CONF.html#7882d6) - [signaling_notify_connection_created_timestamp](SORA_CONF.html#7fe7b3) - [signaling_notify_metadata](SORA_CONF.html#2d9340) - 上記の設定が全て `false` になり、通知する値がなくなった場合、この値は含まれなくなります - 設定値による json 型の中身は、 [sora.conf の設定内容と connection.created 出力の例](SIGNALING_NOTIFY.html#2729eb) をご確認ください - 新規でチャネルに接続した際に、すでにチャネルに参加している接続一覧の情報がはいります- チャネル内で 1 つめの接続である場合は、この値は空のリストになります - 接続を開始して初回の `connection.created` の場合のみこの値が入ります ## sora.conf の設定内容と connection.created 出力の例 `data` に含まれる項目を例に sora.conf の設定内容と `connection.created` 出力の例を示します。 ### デフォルト デフォルトでは全て `true` であり、値が通知されます。 ```ini # 全てコメントアウトされているため、デフォルト値が適用される # signaling_notify_client_id = false # signaling_notify_bundle_id = false # signaling_notify_connection_id = false # signaling_notify_connection_created_timestamp = false # signaling_notify_metadata = false ``` **一部項目を省略しています** ```javascript { "type": "notify", "event_type": "connection.created", "session_id": "P24NZ0AX2D6FX15VFHEGBXGMEW", "bundle_id": "WHSSBG91XS7NXEVYY0F51YFEEW", "client_id": "client3", "connection_id": "WHSSBG91XS7NXEVYY0F51YFEEW", "timestamp": "2023-12-18T07:12:11.876287Z", "authn_metadata": {"spam": "egg"}, "authz_metadata": "bacon", "metadata": "bacon", "data": [ { "bundle_id": "KKBFZTQXDD6H7FD2NYCQX8S474", "client_id": "client1", "connection_id": "KKBFZTQXDD6H7FD2NYCQX8S474", "timestamp": "2023-12-18T07:11:56.585769Z", "authn_metadata": 10, "authz_metadata": {"authz": true}, "metadata": {"authz": true} }, { "bundle_id": "4D40YWH56N5S99QHJV6GAPNHB0", "client_id": "client2", "connection_id": "4D40YWH56N5S99QHJV6GAPNHB0", "timestamp": "2023-12-18T07:11:58.685769Z", "authn_metadata": 10, "metadata": 10 } ] } ``` ### client_id を通知しない `signaling_notify_client_id = false` を指定すると、client_id が含まれなくなります。 ```ini signaling_notify_client_id = false # signaling_notify_bundle_id = false # signaling_notify_connection_id = false # signaling_notify_connection_created_timestamp = false # signaling_notify_metadata = false ``` **一部項目を省略しています** ```javascript { "type": "notify", "event_type": "connection.created", "timestamp": "2023-12-18T07:12:11.876287Z", "session_id": "P24NZ0AX2D6FX15VFHEGBXGMEW", "bundle_id": "WHSSBG91XS7NXEVYY0F51YFEEW", "connection_id": "WHSSBG91XS7NXEVYY0F51YFEEW", "authn_metadata": {"spam": "egg"}, "authz_metadata": "bacon", "metadata": "bacon", "data": [ { "bundle_id": "KKBFZTQXDD6H7FD2NYCQX8S474", "connection_id": "KKBFZTQXDD6H7FD2NYCQX8S474", "timestamp": "2023-12-18T07:11:56.585769Z", "authn_metadata": 10, "authz_metadata": {"authz": true}, "metadata": {"authz": true} }, { "bundle_id": "4D40YWH56N5S99QHJV6GAPNHB0", "connection_id": "4D40YWH56N5S99QHJV6GAPNHB0", "timestamp": "2023-12-18T07:11:58.685769Z", "authn_metadata": 10, "metadata": 10 } ] } ``` ### metadata を通知しない `signaling_notify_metadata = false` を指定すると `metadata`, `authz_metadata`, `authn_metadata` が含まれなくなります。 ```ini # signaling_notify_client_id = false # signaling_notify_bundle_id = false # signaling_notify_connection_id = false # signaling_notify_connection_created_timestamp = false signaling_notify_metadata = false ``` **一部項目を省略しています** ```javascript { "type": "notify", "event_type": "connection.created", "session_id": "P24NZ0AX2D6FX15VFHEGBXGMEW", "bundle_id": "WHSSBG91XS7NXEVYY0F51YFEEW", "connection_id": "WHSSBG91XS7NXEVYY0F51YFEEW", "timestamp": "2023-12-18T07:12:11.876287Z", "data": [ { "bundle_id": "KKBFZTQXDD6H7FD2NYCQX8S474", "connection_id": "KKBFZTQXDD6H7FD2NYCQX8S474", "timestamp": "2023-12-18T07:11:56.585769Z" }, { "bundle_id": "4D40YWH56N5S99QHJV6GAPNHB0", "connection_id": "4D40YWH56N5S99QHJV6GAPNHB0", "timestamp": "2023-12-18T07:11:58.685769Z" } ] } ``` ### client_id と bundle_id と connection_id を通知しない 通知が不要のものを複数指定することができます。 ```ini signaling_notify_client_id = false signaling_notify_bundle_id = false signaling_notify_connection_id = false # signaling_notify_connection_created_timestamp = false # signaling_notify_metadata = false ``` **一部項目を省略しています** ```javascript { "type": "notify", "event_type": "connection.created", "session_id": "P24NZ0AX2D6FX15VFHEGBXGMEW", "timestamp": "2023-12-18T07:12:11.876287Z", "authn_metadata": {"spam": "egg"}, "authz_metadata": "bacon", "metadata": "bacon", "data": [ { "timestamp": "2023-12-18T07:11:56.585769Z", "authn_metadata": 10, "authz_metadata": {"authz": true}, "metadata": {"authz": true} }, { "timestamp": "2023-12-18T07:11:58.685769Z", "authn_metadata": 10, "metadata": 10 } ] } ``` ### data 内の項目全てを通知しない ```ini signaling_notify_client_id = false signaling_notify_bundle_id = false signaling_notify_connection_id = false signaling_notify_connection_created_timestamp = false signaling_notify_metadata = false ``` `data` 項目に関する通知を不要に設定すると、 `data` 項目自体が送信されなくなります。 **一部項目を省略しています** ```javascript { "type": "notify", "event_type": "connection.created", "session_id": "P24NZ0AX2D6FX15VFHEGBXGMEW" } ``` ### "event_type": "connection.created" この event_type は、参加しているチャネルに接続があった場合に、 `signaling_notify` を有効にしている自分を含む全員に通知されます。 この通知を利用することで、他のクライアントが接続してきたことをクライアント側で把握できます。 新規接続クライアントと bundle_id が等しいクライアントに対しては、このイベントは通知されません。 また通知 JSON の data の中身からも bundle_id が等しいクライアントは除外されます。 ### "event_type": "connection.updated" この event_type は、クライアントごとに異なり、 1 分間隔で通知されます。 この通知を利用することで、現在クライアントの累計接続時間をクライアント側で把握できます。 ### "event_type": "connection.destroyed" この event_type は、参加しているチャネルに切断があった場合に、 `signaling_notify` を有効にしている自分以外の全員に通知されます。 この通知を利用することで、他のクライアントが切断したことをクライアント側で把握できます。 切断クライアントと bundle_id が等しいクライアントに対しては、このイベントは通知されません。 ## サイマルキャスト機能のシグナリング通知 サイマルキャスト機能を利用した場合のシグナリング通知は上記の `connection.*` とは別に `simulcast.switched` が通知されます。 - event_type- string - `simulcast.switched` は、映像ストリームの rid が切り替わった場合に通知されます - timestamp- string - RFC3339 (マイクロ秒) - sender_connection_id- string - どの接続のストリームが切り替わったかが入ります - priority- string - `higher` / `lower` のいずれかで、切り替わったストリームの優先度が入ります - `simulcast_request_rid` に `auto` が指定されている場合 `priority` が `higher` はよりビットレートが **低い** rid のストリームに切り替わったことを示します - `simulcast_request_rid` に `auto` が指定されている場合 `priority` が `lower` はよりビットレートが **高い** rid のストリームに切り替わったことを示します - trigger - string - `api` / `rpc` / `sender` / `receiver` のいずれかで切り替わりのトリガーを指定できます - `api` は [RequestSimulcastRid](API_SIMULCAST.html#7d26ab) API による切り替え - `rpc` は [2025.2.0/RequestSimulcastRid](RPC.html#07fda8) RPC による切り替え - `sender` は映像送信側のストリームが増えたり減ったりしたことによる切り替え - `receiver` は映像視聴者側の環境に合わせた切り替え- このトリガーは `simulcast_auto_rids` を指定している場合にのみ含まれます - rpc_rids- string[none | r0 | r1 | r2, ...] - データチャネル経由の RPC 機能で利用できる rid のリスト - [2025.2.0/RequestSimulcastRid](RPC.html#07fda8) RPC で指定できる rid が入ります - `["none", "r0", "r1"]` を指定した場合、Sora は `r2` のストリームを配信しません - `["r0", "r1"]` を指定した場合、どんなに環境に余裕がなくても `none` でのストリーム停止を行いません - auto_rids- string[none | r0 | r1 | r2, ...] - 視聴側の環境に合わせた自動切り替えに利用する rid のリストが入ります- リストが空の場合は自動切り替え機能は無効です - request_rid- string (none | r0 | r1 | r2) - 自身が期待するストリームの rid が入ります - current_rid- string (none | r0 | r1 | r2) - 現在利用しているストリームの rid が入ります - previous_rid- string (none | r0 | r1 | r2) - 以前利用していたストリームの rid が入ります ```javascript { "type": "notify", "timestamp": "2024-06-10T12:34:56.789012Z", "event_type": "simulcast.switched", "sender_connection_id": "4D40YWH56N5S99QHJV6GAPNHB0", "priority": "higher", "trigger": "sender", "rpc_rids": ["none", "r0", "r1"], "auto_rids": ["r0", "r1"], "request_rid": "r1", "current_rid": "r1", "previous_rid": "r0" } ``` ### 設定 この通知は `sora.conf` の [signaling_notify_simulcast_switched](SORA_CONF.html#022113) で有効 / 無効を指定できます。デフォルトは `true` で有効です。 ## スポットライト機能のシグナリング通知 スポットライト機能を利用した場合のシグナリング通知は上記の `connection.*` とは別に `spotlight.*` が通知されます。 ### "event_type": "spotlight.focused" この event_type は、参加しているチャネルの配信がフォーカスされた場合に、 `signaling_notify` を有効にしている全員に通知されます。 この通知を利用することで、配信が切り替わったことをクライアントが気付くことができるようになります。 フォーカスされたクライアントと bundle_id が等しいクライアントに対しては、このイベントは通知されません。 > **重要** > > 新規にチャネルに参加したクライアントには `connection.created` の後に `spotlight.focused` が通知され、 > 既に参加しているどのクライアントがスポットライト機能でフォーカスされているのかを知ることができます。 ### "event_type": "spotlight.unfocused" この event_type は、参加しているチャネルの配信からフォーカスが外れた場合に、 `signaling_notify` を有効にしている全員に通知されます。 この通知を利用することで、配信が切り替わったことをクライアントが気付くことができるようになります。 フォーカスが外れたクライアントと bundle_id が等しいクライアントに対しては、このイベントは通知されません。 ### クライアントに送信される JSON の仕様 - event_type- string - `spotlight.focused` または `spotlight.unfocused` が入ります - channel_id- string - 現在利用しているチャネル ID が入ります - client_id- string - どのクライアントに配信が切り替わったかが入ります - bundle_id- string - 切り替わった配信のバンドル ID が入ります - connection_id- string - どの接続に配信が切り替わったかが入ります - spotlight_number- integer - 現在のスポットライト数が入ります - audio- boolean - 切り替わった配信の audio が有効かどうかが入ります - video- boolean - 切り替わった配信の video が有効かどうかが入ります - fixed- boolean - 切り替わった配信が固定されているかどうかが入ります ```javascript { "type": "notify", "event_type": "spotlight.focused", "client_id": "4D40YWH56N5S99QHJV6GAPNHB0", "bundle_id": "4D40YWH56N5S99QHJV6GAPNHB0", "connection_id": "4D40YWH56N5S99QHJV6GAPNHB0", "spotlight_number": 3, "audio": true, "video": true, "fixed": false } ``` ```javascript { "type": "notify", "event_type": "spotlight.unfocused", "client_id": "4D40YWH56N5S99QHJV6GAPNHB0", "bundle_id": "4D40YWH56N5S99QHJV6GAPNHB0", "connection_id": "4D40YWH56N5S99QHJV6GAPNHB0", "spotlight_number": 3, "audio": true, "video": true, "fixed": false } ``` ## 録画のシグナリング通知 録画のシグナリング通知は録画開始時には `recording.started` 、録画終了時には `recording.stopped` が通知されます。 > **ヒント** > > `role` が `recvonly` のクライアントには通知されません。 ### sora.conf の設定 `sora.conf` の `signaling_notify_recording` で通知するかどうかを指定できます。デフォルトは `true` で通知します。 ```ini signaling_notify_recording = false ``` ### "event_type": "recording.started" 録画開始時に通知されます。 接続前にセッションウェブフック `session.created` で `"recording": true` や `StartRecording` API によって録画が開始されていた場合、 `connection.created` の後に通知されます。 ```javascript { "type": "notify", "event_type": "recording.started", "client_id": "4D40YWH56N5S99QHJV6GAPNHB0", "bundle_id": "4D40YWH56N5S99QHJV6GAPNHB0", "connection_id": "4D40YWH56N5S99QHJV6GAPNHB0" } ``` ### "event_type": "recording.stopped" 録画終了時に通知されます。 `StopRecording` API が実行されたタイミング、または期限が切れたタイミングで通知されます。 ```javascript { "type": "notify", "event_type": "recording.stopped", "client_id": "4D40YWH56N5S99QHJV6GAPNHB0", "bundle_id": "4D40YWH56N5S99QHJV6GAPNHB0", "connection_id": "4D40YWH56N5S99QHJV6GAPNHB0" } ``` ## 転送フィルターのシグナリング通知 ### "event_type": "forwarding.blocked" ```javascript { "type": "notify", "event_type": "forwarding.blocked", "kind": "video", "destination_connection_id": "FCX8X05SJS3Y18RD5MYFZS62RR", "source_connection_id": "SM7WDVYRTH739BB47ZSPQQ2BT4" } ``` ### "event_type": "forwarding.allowed" ```javascript { "type": "notify", "event_type": "forwarding.allowed", "kind": "video", "destination_connection_id": "FCX8X05SJS3Y18RD5MYFZS62RR", "source_connection_id": "SM7WDVYRTH739BB47ZSPQQ2BT4" } ``` ## 音声ストリーミング ### "event_type": "audio-streaming.failed" ```javascript { "type": "notify", "event_type": "audio-streaming.failed", "failed_connection_id": "4D40YWH56N5S99QHJV6GAPNHB0" } ``` ## ICE コネクションステートのシグナリング通知 **これは実験的機能です** ### "event_type": "ice-connection-state.changed" ```javascript { "type": "notify", "event_type": "ice-connection-state.changed", "connection_id": "MV7VSJTA092V70F4796DCS9BAR", "timestamp": "2024-12-06T03:32:58.091149Z", "current_state": "connected", "previous_state": "checking" } ``` ## ネットワークのシグナリング通知 ネットワークのシグナリング通知は、上記の `connection.*` とは別に `network.*` が通知されます。 ### "event_type": "network.status" このシグナリング通知は [signaling_notify_network](SORA_CONF.html#c449d7) が `true` の場合に通知されます。 この通知を利用することで、ネットワークの状態をクライアントが把握できるようになります。 #### 通知間隔の変更 `sora.conf` の [signaling_notify_network_status_interval](SORA_CONF.html#e0f78e) で通知間隔を設定できます。デフォルトは `10 s` です。 ### 帯域推定結果の通知 Sora が帯域推定を行った結果を通知します。 #### 通知する条件 `role` が `sendrecv` または `recvonly` の場合に通知します #### JSON の仕様 - event_type- string - `network.status` が入ります - estimated_bandwidth- integer - 帯域推定結果が入ります - 単位はバイトです - unix_timestamp_ms- integer - 通知時の UNIX タイムスタンプ (ミリ秒) が入ります - total_sent_rtp_byte_size- integer - 通知時の RTP (音声と映像) 送信合計バイトサイズが入ります - previous_unix_timestamp_ms- integer - 前回通知時の UNIX タイムスタンプ (ミリ秒) が入ります - **初回の通知時は 0 が入ります** - previous_estimated_bandwidth- integer - 前回通知時の帯域推定の値が入ります - **初回の通知時は 0 が入ります** - previous_total_sent_rtp_byte_size- integer - 前回通知時の RTP (音声と映像) 送信合計バイトサイズが入ります - **初回の通知時は 0 が入ります** ```javascript // 初回通知時 { "type": "notify", "event_type": "network.status", "timestamp": "2024-05-28T03:32:58.091149Z", "unix_timestamp_ms": 1716854400000, "estimated_bandwidth": 1000000, "total_rtp_sent_byte_size": 1000000, "previous_unix_timestamp_ms": 0, "previous_estimated_bandwidth": 0, "previous_total_rtp_sent_byte_size": 0, } ``` ## シーケンス図 ### コネクション関連の通知 ```mermaid sequenceDiagram participant C1 as クライアント1 participant C2 as クライアント2 participant S as Sora participant A as アプリケーションサーバー C1 ->>+ S: type: "connect"
client_id: "client1" S ->>+ A: 認証ウェブフック A -->>- S: 200 OK S ->>+ A: セッションウェブフック A -->>- S: 200 OK S -->>- C1: type: "offer" C1 -) S: type: "answer" note over C1, S: WebRTC 確立 par S ->>+ A: イベントウェブフック
"type": "connection.created" A -->>- S: 200 OK and S -) C1: type: "notify"
event_type: "connection.created"
client_id: "client1" end note over C1, S: 1 分経過 par S ->>+ A: イベントウェブフック
"type": "connection.updated" A -->>- S: 200 OK and S -) C1: type: "notify"
event_type: "connection.updated"
client_id: "client1" end C2 ->>+ S: type: "connect"
client_id: "client2" S ->>+ A: 認証ウェブフック A -->>- S: 200 OK S -->>- C2: type: "offer" C2 -) S: type: "answer" note over C2, S: WebRTC 確立 par S ->>+ A: イベントウェブフック
"type": "connection.created" A -->>- S: 200 OK and S -) C2: type: "notify"
event_type: "connection.created"
client_id: "client2" and S -) C1: type: "notify"
event_type: "connection.created"
client_id: "client2" end C1 ->> S: type: "disconnect" note over C1, S: 切断 par S ->>+ A: イベントウェブフック
"type": "connection.destroyed" A -->>- S: 200 OK and S -) C2: type: "notify"
event_type: "connection.destroyred"
client_id: "client1" end ``` 録画関連の通知 ------------------------ ```mermaid sequenceDiagram participant C as クライアント participant S as Sora participant A as アプリケーションサーバー C ->>+ S: type: "connect"
client_id: "client1" S ->>+ A: 認証ウェブフック A -->>- S: 200 OK S ->>+ A: セッションウェブフック A -->>- S: 200 OK
recording: true S -->>- C: type: "offer" C -) S: type: "answer" note over C, S: WebRTC 確立 par S ->>+ A: イベントウェブフック
"type": "connection.created" A -->>- S: 200 OK and S -) C: type: "notify"
event_type: "connection.created"
client_id: "client1" S -) C: type: "notify"
event_type: "recording.started"
client_id: "client1" end A ->>+ S: StopRecording API S -->>- A: 200 OK S -) C: type: "notify"
event_type: "recording.stopped"
client_id: "client1" S ->>+ A: イベントウェブフック
"type": "archive.available" A -->>- S: 200 OK S ->>+ A: イベントウェブフック
"type": "recording.report" A -->>- S: 200 OK ``` # シグナリング通知メタデータ ## 概要 `signaling_notify_metadata` はクライアントの状態が変化したときに送られる、シグナリング通知に含まれるメタデータです。 シグナリング接続時、または認証ウェブフック成功の戻り値に `signaling_notify_metadata` で JSON 値を指定することで利用できるようになります。 新しく参加した際に、すでにそのチャネルに参加しているクライアントの `signaling_notify_metadata` の値がリストで共有されます。 ## 注意 ### シグナリング通知メタデータの認証成功時払い出しによる上書き 接続時に指定したシグナリング通知メタデータは、認証成功時に `signaling_notify_metadata` の払い出しによって上書きされます。 詳細は [接続時のシグナリング通知メタデータを認証払い出し時のシグナリング通知メタデータで上書き](SIGNALING_NOTIFY_METADATA.html#2f3416) をご確認ください。 ### シグナリング通知メタデータ拡張 [シグナリング通知メタデータ拡張機能](SIGNALING_NOTIFY_METADATA_EXT.html) を有効にしている場合、 `metadata` はシグナリング通知メタデータ拡張で利用されるため、 `signaling_notify_metadata` で指定した値は `metadata` には含まれません。 - 接続時に指定したシグナリング通知メタデータは `authn_metadata` として含まれます - 認証成功時に払い出したシグナリング通知メタデータは `authz_metadata` として含まれます ## 設定 `sora.conf` で [signaling_notify_metadata](SORA_CONF.html#2d9340) を `false` を指定することで、 シグナリング通知時に `metadata` や `authn_metadata` や `authz_metadata` を含まなくなります。 設定を行ったときの出力例は [sora.conf の設定内容と connection.created 出力の例](SIGNALING_NOTIFY.html#2729eb) をご確認ください。 ## シグナリング接続時での指定 `"type": "connect"` 接続時に `signaling_notify_metadata` で JSON 値を指定できます。 ```javascript { "type": "connect", "role": "sendrecv", "channel_id": "sora", "signaling_notify_metadata": {"authn": true} } ``` シグナリング接続時に指定した値は、通知時に `metadata` として通知されます。 また `authn_metadata` としても通知されます。 `"data"` にはすでにそのチャネルに参加しているクライアントの情報がリストで含まれます。 ```javascript { "type": "notify", "event_type": "connection.created", "authn_metadata": {"authn": true}, "metadata": {"authn": true}, "data": [ { "connection_id": "KKBFZTQXDD6H7FD2NYCQX8S474", "authz_metadata": "xyz", "metadata": "xyz" }, { "connection_id": "4D40YWH56N5S99QHJV6GAPNHB0", "authn_metadata": 10, "metadata": 10 } ] } ``` ### シグナリング接続時に指定できるシグナリング通知メタデータのサイズ制限 > **重要** > > シグナリング接続時に指定できるシグナリング通知メタデータのサイズのデフォルトは 64 KiB (65536 バイト) です。 メタデータのサイズはエンコード済みの JSON 、つまり文字列としてサイズを計算します。 例えば `{"a":"b"}` の場合は 9 バイトで、 `{"a":"b","c":1200}` は 18 バイトです。 最大値を変更したい場合は `sora.conf` の [signaling_notify_authn_metadata_max_size](SORA_CONF.html#a8c147) を変更してください。 また、シグナリング通知メタデータを接続時に指定できなくする場合は [signaling_notify_authn_metadata_max_size](SORA_CONF.html#a8c147) を `0` にしてください。 ## 認証ウェブフックの戻り値での指定 認証ウェブフックでの戻り値は、シグナリング接続時に指定した値を上書きします。 ```javascript { "allowed": true, "signaling_notify_metadata": "authz" } ``` 認証ウェブフックの戻り値で指定した値は、通知時に `metadata` としても通知されます。 また `authz_metadata` としても通知されます。 `"data"` にはすでにそのチャネルに参加しているクライアントの情報がリストで含まれます。 ```javascript { "type": "notify", "event_type": "connection.created", "authn_metadata": "authz", "metadata": "authz", "data": [ { "connection_id": "KKBFZTQXDD6H7FD2NYCQX8S474", "authz_metadata": "xyz", "metadata": "xyz" }, { "connection_id": "4D40YWH56N5S99QHJV6GAPNHB0", "authn_metadata": 10, "metadata": 10 } ] } ``` すでに参加しており、他のクライアントが参加してきた場合や離脱した場合は以下の通りになります。 ```javascript { "type": "notify", "authz_metadata": {"username": "alice"}, "metadata": {"username": "alice"} } ``` ### 認証成功時払い出しのシグナリング通知メタデータのサイズ制限 制限はありません。 ## 接続時のシグナリング通知メタデータを認証払い出し時のシグナリング通知メタデータで上書き 接続時に指定したシグナリング通知メタデータは、 認証成功時の払い出しのシグナリング通知メタデータで上書きされます。 ### 接続時に指定したシグナリング通知メタデータ 接続時に指定したシグナリング通知メタデータを `"authn"` と指定しています。 ```javascript { "type": "connect", "role": "sendrecv", "channel_id": "sora", "signaling_notify_metadata": {"authn": true} } ``` ### 認証成功時に払い出したシグナリング通知メタデータ 認証成功時にシグナリング通知メタデータを `"authz"` と払い出しています。 ```javascript { "allowed": true, "signaling_notify_metadata": "authz" } ``` ### クライアントへ送られるシグナリング通知メタデータ 認証成功時に払い出したシグナリング通知メタデータである `"authz"` が `metadata` として通知されます。 ```javascript { "type": "notify", "event_type": "connection.created", "authn_metadata": {"authn": true}, "authz_metadata": "authz", "metadata": "authz", "data": [] } ``` # シグナリング通知メタデータ拡張機能 ## 概要 シグナリング通知メタデータ拡張機能(以降メタデータ拡張機能)は、 Sora に API 経由で変更できるメタデータを接続ごとに保持する機能です。 - メタデータは新規参加者にシグナリング通知経由で共有されます - メタデータを API 経由で変更した際に変更をプッシュで通知することもできるようになります ## 目的 接続ごとに持たせたメタデータを API 経由で変更し、 既存参加者にはプッシュで通知、新規参加者には参加時に通知するような仕組みを提供することです。 ## シグナリング通知メタデータの課題 今までのシグナリング通知メタデータは、接続時に指定した値を認証成功時の払い出しで上書きするといったものでした。 そのため **接続ごとの状態変更** を管理するために別の仕組みを用意する必要がありました。 メタデータ拡張を利用することで、接続ごとの状態、 例えば「忙しい」といったプレゼンス情報を Sora で管理し、他の接続に通知できるようになります。 ## メタデータ拡張機能を利用することで実現できること - 参加者のプレゼンス状態を変更した際に既存参加者にはプッシュで共有し、新規参加者にはシグナリング通知で共有できるようになる - マイクミュート状態を既存参加者にはプッシュで共有し、新規参加者にはシグナリング通知で共有できるようになる - 画面共有中の配信者を既存参加者にはプッシュで共有し、新規参加者にはシグナリング通知で共有できるようになる 今まで別の場所で保持していた変更可能な状態を Sora 側で持つことができます。 ## メタデータ拡張機能の有効 / 無効について メタデータ拡張機能はデフォルトで無効になっています。 ### sora.conf の指定 メタデータ拡張機能を有効にするには設定を有効にする必要があります。 ```ini signaling_notify_metadata_ext = true ``` ### 有効にした際の変更点 - API 経由で connection.created 時に共有される `metadata` が key / value 形式で指定できるようになります - シグナリング通知時に送られる `metadata` は API でのみ反映され、接続時や認証時の `signaling_notify_metadata` は反映されません - シグナリング通知時に送られる `metadata` の初期値は `{}` で空オブジェクトです - 接続時に指定していた `signaling_notify_metadata` は `authn_metadata` を利用してください- 指定しない場合は `authn_metadata` はシグナリング通知時に含まれません - 認証成功時に払い出していた `signaling_notify_metadata` は `authz_metadata` を利用してください- 指定しない場合は `authz_metadata` はシグナリング通知時に含まれません ## メタデータ拡張機能の特徴 - API 実行時に `"push": true` を指定することで、メタデータの変更と通知を同時に行えます- 通知は `"type": "push"` で行われます - API 経由以外では変更できません ## メタデータ拡張機能の制限 > **重要** > > 1 接続が保持できるメタデータ拡張のサイズは最大 32 KiB (32768 バイト) です。 メタデータのサイズはエンコード済みの JSON 、つまり文字列としてサイズを計算します。 例えば `{"a":"b"}` の場合は 9 バイトで、 `{"a":"b","c":1200}` は 18 バイトです。 ## メタデータ拡張の初期値 メタデータ拡張機能の初期値を認証ウェブフックの成功時に払い出すことができます。 ```javascript { "allowed": true, "signaling_notify_metadata_ext": { "abc": 10 } } ``` 払い出す値は JSON Object である必要があります。 ## 利用方法 **開発ツールを利用します** > **注意** > > シグナリング通知メタデータ拡張 API が有効になるのはイベントウェブフックの `connection.created` が通知されてからです。 1. シグナリング通知メタデータ拡張機能を有効にしましょう- `sora.conf` の `signaling_notify_metadata_ext = true` を設定します 2. まず1つ目の接続をしてみましょう- 開発ツールを開いて、右上の debug にチェックを入れて connect を押してください - `channel_id` はデフォルトの `sora` のままで問題ありません - `connection_id` を `PPD3R008XH0S11CG535JFKQFH0` とします 3. この時点で、まだ `PPD3R008XH0S11CG535JFKQFH0` の `metadata` は `{}` です 4. `PPD3R008XH0S11CG535JFKQFH0` のメタデータに新しいアイテムを追加してみましょう - HTTP API の `PutSignalingNotifyMetadataItem` を利用します - key を "abc" とし value を 10 としてアイテムを追加します - ついでにプッシュ通知も行うように push を true にします ``` $ curl -sS \ -X POST \ http://127.0.0.1:3000/ \ -H "x-sora-target: Sora_20201124.PutSignalingNotifyMetadataItem" \ --json '{"channel_id":"sora","connection_id":"PPD3R008XH0S11CG535JFKQFH0","key":"abc","value":10,"push":true}' \ | jq . { "abc": 10 } ``` 5. 項目に値が入っているか確認してみましょう ``` $ curl -sS \ -X POST \ http://127.0.0.1:3000/ \ -H "x-sora-target: Sora_20201124.GetSignalingNotifyMetadata" \ --json '{"channel_id":"sora","connection_id":"PPD3R008XH0S11CG535JFKQFH0"}' \ | jq . { "abc": 10 } ``` 6. 新しい接続に追加したアイテムが反映されているメタデータが通知されるか確認してみましょう- 別のタブを開いて、debug にチェックを入れて connect して Notify タブを見てみて下さい - `data` の中に `connection_id: PPD3R008XH0S11CG535JFKQFH0` があり、その `metadata` が先程作成した値であれば成功です # Sora クライアント要求仕様 ## 概要 Sora SDK や Sora クライアントの開発者に向けた資料です。 ## クライアント側の終了処理条件 ### RTCPeerConnectionState が failed になる すべての接続において [RTCPeerConnectionState](https://www.w3.org/TR/webrtc/#dom-rtcpeerconnectionstate) が [failed](https://www.w3.org/TR/webrtc/#dom-rtcpeerconnectionstate-failed) になったタイミングで `"type": "disconnect"` は送らず、 クライアント側で終了処理をしてください。 ### WebSocket のみ - RTCPeerConnectionState が failed になった- 終了処理に入る - WebSocket onclose が上がった- 終了処理に入る - WebSocket onerror が上がった- 終了処理に入る ### WebSocket と DataChannel - RTCPeerConnectionState が failed になった- 終了処理に入る - WebSocket onclose が上がった- `"type": "switched"` が送られてきていない- 終了処理に入る - `"type": "switched", "ignore_disconnect_websocket": true` が送られてきていた- 何もしない - `"type": "switched", "ignore_disconnect_websocket": false` が送られてきていて、 RTCPeerConnectionState が failed になっている- 終了処理に入る - `"type": "switched", "ignore_disconnect_websocket": false` が送られてきていて、 RTCPeerConnectionState が failed になっていない- DataChanel で `"type": "disconnect", reason: "WEBSOCKET-ONCLOSE"` を送ることを試みる - 終了処理に入る - WebSocket onerror が上がった- `"type": "switched"` が送られてきていない- 終了処理に入る - `"type": "switched", "ignore_disconnect_websocket": true` が送られてきていた- 何もしない - `"type": "switched", "ignore_disconnect_websocket": false` が送られてきていて、 RTCPeerConnectionState が failed になっている- 終了処理に入る - `"type": "switched", "ignore_disconnect_websocket": false` が送られてきていて、 RTCPeerConnectionState が failed になっていない- DataChanel で `"type": "disconnect", reason: "WEBSOCKET-ONERROR"` を送ることを試みる - 終了処理に入る ### DataChannel のみ - RTCPeerConnectionState が failed になった- 終了処理に入る ### DataChannel の終了 Sora SDK の切断タイムアウトのデフォルト値は 3000 ミリ秒です。 - RTCDataChannel [onclose](https://www.w3.org/TR/webrtc/#dom-rtcdatachannel-onclose) が上がった- RTCDataChannel [onerror](https://www.w3.org/TR/webrtc/#dom-rtcdatachannel-onerror) にコールバックをセットしている場合- 終了処理に入る、または切断タイマーを開始し、すべての RTCDataChannel の [readyState](https://www.w3.org/TR/webrtc/#dom-datachannel-readystate) がすべて [closed](https://www.w3.org/TR/webrtc/#dom-rtcdatachannelstate-closed) にならずタイムアウトした場合は終了処理にはいる - RTCDataChannel onerror にコールバックをセットしていない場合- 終了処理に入る - RTCDataChannel onerror が上がった- 終了処理に入る ## アプリケーション経由の "type": "disconnect" 送信後の終了処理 Sora SDK の切断タイムアウトのデフォルト値は 3000 ミリ秒です。 ### WebSocket のみ `data_channel_signaling: false` の場合。 - WebSocket 経由で `"type": "disconnect", reason: "NO-ERROR"` を送る- 終了処理に入る、または切断タイマーを開始し、WebSocket onclose が上がらずタイムアウトした場合は終了処理に入る ### WebSocket と DataChannel `data_channel_signaling: true` で `ignore_disconnect_websocket: false` の場合。 - `"type": "switched"` が送られて来ていない- WebSocket 経由で `"type": "disconnect", reason: "NO-ERROR"` を送る - 終了処理にはいる、または切断タイマーを開始し、WebSocket onclose が上がらずタイムアウトした場合は終了処理にはいる - `"type": "switched", "ignore_disconnect_websocket": false` が送られてきていて、 WebSocket は切断していない- DataChannel 経由で `"type": "disconnect", reason: "NO-ERROR"` を送る - [RTCDataChannel](https://www.w3.org/TR/webrtc/#dom-rtcdatachannel) [onerror](https://www.w3.org/TR/webrtc/#dom-rtcdatachannel-onerror) にコールバックをセットしている場合- 終了処理に入る、または切断タイマーを開始し、WebSocket の onclose かつ、すべての RTCDataChannel の [readyState](https://www.w3.org/TR/webrtc/#dom-datachannel-readystate) がすべて [closed](https://www.w3.org/TR/webrtc/#dom-rtcdatachannelstate-closed) にならずタイムアウトした場合は終了処理にはいる - [RTCDataChannel](https://www.w3.org/TR/webrtc/#dom-rtcdatachannel) [onerror](https://www.w3.org/TR/webrtc/#dom-rtcdatachannel-onerror) にコールバックをセットしていない場合- 終了処理に入る ### DataChannel のみ `data_channel_signaling: true` で `ignore_disconnect_websocket: true` の場合。 - `"type": "switched"` が送られて来ていない- WebSocket 経由で `"type": "disconnect", reason: "NO-ERROR"` を送る - 切断タイマーを開始する - WebSocket onclose が上がらずタイムアウトした場合は終了処理に入る - `"type": "switched", "ignore_disconnect_websocket": true` が送られてきていて、 WebSocket も切断している- DataChannel 経由で `"type": "disconnect", reason: "NO-ERROR"` を送る - RTCDataChannel [onerror](https://www.w3.org/TR/webrtc/#dom-rtcdatachannel-onerror) にコールバックをセットしている場合- 終了処理に入る、または切断タイマーを開始し、すべての RTCDataChannel の [readyState](https://www.w3.org/TR/webrtc/#dom-datachannel-readystate) がすべて [closed](https://www.w3.org/TR/webrtc/#dom-rtcdatachannelstate-closed) にならずタイムアウトした場合は終了処理にはいる - RTCDataChannel onerror にコールバックをセットしていない場合- 終了処理に入る ## 異常発生による終了 ### シグナリングの異常 終了処理に入ってください。 ### シグナリング以外の異常 `"type": "disconnect", reason: "INTERNAL-ERROR"` を送り、終了処理に入って下さい。 ## ライセンスエラーによる終了 `"type": "connect"` を送った際、ライセンスの期限が過ぎていたり、最大同時接続数を超えた場合、 Sora はエラーメッセージ `SERVICE-UNAVAILABLE` を送信し、 WebSocket を切断し終了します。 ## RTCPeerConnectionState が定義されていない場合 > **注釈** > > ブラウザでは Firefox が RTCPeerConnectionState が定義されていません [RTCDtlsTransport](https://www.w3.org/TR/webrtc/#dom-rtcdtlstransport) が実装されていない場合 RTCPeerConnectionState が正常に動作しないため、 [RTCIceConnectionState](https://www.w3.org/TR/webrtc/#dom-rtciceconnectionstate) を利用してください。 RTCIceConnectionState が [disconnect](https://www.w3.org/TR/webrtc/#dom-rtciceconnectionstate-disconnected) になった場合、切断タイマーを開始し、 タイムアウトした場合 disconnect から変化がなければ切断してください。 Sora SDK の RTCIceConnectionState 用の切断タイマーはデフォルトで 10 秒です。 ## クライアントの状態 ### 認証失敗 接続を試みて、認証ウェブフックが接続を許可しなかった状態です。 Sora は認証失敗理由を WebSocket で送信後に、WebSocket を切断します。 ### 認証成功 接続を試みて、認証ウェブフックが接続を許可した状態です。 この時点ではまだ WebRTC での接続に成功していません。そのため、同時接続数としてもカウントされません 認証は成功しているが、WebRTC での接続に失敗するということがありえるためです。 ### セッション参加 認証が許可されると、そのチャネル ID のセッションが存在していれば **セッションへの参加** が行われます。 もしセッションが存在していなければ **セッションの生成** が行われます。 この時点ではまだ WebRTC での接続に成功していません。そのため、同時接続数としてもカウントされません 認証は成功しているが、WebRTC での接続に失敗するということがありえるためです。 認証が成功したタイミングで、 Sora はクライアントをセッションに参加させます。 この後、クライアントは Sora からの `"type": "offer"` を受け取り、WebRTC の確立を試みます。 ### セッション離脱 セッションからの離脱は、コネクションが破棄された後に発生します。 セッションが API で破棄されたり、セッションのライフタイムが終了した場合、 そのセッションに参加しているクライアントのコネクションを破棄し、セッションから離脱します。 ### コネクション生成 認証が成功し、セッションへ参加後、WebRTC のコネクションが確立された状態です。 つまり [connection.created](EVENT_WEBHOOK.html#eef06c) ウェブフックが送信されたタイミングになります。 このタイミングで Sora は初めて同時接続数に +1 をします。 ### コネクション破棄 何かしらの理由で、WebRTC のコネクションが破棄された状態です。 このタイミングで Sora は同時接続数から -1 をします。 ## クライアントからの "type": "disconnect" による切断 WebSocket シグナリングを利用している場合は、 WebSocket の Close フレームの Reason に `"TYPE-DISCONNECT"` が入るようになりました。 DataChannel シグナリングのみを利用している場合は、 DataChannel を閉じて終了します。 ## WebSocket シグナリング利用時に Sora から正常切断 切断系 API やライフタイム期限などの Sora からの正常切断時に、 WebSocket シグナリングを利用している場合、 WebSocket Close フレームの Code に 1000 、 Reason に切断理由が入ります。 正常な場合の切断理由は以下の 3 つです。 - `LIFETIME-EXPIRED`- ライフタイムによるコネクションの破棄 - `SESSION-DESTROYED`- API やライフタイムなどによるセッションの破棄 - `DISCONNECTED-API`- API によるコネクションの破棄 ## DataChannel シグナリングのみ利用時に Sora から切断が発生した際の `"type": "close"` メッセージの送信 DataChannel シグナリングのみ利用時に Sora から切断が発生した際、 DataChannel を閉じる前に `"type": "close"` メッセージを送信します。 `sora.conf` の [data_channel_signaling_close_message](SORA_CONF.html#058a1e) を `true` に設定することで有効になります。 デフォルトは `false` です。 DataChannel が閉じられたのが正常な処理なのか、それとも何か問題が発生したのかを明確にするための仕組みです。 正常な場合の切断理由は以下の 3 つです。 - `LIFETIME-EXPIRED`- ライフタイムによるコネクションの破棄 - `SESSION-DESTROYED`- API やライフタイムなどによるセッションの破棄 - `DISCONNECTED-API`- API によるコネクションの破棄 # ウェブフック ## 概要 Sora では認証の判断や状態の通知などをすべてウェブフックを利用します。 認証ウェブフックやセッションウェブフックの一部では、ウェブフックの戻り値で設定を払い出すことができます。 ## ウェブフックリクエスト - ウェブフックは HTTP/1.1 で送信します - `content-type` は `application/json` です ## ウェブフックレスポンス - ウェブフックのレスポンスは HTTP/1.1 で返却します - レスポンスの `content-type` は `application/json` です - レスポンスのステータスコードは `200 OK` 等の 200 番台のステータスコードである必要があります ## ウェブフックの設定 - ウェブフック URL を設定しない場合は、ウェブフックリクエストを送信しません - 認証ウェブフックログと統計ウェブフックログは出力しない設定にできます ### 認証ウェブフック **設定**: `auth_webhook_url` に認証ウェブフックの URL を指定します。 **正常ログ**: `auth_webhook.jsonl` に認証ウェブフックが **正常に動作したログ** が出力されます **エラーログ**: `auth_webhook_error.jsonl` に認証ウェブフックがエラーになったログが出力されます 詳細は [認証ウェブフック](AUTH_WEBHOOK.html) をご確認ください。 ### セッションウェブフック **設定**: `session_webhook_url` にセッションウェブフックの URL を指定します。 **正常ログ**: `session_webhook.jsonl` にセッションウェブフックが **正常に動作したログ** が出力されます **エラーログ**: `session_webhook_error.jsonl` にセッションウェブフックがエラーになったログが出力されます 詳細は [セッションウェブフック](SESSION_WEBHOOK.html) をご確認ください。 ### イベントウェブフック **設定**: `event_webhook_url` にイベントウェブフックの URL を指定します。 **全てのログ**: `event_webhook.jsonl` にイベントウェブフックの **全てのログ** が出力されます **エラーログ**: `event_webhook_error.jsonl` にイベントウェブフックでエラーになったログが出力されます 詳細は [イベントウェブフック](EVENT_WEBHOOK.html) をご確認ください。 ### 統計ウェブフック **設定**: `stats_webhook_url` に統計ウェブフックの URL を指定します。 **全てのログ**: `stats_webhook.jsonl` に統計ウェブフックの **全てのログ** が出力されます **エラーログ**: `stats_webhook_error.jsonl` に統計ウェブフックでエラーになったログが出力されます 詳細は [統計ウェブフック](STATS_WEBHOOK.html) をご確認ください。 ## ウェブフックのタイムアウト時間の指定 ### コネクション確立のタイムアウト時間の指定 Sora がウェブフックを送信する際に、ウェブフック送信先のサーバーとのコネクションを確立する際のタイムアウト時間を指定できます。 デフォルトでは 30 秒です。 `sora.conf` の [webhook_connect_timeout](SORA_CONF.html#7a0122) を設定してください。 ### レスポンスのタイムアウト時間の指定 Sora がウェブフックを送信し、そのレスポンスを受け取るまでのタイムアウト時間を指定できます。 デフォルトでは 5 秒です。 `sora.conf` の [webhook_response_timeout](SORA_CONF.html#e81d13) を設定してください。 ## ウェブフックリクエストなどの送信先サーバー証明書の検証に利用する OS 組み込みのルート CA 証明書について Sora は外部サーバーに HTTPS で通信を行う際、デフォルトでは OS に組み込まれた信頼された CA 証明書を利用します。 - Ubuntu は `apt install ca-certificates` でインストールされる証明書を利用します - RHEL (または CentOS) は `dnf install ca-certificates` でインストールされる証明書を利用します それぞれの OS の CA 証明書のパスは以下になります。 - Ubuntu は `/etc/ssl/certs/ca-certificates.crt` のパスにある信頼された CA 証明書を利用します - RHEL (または CentOS) は `/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem` のパスにある信頼された CA 証明書を利用します OS の証明書の読み込みに失敗した場合は、サーバーから送られてくる証明書の検証を行わないようになり、接続ごとに `warning` ログが出力されます。 ウェブフックで利用する CA 証明書は [webhook_tls_verify_cacert_file](SORA_CONF.html#7036dc) に指定することができます。 音声ストリーミングや統計エクスポーターでも CA 証明書を指定することができます。 - [audio_streaming_tls_verify_cacert_file](SORA_CONF.html#feef99) ## ウェブフックリクエスト送信先のサーバーがベーシック認証を利用している場合 もしウェブフックリクエスト送信先のサーバーがベーシック認証を利用している場合は、 `sora.conf` にて [webhook_basic_authn](SORA_CONF.html#081a9f) を `true` に設定することでベーシック認証を利用できます。 [webhook_basic_authn_user_id](SORA_CONF.html#a107fd) と [webhook_basic_authn_password](SORA_CONF.html#f70fe9) に利用するユーザー ID とパスワードを設定してください。 ## ウェブフックリクエスト送信先のサーバーが自己発行証明書などを利用している場合 Sora は `sora.conf` にて CA 証明書を指定しない限り OS に組み込まれた信頼された CA 証明書を利用します。 そのため、自己発行証明書などの正規の認証局から発行されていない証明書を使用した場合には、信頼できないと判断しエラーになります。 この場合は `sora.conf` にて [webhook_tls_verify_cacert_file](SORA_CONF.html#7036dc) を指定することで、 指定されたルート CA を利用してサーバー証明書の検証を行います。 Sora にて自己署名証明書 (Self-signed certificate) を利用する場合、 `sora.conf` にて、[webhook_insecure](SORA_CONF.html#676769) を `true` に設定する必要があります。 ## ウェブフックリクエスト送信先のサーバーが mTLS を利用している場合 mTLS を利用する場合は `sora.conf` にて [webhook_tls_fullchain_file](SORA_CONF.html#93f2b9) にクライアント証明書、 [webhook_tls_privkey_file](SORA_CONF.html#7065d6) にクライアント秘密鍵を指定します。 送信先のサーバーが自己証明書などを利用している場合は [webhook_tls_verify_cacert_file](SORA_CONF.html#7036dc) にサーバー CA 証明書を指定します。 ## ウェブフックリクエスト送信先が IPv6 アドレスのみ対応している場合 Sora は `sora.conf` にて [webhook_ipv6](SORA_CONF.html#6c895b) を `true` にすることで、 IPv6 のみのサーバーに対して、ウェブフックリクエストを送信できるようになります。 ## `connection.updated` と `session.updated` ウェブフック [session.updated](SESSION_WEBHOOK.html#2a5b1b) と [connection.updated](EVENT_WEBHOOK.html#5430cd) は一定間隔で送信してくるウェブフックです。 これらのウェブフックをアプリケーションサーバー側で記録しておくことで、 もし何か障害が発生してウェブフックが通知されなくなった場合でも、 そのコネクションが存在するかどうかの判断を行うことができるようになります。 ## ウェブフックの順番保証 Sora は一部のイベントウェブフックリクエストを送信する際、順番を保証して送信します。 - [connection.created](EVENT_WEBHOOK.html#eef06c) の前に [connection.destroyed](EVENT_WEBHOOK.html#6c02d0) が送信されることはありません - [archive.started](EVENT_WEBHOOK.html#462c97) の前に [archive.available](EVENT_WEBHOOK.html#de9132) や [split-archive.available](EVENT_WEBHOOK.html#555071) や [split-archive.end](EVENT_WEBHOOK.html#31be7a) が送信されることはありません ## ウェブフックの警告メッセージ これらの警告メッセージは sora.jsonl に出力されます。 - AUTH-WEBHOOK-INTERNAL-ERROR - SESSION-WEBHOOK-ERROR - EVENT-WEBHOOK-ERROR - STATS-WEBHOOK-ERROR ### reason - reason に `nxdomain` が含まれる場合- DNS A レコードまたは AAAA レコードが存在しない - reason に `timeout` が含まれる場合- ウェブフック送信先のサーバーとの接続確立が [webhook_connect_timeout](SORA_CONF.html#7a0122) で設定した時間を超えた - ウェブフック送信先のサーバーからのレスポンスが [webhook_response_timeout](SORA_CONF.html#e81d13) で設定した時間を超えた - reason に `closed` が含まれる場合- ウェブフック送信先の TCP 接続が意図しないタイミングで切断された - この問題が発生した場合はウェブフックは失敗と判断します - reason に `enotconn` が含まれる場合- ウェブフック送信先の TCP 接続が意図しないタイミングで切断された際、何かしらの処理を行った - この問題が発生した場合はウェブフックは失敗と判断します # 認証ウェブフック ## 概要 Sora は認証機能を持っていますが、クライアントからの接続可否を判断する機能は持っていません。 接続可否は外部のアプリケーションサーバーにウェブフックを送信し、その戻り値で判断します。 Sora はシグナリング経由で送られてきた情報や、 そのチャネルに接続している情報を HTTP/1.1 POST で `sora.conf` の [auth_webhook_url](SORA_CONF.html#36a99a) に指定された URL へ送信します。 このとき送信する情報は JSON 形式です。 ## 注意 シグナリング `"type": "connect"` 経由で送られてきた情報がそのまま認証ウェブフックのリクエストとして送信されるわけではありません。 ### ログの出力 `sora.conf` の [auth_webhook_url](SORA_CONF.html#36a99a) を有効にしない場合でも `log/auth_webhook.jsonl` は生成されます。 ## HTTP ヘッダー > **警告** > > この機能は [実験的機能](EXPERIMENTAL.html) のため、正式版では仕様が変更される可能性があります > **注釈** > > JSON のパース時の判断などに利用してください。 ### sora-connection-id 認証ウェブフックの HTTP ヘッダー に `sora-connection-id` というヘッダー名でコネクション ID が入ってきます。 コネクション ID が `WCJC78EWK935N7P7Z8FYAKFW9M` の場合は `sora-connection-id: WCJC78EWK935N7P7Z8FYAKFW9M` のように値が入ってきます。 ## 設定 ### auth_webhook_url **デフォルト**: 未設定 認証可否の判断に使用する HTTP リクエストの送信先を `sora.conf` の [auth_webhook_url](SORA_CONF.html#36a99a) に設定します。 認証ウェブフック機能を使用する場合は指定してください。 HTTP のレスポンスは認証の可否に関わらず、 200 OK 等 200 番台のステータスコードを返す必要があります。 ```ini auth_webhook_url = http://127.0.0.1:8080/sora/auth/webhook ``` ### auth_webhook_log > **危険** > > 何か特別な理由がない限り `false` へ変更しないでください。 **デフォルト**: true 認証ウェブフックがログを出力するかどうかを `sora.conf` の [auth_webhook_log](SORA_CONF.html#116686) で設定します。 - 認証ウェブフックが **正常に処理された場合** は `log/auth_webhook.jsonl` にログが出力されます - 認証ウェブフックの **処理が失敗した場合** は `log/auth_webhook_error.jsonl` にログが出力されます- 戻りのステータスコードが 200 番台以外の場合 - 戻りの JSON に `"allowed"` 項目が含まれていない場合 - 戻りの JSON が `"allowed": false` で `"reason"` が含まれていない場合 - 送信先が応答せずタイムアウトになった場合 ## 認証処理時に送信する JSON Sora は、 `sora.conf` の [auth_webhook_url](SORA_CONF.html#36a99a) に設定した URL に対して **POST リクエスト** で次のような JSON を送ります。 型については [認証ウェブフック](WEBHOOK_TYPE.html#cd90e9) を確認してください。 ```javascript { "audio": true, "audio_codec_type": "OPUS", "channel_connections": 0, "channel_id": "sora", "channel_recvonly_connections": 0, "channel_sendonly_connections": 0, "channel_sendrecv_connections": 0, "connection_id": "VSMDDJG3ZH1RHB93W260APVEQW", "data_channel_signaling": true, "data_channels": [ { "compress": false, "direction": "sendrecv", "label": "#abc", "ordered": true } ], "e2ee": false, "ignore_disconnect_websocket": false, "label": "WebRTC SFU Sora", "node_name": "node1@192.0.2.10", "role": "sendrecv", "simulcast": false, "sora_client": { "environment": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.6099.109 Safari/537.36", "raw": "Sora JavaScript SDK 2023.2.0", "type": "Sora JavaScript SDK", "version": "2023.2.0" }, "spotlight": false, "timestamp": "2022-06-08T07:51:32.593704Z", "version": "2024.1.0", "video": true, "video_bit_rate": 1000, "video_codec_type": "VP9", "video_vp9_params": { "profile_id": 0 } } ``` - version- Sora のバージョンが `文字列` で入ってきます - label- `sora.conf` の [label](SORA_CONF.html#815983) で指定した値が入ってきます - node_name- Sora のノード名が入ってきます - timestamp- ウェブフックリクエスト送信時のタイムスタンプが RFC3339 フォーマットで入ってきます - マイクロ秒まで含まれています - id- Base32-UUIDv4 です - ウェブフックごとに割り当てられるユニークな値です - e2ee- 将来的に Message Layer Security (MLS) を利用した End to End Encryption (E2EE) に対応した際の予約項目です - 現時点では常に `false` が含まれます - simulcast- サイマルキャストでの接続要求を出しているかどうかの値が入ってきます - `true` の場合はサイマルキャストを希望している接続です - クライアントが送ってこない場合は `false` が設定されます - simulcast_rid- `simulcast` が `true` かつ `spotlight` が `false` の場合のみこの値が入ってきます - サイマルキャストでの受け取る rid を指定します - simulcast_multicodec- `simulcast` が `true` の場合のみこの値が入ってきます - サイマルキャストマルチコーデックを利用するかどうかの値が入ってきます - spotlight- スポットライトでの接続要求を出しているかどうかの値が入ってきます - クライアントが送ってこない場合は `false` が設定されます - spotlight_focus_rid- `spotlight` が `true` の場合のみこの値が入ってきます - スポットライトでフォーカスされた参加者の映像を受信する rid を指定します - spotlight_unfocus_rid- `spotlight` が `true` の場合のみこの値が入ってきます - スポットライトでフォーカスされていない参加者の映像を受信する rid を指定します - spotlight_number- **この項目はオプションです** - クライアントが送ってこない場合は、この値は含まれません - `spotlight_number` をシグナリングの connect 時に送ってきた場合に値が入ります - whip- WHIP を利用したシグナリングを利用するかどうかの値が入ってきます - whep- WHEP を利用したシグナリングを利用するかどうかの値が入ってきます - role- 以下が入ってきます - `sendrecv` (送受信) - `sendonly` (送信) - `recvonly` (受信) - metadata- **この項目はオプションです** - ユーザーが定義を自由にできる値です - JSON で使用できる形式ならどんな値でも指定できます - `"type": "connect"` で `metadata` が送られてこない場合、アプリケーション側にも送られません - authn_metadata- この項目は metadata と同じです - metadata の別名です - `"type": "connect"` で `metadata` が送られてこない場合、アプリケーション側にも送られません - channel_id- 認証対象のクライアントが接続要求を出しているチャネル ID です - client_id- **この項目はオプションです** - 認証対象のクライアントが利用要求を出しているクライアント ID です - クライアントが指定しない場合は入ってきません - bundle_id- **この項目はオプションです** - 認証対象のコネクションが利用要求を出しているバンドル ID です - クライアントが指定しない場合は入ってきません - connection_id- Base32-UUIDv4 です - 認証対象のコネクションに割り当てられたユニークな ID です - channel_connections- 現在そのチャネルの接続数です - 自分は含まれません - channel_sendrecv_connections- 現在そのチャネルで送受信をしている配信者の接続数です - 自分は含まれません - channel_sendonly_connections- 現在そのチャネルで送信のみをしている配信者の接続数です - 自分は含まれません - channel_recvonly_connections- 現在そのチャネルの配信を受信のみしている視聴者の接続数です - 自分は含まれません - audio- `true` または `false` が入ってきます - `false` の場合は `audio` を使用しません - audio_codec_type- **この項目はオプションです** - `audio` が `false` の場合は含まれません - コーデックはクライアントが送ってこない場合はデフォルトで `OPUS` が使用されます - コーデックの種類は `OPUS` のみです - audio_bit_rate- **この項目はオプションです** - `audio` が `false` やクライアントが送ってこない場合、含まれません - この設定は `audio_codec_type` が `OPUS` の時のみ有効です - [default_audio_bit_rate](SORA_CONF.html#07627a) に値を指定していた場合はその値が利用されます - 最小が 6 で、最大が 510 です - 単位は `kbps` です - video- `true` または `false` が入ってきます - `false` の場合は `video` を使用しません - video_codec_type- **この項目はオプションです** - `video` が `false` の場合は含まれません - コーデックはクライアントが送ってこない場合はデフォルトで `VP9` が使用されます - コーデックの種類は `VP8`、 `VP9`、 `AV1`、 `H264`、 `H265` です - video_bit_rate- **この項目はオプションです** - `video` が `false` の場合は含まれません - ビットレートはクライアントが送ってこない場合は `sora.conf` の [default_video_bit_rate](SORA_CONF.html#620132) が使用されます - デフォルトは 500 です - 最小が 1 で、最大が 30000 です - 15000 より大きい値は現時点でサポート範囲外です - 単位は `kbps` です - video_vp9_params- **この項目はオプションです** - `video_codec_type` が `VP9` の場合に含まれます - 配信者が利用するビデオの VP9 の設定がオブジェクトとして入ってきます - 詳細は [ビデオの VP9 設定指定](WEBSOCKET_SIGNALING.html#b7556a) も参考にしてください - クライアントが `profile_id` の値を送ってこない場合は `sora.conf` の [default_vp9_param_profile_id](SORA_CONF.html#ab0de9) の値が使用されます - video_av1_params- **この項目はオプションです** - `video_codec_type` が `AV1` の場合に含まれます - 配信者が利用するビデオの AV1 の設定がオブジェクトとして入ってきます - 詳細は [ビデオの AV1 設定指定](WEBSOCKET_SIGNALING.html#48f92d) も参考にしてください - クライアントが `profile` の値を送ってこない場合は `sora.conf` の [default_av1_param_profile](SORA_CONF.html#319e30) の値が使用されます - video_h264_params- **この項目はオプションです** - `video_codec_type` が `H264` の場合に含まれます - 配信者が利用するビデオの H264 の設定がオブジェクトとして入ってきます - 詳細は [ビデオの H.264 設定指定](WEBSOCKET_SIGNALING.html#ffc4cb) も参考にしてください - クライアントが `profile_level_id` の値を送ってこない場合は `sora.conf` の [default_h264_param_profile_level_id](SORA_CONF.html#1581db) の値が使用されます - `b_frame` は `sora.conf` の [h264_b_frame](SORA_CONF.html#f546aa) が `true` のときに含まれます - クライアントが `b_frame` の値を送ってこない場合の値は `false` です - video_h265_params- **この項目はオプションです** - `video_codec_type` が `H265` の場合に含まれます - 配信者が利用するビデオの H265 の設定がオブジェクトとして入ってきます - 詳細は [ビデオの H.265 設定指定](WEBSOCKET_SIGNALING.html#bfe45b) も参考にしてください - クライアントが `level_id` の値を送ってこない場合は `sora.conf` の [default_h265_param_level_id](SORA_CONF.html#d15808) の値が使用されます - `b_frame` は `sora.conf` の [h265_b_frame](SORA_CONF.html#a9a8f8) が `true` のときに含まれます - クライアントが `b_frame` の値を送ってこない場合の値は `false` です - metadata- **この項目はオプションです** - ユーザーが定義を自由にできる値です - JSON で使用できる形式ならどんな値でも指定できます - `"type": "connect"` で `metadata` が送られてこない場合、アプリケーション側にも送られません - authn_metadata- **この項目はオプションです** - この項目は metadata と同じです - metadata の別名です - `"type": "connect"` で `metadata` が送られてこない場合、アプリケーション側にも送られません - data_channel_signaling- シグナリングの DataChannel 切り替えをするかどうか - ignore_disconnect_websocket- シグナリングの DataChannel 切り替え時に WebSocket の切断を無視するかどうか - data_channels- **この項目はオプションです** - DataChannel を利用したメッセージングの定義が入ってきます - forwarding_filters- **この項目はオプションです** - 転送フィルターのリストが入ってきます - クライアントが指定しない場合は入ってきません - sora_client- **この項目はオプションです** - クライアントから送られてきた情報が入ってきます - duplicate_client- **この項目はオプションです** - クライアント ID 重複時の既存接続の追い出し機能が有効なセッションの認証ウェブフックに、既に重複する `client_id` のコネクションが存在する場合、そのクライアントの `ice_connection_state` が含まれます - `{"duplicate_client": {"ice_connection_state": "disconnected"}}` のような形式で返されます - シグナリング接続時に指定した `client_id` と重複する `client_id` のコネクションが存在する場合のみ含まれます ## 認証ウェブフックに含まれる同時接続数について > **重要** > > 認証ウェブフックで送られてくる同時接続数、そのウェブフックが送られたタイミングの値であり、 > 厳密にそのチャネルの同時接続数を制限する値としては利用できません。 - channel_connections - channel_sendrecv_connections - channel_sendonly_connections - channel_recvonly_connections これら認証ウェブフックに含まれる同時接続数は WebRTC が確立した後に +1 され、WebRTC が切断されたタイミングで -1 されます。 そのため認証タイミングと WebRTC 確立時の時間差が存在します。 さらに、認証ウェブフックは並列で処理されるため、アプリ側でこの同時接続数の値を利用した厳密な同時接続数の制限を行うことはできません。 もし厳密なチャネル単位での同時接続数を制限したい場合は、 イベントウェブフック [connection.created](EVENT_WEBHOOK.html#eef06c) を利用して、 アプリ側でデータベースでロックを取ってカウントを行い、ロックを取って数値をチェックして認証を行ってください。 ## sora_client 認証ウェブフックの `sora_client` にはクライアントから送られてきた情報が入ってきます。 クライアントから情報が送られてこなければ含まれません。 Sora SDK を利用している場合は必ず入ってきます。 ```javascript "sora_client": { "environment": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.77 Safari/537.36", "raw": "Sora JavaScript SDK 2021.1.0", "type": "Sora JavaScript SDK", "version": "2023.2.0" }, ``` - type- オプションです - クライアントから送られてきた Sora SDK またはクライアントのタイプが入ってきます - raw- オプションです - クライアントから送られてきた sora_client の値がそのまま入ってきます - version- オプションです - クライアントから送られてきた Sora SDK またはクライアントのバージョンが入ってきます - commit_short- オプションです - クライアントから送られてきた Sora SDK のコミットハッシュが入ってきます - environment- オプションです - クライアントから送られてきた端末情報が入ってきます - libwebrtc- オプションです - クライアントから送られてきた libwebrtc のバージョン情報が入ってきます ## 認証成功時のレスポンス JSON 認証に成功した場合は、以下の JSON をステータスコード 200 番台で返してください。 ```javascript { "allowed": true } ``` Sora は `"allowed"` が `true` の場合は認証を成功と判断して処理をします。 ### 認証成功時の払い出し項目 認証成功時に様々な項目を払い出すことができます。 詳細は [認証ウェブフック成功時の払い出し](AUTH_WEBHOOK_RETURN.html) をご確認ください。 ## 認証失敗時のレスポンス JSON 認証に失敗した場合は、以下の JSON を返してください。 ```javascript { "allowed": false, "reason": "" } ``` > **注釈** > > 認証失敗の場合も HTTP レスポンスのステータスコードは 200 番台である必要があります Sora は `"allowed"` が `false` で、 `"reason"` が含まれている場合に認証失敗と判断して処理します。 `"reason"` は必須です。何かしらエラー理由を **100 バイト以内** の文字列で指定してください。 認証に失敗した場合、認証サーバーから送られてきた `"reason"` の内容は、 WebSocket シグナリング切断時のメッセージとしてクライアントに送られます。 ### 例 認証ウェブフックの戻り値で `"reason"` に `"REJECT"` を返した場合、 WebSocket シグナリング切断時のメッセージの `"reason"` に `"REJECT"` が含まれます。 #### 認証ウェブフックの戻り値 ```javascript { "allowed": false, "reason": "REJECT" } ``` #### WebSocket シグナリング切断時のメッセージ - `"code"` が `4490` - `"reason"` が `"REJECT"` ## 認証ウェブフック成功時の払い出し 認証サーバーは認証成功時に様々な値を出すことができます。 ```javascript { "allowed": true, "event_metadata": { "pk": 1 } } ``` 詳細は [認証ウェブフック成功時の払い出し](AUTH_WEBHOOK_RETURN.html) をご確認ください。 ## WebSocket シグナリング時の HTTP ヘッダーを認証ウェブフックにコピーする機能 `sora.conf` の [copy_websocket_signaling_header_names](SORA_CONF.html#db39f3) を設定することで、 認証ウェブフックの HTTP ヘッダーに WebSocket シグナリング時の HTTP ヘッダーをコピーすることができます。 ```ini copy_websocket_signaling_header_names = X-Forwarded-For, X-Real-IP, Tracestate ``` > **危険** > > この機能は指定された WebSocket シグナリング時の HTTP ヘッダーを **そのままコピー** して認証ウェブフックに送信します。 > そのため、指定されたヘッダー名や、実際のヘッダー値に何が含まれていても何も検証は行いません。注意して利用してください。 ## 認証ウェブフックログ `sora.conf` の [auth_webhook_log](SORA_CONF.html#116686) を `true` にしている場合は `log/auth_webhook.jsonl` が出力されます。 > **重要** > > `auth_webhook_log` はデフォルトで `true` です。 このログには認証ウェブフックのリクエストとレスポンス、ウェブフック URL、タイムスタンプが含まれます。 - req- 認証ウェブフックの送信リクエストがそのまま入ります - res- 認証ウェブフックの戻り値がそのまま入ります - url- auth_webhook_url を指定していない場合はログに含まれません - timestamp- RFC3339 フォーマットのタイムスタンプが入ります - UTC です - マイクロ秒まで含まれています - copy_headers- [copy_websocket_signaling_header_names](SORA_CONF.html#db39f3) でコピーされた HTTP ヘッダーが入ります ### auth_webhook_url あり / レスポンスあり ```javascript { "req": { "audio": true, "audio_codec_type": "OPUS", "channel_connections": 0, "channel_id": "sora", "channel_recvonly_connections": 0, "channel_sendonly_connections": 0, "channel_sendrecv_connections": 0, "connection_id": "F2SMT1W59S5ADDZ84CMQ8CDBX4", "e2ee": false, "label": "WebRTC SFU Sora", "node_name": "node1@192.0.2.10", "role": "sendrecv", "simulcast": false, "sora_client": { "environment": "Mozilla/5.0 (Macintosh; Intel Mac OS X 11_0_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36", "raw": "Sora JavaScript SDK 2020.5.0", "type": "Sora JavaScript SDK", "version": "2023.2.0" }, "spotlight": false, "timestamp": "2020-12-07T09:16:54.079650Z", "version": "2024.1.0", "video": true, "video_bit_rate": 1000, "video_codec_type": "VP9", "video_vp9_params": { "profile_id": 0 } }, "res": { "allowed": true, "event_metadata": { "abc": "efg" }, "metadata": "abc", "signaling_notify_metadata": { "a": "b" } }, "timestamp": "2020-12-07T09:16:54.089962Z", "url": "http://127.0.0.1:3001/sora/auth/webhook" } ``` ### auth_webhook_url あり / レスポンスなし - res がありません ```javascript { "req": { "audio": true, "audio_codec_type": "OPUS", "channel_connections": 0, "channel_id": "sora", "channel_recvonly_connections": 0, "channel_sendonly_connections": 0, "channel_sendrecv_connections": 0, "connection_id": "0FBC8HF84544ZDHYYN9BCRNZG8", "e2ee": false, "label": "WebRTC SFU Sora", "node_name": "node1@192.0.2.10", "role": "sendrecv", "simulcast": false, "sora_client": { "environment": "Mozilla/5.0 (Macintosh; Intel Mac OS X 11_0_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36", "raw": "Sora JavaScript SDK 2020.5.0", "type": "Sora JavaScript SDK", "version": "2023.2.0" }, "spotlight": false, "timestamp": "2020-12-07T06:30:56.240917Z", "version": "2024.1.0", "video": true, "video_bit_rate": 1000, "video_codec_type": "VP9", "video_vp9_params": { "profile_id": 0 } }, "timestamp": "2020-12-07T06:30:56.252785Z", "url": "http://127.0.0.1:3001/sora/authn/webhook" } ``` ### auth_webhook_url なし - url がありません ```javascript { "req": { "audio": true, "audio_codec_type": "OPUS", "channel_connections": 0, "channel_id": "sora", "channel_recvonly_connections": 0, "channel_sendonly_connections": 0, "channel_sendrecv_connections": 0, "client_id": "K8PCW533MN1WK24YNZ83HDP74C", "connection_id": "K8PCW533MN1WK24YNZ83HDP74C", "e2ee": false, "label": "WebRTC SFU Sora", "node_name": "node1@192.0.2.10", "role": "sendrecv", "simulcast": false, "sora_client": { "environment": "Mozilla/5.0 (Macintosh; Intel Mac OS X 11_0_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36", "raw": "Sora JavaScript SDK 2020.5.0", "type": "Sora JavaScript SDK", "version": "2023.2.0" }, "spotlight": false, "timestamp": "2020-12-07T06:26:58.916204Z", "version": "2024.1.0", "video": true, "video_bit_rate": 1000, "video_codec_type": "VP9", "video_vp9_params": { "profile_id": 0 } }, "res": { "allowed": true }, "timestamp": "2020-12-07T06:26:58.916242Z" } ``` ## クラスターリレー機能利用時に認証が 2 回行われる場合がある クラスターリレー機能を有効にしている場合、1 クライアントへの認証が **2 回** 行われる場合があります。 特定のノードに同時接続素の寄せを発生させるアフィニティ機能は認証成功時の払い出しで有効か無効かを指定できるため、 リレー機能が存在する場合はアフィニティの確認をするために必ず認証を行います。 その後、アフィニティが有効だったり、ライセンス上限に達していた場合で、別ノードへのリダイレクトが行われた場合、 リダイレクト先のノードで再度認証が発生します。 ### アフィニティが有効で、アフィニティが発生し接続したノードにセッションが存在しない場合 クラスター全体のライセンスに余裕があれば、 既にセッションがある別ノードへリダイレクトを行い、再度認証を行います。 ### アフィニティが有効で、かつ [cluster_affinity_threshold](SORA_CONF.html#2abc6a) の値を超えた場合 クラスター全体のライセンスに余裕があれば、 別ノードへリダイレクトを行い、再度認証を行います。 ### アフィニティ関係なく、接続先ノードのライセンス上限の場合 クラスター全体でライセンスの上限に達していない場合、 別ノードへリダイレクトを行い、再度認証を行います。 ## エラーメッセージ これらエラーメッセージは sora.jsonl に出力されます。 ### AUTH-WEBHOOK-RESPONSE-UNEXPECTED-STATUS-CODE 認証サーバーが返すステータスコードが 200 系ではなかった場合に出力されます。 例えばステータスコードが 400 だと出力されます。 ### INVALID-AUTH-WEBHOOK-RESPONSE-JSON 認証サーバーが返す JSON に必須で項目が含まれていない場合に出力されます。 例えば `allowed` が含まれていない場合に出力されます。 ### AUTH-WEBHOOK-RESPONSE-BAD-JSON 認証サーバーが返す JSON のデコードに失敗した場合に出力されます。 例えば `{"a: b"}` といったような JSON と判断できない場合に出力されます。 ### AUTH-WEBHOOK-RESPONSE-EMPTY-BODY 認証サーバーがステータスコードが 200 系で空のボディを返した場合に出力されます。 ## シーケンス図 ### 認証成功 ```mermaid sequenceDiagram autonumber participant C as クライアント participant S as Sora participant A as アプリケーションサーバー C->>+S: "type": "connect" S->>+A: 認証ウェブフック A-->>-S: 200OK
{"allowed": true} S-->>-C: "type": "offer" C->>S: "type": "answer" note over C,A: WebRTC 確立 ``` ### 認証拒否 ```mermaid sequenceDiagram autonumber participant C as クライアント participant S as Sora participant A as アプリケーションサーバー C->>+S: "type": "connect" S->>+A: 認証ウェブフック A-->>-S: 200OK
{"allowed": false, "reason": "REJECT"} S->>C: WebSocket Close
"code": 4490
"reason": "REJECT" ``` # 認証ウェブフック成功時の払い出し ## 概要 Sora では認証ウェブフック成功時に様々な値を外部の認証サーバーから払い出すことができます。 Sora は払い出された値を反映した状態でクライアントへの接続要求 `"type": "offer"` を送ります。 ## 範囲表記 `2..10` と書いてある場合 2 以上、10 以下の値を指定できることを表しています。 ## audio の払い出し クライアントが指定してきた音声のコーデックやビットレートなどのパラメーターに対して、 認証サーバー側で新たに値を払い出すことで、上書きを行えます。 クライアントが指定してきた値を上書きできるため、 サーバー側でそれぞれのクライアントに対して、音声のコーデックやビットレートをコントロールできます。 ### 指定項目一覧 - audio- `true` または `false` が指定できます > **注意** > > audio_codec_type や audio_bit_rate 等の audio 関連のパラメーターを指定する場合は、あわせて `audio` に `true` を指定する必要があります - audio_codec_type- "OPUS" - codec_type を指定しないこともできます - audio_bit_rate- 6..510 - 単位は kbps です - **デフォルトで最適なビットレートが選択されるようになっているため指定する必要はありません** - audio_opus_params- [オーディオの Opus 設定指定](WEBSOCKET_SIGNALING.html#c82100) をオブジェクトとして指定できます- [オーディオの Opus 設定指定](WEBSOCKET_SIGNALING.html#c82100) の `opus_params` を `audio_opus_params` に変更して指定してください ### 払い出し例 この機能を使用する場合は、認証成功時のレスポンス JSON に `audio` や `audio_codec_type` や `audio_bit_rate` を指定してください。 ここで使用できるのはシグナリングの `"type": "connect"` 時に指定できる `audio` の値です。 ```javascript { "allowed": true, "audio": true, "audio_codec_type": "OPUS", "audio_bit_rate": 64 } ``` ## video の払い出し クライアントが指定してきた映像のコーデックやビットレートなどのパラメーターに対して、 認証サーバー側で新たに値を払い出すことで、上書きを行えます。 クライアントが指定してきた値を上書きできるため、 サーバー側でそれぞれのクライアントに対して、映像のコーデックやビットレートを指定できます。 ### 指定項目一覧 - "video"- true または false が指定できます > **注意** > > video_codec_type や video_bit_rate 等の video 関連のパラメーターを指定する場合は、あわせて `video` に `true` を指定する必要があります - "video_codec_type"- この項目を指定する場合は `"video": true` をあわせて指定してください - 文字列で指定できます - "VP8" - "VP9" - "AV1" - "H264" - "H265" - codec_type を指定しないこともできます - "video_bit_rate"- 1..30000- サポートされている値は 1..15000 です - 単位は kbps です - video_bit_rate を指定しないこともできます - video_vp9_params- [ビデオの VP9 設定指定](WEBSOCKET_SIGNALING.html#b7556a) をオブジェクトとして指定できます- [ビデオの VP9 設定指定](WEBSOCKET_SIGNALING.html#b7556a) の `vp9_params` を `video_vp9_params` に変更して指定してください - video_av1_params- [ビデオの AV1 設定指定](WEBSOCKET_SIGNALING.html#48f92d) をオブジェクトとして指定できます- [ビデオの AV1 設定指定](WEBSOCKET_SIGNALING.html#48f92d) の `av1_params` を `video_av1_params` に変更して指定してください - video_h264_params- [ビデオの H.264 設定指定](WEBSOCKET_SIGNALING.html#ffc4cb) をオブジェクトとして指定できます- [ビデオの H.264 設定指定](WEBSOCKET_SIGNALING.html#ffc4cb) の `h264_params` を `video_h264_params` に変更して指定してください - video_h265_params- [ビデオの H.265 設定指定](WEBSOCKET_SIGNALING.html#bfe45b) をオブジェクトとして指定できます- [ビデオの H.265 設定指定](WEBSOCKET_SIGNALING.html#bfe45b) の `h265_params` を `video_h265_params` に変更して指定してください ### 払い出し例 この機能を使用する場合は、認証成功時のレスポンス JSON に `video` や `video_codec_type` や `video_bit_rate` を指定してください。 ここで使用できるのはシグナリングの `"type": "connect"` 時に指定できる `video` の値です。 ```javascript { "allowed": true, "video": true, "video_codec_type": "VP9", "video_bit_rate": 1000 } ``` ## client_id の払い出し Sora は認証成功時の戻り値に `client_id` を認証サーバーから返すことができます。 シグナリング接続時にも、 認証成功時の戻り値にも `client_id` を指定しない場合は `connection_id` と同じ値が `client_id` に割りあてられます。 ```javascript { "allowed": true, "client_id": "spam" } ``` - client_id- 1 から 255 の長さの文字列 ## bundle_id の払い出し Sora は認証成功時の戻り値に `bundle_id` を認証サーバーから返すことができます。 `bundle_id` を指定した場合、マルチストリーム利用時に `bundle_id` の値が同じ接続からの音声や映像、メッセージング、シグナリング通知を受信しなくなります。 シグナリング接続時にも、認証成功時の戻り値にも `bundle_id` を指定しない場合は `connection_id` と同じ値が `bundle_id` に割り当てられます。 ```javascript { "allowed": true, "bundle_id": "spam" } ``` - bundle_id- 1 から 255 バイトの文字列 ## simulcast の払い出し Sora は認証成功時のタイミングで接続単位での `simulcast` の値を認証サーバーから払い出すことができます。 ```javascript { "allowed": true, "simulcast": true } ``` ### simulcast_request_rid の払い出し *バージョン 2025.2.0 で追加。* Sora は認証成功時のタイミングで接続単位での `simulcast_request_rid` の値を認証サーバーから払い出すことができます。この値を指定するときは必ず `simulacast` も `true` で払い出してください。 この値は `sora.conf` の [default_simulcast_request_rid](SORA_CONF.html#9891c8) の値を上書きします。 ```javascript { "allowed": true, "simulcast": true, "simulcast_request_rid": "r1" } ``` ### simulcast_rid の払い出し > **注意** > > この払い出し項目は 2027 年 12 月リリース予定の Sora にて廃止予定です。 > [simulcast_request_rid の払い出し](AUTH_WEBHOOK_RETURN.html#9939f8) を利用してください。 Sora は認証成功時のタイミングで接続単位での `simulcast_rid` の値を認証サーバーから払い出すことができます。この値を指定するときは必ず `simulacast` も `true` で払い出してください。 この値は `sora.conf` の [default_simulcast_rid](SORA_CONF.html#d95788) の値を上書きします。 ```javascript { "allowed": true, "simulcast": true, "simulcast_rid": "r1" } ``` ### simulcast_auto_rids の払い出し *バージョン 2025.2.0 で追加。* Sora は、認証成功時のタイミングで接続単位での `simulcast_auto_rids` の値を認証サーバーから払い出すことができます。この値は `sora.conf` の [default_simulcast_auto_rids](SORA_CONF.html#97a674) の値を上書きします。この値を指定するときは必ず `simulacast` も `true` で払い出してください。 ```javascript { "allowed": true, "simulcast": true, "simulcast_auto_rids": ["r0", "r1"] } ``` ## simulcast_rpc_rids の払い出し Sora は、認証成功時のタイミングで接続単位での `simulcast_rpc_rids` の値を認証サーバーから払い出すことができます。この値を指定するときは必ず `simulacast` も `true` で払い出してください。 [RPC 機能](RPC.html) の [2025.2.0/RequestSimulcastRid](RPC.html#07fda8) RPC で指定できる rid のリストです。 ```javascript { "allowed": true, "simulcast": true, "simulcast_rpc_rids": ["none", "r0", "r1"] } ``` ## simulcast_encodings の払い出し Sora は、認証成功時のタイミングで接続単位での `simulcast_encodings` の値を認証サーバーから払い出すことができます。この値を指定するときは必ず `simulacast` も `true` で払い出してください。 ```javascript { "allowed": true, "simulcast": true, "simulcast_encodings": [ {"rid": "r0", "active": true, "scaleResolutionDownBy": 2.0, "maxFramerate": 1.0}, {"rid": "r1", "active": true, "scaleResolutionDownBy": 2.0, "maxFramerate": 10.0}, {"rid": "r2", "active": true, "scaleResolutionDownBy": 1.0, "maxFramerate": 30.0} ] } ``` 詳細については [サイマルキャスト](SIMULCAST.html) の [映像のエンコーディングパラメーターのカスタマイズ](SIMULCAST.html#6c680e) をご確認ください。 ## simulcast_codecs の払い出し Sora は、認証成功時のタイミングで接続単位での `simulcast_codecs` の値を認証サーバーから払い出すことができます。この値を指定するときは必ず `simulacast` も `true` で払い出してください。 ```javascript { "allowed": true, "simulcast": true, "simulcast_multicodec": true, "simulcast_codecs": [ {"rid": "r0", "codec_type": "AV1", "codec_params": {"profile": 0}}, {"rid": "r1", "codec_type": "AV1", "codec_params": {"profile": 0}}, {"rid": "r2", "codec_type": "VP9", "codec_params": {"profile_id": 0}} ] } ``` 詳細については [サイマルキャストマルチコーデック](SIMULCAST_MULTICODEC.html) をご確認ください。 ## spotlight_encodings の払い出し Sora は、認証成功時のタイミングで接続単位での `spotlight_encodings` の値を認証サーバーから払い出すことができます。 ```javascript { "allowed": true, "spotlight": true, "spotlight_encodings": [ {"rid": "r0", "active": true, "scaleResolutionDownBy": 4.0, "maxFramerate": 1.0}, {"rid": "r1", "active": true, "scaleResolutionDownBy": 1.0, "maxFramerate": 10.0}, {"rid": "r2", "active": false} ] } ``` 詳細については [スポットライト機能](SPOTLIGHT.html) の [スポットライト利用時の映像のエンコーディングパラメーターのカスタマイズ](SPOTLIGHT.html#bd05eb) をご確認ください。 ## spotlight の払い出し Sora は、認証成功時のタイミングで接続単位での `spotlight` の値を認証サーバーから払い出すことができます。 ```javascript { "allowed": true, "spotlight": true } ``` ### spotlight_number の払い出し > **警告** > > この払い出しは非推奨です。 > セッション単位での払い出し [spotlight_number](SESSION_WEBHOOK.html#c66032) を利用してください。 Sora は、認証成功時のタイミングで接続単位での `spotlight_number` の値を認証サーバーから払い出すことができます。 `spotlight_number` はセッションに参加しているすべてのクライアントが同一の値を指定する必要があります。 ```javascript { "allowed": true, "spotlight": true, "spotlight_number": 3 } ``` ## data_channel_signaling の払い出し Sora は、認証成功時のタイミングで接続単位での `data_channel_signaling` の値を認証サーバーから払い出すことができます。 ```javascript { "allowed": true, "data_channel_signaling": true } ``` この値は `"type": "connect"` の `data_channel_signaling` や `sora.conf` の [default_data_channel_signaling](SORA_CONF.html#adceef) の値を上書きします。 ### 認証成功時にクライアントが受け取る JSON ```javascript { "type": "offer", "sdp": "", "data_channel_signaling": true, "ignore_disconnect_websocket": false } ``` ## ignore_disconnect_websocket の払い出し Sora は、認証成功時のタイミングで接続単位での `ignore_disconnect_websocket` の値を認証サーバーから払い出すことができます。 ```javascript { "allowed": true, "ignore_disconnect_websocket": true } ``` この値は `"type": "connect"` の `ignore_disconnect_websocket` や `sora.conf` の [default_ignore_disconnect_websocket](SORA_CONF.html#58fe04) の値を上書きします。 ただし `data_channel_signaling` が `true` の時のみ、この値は有効になります。 ### 認証成功時にクライアントが受け取る JSON data_channel_signaling が有効な場合、 `"type": "switched"` が送られる際に `ignore_disconnect_websocket` も送られます。 ```javascript { "type": "switched", "ignore_disconnect_websocket": "", } ``` ## rpc_methods の払い出し Sora は、認証成功時のタイミングでそのコネクションが利用できる RPC 機能のメソッド名を `rpc_methods` で認証サーバーから払い出すことができます。 この機能を利用するには、コネクションの `data_channel_signaling` が `true` になっている必要があります。 RPC 機能については [RPC 機能](RPC.html) をご確認ください。 ```javascript { "allowed": true, "rpc_methods": [ "2025.2.0/RequestSimulcastRid", "2025.2.0/PutSignalingNotifyMetadataItem" ] } ``` ## data_channels の払い出し Sora は、認証成功時のタイミングで接続単位での `data_channels` の値を認証サーバーから払い出すことができます。 ```javascript { "allowed": true, "data_channels": [ { "label": "#spam", "max_packet_life_time": 5000, "ordered": true, "protocol": "efg", "compress": false, "direction": "sendonly" }, { "label": "#egg", "max_retransmits": 0, "ordered": false, "protocol": "abc", "compress": false, "direction": "recvonly" } ] } ``` `data_channels` の詳細仕様は [data_channels 仕様](MESSAGING.html#ad1989) をご確認ください。 ## metadata の払い出し Sora は、認証成功時のタイミングで `metadata` という値を認証サーバーから払い出すことができます。 ```javascript { "allowed": true, "metadata": {"spam": "egg"} } ``` 認証サーバーが認証成功時に `metadata` を含めた場合、クライアントへ送る `"type": "offer"` に `metadata` をそのまま送ります。 この機能を使うことで、認証成功のタイミングでユーザーごとに任意の値を送ることができます。 ### 認証成功時にクライアントが受け取る JSON 認証成功の場合は Offer 送信時の JSON に `metadata` が含められます。 ```javascript { "type": "offer", "sdp": "", "metadata": {"spam": "egg"} } ``` ## event_metadata の払い出し > **重要** > > event_metadata はクライアントには送られません Sora は、認証成功時のタイミングで `event_metadata` という値を認証サーバーから払い出すことができます。 認証サーバーが認証成功時に `event_metadata` を含めた場合、 イベントウェブフックリクエスト送信時に `event_metadata` という項目が追加されます。 ```javascript { "allowed": true, "event_metadata": {"pk": 1} } ``` `event_metadata` はクライアントに知られることのない値です。 Sora イベントウェブフックリクエスト送信先のサーバーのみが知り得る値となります。 ### 使用例 この `event_metadata` の値は、クライアントに知られることはありません。そのためユーザー ID を直接入れておくという仕組みも使用できます。 こうすることで通知の際、サーバー側がユーザーの判定をしやすくなります。 ## ICE コネクションステート機能のタイムアウト値の払い出し Sora は、認証成功時のタイミングで `ice_connection_state_disconnected_timeout_ms` と `ice_connection_state_failed_timeout_ms` を認証サーバーから払い出すことができます。 ### ice_connection_state_disconnected_timeout_ms の払い出し ice_connection_state_disconnected_timeout_ms の値は `sora.conf` の [default_ice_connection_state_disconnected_timeout](SORA_CONF.html#420a1e) の値を上書きします。 ```javascript { "allowed": true, "ice_connection_state_disconnected_timeout_ms": 10000, } ``` ### ice_connection_state_failed_timeout_ms の払い出し ice_connection_state_failed_timeout_ms の値は `sora.conf` の [default_ice_connection_state_failed_timeout](SORA_CONF.html#d6f965) の値を上書きします。 ```javascript { "allowed": true, "ice_connection_state_failed_timeout_ms": 20000, } ``` ## シグナリング経由での通知機能の払い出し Sora は、認証成功時のタイミングで `signaling_notify` という値を認証サーバーから払い出すことができます。 ```javascript { "allowed": true, "signaling_notify": true } ``` `signaling_notify` の値を返すことで、クライアントごとにシグナリング通知を受け取るかどうかを指定できるようになります。 シグナリング経由での通知機能の詳細は [シグナリング通知機能](SIGNALING_NOTIFY.html) をご確認ください ## シグナリング経由での通知機能を利用したメタデータの払い出し Sora は、認証成功時のタイミングで `signaling_notify_metadata` という値を認証サーバーから払い出すことができます。 ここに値を指定することで、参加時や離脱時に他の参加者に情報を通知できます。 ```javascript { "allowed": true, "signaling_notify_metadata": { "username": "spam" } } ``` 詳細は [シグナリング通知メタデータ](SIGNALING_NOTIFY_METADATA.html) をご確認ください。 ## シグナリング通知で ICE コネクションステートの変更したことを通知するかどうかの払い出し > **重要** > > この機能は [signaling_notify_ice_connection_state](SORA_CONF.html#e65192) の値が `false` の場合でも利用できます。 Sora は、認証成功時のタイミングで `signaling_notify_ice_connection_state` という値を認証サーバーから払い出すことができます。 `signaling_notify_ice_connection_state` を `true` で払い出すことで、Sora は ICE コネクションステートが変更した際に、 同一チャネルに接続している自分を含むクライアント全員へ通知するようになります。 この値のデフォルト値は `sora.conf` の [signaling_notify_ice_connection_state](SORA_CONF.html#e65192) の値です。 ```javascript { "allowed": true, "signaling_notify_ice_connection_state": true } ``` ## シグナリング通知メタデータ拡張機能の初期値払い出し Sora は、認証成功時のタイミングで `signaling_notify_metadata_ext` という値を認証サーバーから払い出すことができます。 払い出しを利用する場合はシグナリング通知メタデータ拡張が有効である必要があります。 払い出した値がシグナリング通知メタデータ拡張の初期値として使用されます。 ```javascript { "allowed": true, "signaling_notify_metadata_ext": { "mute": true } } ``` ## 録画機能の払い出し Sora は、認証成功時のタイミングで `recording` という値を認証サーバーから払い出すことができます。 ここに `true` を設定することで、録画を有効にできます。 ```javascript { "allowed": true, "recording": true } ``` 録画関連での指定項目詳細はセッションウェブフックでの払い出し項目をご確認ください。 - [recording_expire_time](SESSION_WEBHOOK.html#11485b) - [recording_split_only](SESSION_WEBHOOK.html#2fa13e) - [recording_split_duration](SESSION_WEBHOOK.html#902f0e) - [recording_format](SESSION_WEBHOOK.html#f7a46c) - [recording_metadata](SESSION_WEBHOOK.html#980578) note:: この機能はあくまでセッション開始ではなくある特定の接続が来たタイミングで録画を開始したい場合などに利用する機能です。録画 API を叩かずに録画を開始したい場合に利用してください。 ## 録画ブロック機能の払い出し Sora は、認証成功時のタイミングで `recording_block` という値を認証サーバーから払い出すことができます。 ここに `true` を設定することで、録画有効時にその接続の録画をブロックできます。 録画がブロックされた接続の録画ファイルは出力されません。 未指定の場合は `recording_block` は `false` として扱われます。 ```javascript { "allowed": true, "recording_block": true } ``` ## cluster_affinity の払い出し クラスターリレー機能利用時に `cluster_affinity` を指定することで、コネクション単位で同一ノードへの集約を制御できます。 この値は `sora.conf` の [default_cluster_affinity](SORA_CONF.html#95466d) の値を上書きします。 `cluster_affinity` を `true` に指定した場合、そのセッションでは同一ノードへの集約を試みます。 ```javascript { "allowed": true, "cluster_affinity": true } ``` `cluster_affinity` を `false` に指定した場合、そのセッションでは同一ノードへの集約を行わず、 接続したノードでの WebRTC 確立を試みます。 ```javascript { "allowed": true, "cluster_affinity": false } ``` ## cluster_affinity_node_name_list の払い出し クラスターリレー機能利用時に `cluster_affinity_node_name_list` を指定することで、 接続単位で割り当て可能なノードを指定したリストに固定できます。 この機能を利用するには `cluster_affinity` を `true` で明示する必要があります。 ```javascript { "allowed": true, "cluster_affinity": true, "cluster_affinity_node_name_list": ["sora1@192.0.2.10", "sora2@192.0.2.11"] } ``` 以下のケースは認証失敗として扱われ、クライアントには SERVICE-UNAVAILABLE エラーが返されます。 - `invalid_affinity_node_name_list`: `cluster_affinity_node_name_list` の指定内容が不正 - `no_acceptable_node`: 指定したノードのうち接続先として利用できるノードが 1 つもない 以下のケースは `sora.jsonl` に警告ログを出力した上で `cluster_affinity_node_name_list` を無視し、 接続は継続されます。 - `cluster_affinity` が `true` で明示されていない場合 - [最大ノード数ライセンス](LICENSE.html#aee259) が取得されていない環境で `cluster_affinity: true` を払い出した場合 詳細は [アフィニティ機能の接続先ノード範囲指定機能](CLUSTER.html#c6991a) をご確認ください。 ## forwarding_filters の払い出し Sora は、認証成功時のタイミングで `forwarding_filters` を認証サーバーから払い出すことができます。 転送フィルタールールの詳細については [転送フィルター機能](FORWARDING_FILTER.html) をご確認ください。 ```javascript { "allowed": true, "forwarding_filters": [ { "action": "allow", "name": "audio-only", "priority": 128, "rules": [ [ { "field": "kind", "operator": "is_in", "values": [ "audio" ] } ] ] } ] } ``` ## connection_lifetime の払い出し Sora は、認証成功時のタイミングで `connection_lifetime` を認証サーバーから払い出すことができます。 例えば 3600 を指定すると 1 時間 (3600 秒) 後に接続が切断されます。 ```javascript { "allowed": true, "connection_lifetime": 3600 } ``` - **秒** で指定してください - [default_connection_lifetime](SORA_CONF.html#7ec6a4) の値を上書きします - 最大 2,592,000 秒 (30 日) まで指定できます - コネクション生成後に変更することはできません - `connection_lifetime` が未指定の場合は **無制限** です - `connection.destroyed` の `reason` に `lifetime_expired` が入ります - コネクションのライフタイムが終了すると、コネクションが破棄され切断します - コネクションのライフタイムが終了すると、コネクションウェブフック `connection.destroyed` が送信されます - コネクションのライフタイムよりセッションのライフタイムが優先されます ## ignore_max_connections の払い出し Sora は、認証成功時のタイミングで `ignore_max_connections` を認証サーバーから払い出すことができます。 セッション作成時の `max_connections` にてセッション単位の最大同時接続数を制限できますが、 `ignore_max_connections` を `true` に指定するとこの制限を無視して接続できます。 ```javascript { "allowed": true, "ignore_max_connections": true } ``` ## playout_delay_min_delay と playout_delay_max_delay の払い出し Sora は、認証成功時のタイミングで `playout_delay_min_delay` と `playout_delay_max_delay` を認証サーバーから払い出すことができます。 プレイアウト遅延機能をコネクションに指定する場合は、 `playout_delay_min_delay` と `playout_delay_max_delay` の両方を指定する必要があります。 ```javascript { "allowed": true, "playout_delay_min_delay": 0, "playout_delay_max_delay": 100 } ``` この値は `sora.conf` の [default_playout_delay_min_delay](SORA_CONF.html#194218) と [default_playout_delay_max_delay](SORA_CONF.html#c1b0ab) の値を上書きします。 0~40950 の範囲で指定します。単位はミリ秒です。 この機能を利用することで、コネクションごとにプレイアウト遅延を指定できます。 詳細は [プレイアウト遅延機能](PLAYOUT_DELAY.html) をご確認ください。 ## ipv4_address と ipv6_address の払い出し Sora は、認証成功時のタイミングで `ipv4_address` または `ipv6_address` を認証サーバーから払い出すことができます。 `ipv4_address` と `ipv6_address` は片方だけでも、両方返しても問題ありません。 ```javascript { "allowed": true, "ipv4_address": "192.0.2.10", "ipv6_address": "2001:0DB8::10" } ``` この値は SDP の offer 時の a=candidate と TURN-UDP と TURN-TCP の URL の払い出しに使用されます。 `sora.conf` の [ipv4_address](SORA_CONF.html#04becc) と [ipv6_address](SORA_CONF.html#30f40f) のがこの戻り値で上書きされます。 指定する IP アドレスを間違えると繋がらなくなるため、使用には注意してください。 この機能を使用することでコネクションごとに経路を指定できます。 ## turn_fqdn 払い出し Sora は、認証成功時のタイミングで接続単位での `turn_fqdn` の値を認証サーバーから払い出すことができます。 ```javascript { "allowed": true, "turn_fqdn": "sora-turn.example.com" } ``` この値は `sora.conf` の [turn_fqdn](SORA_CONF.html#6513e4) の値を上書きします。 指定する FQDN を間違えると繋がらなくなるため、使用には注意してください。 ## turn_tls_fqdn の 払い出し Sora は、認証成功時のタイミングで接続単位での `turn_tls_fqdn` の値を認証サーバーから払い出すことができます。 ```javascript { "allowed": true, "turn_tls_fqdn": "sora-turn.example.com" } ``` この値は `sora.conf` の [turn_tls_fqdn](SORA_CONF.html#3bfd30) の値を上書きします。 指定する FQDN を間違えると繋がらなくなるため、使用には注意してください。 ## rtc_stats の払い出し Sora は、認証成功時のタイミングで接続単位での `rtc_stats` の値を認証サーバーから払い出すことができます。 ```javascript { "allowed": true, "rtc_stats": true } ``` この値は `sora.conf` の [default_rtc_stats](SORA_CONF.html#558c2b) の値を上書きします。 ## audio_streaming_language_code の払い出し Sora は、認証成功時のタイミングで音声ストリーミングのランゲージコードの値を認証サーバーから払い出すことができます。 ```javascript { "allowed": true, "audio_streaming_language_code": "ja-JP" } ``` この値は接続時の `audio_streaming_language_code` と `sora.conf` の [default_audio_streaming_language_code](SORA_CONF.html#856531) の値を上書きします。 ## turn_tcp_only / turn_tls_only の払い出し > **重要** > > この設定は検証時のみ利用してください。 Sora は、認証成功時のタイミングで接続単位での `turn_tcp_only` または `turn_tls_only` の値を認証サーバーから払い出すことができます。 ```javascript { "allowed": true, "turn_tcp_only": true } ``` ```javascript { "allowed": true, "turn_tls_only": true } ``` この値は `sora.conf` の [turn_tcp_only](SORA_CONF.html#479c51) や [turn_tls_only](SORA_CONF.html#58d702) の値を上書きします。 ## rtp_packet_loss_simulator_incoming / rtp_packet_loss_simulator_outgoing の払い出し > **重要** > > この設定は検証時のみ利用してください。 **範囲**: 0..100 Sora は、認証成功時のタイミングで接続単位での RTP パケットロスシミュレーターの値を認証サーバーから払い出すことができます。 ```javascript { "allowed": true, "rtp_packet_loss_simulator_outgoing": 5 } ``` ```javascript { "allowed": true, "rtp_packet_loss_simulator_incoming": 5 } ``` この値は `sora.conf` の [rtp_packet_loss_simulator_incoming](SORA_CONF.html#5c9058) や [rtp_packet_loss_simulator_outgoing](SORA_CONF.html#1206b6) の値を上書きします。 ## シーケンス図 ```mermaid sequenceDiagram participant C as クライアント participant S as Sora participant A as アプリケーションサーバー C->>+S: "type": "connect" S->>+A: 認証ウェブフック note right of A: ここで払い出しする A-->>-S: 200 OK
"allowed": true S-)-C: "type": "offer" C-)S: "type": "answer" note over C,S: ICE 確立 note over C,S: DTLS 確立 note over C,S: WebRTC 確立 ``` # セッションウェブフック ## 概要 セッションウェブフックは、セッションの状態を送信するウェブフックです。 例えばチャネルに誰も接続していない状態で新しく接続されたタイミングや、 誰も接続しない状態が一定時間続いたタイミングで、 ウェブフックを利用してセッションの状態などを HTTP リクエストで送信する機能です。 また、セッション開始時にウェブフックの戻り値で録画開始や音声ストリーミングなどを指定することができ、 今まで API を叩いていた処理をウェブフックで行うことができるようになります。 ## 目的 セッションは実際にチャネルに参加しているクライアントの集まりです。 もともと Sora にはチャネルを作るという概念がありません。 チャネルに誰も接続していない状態で、新しく接続があれば、チャネルが利用されている状態になります。 そのため、チャネルが利用されているかどうかの判断は HTTP API を利用したり、 イベントウェブフックリクエストの送信を利用したりして、アプリケーション側で判断する必要がありました。 このセッションウェブフックは、新しくチャネルに状態を持たせ、 その状態をウェブフックリクエストで送信することで、API やイベントウェブフックを利用せずに、 チャネルの状態を判断することができるようになります。 ## セッション ID 特定の期間チャネルに接続していたクライアントをグルーピングするために、 Sora はセッション ID という値を払い出します。 セッション ID は Sora が指定するため、書き換えることはできません。 セッション ID は UUIDv4 を Base32 でエンコードした 26 バイトの文字列です。 ## ログ セッションウェブフックのログは `log/session_webhook.jsonl` と `log/session_webhook_error.jsonl` に出力されます。 これは [session_webhook_url](SORA_CONF.html#76fa79) を指定していなくても出力されます。 ### session_webhook.jsonl セッションウェブフックで送信した **すべて** の処理を書き込みます。 ### session_webhook_error.jsonl セッションウェブフックの送信が正常に処理できなかった処理を書き込みます。 - ステータスコードが 200 番台以外の場合 - タイムアウトした場合 ## 設定 ### session_webhook_url セッションウェブフックリクエストの送信先を指定してください。 ```ini session_webhook_url = https://example.com/sora/session/webhook ``` ### session_created_timeout セッションが存在しない状態で、新しくセッションを生成する際の制限時間です。 これはセッションウェブフック処理も含めた時間で、この時間を超えるとタイムアウトとなり、切断されます。 デフォルトでは 5 秒です。 ```ini session_created_timeout = 5 s ``` ### session_destroyed_timeout そのチャネルの接続数が 0 になってから新しい接続が無い場合に、 `session.destroyed` のセッションウェブフックリクエストを送信するまでの時間を指定します。 デフォルトでは 15 秒です。 ```ini session_destroyed_timeout = 15 s ``` ### session_updated_webhook_interval `session.updated` の送信間隔を指定します。 デフォルトでは `1 min` (1 分) です。単位は `min` しか指定できません。 ```ini session_updated_webhook_interval = 1 min ``` ## ログ セッションウェブフックのログは `log/session_webhook.jsonl` と `log/session_webhook_error.jsonl` に出力されます。 これは [session_webhook_url](SORA_CONF.html#76fa79) を指定していなくても出力されます。 ### session_webhook.jsonl セッションウェブフックの送信が **正常に動作した** 処理を書き込みます。 #### 項目 - id - Base32 UUIDv4 - timestamp- RFC 3339 UTC マイクロ秒 - req - リクエスト - センシティブデータはマスクされます - res - レスポンス - センシティブデータはマスクされます - url- セッションウェブフック URL - セッションウェブフックが指定されていなければ含まれません ### session_webhook_error.jsonl セッションウェブフックの送信が正常に処理できなかった処理を書き込みます。 - ステータスコードが 200 番台以外の場合 - タイムアウトした場合 #### 項目 - id - Base32 UUIDv4 - timestamp- RFC 3339 UTC マイクロ秒 - req - リクエスト - センシティブデータはマスクされません - reason - ウェブフックエラー理由 - url- セッションウェブフック URL - セッションウェブフックが指定されていなければ含まれません ## `spotlight` が既存セッションと異なる場合の挙動 既存セッションが存在する場合、 `spotlight` が異なる新規接続が来た場合は、 `INVALID-MESSAGE` エラーを返し切断するようになります。 ## session.created **セッション生成** 同時接続数が 0 のチャネル ID に対して、新しい接続の認証が成功したタイミングで `session.created` ウェブフックリクエストを送信します。 チャネルの同時接続数が 0 の場合でも、 `spotlight` の値が一致するセッションが過去に生成されており、 まだ破棄されていない場合には、そのセッションが使用されるため `session.created` ウェブフックは送信されません。 * - キー - 型 - 内容 * - type - string - "session.created" * - id - string - ウェブフック ID (ユニーク) * - label - string - sora.conf の label にて指定した値 * - node_name - string - Sora ノード名 * - version - string - Sora のバージョン * - channel_id - string - チャネル ID * - session_id - string - セッション ID * - timestamp - string (RFC3339 UTC マイクロ秒) - ウェブフック作成時間 * - created_time - integer (UNIX 時間) - セッション生成時間 * - created_timestamp - string (RFC3339 UTC マイクロ秒) - セッション生成時間 * - spotlight - boolean - スポットライトが有効かどうか * - external_signaling_url - string - (クラスター機能が有効の場合) 接続先の external_signaling_url ```javascript { "channel_id": "sora", "created_time": 1638337454, "created_timestamp": "2021-12-01T05:44:14.523736Z", "id": "2YN2DQE5KD3GSFSVPAYZ7VTAV4", "label": "WebRTC SFU Sora", "spotlight": false, "node_name": "sora@127.0.0.1", "session_id": "NPR769YPQ914K10FW42PGH4TKW", "timestamp": "2021-12-01T05:44:14.523912Z", "external_signaling_url": "wss://node-01.example.com/signaling", "type": "session.created", "version": "2023.2.0" } ``` ### 戻り値 セッションウェブフックは `"type": "session.created"` の戻り値を指定できます。 #### session_metadata > **注釈** > > この項目はセンシティブデータとして扱われます。 `session_metadata` を指定した場合、セッション更新時の `session.updated` とセッション破棄時の `"type": "session.destroyed"` のウェブフックリクエストに `session_metadata` が含まれます。 ```javascript { "session_metadata": "" } ``` #### session_lifetime セッション生成のタイミングで、セッションのライフタイムを指定することができます。 例えば `3600` を指定した場合、 3600 秒後にセッションは破棄されます ```javascript { "session_lifetime": 3600 } ``` - `session_lifetime` の指定にかかわらず、セッションの同時接続数が 0 になると、 [session_destroyed_timeout](SORA_CONF.html#642cc4) に指定した時間が経過したタイミングでセッションが破棄されます - **秒** で指定してください - 最大 2,592,000 秒 (30 日) まで指定できます - セッション生成後に変更することはできません - `session_lifetime` が未指定の場合は **無制限** です - `session.destroyed` の `reason` に `lifetime_expired` が入ります - `connection.destroyed` の `reason` に `session_destroyed` が入ります - セッションのライフタイムが終了すると、セッションが破棄され切断します - セッションのライフタイムが終了すると、セッションウェブフック `session.destroyed` が送信されます #### spotlight_number セッション生成のタイミングで、スポットライト機能が有効な場合に、スポットライトの数を指定することができます。 クライアント単位でのシグナリング接続時や認証ウェブフック成功時の `spotlight_number` と異なる値を払い出した場合、 エラーとなりますので注意してください。 `spotlight_number` はセッションウェブフックでの指定を推奨します。 セッション単位の `spotlight_number` を変更するには [ChangeSpotlightNumber](API_SPOTLIGHT.html#17e930) API を利用する必要があります。 ```javascript { "spotlight_number": 3 } ``` #### group_id セッション生成のタイミングで、セッションをグルーピングする `group_id` を指定することができます。 [ListSessions](API_SESSION.html#748f19) API にて `group_id` を指定することで、指定した `group_id` のセッションのみを返します。 `group_id` は 1 バイト以上 255 バイト以下の文字列です。未指定の場合は `session_id` が入ります。 ```javascript { "group_id": "group_01" } ``` #### duplicate_client_id セッション生成のタイミングで、 クライアント ID が重複した場合の挙動を `duplicate_client_id` で指定することができます。 `duplicate_client_id` に `evict` を指定した場合、 既に接続している同一クライアント ID の接続を破棄するような挙動になります。 `duplicate_client_id` には `allow` または `evict` を指定できます。 - `allow` は今まで通り重複を許容します - `evict` は既存の接続を破棄し、新規接続を受け入れます、つまり既存接続を追い出します 未指定の場合は `sora.conf` の [default_duplicate_client_id](SORA_CONF.html#c8b57b) の値を利用します。 ```javascript { "duplicate_client_id": "evict" } ``` #### max_connections - `max_connections` を指定した場合、セッション単位での最大同時接続数が指定した値になります。 - 途中で最大同時接続数を変更することはできません。指定できる範囲は `0..10000` です - `max_connections` が `0` の場合は誰も接続することができなくなります - セッションが同時接続数制限に達した場合はクライアントに `SERVICE-UNAVAILABLE` を通知します - セッションが同時接続数制限に達した場合は [ignore_connection_failed_webhook](SORA_CONF.html#45096a) が `false` の場合は [connection.failed](EVENT_WEBHOOK.html#5266b6) が送信されます> - `message` に `"SERVICE-UNAVAILABLE"` が含まれます ```javascript { "max_connections": 3 } ``` #### recording `recording` を `true` を指定した場合、セッション単位の録画を開始します。 詳細は [録画機能 (セッション単位) の session.created](RECORDING.html#3cec61) をご確認ください。 ```javascript { "recording": true } ``` #### recording_expire_time - `recording` が `true` の場合のみ有効です。録画の有効期限を秒単位で指定します - `recording_expire_time` を `3600` を指定した場合、 3600 秒後に録画は終了します 詳細は [録画機能 (セッション単位) の session.created](RECORDING.html#3cec61) をご確認ください。 ```javascript { "recording_expire_time": 3600 } ``` #### recording_split_only - `recording` が `true` の場合のみ有効です。録画を分割のみで行うかどうかを指定します - `recording_split_only` を `true` に指定した場合、録画は分割のみで行われます 詳細は [録画機能 (セッション単位) の session.created](RECORDING.html#3cec61) をご確認ください。 ```javascript { "recording_split_only": true } ``` #### recording_split_duration - `recording` が `true` の場合のみ有効です。分割録画の分割時間を秒単位で指定します - `recording_split_duration` を `60` を指定した場合、 60 秒ごとに録画が分割されます 詳細は [録画機能 (セッション単位) の session.created](RECORDING.html#3cec61) をご確認ください。 ```javascript { "recording_split_duration": 60 } ``` #### recording_metadata `recording` が `true` の場合のみ有効です。recording.report ウェブフックやレポートファイルに含まれます。 詳細は [録画機能 (セッション単位) の session.created](RECORDING.html#3cec61) をご確認ください。 ```javascript { "recording_metadata": {"spam": "egg"} } ``` #### recording_format `recording` が `true` の場合のみ有効です。録画ファイルのフォーマットを指定します。 `webm` と `mp4` が指定できます。 詳細は [録画機能 (セッション単位) の session.created](RECORDING.html#3cec61) をご確認ください。 ```javascript { "recording_format": "mp4" } ``` #### forwarding_filters `forwarding_filters` を指定した場合、転送フィルターをセッションに対して反映することができます。 転送フィルタールールの詳細については [転送フィルター機能](FORWARDING_FILTER.html) をご確認ください。 ```javascript { "forwarding_filters": [ { "action": "allow", "rules": [ // チャネルに接続しているすべてのコネクションに音声のみ転送する [ {"field": "kind", "operator": "is_in", "values": ["audio"]} ] ] } ] } ``` #### audio_streaming `audio_streaming` を `true` に指定した場合、そのセッションで音声ストリーミングが有効になります。 音声ストリーミング機能の詳細については [音声ストリーミング機能](AUDIO_STREAMING.html) をご確認ください。 ```javascript { "audio_streaming": true } ``` #### audio_streaming_auto `audio_streaming_auto` を `true` に指定した場合、そのセッションで音声ストリーミングが有効になり、 かつ自動開始、自動停止機能が有効になります。 この設定を `true` にするときには `audio_streaming` も `true` に設定する必要があります。 詳細は [audio_streaming 関連の払い出し設定の組み合わせによる動作](AUDIO_STREAMING.html#e28478) をご確認ください。 ```javascript { "audio_streaming": true, "audio_streaming_auto": true } ``` ## session.destroyed **セッション破棄** 同時接続数が 0 になったチャネル ID が一定時間経過したタイミングで、 `session.destroyed` ウェブフックリクエストを送信します。 * - キー - 型 - 内容 * - type - string - "session.destroyed" * - id - string - ウェブフック ID (ユニーク) * - label - string - sora.conf の label にて指定した値 * - node_name - string - Sora ノード名 * - version - string - Sora のバージョン * - channel_id - string - チャネル ID * - group_id - string - セッションをグルーピングする ID * - session_id - string - セッション ID * - timestamp - string (RFC3339 UTC マイクロ秒) - ウェブフック作成時間 * - created_time - integer (UNIX 時間) - セッション生成時間 * - created_timestamp - string (RFC3339 UTC マイクロ秒) - セッション生成時間 * - destroyed_time - integer (UNIX 時間) - セッション破棄時間 * - destroyed_timestamp - string (RFC3339 UTC マイクロ秒) - セッション破棄時間 * - spotlight - boolean - スポットライトが有効かどうか * - spotlight_number - integer - スポットライトが有効な場合、スポットライト数 * - total_connections - integer - 延べ接続数 * - max_connections - integer - 最大同時接続数 * - connections - array (object) - (クラスター機能が無効の場合) セッションに参加した接続情報 * - session_metadata - json - (値がある場合) session.created の戻り値で指定した値 * - external_signaling_url - string - (クラスター機能が有効の場合) 接続先の external_signaling_url * - reason - string - セッションが破棄された理由 ("normal", "validation_error", "webhook_error", "terminated_api", "lifetime_expired", "abort") ```javascript { "channel_id": "sora", "connections": [ { "audio": true, "audio_codec_type": "OPUS", "client_id": "W9QE86Z0BS1QFFPZ2QB5DRZ2HC", "bundle_id": "W9QE86Z0BS1QFFPZ2QB5DRZ2HC", "connection_id": "W9QE86Z0BS1QFFPZ2QB5DRZ2HC", "connection_created_timestamp": "2021-12-01T05:44:23.051704Z", "connection_destroyed_timestamp": "2021-12-01T05:44:57.083215Z", "role": "sendrecv", "simulcast": false, "video": true, "video_bit_rate": 1000, "video_codec_type": "VP9", "video_vp9_params": { "profile_id": 0 }, }, { "audio": true, "audio_codec_type": "OPUS", "client_id": "JXMYW6GPX54EH0HGA5X4130FBM", "bundle_id": "JXMYW6GPX54EH0HGA5X4130FBM", "connection_id": "JXMYW6GPX54EH0HGA5X4130FBM", "connection_created_timestamp": "2021-12-01T05:44:21.500272Z", "connection_destroyed_timestamp": "2021-12-01T05:44:56.878019Z", "role": "sendrecv", "simulcast": false, "video": true, "video_bit_rate": 1000, "video_codec_type": "VP9", "video_vp9_params": { "profile_id": 0 }, }, { "audio": true, "audio_codec_type": "OPUS", "client_id": "F8VK9R71BN5S5EDE737C8XAA3C", "bundle_id": "F8VK9R71BN5S5EDE737C8XAA3C", "connection_id": "F8VK9R71BN5S5EDE737C8XAA3C", "connection_created_timestamp": "2021-12-01T05:44:19.811385Z", "connection_destroyed_timestamp": "2021-12-01T05:44:55.897819Z", "role": "sendrecv", "simulcast": false, "video": true, "video_bit_rate": 1000, "video_codec_type": "VP9", "video_vp9_params": { "profile_id": 0 }, }, { "audio": true, "audio_codec_type": "OPUS", "client_id": "VBYS5TV5S510F98GS2VK015AKG", "bundle_id": "VBYS5TV5S510F98GS2VK015AKG", "connection_id": "VBYS5TV5S510F98GS2VK015AKG", "connection_created_timestamp": "2021-12-01T05:44:14.716974Z", "connection_destroyed_timestamp": "2021-12-01T05:44:57.197372Z", "role": "sendrecv", "simulcast": false, "video": true, "video_bit_rate": 1000, "video_codec_type": "VP9", "video_vp9_params": { "profile_id": 0 }, } ], "created_time": 1638337454, "created_timestamp": "2021-12-01T05:44:14.523736Z", "destroyed_time": 1638337502, "destroyed_timestamp": "2021-12-01T05:45:02.199179Z", "id": "M7K1AVS9KS34V9XFJJH04TB400", "label": "WebRTC SFU Sora", "max_connections": 4, "node_name": "sora@127.0.0.1", "group_id": "NPR769YPQ914K10FW42PGH4TKW", "session_id": "NPR769YPQ914K10FW42PGH4TKW", "spotlight": false, "timestamp": "2021-12-01T05:45:02.199419Z", "total_connections": 4, "session_metadata": {"spam": "egg"}, "type": "session.destroyed", "version": "2023.2.0" } ``` ### connections connections に入ってくる以下の二つは RFC3339 形式の時間ではなく `null` が入ってくる場合があります。 - connection_created_timestamp - connection_destroyed_timestamp これは、認証は成功し、セッションに参加はしたが、何らかの理由で WebRTC が確立に失敗した場合発生します。 両方ともの値に null が入ってきます。 ### reason session.destroyed には reason が含まれ、セッションが破棄された理由が入ります。 - `"normal"` は通常のセッション破棄 - `"validation_error"` は [session.created](SESSION_WEBHOOK.html#1d1984) の戻り値が正常ではなかったことによるエラーによるセッション破棄- このセッション破棄は [session_created_response_validate_warning_as_error](SORA_CONF.html#9df65e) が `true` の場合のみ発生します - 例外: [転送フィルター機能](FORWARDING_FILTER.html) に関するバリデーション失敗は、この設定に関わらずエラーになりセッション破棄になります - `"webhook_error"` はセッション生成時のウェブフック [session.created](SESSION_WEBHOOK.html#1d1984) のウェブフック処理中にエラーが発生したことによるセッション破棄- 以下はエラー例です - [session_webhook_url](SORA_CONF.html#76fa79) と接続できなかった場合 - ウェブフック送信先からステータスコードが 2XX 以外だった場合 - ウェブフック送信先からの JSON がパースできなかった場合 - ウェブフック送信先からの JSON のパース結果が JSON Object 以外だった場合 - ウェブフック送信先との HTTPS に失敗した場合 - ウェブフック送信先との mTLS に失敗した場合 - `"terminated_api"` は [TerminateSession](API_SESSION.html#ba022b) API によるセッション破棄 - `"lifetime_expired"` はセッションライフタイムの期限切れによるセッション破棄 - `"abort"` は異常発生のセッション破棄 ### クラスター有効時 クラスター有効時には `connections` 項目は含まれません。 ```javascript { "channel_id": "sora", "created_time": 1638337454, "created_timestamp": "2021-12-01T05:44:14.523736Z", "destroyed_time": 1638337502, "destroyed_timestamp": "2021-12-01T05:45:02.199179Z", "id": "M7K1AVS9KS34V9XFJJH04TB400", "label": "WebRTC SFU Sora", "max_connections": 4, "node_name": "sora@127.0.0.1", "group_id": "NPR769YPQ914K10FW42PGH4TKW", "session_id": "NPR769YPQ914K10FW42PGH4TKW", "spotlight": false, "timestamp": "2021-12-01T05:45:02.199419Z", "reason": "normal", "total_connections": 4, "session_metadata": {"spam": "egg"}, "external_signaling_url": "wss://node-01.example.com/signaling", "type": "session.destroyed", "version": "2023.2.0" } ``` ## session.updated **セッション更新** > **注釈** > > このウェブフックリクエストの送信を停止することができます。 > `sora.conf` の [ignore_session_updated_webhook](SORA_CONF.html#0901a0) を `true` にしてください。 `session.created` 送信後、一定間隔で `session.updated` ウェブフックリクエストを送信します。 送信間隔はデフォルトで 1 分です。 [session_updated_webhook_interval](SORA_CONF.html#4612dc) で送信間隔を変更できます。 `session.updated` の状態を記録することで、もし何らかの理由で `session.destroyed` が送信されなかった場合でも、 そのセッションが存在しているかどうかの判断を行うことができるようになります。 * - キー - 型 - 内容 * - type - string - "session.updated" * - id - string - ウェブフック ID (ユニーク) * - label - string - sora.conf の label にて指定した値 * - node_name - string - Sora ノード名 * - version - string - Sora のバージョン * - channel_id - string - チャネル ID * - group_id - string - セッションをグルーピングする ID * - session_id - string - セッション ID * - timestamp - string (RFC3339 UTC マイクロ秒) - ウェブフック作成時間 * - created_time - integer (UNIX 時間) - セッション生成時間 * - created_timestamp - string (RFC3339 UTC マイクロ秒) - セッション生成時間 * - spotlight - boolean - スポットライトが有効かどうか * - spotlight_number - integer - スポットライトが有効な場合、スポットライト数 * - total_connections - integer - 延べ接続数 * - max_connections - integer - 最大同時接続数 * - connections - array (object) - (クラスター機能が有効の場合) セッションに参加した接続情報 * - session_metadata - json - (値がある場合) session.created の戻り値で指定した値 * - external_signaling_url - string - (クラスター機能が有効の場合) 接続先の external_signaling_url ```javascript { "channel_id": "sora", "connections": [ { "audio": true, "audio_codec_type": "OPUS", "client_id": "W9QE86Z0BS1QFFPZ2QB5DRZ2HC", "bundle_id": "W9QE86Z0BS1QFFPZ2QB5DRZ2HC", "connection_id": "W9QE86Z0BS1QFFPZ2QB5DRZ2HC", "connection_created_timestamp": "2021-12-01T05:44:23.051704Z", "connection_destroyed_timestamp": "2021-12-01T05:44:57.083215Z", "role": "sendrecv", "simulcast": false, "video": true, "video_bit_rate": 1000, "video_codec_type": "VP9", "video_vp9_params": { "profile_id": 0 }, }, { "audio": true, "audio_codec_type": "OPUS", "client_id": "JXMYW6GPX54EH0HGA5X4130FBM", "bundle_id": "JXMYW6GPX54EH0HGA5X4130FBM", "connection_id": "JXMYW6GPX54EH0HGA5X4130FBM", "connection_created_timestamp": "2021-12-01T05:44:21.500272Z", "connection_destroyed_timestamp": "2021-12-01T05:44:56.878019Z", "role": "sendrecv", "simulcast": false, "video": true, "video_bit_rate": 1000, "video_codec_type": "VP9", "video_vp9_params": { "profile_id": 0 }, }, { "audio": true, "audio_codec_type": "OPUS", "client_id": "F8VK9R71BN5S5EDE737C8XAA3C", "bundle_id": "F8VK9R71BN5S5EDE737C8XAA3C", "connection_id": "F8VK9R71BN5S5EDE737C8XAA3C", "connection_created_timestamp": "2021-12-01T05:44:19.811385Z", "connection_destroyed_timestamp": "2021-12-01T05:44:55.897819Z", "role": "sendrecv", "simulcast": false, "video": true, "video_bit_rate": 1000, "video_codec_type": "VP9", "video_vp9_params": { "profile_id": 0 }, }, { "audio": true, "audio_codec_type": "OPUS", "client_id": "VBYS5TV5S510F98GS2VK015AKG", "bundle_id": "VBYS5TV5S510F98GS2VK015AKG", "connection_id": "VBYS5TV5S510F98GS2VK015AKG", "connection_created_timestamp": "2021-12-01T05:44:14.716974Z", "connection_destroyed_timestamp": "2021-12-01T05:44:57.197372Z", "role": "sendrecv", "simulcast": false, "video": true, "video_bit_rate": 1000, "video_codec_type": "VP9", "video_vp9_params": { "profile_id": 0 }, } ], "created_time": 1638337454, "created_timestamp": "2021-12-01T05:44:14.523736Z", "id": "M7K1AVS9KS34V9XFJJH04TB400", "label": "WebRTC SFU Sora", "max_connections": 4, "node_name": "sora@127.0.0.1", "group_id": "NPR769YPQ914K10FW42PGH4TKW", "session_id": "NPR769YPQ914K10FW42PGH4TKW", "spotlight": false, "timestamp": "2021-12-01T05:45:02.199419Z", "total_connections": 4, "session_metadata": {"spam": "egg"}, "external_signaling_url": "wss://node-01.example.com/signaling", "type": "session.updated", "version": "2023.2.0" } ``` ### connections connections に入ってくる以下の二つは RFC3339 形式の時間ではなく `null` が入ってくる場合があります。 - connection_created_timestamp - connection_destroyed_timestamp これは、認証は成功し、セッションに参加はしたが、何らかの理由で WebRTC が確立に失敗した場合発生します。 両方ともの値に null が入ってきます。 ### クラスター有効時 クラスター有効時には `connections` 項目は含まれません。 ```javascript { "channel_id": "sora", "created_time": 1638337454, "created_timestamp": "2021-12-01T05:44:14.523736Z", "id": "M7K1AVS9KS34V9XFJJH04TB400", "label": "WebRTC SFU Sora", "max_connections": 4, "node_name": "sora@127.0.0.1", "group_id": "NPR769YPQ914K10FW42PGH4TKW", "session_id": "NPR769YPQ914K10FW42PGH4TKW", "spotlight": false, "timestamp": "2021-12-01T05:45:02.199419Z", "total_connections": 4, "session_metadata": {"spam": "egg"}, "external_signaling_url": "wss://node-01.example.com/signaling", "type": "session.updated", "version": "2023.2.0" } ``` ### 録画機能 (セッション単位) 有効時 セッションで録画機能 (セッション単位) が有効な場合、 `"recording"` が含まれます。 録画が有効ではない場合は `"recording"` 項目は含まれません。 * - キー - 型 - 内容 * - recording_id - string - 録画機能 (セッション単位) の ID * - format - string - 録画機能 (セッション単位) のフォーマット * - start_timestamp - string - セッションでの録画が開始された時刻 (RFC 3339 (UTC)) * - split_only - boolean - セッションでの録画が分割のみかどうか * - recording_metadata (オプション) - JSONValue - 録画機能 (セッション単位) のメタデータ * - expire_time (オプション) - integer - セッションでの録画期限 * - expired_at (オプション) - integer - セッションでの録画期限 (Unix time) * - split_duration (オプション) - integer - セッションでの録画分割有効時の分割時間 ```javascript { "channel_id": "sora", "created_time": 1638337454, "created_timestamp": "2021-12-01T05:44:14.523736Z", "id": "M7K1AVS9KS34V9XFJJH04TB400", "label": "WebRTC SFU Sora", "max_connections": 4, "node_name": "sora@127.0.0.1", "group_id": "NPR769YPQ914K10FW42PGH4TKW", "session_id": "NPR769YPQ914K10FW42PGH4TKW", "spotlight": false, "timestamp": "2021-12-01T05:45:02.199419Z", "total_connections": 4, "session_metadata": {"spam": "egg"}, "external_signaling_url": "wss://node-01.example.com/signaling", "type": "session.destroyed", "version": "2023.2.0", "recording": { "recording_id": "WHEJ888HQ55KDCFE3TZ4VPFQHR", "format": "mp4", "recording_metadata": {"spam": "egg"}, "expire_time": 3600, "expired_at": 1615527737, "split_duration": 3600, "split_only": false, "start_timestamp": "2021-03-12T04:42:17.455668Z" } } ``` ## recording.started > **重要** > > このウェブフックリクエストが送信されるにはセッションベースの録画を利用する必要があります **録画開始** - data.start_timestamp- 録画機能 (セッション単位) を開始したタイムスタンプ (RFC3339 UTC マイクロ秒) が入ります - data.trigger- 録画開始のトリーガーが何によるかが入ります - [StartRecording](API_RECORDING.html#c5b527) API による開始を行った場合は `api` が入ります - 認証ウェブフック成功時の戻り値により録画を開始した場合は `auth_webhook` が入ります - [session.created](SESSION_WEBHOOK.html#1d1984) の戻り値により録画を開始した場合は `session_webhook` が入ります - data.expire_time- **この項目はオプションです** - API による開始を行った場合は [StartRecording](API_RECORDING.html#c5b527) API で指定した `expire_time` が入ります - session.created ウェブフックリクエストの戻り値により録画を開始した場合は戻り値 `recording_expire_time` が入ります - 指定していない場合は `expire_time` の項目が入ってきません - data.expired_at- **この項目はオプションです** - API による開始を行った場合は [StartRecording](API_RECORDING.html#c5b527) API で指定した `expire_time` から計算した有効期限 (UNIX Time) が入ります - session.created ウェブフックリクエストの戻り値により録画を開始した場合は戻り値 `recording_expire_time` から計算した有効期限 (UNIX Time) が入ります - `expire_time` を指定していない場合は `expired_at` の項目が入ってきません - data.split_duration- **この項目はオプションです** - API による開始を行った場合は [StartRecording](API_RECORDING.html#c5b527) API で指定した `split_duration` が入ります - session.created ウェブフックリクエストの戻り値により録画を開始した場合は戻り値 `recording_split_duration` が入ります - 指定していない場合は `split_duration` の項目が入ってきません - data.split_only- API による開始を行った場合は [StartRecording](API_RECORDING.html#c5b527) API で指定した `split_only` が入ります - session.created ウェブフックリクエストの戻り値により録画を開始した場合は戻り値 `recording_split_only` が入ります - 指定していない場合は `false` が入ります - data.recording_metadata- **この項目はオプションです** - API による開始を行った場合は [StartRecording](API_RECORDING.html#c5b527) API で指定した `metadata` が入ります - session.created ウェブフックリクエストの戻り値により録画を開始した場合は戻り値 `recording_metadata` が入ります - 指定していない場合は `recording_metadata` の項目が入ってきません - data.format- **この項目はオプションです** - API による開始を行った場合は [StartRecording](API_RECORDING.html#c5b527) API で指定した `format` が入ります - session.created ウェブフックリクエストの戻り値により録画を開始した場合は戻り値 `recording_format` が入ります - 指定していない場合は [default_recording_format](SORA_CONF.html#f9fa7d) の値が入ります ```javascript { "type": "recording.started", "id": "", "version": "", "label": "", "node_name": "", "channel_id": "", "group_id": "", "session_id": "", "session_metadata": "", "timestamp": "", "data": { "channel_id": "", "recording_id": "", "recording_metadata": "", "split_only": "", "created_at": "", "expire_time": "", "expired_at": "", "start_timestamp": "", "split_duration": "", "format": "", "trigger": "" } } ``` ## recording.report > **重要** > > このウェブフックリクエストが送信するには、セッションベースの録画を利用する必要があります > **注釈** > > セッションが破棄されたタイミングでの `recording.report` は `session.destroyed` の **後** に送信されます。 **録画結果報告** - data.archives[].start_time_offset- 録画を開始してから何秒経過した後にこの録画が開始したかを表しています - data.archives[].stop_time_offset- 録画を開始してから何秒経過した後にこの録画が終了したかを表しています - data.recording_metadata- StartRecording API で指定した metadata 、または `session.created` で払い出した `recording_metadata` が入ります - 指定していない場合は `recording_metadata` の項目が入ってきません - data.expired_at- 期限が切れた日時を UNIX Time で返します - data.trigger- 録画終了のトリーガーが何によるかが入ります - [StopRecording](API_RECORDING.html#fd0de5) API による停止を行った場合は `api` が入ります - 録画の有効期限が切れたタイミングで停止した場合は `expired` が入ります - セッションが破棄されたタイミングで停止した場合は `session_destroyed` が入ります ### 一括録画時 recording.report ```javascript { "type": "recording.report", "id": "", "version": "", "label": "", "node_name": "", "channel_id": "", "group_id": "", "session_id": "", "session_metadata": "", "timestamp": "", "data": { "channel_id": "", "group_id": "", "session_id": "", "recording_id": "", "recording_metadata": "", "split_only": "", "split_duration": "", "created_at": "", "expire_time": "", "expired_at": "", "file_path": "", "filename": "", "file_written": "", "start_timestamp": "", "stop_timestamp": "", "format": "", "trigger": "", "archives": [ { "label": "", "node_name": "", "client_id": "", "bundle_id": "", "connection_id": "", "file_path": "", "filename": "", "metadata_file_path": "", "metadata_filename": "", "start_time_offset": "", "start_timestamp": "", "stop_time_offset": "", "stop_timestamp": "", "size": "" }, { "label": "", "node_name": "", "client_id": "", "bundle_id": "", "connection_id": "", "file_path": "", "filename": "", "metadata_file_path": "", "metadata_filename": "", "start_time_offset": "", "start_timestamp": "", "stop_time_offset": "", "stop_timestamp": "", "size": "" } ], "failed_archives": [ { "label": "", "node_name": "", "client_id": "", "bundle_id": "", "connection_id": "" }, { "label": "", "node_name": "", "client_id": "", "bundle_id": "", "connection_id": "" } ] } } ``` ### 分割録画時 recording.report ```javascript { "type": "recording.report", "id": "", "version": "", "label": "", "node_name": "", "channel_id": "", "group_id": "", "session_id": "", "session_metadata": "", "timestamp": "", "data": { "channel_id": "", "group_id": "", "session_id": "", "recording_id": "", "recording_metadata": "", "split_only": "", "split_duration": "", "created_at": "", "expire_time": "", "expired_at": "", "file_path": "", "filename": "", "file_written": "", "start_timestamp": "", "stop_timestamp": "", "format": "", "trigger": "", "archives": [ { "label": "", "node_name": "", "client_id": "", "bundle_id": "", "connection_id": "", "start_time_offset": "", "start_timestamp": "", "stop_time_offset": "", "stop_timestamp": "", "split_last_index": "" }, { "label": "", "node_name": "", "client_id": "", "bundle_id": "", "connection_id": "", "start_time_offset": "", "start_timestamp": "", "stop_time_offset": "", "stop_timestamp": "", "split_last_index": "" } ], "failed_archives": [ { "label": "", "node_name": "", "client_id": "", "bundle_id": "", "connection_id": "" }, { "label": "", "node_name": "", "client_id": "", "bundle_id": "", "connection_id": "" } ] } } ``` ## audio-streaming.started > **重要** > > このウェブフックリクエストが送信されるには > `sora.conf` の [ignore_audio_streaming_webhook](SORA_CONF.html#8f086b) が `false` である必要があります。 以下の 2 つの条件で音声ストリーミングが開始した時にウェブフックリクエストを送信します。 - [StartAudioStreaming](API_AUDIO_STREAMING.html#0f1087) API が実行されるか、またはセッションウェブフックで `audio_streaming: true` 払い出されたタイミングでウェブフックリクエストを送信します。 - 音声ストリーミングの [ウェブフック](AUDIO_STREAMING.html#a62cea) を利用時に[SubscribeAudioStreamingResultPush](API_AUDIO_STREAMING.html#d26262) API が呼び出される、もしくはクライアントが接続されて、そのチャネルで音声ストリーミングの結果をサブスクライブしているクライアント数が 1 以上になった場合 [session.created](SESSION_WEBHOOK.html#1d1984) よりも必ず **後に** ウェブフックが送信されます。 * - キー - 型 - 内容 * - type - string - "audio-streaming.started" * - id - string - ウェブフック ID (ユニーク) * - label - string - sora.conf の label にて指定した値 * - node_name - string - Sora ノード名 * - version - string - Sora のバージョン * - channel_id - string - チャネル ID * - group_id - string - セッションをグルーピングする ID * - session_id - string - セッション ID * - timestamp - string (RFC3339 UTC マイクロ秒) - ウェブフック作成時間 * - created_time - integer (UNIX 時間) - セッション生成時間 * - created_timestamp - string (RFC3339 UTC マイクロ秒) - セッション生成時間 * - spotlight - boolean - スポットライトが有効かどうか * - session_metadata - json - (値がある場合) session.created の戻り値で指定した値 * - external_signaling_url - string - (クラスター機能が有効の場合) 接続先の external_signaling_url * - data - object - 音声ストリーミング固有 data には以下が含まれます。 * - キー - 型 - 内容 * - audio_streaming_auto - boolean - 自動開始/停止が有効かどうか * - audio_streaming_started_timestamp - string (RFC3339 UTC マイクロ秒) - 音声ストリーミングを開始した時間 ```javascript { "channel_id": "sora", "created_time": 1638337454, "created_timestamp": "2021-12-01T05:44:14.523736Z", "id": "2YN2DQE5KD3GSFSVPAYZ7VTAV4", "label": "WebRTC SFU Sora", "spotlight": false, "node_name": "sora@127.0.0.1", "group_id": "NPR769YPQ914K10FW42PGH4TKW", "session_id": "NPR769YPQ914K10FW42PGH4TKW", "timestamp": "2022-12-01T05:44:14.523912Z", "type": "audio-streaming.started", "version": "2023.2.0", "session_metadata": {"spam": "egg"}, "external_signaling_url": "wss://node-01.example.com/signaling", "data": { "audio_streaming_auto": true, "audio_streaming_started_timestamp": "2021-12-01T05:44:16.523912Z" } } ``` ## audio-streaming.stopped > **重要** > > このウェブフックリクエストが送信されるには > `sora.conf` の [ignore_audio_streaming_webhook](SORA_CONF.html#8f086b) が `false` である必要があります。 以下の 3 つの条件で音声ストリーミングが停止した時にウェブフックリクエストを送信します。 - セッションが破棄された場合 - [StopAudioStreaming](API_AUDIO_STREAMING.html#bad1bb) API が呼び出す場合 - 音声ストリーミングの [ウェブフック](AUDIO_STREAMING.html#a62cea) を利用時に[UnsubscribeAudioStreamingResultPush](API_AUDIO_STREAMING.html#b63656) API が呼び出される、もしくはクライアントが切断されて、そのチャネルで音声ストリーミングの結果をサブスクライブしているクライアント数が 0 になった場合 [session.destroyed](SESSION_WEBHOOK.html#ccb165) よりも必ず **前に** ウェブフックが送信されます。 * - キー - 型 - 内容 * - type - string - "audio-streaming.started" * - id - string - ウェブフック ID (ユニーク) * - label - string - sora.conf の label にて指定した値 * - node_name - string - Sora ノード名 * - version - string - Sora のバージョン * - channel_id - string - チャネル ID * - group_id - string - セッションをグルーピングする ID * - session_id - string - セッション ID * - timestamp - string (RFC3339 UTC マイクロ秒) - ウェブフック作成時間 * - created_time - integer (UNIX 時間) - セッション生成時間 * - created_timestamp - string (RFC3339 UTC マイクロ秒) - セッション生成時間 * - spotlight - boolean - スポットライトが有効かどうか * - session_metadata - json - (値がある場合) session.created の戻り値で指定した値 * - external_signaling_url - string - (クラスター機能が有効の場合) 接続先の external_signaling_url * - data - object - 音声ストリーミング固有 data には以下が含まれます。 * - キー - 型 - 内容 * - audio_streaming_auto - boolean - 自動開始/停止が有効かどうか * - audio_streaming_started_timestamp - string (RFC3339 UTC マイクロ秒) - 音声ストリーミングを開始した時間 * - audio_streaming_stopped_timestamp - string (RFC3339 UTC マイクロ秒) - 音声ストリーミングを停止した時間 ```javascript { "channel_id": "sora", "created_time": 1638337454, "created_timestamp": "2021-12-01T05:44:14.523736Z", "id": "2YN2DQE5KD3GSFSVPAYZ7VTAV4", "label": "WebRTC SFU Sora", "spotlight": false, "node_name": "sora@127.0.0.1", "group_id": "NPR769YPQ914K10FW42PGH4TKW", "session_id": "NPR769YPQ914K10FW42PGH4TKW", "timestamp": "2022-12-01T05:44:14.523912Z", "type": "audio-streaming.stopped", "version": "2023.2.0", "session_metadata": {"spam": "egg"}, "external_signaling_url": "wss://node-01.example.com/signaling", "data": { "audio_streaming_auto": true, "audio_streaming_started_timestamp": "2021-12-01T05:44:16.523912Z", "audio_streaming_stopped_timestamp": "2021-12-01T05:44:16.523912Z" } } ``` ## API ### [TerminateSession](API_SESSION.html#ba022b) API セッションを強制的に終了させる API です。 `channel_id` を指定して、セッションを終了させます。 `session_id` を追加で指定することができますが、 `session_id` が見つからない場合はエラーになります。 API 実行中に新規の接続が来た場合、その接続はいったん保留して、セッション破棄後に新規セッションでの接続として扱います。 ## クラスター時の挙動について ### セッションが存在していたノードで障害が起きた場合でも、 `session.destroyed` は送信されます 別のノードが `session.destroyed` を送信します。その際 `reason` 項目には `abort` が入ります。 `reason` が `abort` の場合、以下の情報が **最新の状態** ではない場合があります。 - `total_connections` - `max_connections` ### セッションが存在していたノードで障害が起きた際、同一ウェブフックが複数回送られることがあります 以下のウェブフックは複数回送られる可能性はあります、その際はウェブフックの `"id"` は同一になります。 - `session.destroyed` - `recording.started` - `recording.report` - `audio-streaming.stopped` ## クラスターリレー時の挙動について ### セッションウェブフックはどのノードが送信しますか? `session.created` を送信したノードが `session.destroyed` を送信します。 ## HTTP ヘッダー > **警告** > > この機能は [実験的機能](EXPERIMENTAL.html) のため、正式版では仕様が変更される可能性があります > **注釈** > > JSON のパース時の判断などに利用してください。 ### sora-session-webhook-type > **注意** > > `x-sora-session-webhook-type` は非推奨です、 `sora-session-webhook-type` を利用してください セッションウェブフックの HTTP ヘッダー に `sora-session-webhook-type` または `x-sora-session-webhook-type` というヘッダー名でセッションウェブフックのタイプが入ってきます。 `type` が `session.created` の場合は `sora-session-webhook-type: session.created` または `x-sora-session-webhook-type: session.created` のように値が入ってきます。 ### sora-session-id セッションウェブフックの HTTP ヘッダー に `sora-session-id` というヘッダー名でセッション ID が入ってきます。 セッション ID が `46NNAV9S0X3TD778A1JBYYCBS8` の場合は `sora-session-id: 46NNAV9S0X3TD778A1JBYYCBS8` のように値が入ってきます。 ## シーケンス図 ```mermaid sequenceDiagram autonumber participant C1 as クライアント1 participant C2 as クライアント2 participant S as Sora participant A as アプリケーションサーバー C1->>S: type: connect S->>+A: 認証ウェブフック A-->>-S: 200 OK S->>+A: セッションウェブフック
type: session.created A-->>-S: 200 OK S->>C1: type: offer C1->>S: type: answer Note over C1,A: クライアント1 WebRTC 確立 S->>+A: イベントウェブフック
type: connection.created A-->>-S: 200 OK C2->>S: type: connect S->>+A: 認証ウェブフック A-->>-S: 200 OK S->>C2: type: offer C2->>S: type: answer Note over C1,A: クライアント2 WebRTC 確立 S->>+A: イベントウェブフック
type: connection.created A-->>-S: 200 OK C1->>S: "type": "disconnect" S->>+A: イベントウェブフック
type: connection.destroyed A-->>-S: 200 OK S->>C1: WebSocket Close Note over C1,A: クライアント1 WebRTC 切断 C2->>S: "type": "disconnect" S->>+A: イベントウェブフック
type: connection.destroyed A-->>-S: 200 OK S->>C2: WebSocket Close Note over C1,A: クライアント2 WebRTC 切断 note right of S: 接続数 0 から 15 秒経過 S->>+A: セッションウェブフック
type: session.destroyed A-->>-S: 200 OK ``` # イベントウェブフック ## 概要 Sora は、予め設定しておいた URL に、シグナリングの接続や切断、 録画の開始や終了といった様々なイベントを HTTP リクエストとして送信するウェブフックの機能を持っています。 この機能を使うことで、Sora のイベントをアプリケーション側と簡単に連携できます。 ## 注意 `sora.conf` の [event_webhook_url](SORA_CONF.html#e1a4d2) を有効にしない場合でも `log/event_webhook.jsonl` は生成されます。 ## ログ イベントウェブフックのログは `log/event_webhook.jsonl` と `log/event_webhook_error.jsonl` に出力されます。 これは [event_webhook_url](SORA_CONF.html#e1a4d2) を指定していなくても出力されます。 ### event_webhook.jsonl イベントウェブフックで送信した **すべて** の処理を書き込みます。 ### event_webhook_error.jsonl イベントウェブフックの送信が正常に処理できなかった処理を書き込みます。 - ステータスコードが 200 番台以外の場合 - タイムアウトした場合 ## 設定 ### event_webhook_url **デフォルト**: 未設定 イベントウェブフックリクエスト送信先の URL です。イベントウェブフック機能を利用する場合は指定してください。 この URL には HTTP または HTTPS の URL を指定することができます。 HTTPS の URL を指定する場合、リクエスト送信先のアプリケーションについて基本的には正規の認証局から発行された証明書を利用してください。 独自の証明書を利用する場合は [ウェブフックリクエスト送信先のサーバーが自己発行証明書などを利用している場合](WEBHOOK.html#341b9a) をご確認ください。 HTTP のレスポンスは `200 OK` 等の 200 番台のステータスコードの必要があります。 ### connection_updated_webhook_interval **デフォルト**: `1 min` イベントウェブフック `connection.updated` の送信間隔を設定します。設定は分単位 (min) のみで行えます。 詳細は [connection_updated_webhook_interval](SORA_CONF.html#e67c3b) をご確認ください。 ### ignore_connection_updated_webhook **デフォルト**: false イベントウェブフック `connection.updated` の送信有無を設定します。 詳細は [ignore_connection_updated_webhook](SORA_CONF.html#f3f12a) をご確認ください。 ## イベントウェブフックワーカー Sora はイベントウェブフックを送信する際、事前に用意されたウェブフックワーカーを利用します。 ウェブフックワーカーは指定された URL に HTTP/1.1 でリクエストを送信します。 このリクエストが戻ってくるまで次のイベントウェブフックの処理は **ブロック** します。 つまり、ウェブフックの処理が遅くなる場合、次のイベントウェブフックが遅延します。 ウェブフックワーカーはキューを持っており、もしそのウェブフックワーカーがリクエストを処理中の場合、キューに追加されます。 そのリクエストのレスポンスが返ってきた後、キューから取り出され次のリクエストが送信されます。 ### event_webhook_worker_key ウェブフックワーカーを割り当てる場合のキーを指定します。デフォルトは `channel_id` です。 キーが同一の場合、同一のウェブフックワーカーを利用します。 - `channel_id` と `connection_id` が指定できます - `channel_id` を割り当てた場合、同一チャネルに接続しているコネクションは全て同じウェブフックワーカーを利用します - `connection_id` を割り当てた場合、コネクション ID 単位でウェブフックワーカーを利用します > **重要** > > もし 1 チャネル辺りの同時接続数が 5 を超えるような場合は `connection_id` を指定してください。 ### event_webhook_worker_number ウェブフックワーカーの数を指定します。デフォルトでは 100 です。 [event_webhook_worker_number](SORA_CONF.html#58523d) にて 100 から 5000 までの値を指定することができます。 ## 接続イベント - `connection.created` と `connection.destroyed` はセットです - `connection.created` がリクエスト送信されずに `connection.destroyed` がリクエスト送信されることはありません - `connection.created` がリクエスト送信された場合、 `connection.destroyed` が **必ず** リクエスト送信されます - `connection.created` の後に `connection.destroyed` がリクエスト送信されます。順番は保証されます ### 共通項目 - id- イベントごとの ID です - version- Sora のバージョンが `文字列` で入ってきます - label- sora.conf の label で指定した値が入ってきます - node_name- Sora のノード名が入ってきます - log_written- イベントウェブフックログの書き込みが成功したかどうかが入ってきます - 書き込みが成功した場合は `true` が入ってきます - data.minutes- 接続経過時間 (分) が入ってきます - data.created_time- connection.created 時の時間が UNIX 時間形式で入ってきます - 例: 1704067199 - data.created_timestamp- connection.created 時の時間が RFC 3339 UTC 形式 (マイクロ秒) で入ってきます - 例: 2023-12-31T23:59:59.999999Z - data.total_received_bytes- Sora がクライアントから受信したパケットの合計数です - data.total_sent_bytes- Sora がクライアントへ送信したパケットの合計数です - data.turn_transport_type- udp か tcp が入ってきます - TURN-UDP または TURN-TCP (TURN-TLS 含む) のどちらを使用したかがわかります - data.audio- `true` または `false` が入ってきます - `false` の場合は `audio` を使用しません - data.audio_codec_type- **この項目はオプションです** - `audio` が `false` の場合は含まれません - コーデックの種類は `OPUS` です - data.audio_bit_rate- **この項目はオプションです** - `audio` が `false` やクライアントが送ってこない場合、含まれません - この設定は `audio_codec_type` が `OPUS` の時のみ有効です - [default_audio_bit_rate](SORA_CONF.html#07627a) に値を指定していた場合はその値が利用されます - 最小が 6 で、最大が 510 です - 単位は `kbps` です - data.video- `true` または `false` が入ってきます - `false` の場合は `video` を使用しません - data.video_codec_type- **この項目はオプションです** - `video` が `false` の場合は含まれません - コーデックはクライアントが送ってこない場合はデフォルトで `VP9` が使用されます - コーデックの種類は `VP8`、 `VP9`、 `AV1`、 `H264`、 `H265` です - data.video_bit_rate- **この項目はオプションです** - `video` が `false` の場合は含まれません - ビットレートはクライアントが送ってこない場合は `sora.conf` の [default_video_bit_rate](SORA_CONF.html#620132) が使用されます - デフォルトは 500 です - 最小が 1 で、最大が 30000 です - 15000 より大きい値は現時点でサポート範囲外です - 単位は `kbps` です - data.video_vp9_params- **この項目はオプションです** - `video` が `false` の場合は含まれません - 詳細は [ビデオの VP9 設定指定](WEBSOCKET_SIGNALING.html#b7556a) をご確認ください - data.video_av1_params- **この項目はオプションです** - `video` が `false` の場合は含まれません - 詳細は [ビデオの AV1 設定指定](WEBSOCKET_SIGNALING.html#48f92d) をご確認ください - data.video_h264_params- **この項目はオプションです** - `video` が `false` の場合は含まれません - 詳細は [ビデオの H.264 設定指定](WEBSOCKET_SIGNALING.html#ffc4cb) をご確認ください - data.video_h265_params- **この項目はオプションです** - `video` が `false` の場合は含まれません - 詳細は [ビデオの H.265 設定指定](WEBSOCKET_SIGNALING.html#bfe45b) をご確認ください - simulcast- true の場合はサイマルキャストが有効な接続です - simulcast_multicodec- この項目はオプションです - true の場合はサイマルキャストでマルチコーデックが有効な接続です - spotlight- true の場合はスポットライトが有効な接続です - role- `sendrecv` (送受信) / `sendonly` (送信のみ) / `recvonly` (受信のみ) - event_metadata- この項目はオプションです - サーバーが定義を自由にできる値です - 認証サーバーから event_metadata を返した値が含まれます - 詳細は [event_metadata の払い出し](AUTH_WEBHOOK_RETURN.html#8b1b1f) をご確認ください - channel_id- コネクションが接続しているチャネル ID です - group_id- セッションをグルーピングする ID です - 未指定の場合は `session_id` が入ります - session_id- コネクションが接続しているチャネル の現在のセッションの ID です - UUIDv4 を Base32 でエンコードした 26 バイトの文字列です - client_id- コネクションに割り当てられたクライアント ID です - bundle_id- コネクションに割り当てられたバンドル ID です - connection_id- コネクションに割り当てられたユニークな ID です - UUIDv4 を Base32 でエンコードした 26 バイトの文字列です - data.ice_connection_state- total_checking_duration_ms- ICE 接続の状態が `checking` になった時間の合計 (ミリ秒) です - total_disconnected_duration_ms- ICE 接続の状態が `disconnected` になった時間の合計 (ミリ秒) です - data.recording_block- 録画(セッション単位)時に録画をブロックするかどうかが入ってきます - `true` であれば録画をブロックします - `false` であれば録画をブロックしません ### connection.created **接続** シグナリングの接続が成功して、WebRTC としての通信が開始できるようになった時の状態を送信します。 - data.channel_connections- 現在そのチャネルに接続しているクライアントの接続数です - 自分は含まれます - data.channel_sendrecv_connections- 現在そのチャネルで送受信している配信者の接続数です - 自分は含まれます - data.channel_sendonly_connections- 現在そのチャネルを送信のみしている配信者の接続数です - 自分は含まれます - data.channel_recvonly_connections- 現在そのチャネルを受信のみしている視聴者の接続数です - 自分は含まれます ```javascript { "type": "connection.created", "channel_id": "", "group_id": "", "session_id": "", "client_id": "", "bundle_id": "", "connection_id": "", "timestamp": "", "event_metadata": "", "data": { "ice_connection_state": { "total_checking_duration_ms": "", "total_disconnected_duration_ms": "" }, "recording_block": "", "created_time": "", "created_timestamp": "", "audio": "", "audio_codec_type": "", "channel_connections": "", "channel_recvonly_connections": "", "channel_sendonly_connections": "", "channel_sendrecv_connections": "", "minutes": "", "total_received_bytes": "", "total_sent_bytes": "", "turn_transport_type": "", "video": "", "video_bit_rate": "", "video_codec_type": "" }, "id": "", "label": "", "node_name": "", "log_written": "", "role": "", "simulcast": "", "spotlight": "", "version": "" } ``` ### connection.destroyed **切断** シグナリングの接続が切断した時に送信します。 - data.type_disconnect_reason- クライアントから ["type": "disconnect"](WEBSOCKET_SIGNALING.html#306b81) シグナリングメッセージに `"reason"` が項目に含まれていた際、その **文字列** が入ります - シグナリングメッセージに `"reason"` が含まれていなかった場合、この項目は含まれません - data.disconnect_api_reason- [DisconnectChannel](API_SIGNALING.html#a87366) API または [DisconnectConnection](API_SIGNALING.html#2ec3a0) API を利用して切断した際、オプションの `"reason"` に指定した **JSON オブジェクト** がこの `"reason"` に含まれます - `"reason"` を指定されていなかった場合、この項目は含まれません - data.reason- コネクションが破棄された理由が含まれます- この値は常に含まれます - `"normal"` は通常のコネクション破棄 - `"disconnected_api"` シグナリング切断系 API でのコネクション破棄 - `"session_destroyed"` セッションライフタイム期限切れ、または [TerminateSession](API_SESSION.html#ba022b) API によるセッションの強制破棄でのコネクション破棄 - `"lifetime_expired"` ライフタイム期限切れによるコネクション破棄 - `"duplicate_client_id"` クライアント ID の重複によるコネクション破棄 - data.channel_connections- 現在そのチャネルに接続しているクライアントの接続数です - 自分は含まれません - data.channel_sendrecv_connections- 現在そのチャネルで送受信している配信者の接続数です - 自分は含まれません - data.channel_sendonly_connections- 現在そのチャネルを送信のみしている配信者の接続数です - 自分は含まれません - data.channel_recvonly_connections- 現在そのチャネルを受信のみしている視聴者の接続数です - 自分は含まれません - data.destroyed_time- connection.destroyed 時の時間が UNIX 時間形式で入ってきます - data.destroyed_timestamp- connection.destroyed 時の時間が RFC 3339 UTC 形式 (マイクロ秒) で入ってきます ```javascript { "type": "connection.destroyed", "channel_id": "", "group_id": "", "session_id": "", "client_id": "", "bundle_id": "", "connection_id": "", "timestamp": "", "event_metadata": "", "data": { "ice_connection_state": { "total_checking_duration_ms": "", "total_disconnected_duration_ms": "" }, "recording_block": "", "created_time": "", "created_timestamp": "", "destroyed_time": "", "destroyed_timestamp": "", "audio": "", "audio_codec_type": "", "channel_connections": "", "channel_recvonly_connections": "", "channel_sendonly_connections": "", "channel_sendrecv_connections": "", "minutes": "", "reason": "", "type_disconnect_reason": "", "total_received_bytes": "", "total_sent_bytes": "", "turn_transport_type": "", "video": "", "video_bit_rate": "", "video_codec_type": "" }, "id": "", "label": "", "node_name": "", "log_written": "", "role": "", "simulcast": "", "spotlight": "", "version": "" } ``` ### connection.updated **接続状態更新** > **注釈** > > このウェブフックリクエストの送信を停止することができます。 > `sora.conf` の [ignore_connection_updated_webhook](SORA_CONF.html#f3f12a) を `true` にしてください。 `connection.created` を送信したタイミングから、クライアントごとの接続状態が、それぞれ一定間隔で送信されます。 送信間隔はデフォルトで 1 分です。 [connection_updated_webhook_interval](SORA_CONF.html#e67c3b) で送信間隔を変更できます。 - data.channel_connections- 現在そのチャネルに接続しているクライアントの接続数です - 自分が含まれます - data.channel_sendrecv_connections- 現在そのチャネルで送受信している配信者の接続数です - 自分が含まれます - data.channel_sendonly_connections- 現在そのチャネルを送信のみしている配信者の接続数です - 自分が含まれます - data.channel_recvonly_connections- 現在そのチャネルを受信のみしている視聴者の接続数です - 自分が含まれます ```javascript { "type": "connection.updated", "channel_id": "", "group_id": "", "session_id": "", "client_id": "", "bundle_id": "", "connection_id": "", "timestamp": "", "event_metadata": "", "data": { "ice_connection_state": { "total_checking_duration_ms": "", "total_disconnected_duration_ms": "" }, "recording_block": "", "audio": "", "audio_codec_type": "", "channel_connections": , "channel_recvonly_connections": "", "channel_sendonly_connections": "", "channel_sendrecv_connections": "", "created_time": "", "created_timestamp": "", "minutes": "", "total_received_bytes": "", "total_sent_bytes": "", "turn_transport_type": "", "video": "", "video_bit_rate": "", "video_codec_type": "" }, "id": "", "label": "", "node_name": "", "log_written": "", "role": "", "simulcast": "", "spotlight": "", "version": "" } ``` ### connection.failed **接続失敗** > **重要** > > このイベントのログの出力やウェブフックを出力する場合、 > `sora.conf` にて [ignore_connection_failed_webhook](SORA_CONF.html#45096a) を無効にする必要があります。 - [connection.created](EVENT_WEBHOOK.html#eef06c) の送信前に失敗や異常が起きた場合に送信されます - [connection.created](EVENT_WEBHOOK.html#eef06c) の送信後に失敗や異常が起きた場合、 [connection.destroyed](EVENT_WEBHOOK.html#6c02d0) が送信されます ```javascript { "type": "connection.failed", "id": "", "role": "", "channel_id": "", "client_id": "", "bundle_id": "", "connection_id": "", "timestamp": "", "data": { "message": "", "channel_connections": "", "channel_sendrecv_connections": "", "channel_sendonly_connections": "", "channel_recvonly_connections": "", "total_received_bytes": "", "total_sent_bytes": "" }, "label": "", "node_name": "", "log_written": "", "simulcast": "", "spotlight": "", "version": "" } ``` ## 録画・録音保存イベント ### archive.started **録画ファイル保存開始** - data.start_timestamp- この録画が開始された時間 (UTC) を RFC 3339 形式 (マイクロ秒) で表しています - data.format- 録画ファイルのフォーマット - `webm` または `mp4` が入ります ```javascript { "type": "archive.started", "id": "", "version": "", "label": "", "node_name": "", "log_written": "", "channel_id": "", "group_id": "", "session_id": "", "client_id": "", "bundle_id": "", "connection_id": "", "timestamp": "", "event_metadata": "", "data": { "channel_id": "", "recording_id": "", "session_id": "", "group_id": "", "client_id": "", "bundle_id": "", "connection_id": "", "created_at": "", "audio": true, "audio_codec_type": "", "video": true, "video_codec_type": "", "video_bit_rate": "", "start_time": "", "start_time_offset": "", "start_timestamp": "", "format": "" } } ``` ### archive.available **録画保存ファイル出力** 録画ファイルが出力されて利用できるようになったことを通知するウェブフックです。 - data.start_timestamp- この録画が開始された時間 (UTC) を RFC 3339 形式 (マイクロ秒) で表しています - data.stop_timestamp- この録画が終了した時間(UTC) を RFC 3339 形式 (マイクロ秒) で表しています - data.start_time- この録画が開始された時間を UNIX 時間形式で表しています - data.stop_time- この録画が終了した時間を UNIX 時間形式で表しています - data.start_time_offset- [StartRecording](OBSOLETE_API_LEGACY_RECORDING.html#c5b527) API を叩いてから何秒経過した後にこの録画が開始したかを表しています - data.stop_time_offset- [StartRecording](OBSOLETE_API_LEGACY_RECORDING.html#c5b527) API を叩いてから何秒経過した後にこの録画が終了したかを表しています - data.stats- サポート向けに、録画に使用したパケット情報の統計を格納しています - 内部向け情報のため、予告なく変更されることがあります - data.format- 録画ファイルのフォーマット - `webm` または `mp4` が入ります ```javascript { "type": "archive.available", "id": "", "version": "", "label": "", "node_name": "", "log_written": "", "channel_id": "", "group_id": "", "session_id": "", "client_id": "", "bundle_id": "", "connection_id": "", "timestamp": "", "event_metadata": "", "data": { "channel_id": "", "recording_id": "", "group_id": "", "session_id": "", "client_id": "", "bundle_id": "", "connection_id": "", "created_at": "", "file_path": "", "filename": "", "metadata_file_path": "", "metadata_filename": "", "size": "", "audio": true, "audio_codec_type": "", "video": true, "video_codec_type": "", "video_bit_rate": "", "video_height": "", "video_width": "", "stats": {}, "start_time": "", "start_time_offset": "", "start_timestamp": "", "stop_time": "", "stop_time_offset": "", "stop_timestamp": "", "format": "" } } ``` ### split-archive.available **分割録画ファイル出力** 分割録画ファイルが出力されて利用できるようになったことを通知するウェブフックです。 - data.split_index- 分割された録画ファイルのインデックス - 0001 から始まり 9999 までいったら、その後は 10000, 10001 と増えていきます - data.start_timestamp- 分割して出力された録画ファイルを開始された時間 (UTC) を RFC 3339 形式 (マイクロ秒) で表しています - data.stop_timestamp- 分割して出力された録画ファイルを終了した時間 (UTC) を RFC 3339 形式 (マイクロ秒) で表しています - data.start_time- 分割して出力された録画ファイルを開始した時間を UNIX 時間形式で表しています - data.stop_time- 分割して出力された録画ファイルを終了した時間を UNIX 時間形式で表しています - data.start_time_offset- この分割して出力された録画が、StartRecording API を叩いてから何秒経過した後に開始したかを表しています - data.stop_time_offset- この分割して出力された録画が、StartRecording API を叩いてから何秒経過した後に終了したかを表しています - data.stats- サポート向けに、録画に使用したパケット情報の統計を格納しています - 内部向け情報のため、予告なく変更されることがあります ```javascript { "type": "split-archive.available", "id": "", "version": "", "label": "", "node_name": "", "log_written": "", "channel_id": "", "group_id": "", "session_id": "", "client_id": "", "bundle_id": "", "connection_id": "", "timestamp": "", "event_metadata": "", "data": { "channel_id": "", "recording_id": "", "split_index": "", "group_id": "", "session_id": "", "client_id": "", "bundle_id": "", "connection_id": "", "created_at": "", "file_path": "", "filename": "", "metadata_file_path": "", "metadata_filename": "", "size": "", "audio": true, "audio_codec_type": "", "video": true, "video_codec_type": "", "video_bit_rate": "", "video_height": "", "video_width": "", "stats": { }, "start_time": "", "start_time_offset": "", "start_timestamp": "", "stop_time": "", "stop_time_offset": "", "stop_timestamp": "", "format": "" } } ``` > **注釈** > > stats は省略しています ### split-archive.end **分割録画終了** 分割録画ファイルが全て出力し終わったことを通知するウェブフックです。 このウェブフック以降は [split-archive.available](EVENT_WEBHOOK.html#555071) は送信されません。 - data.start_time- 録画を開始した UNIX 時間形式で表しています - data.stop_time- 録画を終了した UNIX 時間形式で表しています - data.start_timestamp- 録画を開始した時間 (UTC) を RFC 3339 形式 (マイクロ秒) で表しています - data.stop_timestamp- 録画を終了した時間 (UTC) を RFC 3339 形式 (マイクロ秒) で表しています - data.stats- サポート向けに、録画に使用したパケット情報の統計を格納しています - 内部向け情報のため、予告なく変更されることがあります ```javascript { "type": "split-archive.end", "id": "", "version": "", "label": "", "node_name": "", "log_written": "", "channel_id": "", "group_id": "", "session_id": "", "client_id": "", "bundle_id": "", "connection_id": "", "timestamp": "", "event_metadata": "", "data": { "split_last_index": "", "recording_id": "", "channel_id": "", "group_id": "", "session_id": "", "client_id": "", "bundle_id": "", "connection_id": "", "audio": true, "audio_codec_type": "", "video": true, "video_codec_type": "", "video_bit_rate": "", "file_path": "", "filename": "", "stats": {}, "start_time": "", "start_time_offset": "", "start_timestamp": "", "stop_time": "", "stop_time_offset": "", "stop_timestamp": "", "format": "" } } ``` ### archive.failed **録画ファイル保存失敗** このウェブフックが発生するのは、ディスク容量が足らなかったり、ディスクが故障してたり、 パーミッションにより書き込めなかった場合です。 一括録画、分割録画関係なくクライアントの録画ファイル保存に失敗した場合には発生し、クライアントの録画は停止されます。 書き込めない可能性がとても高いため、分割録画の場合でも録画はその時点で停止します。 もし問題を解決できた場合は、一度録画を停止し、再度録画を開始するようにしてください。 ```javascript { "type": "archive.failed", "id": "", "version": "", "label": "", "node_name": "", "log_written": "", "timestamp": "", "channel_id": "", "group_id": "", "session_id": "", "client_id": "", "bundle_id": "", "connection_id": "", "event_metadata": "", "data": { "recording_id": "", "group_id": "", "session_id": "", "split": "", "split_only": "", "file_path": "", "filename": "", "audio": true, "audio_codec_type": "", "video": true, "video_codec_type": "", "video_bit_rate": "", "video_height": "", "video_width": "", "stats": {}, "start_time": "", "start_timestamp": "", "stop_time": "", "stop_timestamp": "", "format": "" } } ``` ## スポットライト機能 ### spotlight.focused **フォーカス設定** フォーカスされた際にウェブフックを送信します。 ```javascript { "type": "spotlight.focused", "channel_id": "", "client_id": "", "bundle_id": "", "connection_id": "", "timestamp": "", "spotlight_number:": "", "fixed": "", "id": "", "label": "", "version": "", "node_name": "", "log_written": "", "audio": "", "video": "" } ``` ### spotlight.unfocused **フォーカス解除** フォーカスが外れた際にウェブフックを送信します。 ```javascript { "type": "spotlight.unfocused", "channel_id": "", "client_id": "", "bundle_id": "", "connection_id": "", "timestamp": "", "spotlight_number:": "", "audio": "", "id": "", "label": "", "version": "", "node_name": "", "log_written": "", "audio": "", "video": "" } ``` ## 音声ストリーミング機能 ### audio-streaming.failed 音声ストリーミング URL への接続を諦めた際にウェブフックを送信します。 ```javascript { "type": "audio-streaming.failed", "id": "", "timestamp": "", "label": "", "version": "", "node_name": "", "log_written": "", "channel_id": "", "group_id": "", "session_id": "", "client_id": "", "bundle_id": "", "connection_id": "", "data": { "failed_reason": "" }, "role": "", "simulcast": "", "spotlight": "" } ``` ## HTTP ヘッダー > **警告** > > この機能は [実験的機能](EXPERIMENTAL.html) のため、正式版では仕様が変更される可能性があります > **注釈** > > JSON のパース時の判断などに利用してください。 ### sora-event-webhook-type > **注意** > > `x-sora-event-webhook-type` は非推奨です、 `sora-event-webhook-type` を利用してください イベントウェブフックの HTTP ヘッダー に `sora-event-webhook-type` と `x-sora-event-webhook-type` というヘッダー名でイベントウェブフックのタイプが入ってきます。 `type` が `connection.created` の場合は `sora-event-webhook-type: connection.created` と `x-sora-event-webhook-type: connection.created` のように値が入ってきます。 ### sora-session-id イベントウェブフックの HTTP ヘッダー に `sora-session-id` というヘッダー名でセッション ID が入ってきます。 セッション ID が `46NNAV9S0X3TD778A1JBYYCBS8` の場合は `sora-session-id: 46NNAV9S0X3TD778A1JBYYCBS8` のように値が入ってきます。 ### sora-connection-id イベントウェブフックの HTTP ヘッダー に `sora-connection-id` というヘッダー名でコネクション ID が入ってきます。 コネクション ID が `7WSWCM0Z2H0614W5PJERR3F5WR` の場合は `sora-connection-id: 7WSWCM0Z2H0614W5PJERR3F5WR` のように値が入ってきます。 ## シーケンス図 ### connection.* ```mermaid sequenceDiagram participant C as クライアント participant S as WebRTC SFU S participant A as アプリケーションサーバー note over C,A: 認証成功 S->>C: "type": "offer" C->>S: "type": "answer" note over C,S: WebRTC 確立 S->>+A: イベントウェブフック
"type": "connection.created" A-->>-S: 200 OK note over C,S: 接続から 1 分経過 S->>+A: イベントウェブフック
"type": "connection.updated" A-->>-S: 200 OK C->>S: "type": "disconnect" S->>+A: イベントウェブフック
"type": "connection.destroyed" A-->-S: 200 OK S->>C: WebSocket Close ``` ### event_metadata ```mermaid sequenceDiagram participant C as クライアント participant S as WebRTC SFU S participant A as アプリケーションサーバー C->>+S: "type": "connect" S->>+A: 認証ウェブフック A-->>-S: 200 OK
"allowed: true,
"event_metadata": {"pk": 1} S->>C: "type": "offer" C->>S: "type": "answer" note over C,S: WebRTC 確立 S->>+A: イベントウェブフック
"type": "connection.created",
"event_metadata": {"pk": 1} A-->>-S: 200 OK note over C,S: 接続から 1 分経過 S->>+A: イベントウェブフック
"type": "connection.updated",
"event_metadata": {"pk": 1} A-->>-S: 200 OK C->>S: "type": "disconnect" S->>+A: イベントウェブフック
"type": "connection.destroyed",
"event_metadata": {"pk": 1} A-->-S: 200 OK S->>C: WebSocket Close ``` # 統計ウェブフック *バージョン 2024.2.0 で追加。* ## 概要 統計情報をウェブフックで送信する機能です。 ## 注意 `sora.conf` の [stats_webhook_url](SORA_CONF.html#1f750f) を有効にしない場合、 `log/stats_webhook.jsonl` は生成されません。 ## ログ 統計ウェブフックのログは `log/stats_webhook.jsonl` と `log/stats_webhook_error.jsonl` に出力されます。 統計ウェブフックのログではデフォルトで出力されません。 [stats_webhook_url](SORA_CONF.html#1f750f) を有効にしたとしても [stats_webhook_log](SORA_CONF.html#2fa540) を `true` に設定するまでは、 ログが出力されません。 ### stats_webhook.jsonl 統計ウェブフックで送信した **すべて** の処理を書き込みます。 ### stats_webhook_error.jsonl 統計ウェブフックの送信が失敗した処理を書き込みます。 ## 統計ウェブフックの間隔 Sora は一定間隔でクライアントへ統計情報を要求します。 統計ウェブフックの送信間隔はクライアントが送ってくる RTC 統計情報の間隔に依存します。デフォルトは 60 秒です。 ### WebSocket シグナリングを利用している場合 [websocket_stats_timer_interval](SORA_CONF.html#67a631) に指定した間隔になります。 WebSocket の場合は `"type": "ping"` に `"stats": true` を付けて送信することで、 クライアントへ統計情報を要求します。 クライアントは `"type": "pong"` で `"stats": ...` に統計情報を含めて送ります。 この `"stats"` が統計ウェブフックの `"stats"` 項目として送信されます。 ```mermaid sequenceDiagram participant C as クライアント participant S as Sora participant A as アプリケーションサーバー note over C,S: WebRTC 確立 S-)C: "type": "ping"
WebSocket C-)S: "type": "pong"
WebSocket S-)C: "type": "ping"
"stats": true
WebSocket C-)S: "type": "pong"
"stats": ...
WebSocket S->>+A: Stats over HTTP/1.1 A->>-S: 200 OK note over C,S: 60 秒経過 S-)C: "type": "ping"
"stats": true
WebSocket C-)S: "type": "pong"
"stats": ...
WebSocket S->>+A: Stats over HTTP/1.1 A->>-S: 200 OK ``` ### DataChannel シグナリングを利用している場合 [data_channel_stats_timer_interval](SORA_CONF.html#217b39) に指定した間隔になります。 DataChannel シグナリングの場合は `stats` ラベルを利用して、 `"type": "req-stats"` を送ってクライアントへ統計情報を要求します。 クライアントは `stats` ラベルを利用して、 `"type": "stats"` で `"reports"` に統計情報を含めて送ります。 この `"reports"` が統計ウェブフックの `"stats"` 項目として送信されます。 ```mermaid sequenceDiagram participant C as クライアント participant S as Sora participant A as アプリケーションサーバー note over C,S: WebRTC 確立 S-)C: "type": "stats-req"
DataChannel C-)S: "type": "stats"
DataChannel S->>+A: Stats over HTTP/1.1 A->>-S: 200 OK note over C,S: 60 秒経過 S-)C: "type": "stats-req"
DataChannel C-)S: "type": "stats"
DataChannel S->>+A: Stats over HTTP/1.1 A->>-S: 200 OK ``` ## 設定 ### stats_webhook_url 統計情報を送信するウェブフック URL を指定します。 HTTP または HTTPS の URL が指定できます。 ```ini stats_webhook_url = http://192.0.2.10:5890/sora/webhook/stats ``` ### stats_webhook_log 統計情報ウェブフックのログを出力するかどうかを指定します。デフォルトは `false` で出力しません。 - 統計情報ウェブフックの送信した **全ての処理** は `log/stats_webhook.jsonl` ログに出力されます - 統計情報ウェブフックの送信が **失敗した処理** は `log/stats_webhook_error.jsonl` ログに出力されます ```ini stats_webhook_log = true ``` ### ignore_connection_rtc_webhook 統計情報ウェブフックの `type: connection.rtc` を送信するかどうかを指定します。デフォルトは `false` で送信します。 ### rtc_stats_log 統計情報ウェブフックの `type: connection.rtc` の `stats` をリストではなく個別に `rtc_stats.jsonl` として出力するどうかを指定します。 ログは `log/rtc_stats.jsonl` に出力されます。 ```ini rtc_stats_log = true ``` ### stats_webhook_worker_number 統計ウェブフックのワーカー数を指定できます。 基本的にはデフォルトの 5 で足りますが、同時接続数が多い場合は変更をお勧めします。 ```ini stats_webhook_worker_number = 5 ``` ## 統計情報 統計情報をウェブフック URL に対して送信します ### 共通 - type- 統計情報の種類が入ります - id- ウェブフック ID が入ります - node_name- Sora のノード名が入ります - クラスター機能を利用していない場合は `sora@127.0.0.1` です - version- Sora のバージョンが入ります - label- sora.conf に設定された label が入ります - timestamp- Sora が stats を送る直前の時間 RFC3339 形式 (UTC) が入ります ### HTTP ヘッダー > **注釈** > > JSON のパース時の判断などに利用してください。 統計ウェブフックの HTTP ヘッダー に `sora-stats-webhook-type` というヘッダー名で統計ウェブフックのタイプが入ってきます。 `type` が `connection.rtc` の場合は `sora-stats-webhook-type: connection.rtc` が入ってきます。 ### type: connection.rtc クライアントから送られてくる統計情報です。 クライアント統計情報は W3C の [Identifiers for WebRTC's Statistics API](https://www.w3.org/TR/webrtc-stats/) に準拠している必要があります。 - type- `connection.rtc` - channel_id- チャネル ID が入ります - role - group_id - session_id- セッション ID が入ります - client_id - bundle_id - connection_id - simulcast - spotlight - stats- クライアントから送られてくる統計情報が入ります ```javascript { "channel_id": "sora", "group_id": "78K3N8E5M551XEKEWR8QN77PHW", "session_id": "78K3N8E5M551XEKEWR8QN77PHW", "client_id": "NCD5EF3ME900ZDJ3SE27Y6AB6R", "bundle_id": "NCD5EF3ME900ZDJ3SE27Y6AB6R", "connection_id": "NCD5EF3ME900ZDJ3SE27Y6AB6R", "id": "N6W0DBF6A957B01BKNJJR1HC04", "label": "WebRTC SFU Sora", "spotlight": false, "simulcast": true, "stats": [ { "id": "RTCAudioSource_5", "kind": "audio", "timestamp": 1629449091306.655, "type": "media-source", "audioLevel": 0.02237006744590594, "totalAudioEnergy": 0.15581033797981153, "totalSamplesDuration": 5.089999999999936, "trackIdentifier": "922dd031-8a4f-4122-9687-ce094fa11ee2" }, ... ], "timestamp": "2021-08-20T08:44:51.308778Z", "type": "connection.rtc", "node_name": "sora@127.0.0.1", "version": "2024.1.0", "log_written": false } ``` > **警告** > > `stats` 項目はかなり大きな JSON になるため取り扱いには注意してください。 ## stats 項目に含まれる統計情報の送信頻度 変化が無かったり変化の少ない `stats` 項目に含まれる統計情報を送る頻度を減らしています。 デフォルト 600 秒間隔にしています。 ### type: connection.rtc 送信頻度を抑えている `RTCStatsType` は以下の通りです。 - codec- Sora の場合、初期値から変更される項目が無いため - local-candidate- Sora の場合、初期値から変更される項目が無いため - remote-candidate- Sora の場合、初期値から変更される項目が無いため - certificate- Sora の場合、初期値から変更される項目が無いため - peer-connection- Sora の場合、初期値から変更される項目が無いため - track- DEPRECATED 項目のため - stream- DEPRECATED 項目のため これらの統計情報は 600 秒間隔で `stats` 項目に含まれるようになります。 ## RTC 統計情報ログ出力 `sora.conf` で `rtc_stats_log = true` に設定すると、 `log/rtc_stats.jsonl` に RTC 統計情報が出力されます。 解析をしやすくするため、このログは `type: connection.rtc` の `stats` をリストではなく個別に出力します。 ### 項目 - rtc_timestamp- RTCStats の timestamp が浮動小数点で入ります - rtc_type- RTCStats の type が文字列で入ります - rtc_id- RTCStats の id が文字列で入ります - rtc_data- RTCStats がそのまま入ります ### 例 ```javascript { "connection_id": "16ZN7HHK5H3PFDFRZCZQN3WVD4", "id": "Z47B1V0DBN7R1AV90HY98CF6Y8", "label": "WebRTC SFU Sora", "timestamp": "2024-03-24T07:14:37.423158Z", "type": "connection.rtc", "version": "2024.1.0", "node_name": "sora@192.0.2.1", "group_id": "FVR7SV953D08ZA0Z3SVCF9HFBR", "session_id": "FVR7SV953D08ZA0Z3SVCF9HFBR", "role": "sendrecv", "channel_id": "sora", "client_id": "16ZN7HHK5H3PFDFRZCZQN3WVD4", "bundle_id": "16ZN7HHK5H3PFDFRZCZQN3WVD4", "spotlight": false, "simulcast": false, "log_written": true, "rtc_data": { "active": true, "id": "OTdata1A2223648171", "type": "outbound-rtp", "kind": "audio", "ssrc": 2223648171, "mid": "audio_jDlbho", "bytesSent": 117003, "codecId": "COTdata1_109_maxplaybackrate=48000;minptime=10;sprop-stereo=1;stereo=1;usedtx=0;useinbandfec=1", "headerBytesSent": 1248040, "mediaSourceId": "SA21", "mediaType": "audio", "nackCount": 0, "packetsSent": 39001, "remoteId": "RIA2223648171", "retransmittedBytesSent": 0, "retransmittedPacketsSent": 0, "targetBitrate": 64000, "totalPacketSendDelay": 0.0139959999999999997605, "transportId": "Tdata1" }, "rtc_id": "OTdata1A2223648171", "rtc_timestamp": 1711264477421.78710938, "rtc_type": "outbound-rtp" } { "connection_id": "16ZN7HHK5H3PFDFRZCZQN3WVD4", "id": "Z47B1V0DBN7R1AV90HY98CF6Y8", "label": "WebRTC SFU Sora", "timestamp": "2024-03-24T07:14:37.423158Z", "type": "connection.rtc", "version": "2024.1.0", "node_name": "sora@192.0.2.1", "group_id": "FVR7SV953D08ZA0Z3SVCF9HFBR", "session_id": "FVR7SV953D08ZA0Z3SVCF9HFBR", "role": "sendrecv", "channel_id": "sora", "client_id": "16ZN7HHK5H3PFDFRZCZQN3WVD4", "spotlight": false, "simulcast": false, "log_written": true, "rtc_data": { "id": "Tdata1", "type": "transport", "bytesReceived": 104251, "bytesSent": 28783357, "dtlsCipher": "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", "dtlsRole": "client", "dtlsState": "connected", "iceLocalUsernameFragment": "90QS", "iceRole": "controlled", "iceState": "connected", "localCertificateId": "CF1F:6E:2B:47:36:FB:64:72:F9:D7:63:C3:16:6D:02:BB:72:62:E9:C0:E1:40:B6:13:E0:90:B2:E5:6C:49:98:6A", "packetsReceived": 1305, "packetsSent": 74835, "remoteCertificateId": "CF0E:AE:2F:F6:0D:EC:07:E4:27:13:34:38:02:EE:BB:EC:07:BA:77:9D:1C:B5:19:93:E0:A2:87:D5:A6:AA:6B:9A", "selectedCandidatePairChanges": 5, "selectedCandidatePairId": "CPLE514/b5_sVhdyppm", "srtpCipher": "AEAD_AES_128_GCM", "tlsVersion": "FEFD" }, "rtc_id": "Tdata1", "rtc_timestamp": 1711264477421.78710938, "rtc_type": "transport" } ``` # ウェブフックの型定義 ここではウェブフックの型について説明します。 型の表記は TypeScript で記述します。 ## 基本的な型 ```typescript // @ts-check // JSON 値を表します。 // 仕様は RFC 8259 に従います。 type JSONValue = | null | boolean | number | string | JSONValue[] | { [key: string]: JSONValue | undefined }; // UnixTime // 例: 1704067199 type UnixTime = number; // RFC3339 UTC (マイクロ秒) // 例: 2023-12-31T23:59:59.999999Z type Timestamp = string; // ストリームの種別 type Role = "sendrecv" | "sendonly" | "recvonly"; // 最大 255 バイト type ChannelId = string; type SessionId = string; type ClientId = string; type BundleId = string; // Base32(UUIDv4) 26 文字の文字列 type ConnectionId = string; // サイマルキャストで視聴する映像の種類 type SimulcastRid = "none" | "r0" | "r1" | "r2"; type OpusParams = { channels?: number; maxplaybackrate?: number; // 6000..510000 maxaveragebitrate?: number; minptime?: number; ptime?: number; stereo?: boolean; sprop_stereo?: boolean; useinbandfec?: boolean; usedtx?: boolean; }; // 音声の設定 type Audio = | boolean | { codec_type?: AudioCodecType; bit_rate?: number; opus_params?: OpusParams; }; type VideoVP9Params = { // 0..3 profile_id?: number; }; type VideoAV1Params = { // 0..2 profile?: number; // 0..15 level_idx?: number; // 0..1 tier?: number; }; type VideoH264Params = { profile_level_id?: string; // 0..2 packetization_mode?: number; // 0..1 level_asymmetry_allowed?: number; // sora.conf で h264_b_frame = true を設定する必要があります b_frame?: boolean; }; type VideoH265Params = { level_id?: number; // 0..31 profile_id?: number; // 0..1 tier_flag?: number; // "SRST" | "MRST" | "MRMT" tx_mode?: H265TxMode; // sora.conf で h265_b_frame = true を設定する必要があります b_frame?: boolean; }; // 映像の設定 type Video = | boolean | { codec_type?: VideoCodecType; bit_rate?: number; // 利用するには sora.conf で signaling_vp9_params = true を設定する必要があります vp9_params?: VideoVP9Params; // 利用するには sora.conf で signaling_av1_params = true を設定する必要があります av1_params?: VideoAV1Params; // 利用するには sora.conf で signaling_h264_params = true を設定する必要があります h264_params?: VideoH264Params; // 利用するには sora.conf で signaling_h265_params = true を設定する必要があります h265_params?: VideoH265Params; }; // 音声コーデックの種類 type AudioCodecType = "OPUS"; // 映像コーデックの種類 type VideoCodecType = "VP9" | "VP8" | "AV1" | "H264" | "H265"; type H265TxMode = "SRST" | "MRST" | "MRMT"; // DataChannel の方向 type Direction = "sendrecv" | "sendonly" | "recvonly"; type DataChannelMessagingHeaderFieldType = "sender_connection_id"; type DataChannelMessagingHeaderField = { type: DataChannelMessagingHeaderFieldType; // * length は "type": "offer" 時の data_channels にのみ含まれる // * length は"type": "connect" 時には指定できない // * length は認証成功時の払い出し時には指定できない length?: number; }; // DataChannels type DataChannel = { label: string; direction: Direction; ordered: boolean; max_packet_life_time?: number; max_retransmits?: number; protocol?: string; compress: boolean; header?: DataChannelMessagingHeaderField[]; }; type TurnTransportType = "udp" | "tcp"; type ForwardingFilterRuleField = "connection_id" | "client_id" | "kind"; type ForwardingFilterRuleOperator = "is_in" | "is_not_in"; type ForwardingFilterRuleKindValue = "audio" | "video"; type ForwardingFilterRule = { field: ForwardingFilterRuleField; operator: ForwardingFilterRuleOperator; values: string[]; }; type ForwardingFilterAction = "block" | "allow"; type ForwardingFilter = { version?: string; metadata?: JSONValue; name?: string; priority?: number; action?: ForwardingFilterAction; rules: ForwardingFilterRule[][]; }; type SoraClientType = | "Sora JavaScript SDK" | "Sora iOS SDK" | "Sora Android SDK" | "Sora Unity SDK" | "Sora C++ SDK" | "Sora Python SDK" | "Sora C SDK" | "Sora Flutter SDK" | "OBS-Studio" | "OBS-Studio-WHIP" | "OBS-Studio-WHEP" | "WebRTC Native Client Momo" | "WebRTC Load Testing Tool Zakuro"; // SoraClient type SoraClient = { environment?: string; raw?: string; type?: SoraClientType; version?: string; commit_short?: string; libwebrtc?: string; }; // RTCRtpCodecParameters // https://www.w3.org/TR/webrtc/#dom-rtcrtpcodecparameters type SimulcastCodec = { // payloadType や channels は省略 mimeType: string; clockRate: number; sdpFmtpLine?: string; }; // RTCRtpEncodingParameters // https://w3c.github.io/webrtc-pc/#dom-rtcrtpencodingparameters type SimulcastEncoding = { // https://www.w3.org/TR/webrtc/#dom-rtcrtpcodingparameters-rid rid: SimulcastRid; // https://www.w3.org/TR/webrtc/#dom-rtcrtpencodingparameters-active active?: boolean; // https://www.w3.org/TR/webrtc/#dom-rtcrtpencodingparameters-maxframerate maxFramerate?: number; // https://www.w3.org/TR/webrtc/#dom-rtcrtpencodingparameters-maxbitrate maxBitrate?: number; // https://www.w3.org/TR/webrtc/#dom-rtcrtpencodingparameters-scaleresolutiondownby scaleResolutionDownBy?: number; // https://www.w3.org/TR/webrtc/#dom-rtcrtpcodec codec?: SimulcastCodec; // https://w3c.github.io/webrtc-extensions/#dom-rtcrtpencodingparameters-scaleresolutiondownto // @ts-expect-error RTCResolutionRestriction は typed で未定義のため型チェックを無視(型定義が追加され次第削除) scaleResolutionDownTo?: RTCResolutionRestriction; // https://w3c.github.io/webrtc-extensions/#dom-rtcrtpencodingparameters-adaptiveptime adaptivePtime?: boolean; // https://www.w3.org/TR/webrtc-svc/#dom-rtcrtpencodingparameters-scalabilitymode scalabilityMode?: string; }; ``` ## 型定義 ### 認証ウェブフック ```typescript // @ts-check // 認証ウェブフックリクエスト type AuthWebhookRequest = { timestamp: Timestamp; id: string; version: string; label: string; node_name: string; role: Role; channel_id: ChannelId; client_id?: ClientId; bundle_id?: BundleId; connection_id: ConnectionId; simulcast: boolean; // simulcast_rid は 2027 年 12 月リリース予定の Sora にて廃止します // 今後は simulcast_request_rid をご利用ください simulcast_rid?: SimulcastRid; simulcast_request_rid?: SimulcastRid; // sora.conf にて simulcast_multicodec = true を有効にする必要があります simulcast_multicodec?: boolean; spotlight: boolean; spotlight_number?: number; spotlight_focus_rid?: SimulcastRid; spotlight_unfocus_rid?: SimulcastRid; audio: boolean; // Sora 2025.2.0 から audio_* は sendrecv または recvonly のみ含まれます audio_codec_type?: string; audio_bit_rate?: number; video: Video; // Sora 2025.2.0 かr video_* は sendrecv または recvonly のみ含まれます video_codec_type?: VideoCodecType; video_bit_rate?: number; video_vp9_params?: VideoVP9Params; video_av1_params?: VideoAV1Params; video_h264_params?: VideoH264Params; video_h265_params?: VideoH265Params; data_channel_signaling: boolean; ignore_disconnect_websocket: boolean; data_channels?: DataChannel[]; forwarding_filters?: ForwardingFilter[]; authn_metadata?: JSONValue; metadata?: JSONValue; whip?: boolean; whep?: boolean; // Client ID が重複しているクライアントの接続状態 duplicate_client?: { ice_connection_state: "connected" | "checking" | "disconnected"; }; sora_client?: SoraClient; channel_connections: number; channel_sendrecv_connections: number; channel_sendonly_connections: number; channel_recvonly_connections: number; e2ee: false; }; // type: offer の encodings に含まれる codec 払い出される値とは異なるので注意 type SimulcastCodecs = [ { rid: SimulcastRid; codec_type: VideoCodecType; codec_params?: VideoVP9Params | VideoAV1Params | VideoH264Params | VideoH265Params; }, ]; // 認証ウェブフック成功レスポンス // 200 OK で返してください type AuthWebhookAcceptResponse = { allowed: true; audio?: boolean; // audio_* は sendrecv または sendonly のみ有効です audio_codec_type?: string; audio_bit_rate?: number; audio_opus_params?: OpusParams; video?: boolean; // video_* は sendrecv または sendonly のみ有効です video_codec_type?: string; video_bit_rate?: number; video_vp9_params?: VideoVP9Params; video_av1_params?: VideoAV1Params; video_h264_params?: VideoH264Params; video_h265_params?: VideoH265Params; client_id?: ClientId; bundle_id?: BundleId; simulcast?: boolean; // simulcast_rid は 2027 年 12 月リリース予定の Sora にて廃止します // 今後は simulcast_request_rid をご利用ください simulcast_rid?: SimulcastRid; simulcast_request_rid?: SimulcastRid; simulcast_auto_rids?: SimulcastRid[]; simulcast_constraints?: SimulcastRid[]; simulcast_encodings?: SimulcastEncoding[]; simulcast_multicodec?: boolean; simulcast_codecs?: SimulcastCodecs; spotlight?: boolean; // 非推奨です // session.created の戻り値をご利用ください spotlight_number?: number; spotlight_focus_rid?: "none" | SimulcastRid; spotlight_unfocus_rid?: "none" | SimulcastRid; spotlight_encodings?: SimulcastEncoding[]; data_channel_signaling?: boolean; ignore_disconnect_websocket?: boolean; data_channels?: DataChannel[]; forwarding_filters?: ForwardingFilter[]; rpc_methods?: string[]; connection_lifetime?: number; cluster_affinity?: string; cluster_affinity_node_name_list?: string[]; metadata?: JSONValue; event_metadata?: JSONValue; signaling_notify?: boolean; signaling_notify_metadata?: JSONValue; signaling_notify_metadata_ext?: JSONValue; signaling_notify_ice_connection_state?: boolean; recording?: boolean; recording_metadata?: JSONValue; recording_expire_time?: number; recording_split_only?: boolean; recording_split_duration?: number; recording_format?: RecordingFormat; recording_block?: boolean; // セッション単位での最大同時接続数制限を無視して接続を許可する場合に指定します ignore_max_connections?: boolean; ipv4_address?: string; ipv6_address?: string; turn_fqdn?: string; turn_tls_fqdn?: string; playout_delay_min_delay?: number; playout_delay_max_delay?: number; rtc_stats?: boolean; audio_streaming_language_code?: string; turn_tcp_only?: boolean; turn_tls_only?: boolean; rtp_packet_loss_simulator_incoming?: number; rtp_packet_loss_simulator_outgoing?: number; }; // 認証ウェブフック失敗レスポンス // 200 OK で返してください type AuthWebhookRejectResponse = { allowed: false; reason: string; }; ``` ### セッションウェブフック ```typescript // @ts-check type SessionWebhookRequest = | SessionWebhookCreatedRequest | SessionWebhookUpdatedRequest | SessionWebhookDestroyedRequest // 録画 | SessionWebhookRecordingRequest // 音声ストリーミング | SessionWebhookAudioStreamingRequest; type SessionWebhookResponse = SessionWebhookCreatedResponse; // セッションウェブフック生成リクエスト type SessionWebhookCreatedRequest = { type: "session.created"; timestamp: Timestamp; id: string; version: string; label: string; node_name: string; // cluster = true の時のみ含まれる external_signaling_url?: string; channel_id: ChannelId; session_id: SessionId; spotlight: boolean; created_time: UnixTime; created_timestamp: Timestamp; }; // 200 OK で返してください type SessionWebhookCreatedResponse = { // 最大 2,592,000 秒 (30 日) まで指定できます session_lifetime?: number; session_metadata?: JSONValue; spotlight_number?: number; // セッション単位での最大同時接続数を指定します max_connections?: number; forwarding_filters?: ForwardingFilter[]; duplicate_client_id?: "allow" | "evict"; audio_streaming?: boolean; audio_streaming_auto?: boolean; recording?: boolean; recording_metadata?: JSONValue; recording_expire_time?: number; recording_split_only?: boolean; recording_split_duration?: number; recording_format?: RecordingFormat; }; // セッションウェブフック更新リクエスト type SessionWebhookUpdatedRequest = { type: "session.updated"; timestamp: Timestamp; id: string; version: string; label: string; node_name: string; // cluster = true の時のみ含まれる external_signaling_url?: string; channel_id: ChannelId; group_id: SessionId; session_id: SessionId; spotlight: boolean; spotlight_number: number; created_time: number; created_timestamp: string; max_connections: number; total_connections: number; session_metadata?: JSONValue; // 録画機能 (セッション単位) が有効な時のみ recording?: SessionRecording; // クラスター有効の場合は含まれない connections?: SessionConnection[]; }; type SessionWebhookDestroyedReason = | "normal" | "validation_error" | "webhook_error" | "terminated_api" | "lifetime_expired" | "abort"; // セッションウェブフック破棄リクエスト type SessionWebhookDestroyedRequest = { type: "session.destroyed"; timestamp: Timestamp; id: string; version: string; label: string; node_name: string; // cluster = true の時のみ含まれる external_signaling_url?: string; channel_id: ChannelId; group_id: SessionId; session_id: SessionId; spotlight: boolean; spotlight_number?: number; created_time: number; created_timestamp: string; destroyed_time: number; destroyed_timestamp: string; reason: SessionWebhookDestroyedReason; max_connections: number; total_connections: number; session_metadata?: JSONValue; // クラスター有効の場合は含まれない connections?: SessionConnection[]; }; type SessionRecording = { recording_id: string; // 未指定の場合は含まれない recording_metadata?: JSONValue; // 未指定の場合は含まれない expire_time?: number; // expire_time が未指定の場合は含まれない expired_at?: number; split_only: boolean; split_duration?: number; format: RecordingFormat; start_timestamp: string; }; type SessionConnection = { role: Role; client_id: ClientId; bundle_id: BundleId; connection_id: ConnectionId; simulcast: boolean; audio: boolean; audio_codec_type?: string; audio_bit_rate?: number; video: boolean; video_codec_type?: string; video_bit_rate?: number; video_vp9_params?: VideoVP9Params; video_av1_params?: VideoAV1Params; video_h264_params?: VideoH264Params; video_h265_params?: VideoH265Params; // 認証は成功したが WebRTC が確立できなかった場合、 null が入ってくる connection_created_timestamp: Timestamp | null; // 認証は成功したが WebRTC が確立できなかった場合、 null が入ってくる connection_destroyed_timestamp: Timestamp | null; event_metadata?: JSONValue; }; ``` ### セッションウェブフック (録画) ```typescript // @ts-check type RecordingFormat = "webm" | "mp4"; type SessionWebhookRecordingRequest = | SessionWebhookRecordingStartedRequest | SessionWebhookRecordingReportRequest; type SessionWebhookRecordingStartedRequest = { type: "recording.started"; timestamp: Timestamp; id: string; version: string; label: string; node_name: string; channel_id: ChannelId; group_id: SessionId; session_id: SessionId; session_metadata?: JSONValue; data: SessionWebhookRecordingStartedData; }; type SessionWebhookRecordingStartedData = { channel_id: ChannelId; group_id: SessionId; session_id: SessionId; recording_id: string; recording_metadata?: JSONValue; split_only: boolean; split_duration?: number; created_at: number; expire_time?: number; expired_at?: number; start_timestamp: Timestamp; format: RecordingFormat; }; type SessionWebhookRecordingReportRequest = { type: "recording.report"; timestamp: Timestamp; id: string; version: string; label: string; node_name: string; channel_id: ChannelId; group_id: SessionId; session_id: SessionId; session_metadata?: JSONValue; data: SessionWebhookRecordingReportData; }; type SessionWebhookRecordingReportData = { channel_id: ChannelId; group_id: SessionId; session_id: SessionId; recording_id: string; recording_metadata?: JSONValue; split_only: boolean; split_duration?: number; created_at: number; expire_time?: number; expired_at?: number; file_path: string; filename: string; file_written: boolean; start_timestamp: Timestamp; stop_timestamp: Timestamp; format: RecordingFormat; archives: SessionWebhookRecordingReportArchive[]; failed_archives: SessionWebhookRecordingReportFailedArchive[]; }; type SessionWebhookRecordingReportArchive = { label: string; node_name: string; client_id: ClientId; bundle_id: BundleId; connection_id: ConnectionId; file_path?: string; filename?: string; metadata_file_path?: string; metadata_filename?: string; start_time_offset: number; start_timestamp: Timestamp; stop_time_offset: number; stop_timestamp: Timestamp; size?: number; split_last_index?: string; }; type SessionWebhookRecordingReportFailedArchive = { label: string; node_name: string; client_id: ClientId; bundle_id: BundleId; connection_id: ConnectionId; }; ``` ### セッションウェブフック (音声ストリーミング) ```typescript // @ts-check type SessionWebhookAudioStreamingRequest = | SessionWebhookAudioStreamingStartedRequest | SessionWebhookAudioStreamingStoppedRequest; // セッションウェブフック音声ストリーミング開始リクエスト type SessionWebhookAudioStreamingStartedRequest = { type: "audio-streaming.started"; timestamp: Timestamp; id: string; version: string; label: string; node_name: string; // cluster = true の時のみ含まれる external_signaling_url?: string; channel_id: ChannelId; group_id: SessionId; session_id: SessionId; spotlight: boolean; created_time: UnixTime; created_timestamp: Timestamp; session_metadata?: JSONValue; data: AudioStreamingStartedData; }; type AudioStreamingStartedData = { audio_streaming_auto: boolean; audio_streaming_started_timestamp: string; }; // セッションウェブフック音声ストリーミング停止リクエスト type SessionWebhookAudioStreamingStoppedRequest = { type: "audio-streaming.stopped"; timestamp: Timestamp; id: string; version: string; label: string; node_name: string; // cluster = true の時のみ含まれる external_signaling_url?: string; channel_id: ChannelId; group_id: SessionId; session_id: SessionId; spotlight: boolean; created_time: UnixTime; created_timestamp: Timestamp; session_metadata?: JSONValue; data: AudioStreamingStoppedData; }; type AudioStreamingStoppedData = { audio_streaming_auto: boolean; audio_streaming_started_timestamp: Timestamp; audio_streaming_stopped_timestamp: Timestamp; }; ``` ### イベントウェブフック ```typescript // @ts-check type EventWebhookRequest = // 接続 | EventWebhookConnectionRequest // 録画 | EventWebhookArchiveRequest // スポットライト | EventWebhookSpotlightRequest // 音声ストリーミング | EventWebhookAudioStreamingFailedRequest; type EventWebhookConnectionRequest = | EventWebhookConnectionCreatedRequest | EventWebhookConnectionUpdatedRequest | EventWebhookConnectionDestroyedRequest | EventWebhookConnectionFailedRequest; // イベントコネクション生成ウェブフックリクエスト type EventWebhookConnectionCreatedRequest = { type: "connection.created"; timestamp: Timestamp; id: string; log_written: boolean; version: string; label: string; node_name: string; role: Role; channel_id: ChannelId; group_id: SessionId; session_id: SessionId; client_id: ClientId; bundle_id: BundleId; connection_id: ConnectionId; simulcast: boolean; simulcast_multicodec?: boolean; spotlight: boolean; event_metadata?: JSONValue; data: EventWebhookConnectionCreatedData; }; // イベントコネクション生成ウェブフックデータ type EventWebhookConnectionCreatedData = { minutes: number; audio: boolean; audio_codec_type?: AudioCodecType; audio_bit_rate?: number; video: boolean; video_codec_type?: VideoCodecType; video_bit_rate?: number; video_vp9_params?: VideoVP9Params; video_av1_params?: VideoAV1Params; video_h264_params?: VideoH264Params; video_h265_params?: VideoH265Params; recording_block: boolean; channel_connections: number; channel_sendrecv_connections: number; channel_sendonly_connections: number; channel_recvonly_connections: number; turn_transport_type: TurnTransportType; created_time: UnixTime; created_timestamp: Timestamp; ice_connection_state: IceConnectionState; total_received_bytes: number; total_sent_bytes: number; }; // イベントコネクション更新ウェブフックリクエスト type EventWebhookConnectionUpdatedRequest = { type: "connection.updated"; timestamp: Timestamp; id: string; log_written: boolean; version: string; label: string; node_name: string; role: Role; channel_id: ChannelId; group_id: SessionId; session_id: SessionId; client_id: ClientId; bundle_id: BundleId; connection_id: ConnectionId; simulcast: boolean; simulcast_multicodec?: boolean; spotlight: boolean; event_metadata?: JSONValue; data: EventWebhookConnectionUpdatedData; }; // イベントコネクション更新ウェブフックデータ type EventWebhookConnectionUpdatedData = { minutes: number; audio: boolean; audio_codec_type?: AudioCodecType; audio_bit_rate?: number; video: boolean; video_codec_type?: VideoCodecType; video_bit_rate?: number; video_vp9_params?: VideoVP9Params; video_av1_params?: VideoAV1Params; video_h264_params?: VideoH264Params; video_h265_params?: VideoH265Params; recording_block: boolean; channel_connections: number; channel_sendrecv_connections: number; channel_sendonly_connections: number; channel_recvonly_connections: number; turn_transport_type: TurnTransportType; created_time: UnixTime; created_timestamp: Timestamp; ice_connection_state: IceConnectionState; total_received_bytes: number; total_sent_bytes: number; }; // イベントコネクション破棄ウェブフックリクエスト type EventWebhookConnectionDestroyedRequest = { type: "connection.destroyed"; timestamp: Timestamp; id: string; log_written: boolean; version: string; label: string; node_name: string; role: Role; channel_id: ChannelId; group_id: SessionId; session_id: SessionId; client_id: ClientId; bundle_id: BundleId; connection_id: ConnectionId; simulcast: boolean; simulcast_multicodec?: boolean; spotlight: boolean; event_metadata?: JSONValue; data: EventWebhookConnectionDestroyedData; }; type ConnectionDestroyedReason = | "normal" | "disconnected_api" | "session_destroyed" | "lifetime_expired" | "duplicate_client_id" | "abort" | "signaling_re_answer_timeout"; // イベントコネクション破棄ウェブフックデータ type EventWebhookConnectionDestroyedData = { minutes: number; audio: boolean; audio_codec_type?: AudioCodecType; audio_bit_rate?: number; video: boolean; video_codec_type?: VideoCodecType; video_bit_rate?: number; video_vp9_params?: VideoVP9Params; video_av1_params?: VideoAV1Params; video_h264_params?: VideoH264Params; video_h265_params?: VideoH265Params; recording_block: boolean; channel_connections: number; channel_sendrecv_connections: number; channel_sendonly_connections: number; channel_recvonly_connections: number; turn_transport_type: TurnTransportType; created_time: UnixTime; created_timestamp: Timestamp; destroyed_time: UnixTime; destroyed_timestamp: Timestamp; ice_connection_state: IceConnectionState; total_received_bytes: number; total_sent_bytes: number; reason?: ConnectionDestroyedReason; disconnect_api_reason?: string; type_disconnect_reason?: string; }; // 2024.2.0 から認証成功後のみ送信されるようになりました // そのため role / channel_id / client_id / bundle_id / connection_id は必須となりました type EventWebhookConnectionFailedRequest = { type: "connection.failed"; timestamp: Timestamp; id: string; log_written: boolean; version: string; label: string; node_name: string; role: Role; channel_id: ChannelId; client_id: ClientId; bundle_id: BundleId; connection_id: ConnectionId; simulcast: boolean; spotlight: boolean; data: EventWebhookConnectionFailedData; }; type EventWebhookConnectionFailedData = { message: string; channel_connections: number; channel_sendrecv_connections: number; channel_sendonly_connections: number; channel_recvonly_connections: number; total_received_bytes: number; total_sent_bytes: number; }; type IceConnectionState = { total_checking_duration_ms: number; total_disconnected_duration_ms: number; }; ``` ### イベントウェブフック (録画) ```typescript // @ts-check type EventWebhookArchiveRequest = | EventWebhookArchiveStartedRequest | EventWebhookArchiveAvailableRequest | EventWebhookSplitArchiveAvailableRequest | EventWebhookSplitArchiveEndRequest | EventWebhookArchiveFailedRequest; type EventWebhookArchiveStartedRequest = { type: "archive.started"; timestamp: Timestamp; id: string; log_written: boolean; version: string; label: string; node_name: string; channel_id: ChannelId; group_id: SessionId; session_id: SessionId; client_id: ClientId; bundle_id: BundleId; connection_id: ConnectionId; event_metadata?: JSONValue; data: EventWebhookArchiveStartedData; }; type EventWebhookArchiveStartedData = { recording_id: string; channel_id: ChannelId; group_id: SessionId; session_id: SessionId; client_id: ClientId; bundle_id: BundleId; connection_id: ConnectionId; created_at: number; audio: boolean; audio_codec_type?: string; audio_bit_rate?: number; video: boolean; video_codec_type?: string; video_bit_rate?: number; video_vp9_params?: VideoVP9Params; video_av1_params?: VideoAV1Params; video_h264_params?: VideoH264Params; start_time: UnixTime; start_time_offset: number; start_timestamp: Timestamp; format: RecordingFormat; }; type EventWebhookArchiveAvailableRequest = { type: "archive.available"; timestamp: Timestamp; id: string; log_written: boolean; version: string; label: string; node_name: string; channel_id: ChannelId; group_id: SessionId; session_id: SessionId; client_id: ClientId; bundle_id: BundleId; connection_id: ConnectionId; event_metadata?: JSONValue; data: EventWebhookArchiveAvailableData; }; type EventWebhookArchiveAvailableData = { recording_id: string; channel_id: ChannelId; group_id: SessionId; session_id: SessionId; client_id: ClientId; bundle_id: BundleId; connection_id: ConnectionId; file_path: string; filename: string; metadata_file_path: string; metadata_filename: string; size: number; created_at: number; audio: boolean; audio_codec_type?: string; audio_bit_rate?: number; video: boolean; video_codec_type?: string; video_bit_rate?: number; video_height?: number; video_width?: number; video_vp9_params?: VideoVP9Params; video_av1_params?: VideoAV1Params; video_h264_params?: VideoH264Params; start_time: UnixTime; start_time_offset: number; start_timestamp: Timestamp; stop_time: UnixTime; stop_time_offset: number; stop_timestamp: Timestamp; split_only: boolean; format: RecordingFormat; expire_time?: number; expired_at?: number; split_duration?: number; stats: JSONValue; }; type EventWebhookSplitArchiveAvailableRequest = { type: "split-archive.available"; id: string; timestamp: Timestamp; log_written: boolean; version: string; label: string; node_name: string; channel_id: ChannelId; group_id: SessionId; session_id: SessionId; client_id: ClientId; bundle_id: BundleId; connection_id: ConnectionId; event_metadata?: JSONValue; data: EventWebhookSplitArchiveAvailableData; }; type EventWebhookSplitArchiveAvailableData = { recording_id: string; channel_id: ChannelId; group_id: SessionId; session_id: SessionId; client_id: ClientId; bundle_id: BundleId; connection_id: ConnectionId; split_index: string; file_path: string; filename: string; metadata_file_path: string; metadata_filename: string; size: number; created_at: number; audio: boolean; audio_codec_type?: string; audio_bit_rate?: number; video: boolean; video_codec_type?: string; video_bit_rate?: number; video_height?: number; video_width?: number; video_vp9_params?: VideoVP9Params; video_av1_params?: VideoAV1Params; video_h264_params?: VideoH264Params; start_time: number; start_time_offset: number; start_timestamp: Timestamp; stop_time: UnixTime; stop_time_offset: number; stop_timestamp: Timestamp; split_only: boolean; format: RecordingFormat; expire_time?: number; expired_at?: number; split_duration?: number; stats: JSONValue; }; type EventWebhookSplitArchiveEndRequest = { type: "split-archive.end"; id: string; timestamp: Timestamp; log_written: boolean; version: string; label: string; node_name: string; channel_id: ChannelId; group_id: SessionId; session_id: SessionId; client_id: ClientId; bundle_id: BundleId; connection_id: ConnectionId; event_metadata?: JSONValue; data: EventWebhookSplitArchiveEndData; }; type EventWebhookSplitArchiveEndData = { split_last_index: string; recording_id: string; channel_id: ChannelId; group_id: SessionId; session_id: SessionId; client_id: ClientId; bundle_id: BundleId; connection_id: ConnectionId; file_path: string; filename: string; audio: boolean; audio_codec_type?: string; audio_bit_rate?: number; video: Video; video_codec_type?: string; video_bit_rate?: number; video_vp9_params?: VideoVP9Params; video_av1_params?: VideoAV1Params; video_h264_params?: VideoH264Params; start_time: UnixTime; start_time_offset: number; start_timestamp: Timestamp; stop_time: UnixTime; stop_time_offset: number; stop_timestamp: Timestamp; split_only: boolean; format: RecordingFormat; expire_time?: number; expired_at?: number; split_duration?: number; stats: JSONValue; }; type EventWebhookArchiveFailedRequest = { type: "archive.failed"; timestamp: Timestamp; id: string; log_written: boolean; version: string; label: string; node_name: string; channel_id: ChannelId; group_id: SessionId; session_id: SessionId; client_id: ClientId; bundle_id: BundleId; connection_id: ConnectionId; event_metadata?: JSONValue; data: EventWebhookSplitArchiveFailedData; }; type EventWebhookSplitArchiveFailedData = { recording_id: string; group_id: SessionId; session_id: SessionId; file_path?: string; filename?: string; split_index?: string; split_file_path?: string; split_filename?: string; audio: boolean; audio_codec_type?: string; audio_bit_rate?: number; video: boolean; video_codec_type?: string; video_bit_rate?: number; video_height?: number; video_width?: number; video_vp9_params?: VideoVP9Params; video_av1_params?: VideoAV1Params; video_h264_params?: VideoH264Params; start_time: UnixTime; start_timestamp: Timestamp; stop_time: UnixTime; stop_timestamp: Timestamp; split: boolean; split_only: boolean; format: RecordingFormat; expire_time?: number; expired_at?: number; split_duration?: number; stats: JSONValue; }; ``` ### イベントウェブフック (スポットライト) ```typescript // @ts-check type EventWebhookSpotlightRequest = | EventWebhookSpotlightFocusedRequest | EventWebhookSpotlightUnfocusedRequest; // イベントウェブフックスポットライトフォーカスリクエスト type EventWebhookSpotlightFocusedRequest = { type: "spotlight.focused"; timestamp: Timestamp; id: string; log_written: boolean; version: string; label: string; node_name: string; channel_id: ChannelId; client_id: ClientId; bundle_id: BundleId; connection_id: ConnectionId; spotlight_number: number; fixed: boolean; audio: boolean; video: boolean; }; type EventWebhookSpotlightUnfocusedRequest = { type: "spotlight.unfocused"; timestamp: Timestamp; id: string; log_written: boolean; version: string; label: string; node_name: string; channel_id: ChannelId; client_id: ClientId; bundle_id: BundleId; connection_id: ConnectionId; spotlight_number: number; audio: boolean; video: boolean; }; ``` ### イベントウェブフック (音声ストリーミング失敗) ```typescript // @ts-check type EventWebhookAudioStreamingFailedRequest = { type: "audio-streaming.failed"; timestamp: Timestamp; id: string; log_written: boolean; version: string; label: string; node_name: string; role: Role; channel_id: ChannelId; group_id: SessionId; session_id: SessionId; client_id: ClientId; bundle_id: BundleId; connection_id: ConnectionId; simulcast: boolean; spotlight: boolean; data: { failed_reason: string; }; }; ``` ### 統計ウェブフック ```typescript // @ts-check // コネクション RTC 統計情報ウェブフックリクエスト type StatsWebhookConnectionRtcRequest = { type: "connection.rtc"; timestamp: Timestamp; id: string; log_written: boolean; version: string; label: string; node_name: string; role: Role; channel_id: ChannelId; group_id: SessionId; session_id: SessionId; client_id: ClientId; bundle_id: BundleId; connection_id: ConnectionId; simulcast: boolean; spotlight: boolean; // https://www.w3.org/TR/webrtc-stats/ stats?: RTCStatsReport[]; }; ``` # API ## 概要 API は Sora に対して HTTP 経由で実行できます。 ## 用語 - object- `JSON Object` です - curl では `-d '{"key": {"spam": "egg"}}'` のように指定してください ## API の種類 ### API 正式リリースされている API ### 実験的 API 仕様が確定していない API 詳細は [実験的 API](EXPERIMENTAL_API.html) をご確認ください。 ### 非推奨 API 期限が来たら廃止される API 詳細は [非推奨 API](DEPRECATED_API.html) をご確認ください。 ### 廃止 API 廃止された API 詳細は [廃止 API](OBSOLETE_API.html) をご確認ください。 ### テスト API テストで利用する API 詳細は [テスト API](TEST_API.html) をご確認ください。 ## x-sora-target ヘッダー API は [DynamoDB や Route53 などの AWS API が独特な仕様なので紹介](https://gist.github.com/voluntas/811240c5b6a169ae1c6ac401e0197417) を参考にしており、 `x-sora-target` というヘッダーを使って実行します。 - すべての API は POST を使用します - すべての API の PATH は `/` です - リクエストの Body には JSON を使用します - レスポンスの Body には JSON を使用します ## 設定 ### api_port API のポート番号を変更したい場合は `sora.conf` の [api_port](SORA_CONF.html#4adab7) にて、 API のポート番号を設定してください。 デフォルトでは 3000 番を利用します。 ```ini api_port = 3000 ``` ### api_loopback_address_only API へのアクセスをループバックアドレスからのみに制限します。 本番環境では可能な限り有効にしてください。 ```ini api_loopback_address_only = true ``` ### api_cors_origin > **警告** > > 本番環境ではこの設定は有効にしないでください。 API をクロスドメインで使用したい場合に設定します。 ```ini api_cors_origin = http://127.0.0.1:5000 ``` こうすることで、ブラウザで `http://127.0.0.1:5000` から API を叩くことができるようになります。 ## curl HTTP API を実行するために curl というコマンドラインツールを使用しています。 [curl](https://curl.se/) このドキュメントの例では curl 8.20.0 を利用しています。 からインストールしてください。 ## jq curl の JSON レスポンスを整形するために jq というコマンドラインツールを使用しています。 [jq](https://github.com/jqlang/jq) このドキュメントの例では jq 1.8.1 を利用しています。 からインストールしてください。 # シグナリング API ## DisconnectChannel **x-sora-target**: Sora_20151104.DisconnectChannel 指定したチャネルの接続をすべて切断します。 * - キー - 型 * - channel_id - string * - reason (オプション) - object `reason` に値を指定した場合、イベントウェブフック `connection.destroyed` の `disconnect_api_reason` に指定した値が入ってきます。 ```console $ curl -sS \ -X POST \ http://127.0.0.1:3000 \ -H "x-sora-target: Sora_20151104.DisconnectChannel" \ --json '{"channel_id":"sora"}' \ | jq . { "channel_id": "sora" } ``` ## DisconnectClient **x-sora-target**: Sora_20151104.DisconnectClient 指定したクライアント ID の接続をすべて切断します。 * - キー - 型 * - channel_id - string * - client_id - string * - reason (オプション) - object `reason` に値を指定した場合、イベントウェブフック `connection.destroyed` の `disconnect_api_reason` に指定した値が入ってきます。 ```console $ curl -sS \ -X POST \ http://127.0.0.1:3000/ \ -H "x-sora-target: Sora_20151104.DisconnectClient" \ --json '{"channel_id":"sora","client_id":"E2APPNQ9P97Q32V2ABW546SWW8"}' \ | jq . { "channel_id": "sora", "client_id": "E2APPNQ9P97Q32V2ABW546SWW8" } ``` ## DisconnectConnection **x-sora-target**: Sora_20151104.DisconnectConnection 指定したコネクション ID の接続を切断します。 * - キー - 型 * - channel_id - string * - connection_id - string * - reason (オプション) - object `reason` に値を指定した場合、イベントウェブフック `connection.destroyed` の `disconnect_api_reason` に指定した値が入ってきます。 ```console $ curl -sS \ -X POST \ http://127.0.0.1:3000/ \ -H "x-sora-target: Sora_20151104.DisconnectConnection" \ --json '{"channel_id":"sora","connection_id":"T34CDBMRJS1B5BVPF17RTBQA3C"}' \ | jq . { "channel_id": "sora", "connection_id": "T34CDBMRJS1B5BVPF17RTBQA3C" } ``` ## DisconnectChannelByRole **x-sora-target**: Sora_20201120.DisconnectChannelByRole 指定したチャネルの指定したロールの接続を切断します。 * - キー - 型 * - channel_id - string * - role - string (sendrecv | sendonly | recvonly) * - reason (オプション) - object ```console $ curl -sS \ -X POST \ http://127.0.0.1:3000/ \ -H "x-sora-target: Sora_20201120.DisconnectChannelByRole" \ --json '{"channel_id":"sora","role":"sendrecv"}' \ | jq . { "channel_id": "sora", "role": "sendrecv" } ``` ## ListConnections **x-sora-target**: Sora_20201013.ListConnections すべての接続一覧を取得します。 * - キー - 型 - デフォルト * - local (オプション) - boolean - true `local` はクラスター機能利用時に、全てのノードの情報を取得するかどうかを指定します。 ```console $ curl -sS \ -X POST \ http://127.0.0.1:3000/ \ -H "x-sora-target: Sora_20201013.ListConnections" \ | jq . [ { "node_name": "sora@127.0.0.1", "audio": { "codec_type": "OPUS" }, "channel_id": "akane", "session_id": "JJJ5BFH7QN6DQBTKSS7JA8ZYQR", "client_id": "DV2Z3MSXC50M78Y11ETN3VZ360", "bundle_id": "DV2Z3MSXC50M78Y11ETN3VZ360", "connection_id": "DV2Z3MSXC50M78Y11ETN3VZ360", "created_time": 1734420116038137, "created_timestamp": "2024-12-17T07:21:56.038137Z", "event_metadata": {"spam": "egg"}, "recording_block": false, "role": "sendrecv", "simulcast": false, "spotlight": false, "video": { "bit_rate": 1000, "codec_type": "VP9", "vp9_params": { "profile_id": 0 } } }, { "node_name": "sora@127.0.0.1", "audio": { "codec_type": "OPUS" }, "channel_id": "sora", "session_id": "FDYSGDVQ592CK5D4ZMC0W4XXDM", "client_id": "DKF93NH82X3BDB0CVKEH32JMVR", "bundle_id": "DKF93NH82X3BDB0CVKEH32JMVR", "connection_id": "DKF93NH82X3BDB0CVKEH32JMVR", "created_time": 1734420116038137, "created_timestamp": "2024-12-17T07:21:56.038137Z", "event_metadata": {"spam": "egg"}, "recording_block": false, "role": "sendrecv", "simulcast": false, "spotlight": false, "video": { "bit_rate": 1000, "codec_type": "VP9", "vp9_params": { "profile_id": 0 } } }, { "node_name": "sora@127.0.0.1", "audio": { "codec_type": "OPUS" }, "channel_id": "sora", "session_id": "FDYSGDVQ592CK5D4ZMC0W4XXDM", "client_id": "W6725M370N2W301378Y5SFG01C", "bundle_id": "W6725M370N2W301378Y5SFG01C", "connection_id": "W6725M370N2W301378Y5SFG01C", "created_time": 1734420116038137, "created_timestamp": "2024-12-17T07:21:56.038137Z", "event_metadata": {"spam": "egg"}, "recording_block": false, "role": "sendrecv", "simulcast": false, "spotlight": false, "video": { "bit_rate": 1000, "codec_type": "VP9", "vp9_params": { "profile_id": 0 } } } ] ``` ## ListChannelConnections **x-sora-target**: Sora_20201013.ListChannelConnections 指定したチャネルの接続一覧を取得します。 * - キー - 型 * - channel_id - string ```console $ curl -sS \ -X POST \ http://127.0.0.1:3000/ \ -H "x-sora-target: Sora_20201013.ListChannelConnections" \ --json '{"channel_id":"sora"}' \ | jq . [ { "node_name": "sora@127.0.0.1", "audio": { "codec_type": "OPUS" }, "channel_id": "sora", "session_id": "FDYSGDVQ592CK5D4ZMC0W4XXDM", "client_id": "DKF93NH82X3BDB0CVKEH32JMVR", "bundle_id": "DKF93NH82X3BDB0CVKEH32JMVR", "connection_id": "DKF93NH82X3BDB0CVKEH32JMVR", "created_time": 1734420116038137, "created_timestamp": "2024-12-17T07:21:56.038137Z", "event_metadata": {"spam": "egg"}, "recording_block": false, "role": "sendrecv", "simulcast": false, "spotlight": false, "video": { "bit_rate": 1000, "codec_type": "VP9", "vp9_params": { "profile_id": 0 } } }, { "node_name": "sora@127.0.0.1", "audio": { "codec_type": "OPUS" }, "channel_id": "sora", "session_id": "FDYSGDVQ592CK5D4ZMC0W4XXDM", "client_id": "W6725M370N2W301378Y5SFG01C", "bundle_id": "W6725M370N2W301378Y5SFG01C", "connection_id": "W6725M370N2W301378Y5SFG01C", "created_time": 1734420116038137, "created_timestamp": "2024-12-17T07:21:56.038137Z", "event_metadata": {"spam": "egg"}, "recording_block": false, "role": "sendrecv", "simulcast": false, "spotlight": false, "video": { "bit_rate": 1000, "codec_type": "VP9", "vp9_params": { "profile_id": 0 } } } ] ``` # コネクション API ## RequestKeyFrame *バージョン 2024.2.0 で追加。* **x-sora-target**: Sora_20241218.RequestKeyFrame 指定したチャネルで配信している接続に対してキーフレームを要求します。 この API は `role` が `sendrecv` または `sendonly` の接続にのみ有効です。 キーフレーム要求を送ってからキーフレームが送られてくるまでは、 1 秒間隔で最大 5 回までリクエストを送信します。 `channel_id` や `connection_id` が存在しない場合はエラーとなります。 * - キー - 型 * - channel_id - string * - connection_id - string ```console $ curl -sS \ -X POST \ http://127.0.0.1:3000/ \ -H "x-sora-target: Sora_20241218.RequestKeyFrame" \ --json '{"channel_id":"sora","connection_id":"KDBN2YD1A919V5BA2JX6TG2RP8"}' \ | jq . { "channel_id": "sora", "connection_id": "KP8VZZ321D0A90RSVJC4RMGJ08" } ``` # セッション API ## TerminateSession **x-sora-target**: Sora_20230628.TerminateSession 指定したセッションを強制的に破棄させる API です。そのセッションに接続しているクライアントはすべて切断します。 この API は非同期のため、リクエストを受け付けた後に即座にレスポンスを返します。 セッション破棄の完了は [session.destroyed](SESSION_WEBHOOK.html#ccb165) で確認してください。 * - キー - 型 * - channel_id - string * - session_id (オプション) - string - `channel_id` を指定して、セッションを終了させます - `session_id` を追加で指定することができますが、 `session_id` が見つからない場合はエラーになります API 実行中に新規の接続が来た場合、その接続はいったん保留して、セッション破棄後に新規セッションでの接続として扱います。 ```console $ curl -sS \ -X POST \ http://127.0.0.1:3000/ \ -H "x-sora-target: Sora_20230628.TerminateSession" \ --json '{"channel_id":"sora","session_id":"JJJ5BFH7QN6DQBTKSS7JA8ZYQR"}' \ | jq . { "session_id": "JJJ5BFH7QN6DQBTKSS7JA8ZYQR" } ``` ## GetSession **x-sora-target**: Sora_20231220.GetSession 指定したチャネルのセッションを表示する API です。 * - キー - 型 * - channel_id - string * - session_id (オプション) - string 戻り値の項目はセッションウェブフック `session.updated` と同様です。 ```console $ curl -sS \ -X POST \ http://127.0.0.1:3000/ \ -H "x-sora-target: Sora_20231220.GetSession" \ --json '{"channel_id":"sora"}' \ | jq . { "label": "WebRTC SFU Sora", "node_name": "sora@127.0.0.1", "version": "2023.2.0", "channel_id": "sora", "group_id": "JJJ5BFH7QN6DQBTKSS7JA8ZYQR", "session_id": "JJJ5BFH7QN6DQBTKSS7JA8ZYQR", "session_metadata": {"spam": "egg"}, "created_time": 1638337454, "created_timestamp": "2021-12-01T05:44:14.523736Z", "spotlight": false, "max_connections": 4, "total_connections": 4, "external_signaling_url": "wss://node-01.example.com/signaling", "connections": [ { "audio": true, "audio_codec_type": "OPUS", "client_id": "W9QE86Z0BS1QFFPZ2QB5DRZ2HC", "bundle_id": "W9QE86Z0BS1QFFPZ2QB5DRZ2HC", "connection_id": "W9QE86Z0BS1QFFPZ2QB5DRZ2HC", "connection_created_timestamp": "2021-12-01T05:44:23.051704Z", "connection_destroyed_timestamp": "2021-12-01T05:44:56.878019Z", "role": "sendrecv", "simulcast": false, "video": true, "video_bit_rate": 1000, "video_codec_type": "VP9", "video_vp9_params": { "profile_id": 0 } }, { "audio": true, "audio_codec_type": "OPUS", "client_id": "JXMYW6GPX54EH0HGA5X4130FBM", "bundle_id": "JXMYW6GPX54EH0HGA5X4130FBM", "connection_id": "JXMYW6GPX54EH0HGA5X4130FBM", "connection_created_timestamp": "2021-12-01T05:44:23.051704Z", "connection_destroyed_timestamp": "2021-12-01T05:44:56.878019Z", "role": "sendrecv", "simulcast": false, "video": true, "video_bit_rate": 1000, "video_codec_type": "VP9", "video_vp9_params": { "profile_id": 0 } }, { "audio": true, "audio_codec_type": "OPUS", "client_id": "F8VK9R71BN5S5EDE737C8XAA3C", "bundle_id": "F8VK9R71BN5S5EDE737C8XAA3C", "connection_id": "F8VK9R71BN5S5EDE737C8XAA3C", "connection_created_timestamp": "2021-12-01T05:44:23.051704Z", "connection_destroyed_timestamp": "2021-12-01T05:44:56.878019Z", "role": "sendrecv", "simulcast": false, "video": true, "video_bit_rate": 1000, "video_codec_type": "VP9", "video_vp9_params": { "profile_id": 0 } } ] } ``` ### クラスターが有効な場合 `connections` 項目が含まれなくなります。 ```javascript { "label": "WebRTC SFU Sora", "node_name": "sora@127.0.0.1", "version": "2023.2.0", "channel_id": "sora", "group_id": "JJJ5BFH7QN6DQBTKSS7JA8ZYQR", "session_id": "JJJ5BFH7QN6DQBTKSS7JA8ZYQR", "session_metadata": {"spam": "egg"}, "created_time": 1638337454, "created_timestamp": "2021-12-01T05:44:14.523736Z", "spotlight": false, "max_connections": 4, "total_connections": 4, "external_signaling_url": "wss://node-01.example.com/signaling" } ``` ### 録画機能 (セッション単位) が有効な場合 `recording` 項目が含まれるようになります。 * - キー - 型 - 内容 * - recording_id - string - 録画機能 (セッション単位) の ID * - recording_metadata (オプション) - JSONValue - 録画機能 (セッション単位) のメタデータ * - expire_time - integer - セッションでの録画期限 * - expired_at - integer - セッションでの録画期限 (Unix time) * - split_only - boolean - セッションでの録画が分割のみかどうか * - split_duration (オプション) - integer - セッションでの録画分割有効時の分割時間 * - start_timestamp - string - セッションでの録画が開始された時刻 (RFC 3339 (UTC)) * - format - string - 録画フォーマット (``"webm"`` または ``"mp4"``) ```javascript { "label": "WebRTC SFU Sora", "node_name": "sora@127.0.0.1", "version": "2023.2.0", "channel_id": "sora", "group_id": "JJJ5BFH7QN6DQBTKSS7JA8ZYQR", "session_id": "JJJ5BFH7QN6DQBTKSS7JA8ZYQR", "session_metadata": {"spam": "egg"}, "created_time": 1638337454, "created_timestamp": "2021-12-01T05:44:14.523736Z", "spotlight": false, "max_connections": 4, "total_connections": 4, "external_signaling_url": "wss://node-01.example.com/signaling", "recording": { "recording_id": "WHEJ888HQ55KDCFE3TZ4VPFQHR", "recording_metadata": {"spam": "egg"}, "expire_time": 3600, "expired_at": 1615527737, "split_duration": 3600, "split_only": false, "start_timestamp": "2021-03-12T04:42:17.455668Z", "format": "mp4" } } ``` ## ListSessions **x-sora-target**: Sora_20231220.ListSessions Sora の全てのセッションを表示する API です。 * - キー - 型 * - group_id (オプション) - string `group_id` を指定すると、セッションウェブフック [session.created](SESSION_WEBHOOK.html#1d1984) で払い出した `group_id` に一致するセッションのみを表示します。 - 録画機能 (セッション単位) が有効な場合は `"recording"` 項目が追加されます ```console $ curl -sS \ -X POST \ http://127.0.0.1:3000/ \ -H "x-sora-target: Sora_20231220.ListSessions" \ | jq . [ { "label": "WebRTC SFU Sora", "node_name": "sora@127.0.0.1", "version": "2023.2.0", "channel_id": "sora", "group_id": "JJJ5BFH7QN6DQBTKSS7JA8ZYQR", "session_id": "JJJ5BFH7QN6DQBTKSS7JA8ZYQR", "session_metadata": {"spam": "egg"}, "created_time": 1638337454, "created_timestamp": "2021-12-01T05:44:14.523736Z", "spotlight": false, "max_connections": 4, "total_connections": 4, "connections": [ { "audio": true, "audio_codec_type": "OPUS", "client_id": "W9QE86Z0BS1QFFPZ2QB5DRZ2HC", "bundle_id": "W9QE86Z0BS1QFFPZ2QB5DRZ2HC", "connection_id": "W9QE86Z0BS1QFFPZ2QB5DRZ2HC", "connection_created_timestamp": "2021-12-01T05:44:23.051704Z", "connection_destroyed_timestamp": "2021-12-01T05:44:56.878019Z", "role": "sendrecv", "simulcast": false, "video": true, "video_bit_rate": 1000, "video_codec_type": "VP9", "video_vp9_params": { "profile_id": 0 } }, { "audio": true, "audio_codec_type": "OPUS", "client_id": "JXMYW6GPX54EH0HGA5X4130FBM", "bundle_id": "JXMYW6GPX54EH0HGA5X4130FBM", "connection_id": "JXMYW6GPX54EH0HGA5X4130FBM", "connection_created_timestamp": "2021-12-01T05:44:23.051704Z", "connection_destroyed_timestamp": "2021-12-01T05:44:56.878019Z", "role": "sendrecv", "simulcast": false, "video": true, "video_bit_rate": 1000, "video_codec_type": "VP9", "video_vp9_params": { "profile_id": 0 } }, { "audio": true, "audio_codec_type": "OPUS", "client_id": "F8VK9R71BN5S5EDE737C8XAA3C", "bundle_id": "F8VK9R71BN5S5EDE737C8XAA3C", "connection_id": "F8VK9R71BN5S5EDE737C8XAA3C", "connection_created_timestamp": "2021-12-01T05:44:23.051704Z", "connection_destroyed_timestamp": "2021-12-01T05:44:56.878019Z", "role": "sendrecv", "simulcast": false, "video": true, "video_bit_rate": 1000, "video_codec_type": "VP9", "video_vp9_params": { "profile_id": 0 } } ] }, { "label": "WebRTC SFU Sora", "node_name": "sora@127.0.0.1", "version": "2023.2.0", "channel_id": "sora", "group_id": "JJJ5BFH7QN6DQBTKSS7JA8ZYQR", "session_id": "JJJ5BFH7QN6DQBTKSS7JA8ZYQR", "session_metadata": {"spam": "egg"}, "created_time": 1638337454, "created_timestamp": "2021-12-01T05:44:14.523736Z", "spotlight": false, "max_connections": 4, "total_connections": 4, "connections": [ { "audio": true, "audio_codec_type": "OPUS", "client_id": "W9QE86Z0BS1QFFPZ2QB5DRZ2HC", "bundle_id": "W9QE86Z0BS1QFFPZ2QB5DRZ2HC", "connection_id": "W9QE86Z0BS1QFFPZ2QB5DRZ2HC", "connection_created_timestamp": "2021-12-01T05:44:23.051704Z", "connection_destroyed_timestamp": "2021-12-01T05:44:56.878019Z", "role": "sendrecv", "simulcast": false, "video": true, "video_bit_rate": 1000, "video_codec_type": "VP9", "video_vp9_params": { "profile_id": 0 } }, { "audio": true, "audio_codec_type": "OPUS", "client_id": "JXMYW6GPX54EH0HGA5X4130FBM", "bundle_id": "JXMYW6GPX54EH0HGA5X4130FBM", "connection_id": "JXMYW6GPX54EH0HGA5X4130FBM", "connection_created_timestamp": "2021-12-01T05:44:23.051704Z", "connection_destroyed_timestamp": "2021-12-01T05:44:56.878019Z", "role": "sendrecv", "simulcast": false, "video": true, "video_bit_rate": 1000, "video_codec_type": "VP9", "video_vp9_params": { "profile_id": 0 } } ], "recording": { "recording_id": "WHEJ888HQ55KDCFE3TZ4VPFQHR", "recording_metadata": {"spam": "egg"}, "expire_time": 3600, "expired_at": 1615527737, "split_duration": 3600, "split_only": false, "start_timestamp": "2021-03-12T04:42:17.455668Z", "format": "webm" } } ] ``` ### クラスターが有効な場合 `connections` 項目が含まれなくなります。 ```javascript [ { "label": "WebRTC SFU Sora", "node_name": "sora@127.0.0.1", "version": "2023.2.0", "channel_id": "sora", "group_id": "JJJ5BFH7QN6DQBTKSS7JA8ZYQR", "session_id": "JJJ5BFH7QN6DQBTKSS7JA8ZYQR", "session_metadata": {"spam": "egg"}, "created_time": 1638337454, "created_timestamp": "2021-12-01T05:44:14.523736Z", "spotlight": false, "max_connections": 4, "total_connections": 4, "external_signaling_url": "wss://node-01.example.com/signaling" }, { "label": "WebRTC SFU Sora", "node_name": "sora@127.0.0.1", "version": "2023.2.0", "channel_id": "sora", "group_id": "JJJ5BFH7QN6DQBTKSS7JA8ZYQR", "session_id": "JJJ5BFH7QN6DQBTKSS7JA8ZYQR", "session_metadata": {"spam": "egg"}, "created_time": 1638337454, "created_timestamp": "2021-12-01T05:44:14.523736Z", "spotlight": false, "max_connections": 4, "total_connections": 4, "external_signaling_url": "wss://node-01.example.com/signaling", "recording": { "recording_id": "WHEJ888HQ55KDCFE3TZ4VPFQHR", "recording_metadata": {"spam": "egg"}, "expire_time": 3600, "expired_at": 1615527737, "split_duration": 3600, "split_only": false, "start_timestamp": "2021-03-12T04:42:17.455668Z", "format": "webm" } } ] ``` # サイマルキャスト API ## RequestSimulcastRid **x-sora-target**: Sora_20251217.RequestSimulcastRid 指定した視聴者が受信するストリームの `rid` をリクエストします。 * - キー - 型 * - channel_id - string * - receiver_connection_id - string * - sender_connection_id (オプション) - string * - rid - string (none | r0 | r1 | r2) - `r1` までしか配信されていない場合、 `r2` をリクエストすると `r1` を受信し始めます - `none` をリクエストすると映像ストリームが配信されなくなります ```console $ curl -sS \ -X POST \ http://127.0.0.1:3000/ \ -H "x-sora-target: Sora_20251217.RequestSimulcastRid" \ --json '{"channel_id":"sora","receiver_connection_id":"4EVK3MN5Z17GB62RE5TGD045ZM","sender_connection_id":"EKNQ103WRD4ZZ74B6TKRM9YK78","rid":"r1"}' \ | jq . { "channel_id": "sora", "receiver_connection_id": "4EVK3MN5Z17GB62RE5TGD045ZM", "rid": "r1", "sender_connection_id": "EKNQ103WRD4ZZ74B6TKRM9YK78" } ``` # スポットライト API ## FocusSpotlightFixed **x-sora-target**: Sora_20200807.FocusSpotlightFixed 指定した Connection ID のクライアントに常にフォーカスが当たるようにします。 UnfocusSpotlight API が呼ばれるまでフォーカスが当たり続けます。 * - キー - 型 * - channel_id - string * - connection_id - string ``` $ curl -sS \ -X POST \ http://127.0.0.1:3000/ \ -H "x-sora-target: Sora_20200807.FocusSpotlightFixed" \ --json '{"channel_id":"sora","connection_id":"7QSNT842FS0J9E6BZDBC2DRYY8"}' \ | jq . { "channel_id": "sora", "connection_id": "7QSNT842FS0J9E6BZDBC2DRYY8" } ``` ## FocusSpotlight **x-sora-target**: Sora_20200807.FocusSpotlight 指定した Connection ID のクライアントに強制的にフォーカスを当てます。 * - キー - 型 * - channel_id - string * - connection_id - string ``` $ curl -sS \ -X POST \ http://127.0.0.1:3000/ \ -H "x-sora-target: Sora_20200807.FocusSpotlight" \ --json '{"channel_id":"sora","connection_id":"74Z2G1JS7S67DE226T8R1H3YGW"}' \ | jq . { "channel_id": "sora", "connection_id": "74Z2G1JS7S67DE226T8R1H3YGW" } ``` ## UnfocusSpotlight **x-sora-target**: Sora_20200807.UnfocusSpotlight 指定した Connection ID のフォーカスを外します。 この API は FocusSpotlightFixed でフォーカスを当て続けている状態を解除する場合にも利用します。 * - キー - 型 * - channel_id - string * - connection_id - string ``` $ curl -sS \ -X POST \ http://127.0.0.1:3000/ \ -H "x-sora-target: Sora_20200807.UnfocusSpotlight" \ --json '{"channel_id":"sora","connection_id":"74Z2G1JS7S67DE226T8R1H3YGW"}' \ | jq . { "channel_id": "sora", "connection_id": "74Z2G1JS7S67DE226T8R1H3YGW" } ``` ## ChangeSpotlightNumber **x-sora-target**: Sora_20200807.ChangeSpotlightNumber フォーカスする最大数を変更します。最小は 1 で最大は 8 です。 この API でフォーカス最大数を変更した後に、 `type:connect` で `spotlight_number` を指定するクライアントは、 **変更後の値** を指定する必要があります。 * - キー - 型 * - channel_id - string * - spotlight_number - integer (1..8) ``` $ curl -sS \ -X POST \ http://127.0.0.1:3000/ \ -H "x-sora-target: Sora_20200807.ChangeSpotlightNumber" \ --json '{"channel_id":"sora","spotlight_number":1}' \ | jq . { "channel_id": "sora", "spotlight_number": 1 } ``` ## RequestSpotlightRid **x-sora-target**: Sora_20211215.RequestSpotlightRid スポットライトのフォーカス時とアンフォーカス時の rid を指定します。 これにより接続時に指定した `spotlight_focus_rid` と `spotlight_unfocus_rid` の値を変更できます。 * - キー - 型 * - channel_id - string * - recv_connection_id - string * - send_connection_id (オプション) - string * - spotlight_focus_rid - string (none | r0 | r1 | r2) * - spotlight_unfocus_rid - string (none | r0 | r1 | r2) ``` $ curl -sS \ -X POST \ http://127.0.0.1:3000/ \ -H "x-sora-target: Sora_20211215.RequestSpotlightRid" \ --json '{"channel_id":"sora","recv_connection_id":"AD0ZWY8W492XV9RQGB40GX5C94","spotlight_focus_rid":"none","spotlight_unfocus_rid":"none"}' \ | jq . { "channel_id": "sora", "recv_connection_id": "AD0ZWY8W492XV9RQGB40GX5C94", "spotlight_focus_rid": "none", "spotlight_unfocus_rid": "none" } ``` ## ResetSpotlightRid **x-sora-target**: Sora_20211215.ResetSpotlightRid スポットライトのフォーカス時とアンフォーカス時の rid を接続時に指定した値に戻します。 * - キー - 型 * - channel_id - string * - recv_connection_id - string * - send_connection_id (オプション) - string ``` $ curl -sS \ -X POST \ http://127.0.0.1:3000/ \ -H "x-sora-target: Sora_20211215.ResetSpotlightRid" \ --json '{"channel_id":"sora","recv_connection_id":"AD0ZWY8W492XV9RQGB40GX5C94"}' \ | jq . { "channel_id": "sora", "recv_connection_id": "AD0ZWY8W492XV9RQGB40GX5C94" } ``` ## BatchRequestSpotlightRid **x-sora-target**: Sora_20211215.BatchRequestSpotlightRid スポットライトのフォーカス時とアンフォーカス時の rid を一括で変更します。 * - キー - 型 * - channel_id - string * - item_list - array item_list には以下が含まれます。 * - キー - 型 * - recv_connection_id - string * - send_connection_id - string * - spotlight_focus_rid - string (none | r0 | r1 | r2) * - spotlight_unfocus_rid - string (none | r0 | r1 | r2) ``` $ curl -sS \ -X POST \ http://127.0.0.1:3000/ \ -H "x-sora-target: Sora_20211215.BatchRequestSpotlightRid" \ --json '{"channel_id":"sora","item_list":[{"recv_connection_id":"AD0ZWY8W492XV9RQGB40GX5C94","send_connection_id":"RGEFFZM95S2XN0PC03XNMCRTB0","spotlight_focus_rid":"none","spotlight_unfocus_rid":"none"},{"recv_connection_id":"AD0ZWY8W492XV9RQGB40GX5C94","send_connection_id":"P9AFYE2BQN7JB93Q6GK0VYWGHM","spotlight_focus_rid":"none","spotlight_unfocus_rid":"none"}]}' \ | jq . { "channel_id": "sora", "item_list": [ { "recv_connection_id": "AD0ZWY8W492XV9RQGB40GX5C94", "result": "ok", "send_connection_id": "RGEFFZM95S2XN0PC03XNMCRTB0", "spotlight_focus_rid": "none", "spotlight_unfocus_rid": "none" }, { "recv_connection_id": "AD0ZWY8W492XV9RQGB40GX5C94", "result": "ok", "send_connection_id": "P9AFYE2BQN7JB93Q6GK0VYWGHM", "spotlight_focus_rid": "none", "spotlight_unfocus_rid": "none" } ] } ``` # プッシュ API シグナリングで使用している WebSocket や DataChannel を活用できる API です。 この機能を使うことでアプリケーション側でプッシュの仕組みを用意する必要がなくなります。 ## PushChannel *バージョン 2.6.0 で追加。* **x-sora-target**: Sora_20160711.PushChannel 指定したチャネル全員にプッシュ通知を送ります。 * - キー - 型 * - channel_id - string * - data - object data には全員に通知する値 (JSON object) を指定してください。 クライアントには data に指定した値 (JSON object) が送られます。 ```console $ curl -sS \ -X POST \ http://127.0.0.1:3000/ \ -H "x-sora-target: Sora_20160711.PushChannel" \ --json '{"channel_id":"sora","data":{"spam":"egg"}}' \ | jq . { "data": { "spam": "egg" }, "type": "push" } ``` ## PushClient *バージョン 2.6.0 で追加。* **x-sora-target**: Sora_20160711.PushClient 指定したチャネルのクライアントにプッシュ通知を送ります。 * - キー - 型 * - channel_id - string * - client_id - string * - data - object 複数の接続に同一の `client_id` が指定されていた場合、複数の接続にプッシュ通知が送られます。 ```console $ curl -sS \ -X POST \ http://127.0.0.1:3000/ \ -H "x-sora-target: Sora_20160711.PushClient" \ --json '{"channel_id":"sora","client_id":"C0YTCRZM715BKATBXWFPKTYGRM","data":{"spam":"egg"}}' \ | jq . { "data": { "spam": "egg" }, "type": "push" } ``` ## PushConnection *バージョン 2.6.0 で追加。* **x-sora-target**: Sora_20160711.PushConnection 指定したチャネルの接続にプッシュ通知を送ります。 * - キー - 型 * - channel_id - string * - connection_id - string * - data - object ```console $ curl -sS \ -X POST \ http://127.0.0.1:3000/ \ -H "x-sora-target: Sora_20160711.PushConnection" \ --json '{"channel_id":"sora","connection_id":"C0YTCRZM715BKATBXWFPKTYGRM","data":{"spam":"egg"}}' \ | jq . { "data": { "spam": "egg" }, "type": "push" } ``` ## PushChannelByRole *バージョン 2020.3 で追加。* **x-sora-target**: Sora_20201120.PushChannelByRole 指定したチャネルの指定したロールにプッシュ通知を送ります。 * - キー - 型 * - channel_id - string * - role - string (sendrecv | sendonly | recvonly) * - data - object ```console $ curl -sS \ -X POST \ http://127.0.0.1:3000/ \ -H "x-sora-target: Sora_20201120.PushChannelByRole" \ --json '{"channel_id":"sora","role":"sendrecv","data":{"spam":"egg"}}' \ | jq . { "data": { "spam": "egg" }, "type": "push" } ``` # 録画 (セッション単位) API 録画されたファイルは `sora.conf` の [archive_dir](SORA_CONF.html#ad2156) に指定したディレクトリに置かれます。 ## StartRecording *バージョン 2023.2.0 で追加。* **x-sora-target**: Sora_20231220.StartRecording 指定したチャネルの録画を開始します。 クラスター機能利用時には、クラスター内のどのノードで実行しても開始された録画情報はすべてのノードで共有されます。 * - キー - 型 * - channel_id - string * - expire_time (オプション) - integer * - split_duration (オプション) - integer * - split_only (オプション) - boolean * - metadata (オプション) - JSONValue * - format (オプション) - string - `expire_time` を指定しない場合は未指定になります- `expire_time` を指定しない場合、録画の期限が無くなります - `expire_time` を指定する範囲は `1` から `86400` までで、秒数を指定してください- 指定できる最大値はデフォルトで `86400` で [recording_max_expire_time](SORA_CONF.html#f3ff8d) に指定した値で変わります - `split_only` は `true` か `false` を指定してください。指定しない場合は `false` が指定されます - `split_only` を `true` に指定する場合は `split_duration` を指定する必要があります - `split_duration` を指定する範囲は `1` から `86400` までで、秒数を指定してください- 指定できる最大値はデフォルトで `86400` で、 [recording_max_split_duration](SORA_CONF.html#927da9) に指定した値で変わります - `metadata` は `recording.report` ウェブフックやレポートファイルに `recording_metadata` として含まれるようになります。 - `format` は `webm` または `mp4` を指定してください- `format` が未指定の場合は [default_recording_format](SORA_CONF.html#f9fa7d) の値が利用されます - 映像コーデックが H.265 の場合 `format` に `mp4` を指定しない場合、録画が行われません ### 一括録画を行いたい場合 - `split_only` を `false` に指定するか、未指定にしてください ### 分割録画を行いたい場合 - `split_only` を `true` に指定してください - `split_duration` を指定してください ### 一括&分割録画を行いたい場合 - `sora.conf` の [recording_dual_output](SORA_CONF.html#4cc9c0) を `true` に指定してください - `split_only` を `false` に指定するか、未指定にしてください - `split_duration` を指定してください ### expire_time が指定無し ```console $ curl -sS \ -X POST \ http://127.0.0.1:3000/ \ -H "x-sora-target: Sora_20231220.StartRecording" \ --json '{"channel_id":"sora"}' \ | jq . { "channel_id": "sora", "expire_time": 0, "session_id": "96D7CQDEMS5CHCKDX46REWWTX4", "recording_id": "C0YTCRZM715BKATBXWFPKTYGRM" } ``` ### expire_time が 3600 ```console $ curl -sS \ -X POST \ http://127.0.0.1:3000/ \ -H "x-sora-target: Sora_20231220.StartRecording" \ --json '{"channel_id":"sora","expire_time":3600}' \ | jq . { "channel_id": "sora", "expire_time": 3600, "session_id": "96D7CQDEMS5CHCKDX46REWWTX4", "recording_id": "C0YTCRZM715BKATBXWFPKTYGRM" } ``` ### split_only が true ```console $ curl -sS \ -X POST \ http://127.0.0.1:3000/ \ -H "x-sora-target: Sora_20231220.StartRecording" \ --json '{"channel_id":"sora","split_duration":3600,"split_only":true}' \ | jq . { "channel_id": "sora", "expire_time": 0, "session_id": "96D7CQDEMS5CHCKDX46REWWTX4", "recording_id": "MK4J54QBGS4ES0MCSZMF6C9M9M", "split_duration": 3600, "split_only": true } ``` ### エラー - "STARTED-RECORDING"- 指定したチャネル ID で、すでに録画が開始している - "NOT-CLUSTER-MAJORITY"- クラスターで半数以下のグループに所属している ```console $ curl -sS \ -X POST \ http://127.0.0.1:3000/ \ -H "x-sora-target: Sora_20231220.StartRecording" \ --json '{"channel_id":"sora","expire_time":3600}' \ | jq . { "error_type": "STARTED-RECORDING" } ``` ## StopRecording *バージョン 2023.2.0 で追加。* **x-sora-target**: Sora_20231220.StopRecording 指定したチャネルの録画を停止します。 この API は非同期です。200 が返ってきた場合でも録画ファイルや録画メタデータファイルが生成されていることを保証しません。 イベントウェブフックの [archive.available](EVENT_WEBHOOK.html#de9132) または [recording.report](SESSION_WEBHOOK.html#920a02) の通知を利用してください。 * - キー - 型 * - channel_id - string ```console $ curl -sS \ -X POST \ http://127.0.0.1:3000/ \ -H "x-sora-target: Sora_20231220.StopRecording" \ --json '{"channel_id":"sora"}' \ | jq . { "channel_id": "sora", "session_id": "96D7CQDEMS5CHCKDX46REWWTX4", "recording_id": "C0YTCRZM715BKATBXWFPKTYGRM" } ``` ### エラー - "NOT-STARTED-RECORDING"- 指定したチャネルの録画が開始されていない - "NOT-CLUSTER-MAJORITY"- クラスターで半数以下のグループに所属している # 統計 API ## 統計項目一覧 **説明が書いていないものは項目名そのままの内容になります** - timestamp- API を取得した時点の UTC 時間 RFC3339 形式 (マイクロ秒) - channel_id - group_id - session_id - client_id - bundle_id - connection_id - simulcast- r0- rtp- total_decrypt_skipped_srtp - total_received_rtp - total_received_rtp_byte_size - total_received_rtp_padding - total_received_rtp_padding_size - total_received_rtp_red - total_received_rtp_red_rtx - total_received_rtp_red_ulpfec - total_received_rtp_rtx - rtp_hdrext- total_received_rtp_hdrext_abs_send_time - total_received_rtp_hdrext_audio_level - total_received_rtp_hdrext_av1_rtp_sepc - total_received_rtp_hdrext_color_space - total_received_rtp_hdrext_inband_cn - total_received_rtp_hdrext_playout_delay - total_received_rtp_hdrext_sdes_mid - total_received_rtp_hdrext_sdes_repaired_rtp_stream_id - total_received_rtp_hdrext_sdes_rtp_stream_id - total_received_rtp_hdrext_toffset - total_received_rtp_hdrext_transport_wide_cc - total_received_rtp_hdrext_unknown - total_received_rtp_hdrext_video_content_type - total_received_rtp_hdrext_video_orientation - total_received_rtp_hdrext_video_timing - total_received_rtp_hdrext_video_composition_time - r1- r0 と同様 - r2- r0 と同様 - simulcast_auto- target_sender_count - total_switched - total_up_trend - total_history_not_ready - spotlight- total_spotlight_audible_to_focus_delay_us- 発話開始からフォーカス取得までの累積遅延 (マイクロ秒単位) - total_spotlight_focus_failed - total_spotlight_focus_succeeded - total_spotlight_unfocus_audio_no_room - total_spotlight_unfocus_audio_out_packet - total_spotlight_unfocus_audio_publish - dtls- total_received_dtls- 受信した DTLS パケットの総数 - total_sent_dtls- 送信した DTLS パケットの総数 - ice_connection_state- total_connected_req- `connected` 状態での疎通確認用のリクエスト送信回数 - total_connected_ack- `connected` 状態での疎通確認用の応答受信回数 - total_checking_req- `checking` 状態での疎通確認用のリクエスト送信回数 - total_checking_ack- `checking` 状態での疎通確認用の応答受信回数 - total_disconnected_req- `disconnected` 状態での疎通確認用のリクエスト送信回数 - total_disconnected_ack- `disconnected` 状態での疎通確認用の応答受信回数 - total_connected_to_checking- `connected` 状態から `checking` 状態へ遷移した回数 - total_checking_to_disconnected- `checking` 状態から `disconnected` 状態へ遷移した回数 - total_disconnected_to_failed- `disconnected` 状態から `failed` 状態へ遷移した回数 - total_checking_to_connected- `checking` 状態から `connected` 状態へ遷移した回数 - total_disconnected_to_checking- `disconnected` 状態から `checking` 状態へ遷移した回数 - total_checking_duration_ms- `checking` 状態であった時間の合計 - total_disconnected_duration_ms- `disconnected` 状態であった時間の合計 - signaling- total_received_signaling_pong - total_sent_signaling_ping - media_publish_worker- peak_count- その接続でこれまでに同時に起動した配信ワーカー数の最大値 - total_started- その接続でこれまでに起動した配信ワーカーの総数 - total_stopped- その接続でこれまでに停止した配信ワーカーの総数 - total_unknown_subscriber- 配信ワーカーとの対応が存在しないサブスクライバー (受信側接続) の数 - packet_loss_simulator- total_dropped_received_rtp- 受信したがパケロスシミュレータが落とした RTP パケットの総数 - total_dropped_sent_rtp- 送信したがパケロスシミュレータが落とした RTP パケットの総数 - total_dropped_received_data_channel- 受信したがパケロスシミュレータが落とした DataChannel パケットの総数 - total_dropped_sent_data_channel- 送信したがパケロスシミュレータが落とした DataChannel パケットの総数 - rtp- total_received - total_received_byte_size - total_received_rtp - total_received_rtp_byte_size - total_received_rtp_red - total_received_rtp_red_rtx - total_received_rtp_red_ulpfec - total_received_rtp_rtx - total_received_sounding_rtp - total_sent - total_sent_byte_size - total_sent_rtp - total_sent_rtp_byte_size- SFU 遅延を含む RTP パケットの総数 - total_sent_rtp_sfu_delay_us- Sora 内部で発生した遅延の累積値 (マイクロ秒単位) - total_decrypt_skipped_srtp- 復号をスキップした SRTP 総数 - total_decrypt_skipped_video_srtp- 復号をスキップした映像 SRTP 総数 - total_decrypt_skipped_audio_srtp- 復号をスキップした音声 SRTP 総数 - total_received_srtp_invalid - total_received_rtp_padding - total_received_rtp_padding_size - total_received_rtp_payload_invalid - total_received_key_frame- キーフレームを受信した総数 - total_ulpfec_recovered- ULPFEC を利用して損失パケットを回復した総数 - rtp_hdrext- total_received_rtp_hdrext_abs_capture_time - total_received_rtp_hdrext_abs_send_time - total_received_rtp_hdrext_audio_level - total_received_rtp_hdrext_av1_rtp_sepc - total_received_rtp_hdrext_color_space - total_received_rtp_hdrext_inband_cn - total_received_rtp_hdrext_playout_delay - total_received_rtp_hdrext_sdes_mid - total_received_rtp_hdrext_sdes_repaired_rtp_stream_id - total_received_rtp_hdrext_sdes_rtp_stream_id - total_received_rtp_hdrext_toffset - total_received_rtp_hdrext_transport_wide_cc - total_received_rtp_hdrext_unknown - total_received_rtp_hdrext_video_content_type - total_received_rtp_hdrext_video_orientation - total_received_rtp_hdrext_video_timing - total_received_rtp_hdrext_abs_capture_time - total_received_rtp_hdrext_video_composition_time - total_sent_rtp_hdrext_abs_capture_time - total_sent_rtp_hdrext_abs_send_time - total_sent_rtp_hdrext_audio_level - total_sent_rtp_hdrext_av1_rtp_sepc - total_sent_rtp_hdrext_color_space - total_sent_rtp_hdrext_inband_cn - total_sent_rtp_hdrext_playout_delay - total_sent_rtp_hdrext_sdes_mid - total_sent_rtp_hdrext_sdes_repaired_rtp_stream_id - total_sent_rtp_hdrext_sdes_rtp_stream_id - total_sent_rtp_hdrext_toffset - total_sent_rtp_hdrext_transport_wide_cc - total_sent_rtp_hdrext_unknown - total_sent_rtp_hdrext_video_content_type - total_sent_rtp_hdrext_video_orientation - total_sent_rtp_hdrext_video_timing - total_sent_rtp_hdrext_abs_capture_time - total_sent_rtp_hdrext_video_composition_time - rtcp- total_generic_nack_cache_hit- 再送要求に答えた総数 - total_generic_nack_cache_miss- 再送要求に答えられなかった総数 - total_pli_trigger- 再送要求が限界に来たため全画面要求(PLI) を送信した総数 - total_received_rtcp - total_received_rtcp_bye - total_received_rtcp_byte_size - total_received_rtcp_psfb_afb - total_received_rtcp_psfb_fir - total_received_rtcp_psfb_pli - total_received_rtcp_rr - total_received_rtcp_rtpfb_generic_nack - total_received_rtcp_rtpfb_tmmbn - total_received_rtcp_rtpfb_tmmbr - total_received_rtcp_rtpfb_transport_wide - total_received_rtcp_sdes - total_received_rtcp_sr - total_received_rtcp_unknown - total_received_rtcp_xr - total_sent_rtcp - total_sent_rtcp_bye - total_sent_rtcp_byte_size - total_sent_rtcp_psfb_afb - total_sent_rtcp_psfb_fir - total_sent_rtcp_psfb_pli - total_sent_rtcp_rr - total_sent_rtcp_rtpfb_generic_nack - total_sent_rtcp_rtpfb_tmmbn - total_sent_rtcp_rtpfb_tmmbr - total_sent_rtcp_rtpfb_transport_wide - total_sent_rtcp_sdes - total_sent_rtcp_sr - total_sent_rtcp_unknown - total_sent_rtcp_xr - turn- total_received_allocate_request - total_received_binding_request - total_received_channel_bind_request - total_received_channel_data - total_received_create_permission_request - total_received_expired_channel_number - total_received_invalid_channel_data - total_received_refresh_request - total_received_send_indication - total_received_stun_invalid - total_received_stun_unknown - total_received_turn_binding_error - total_received_turn_binding_request - total_received_turn_binding_success - total_received_turn_invalid_stun - total_received_turn_unknown - total_received_turn_unknown_stun - total_received_unknown_channel_number - total_received_unknown_packet - total_sent_allocate_error - total_sent_allocate_success - total_sent_binding_error - total_sent_binding_success - total_sent_channel_bind_error - total_sent_channel_bind_success - total_sent_channel_data - total_sent_create_permission_error - total_sent_create_permission_success - total_sent_data_indication - total_sent_refresh_error - total_sent_refresh_success - total_sent_turn_binding_error - total_sent_turn_binding_request - total_sent_turn_binding_success - total_sent_turn_unknown - data_channel- signaling- ordered - max_packet_life_time - max_retransmits - protocol - direction - compress - total_data_channel_abandon_message - total_data_channel_retransmit_message - total_data_channel_open_message - total_data_channel_ack_message - total_received_data_channel_message - total_received_data_channel_message_byte_size - total_sent_data_channel_message - total_sent_data_channel_message_byte_size - notify- signaling と同様 - push- signaling と同様 - stats- signaling と同様 - # から始まるメッセージング用ラベル- signaling と同様 - sctp- total_received_sctp_zero_checksum- SCTP チェックサムを 0 で受信した総数 - total_sent_sctp_zero_checksum- SCTP チェックサムを 0 で送信した総数 - total_received_invalid_sctp - total_received_sctp - total_received_sctp_byte_size - total_received_sctp_chunk_abort - total_received_sctp_chunk_asconf - total_received_sctp_chunk_asconf_ack - total_received_sctp_chunk_auth - total_received_sctp_chunk_cookie_ack - total_received_sctp_chunk_cookie_echo - total_received_sctp_chunk_cwr - total_received_sctp_chunk_data - total_received_sctp_chunk_ecne - total_received_sctp_chunk_error - total_received_sctp_chunk_forward_tsn - total_received_sctp_chunk_heartbeat - total_received_sctp_chunk_heartbeat_ack - total_received_sctp_chunk_i_data - total_received_sctp_chunk_i_forward_tsn - total_received_sctp_chunk_init - total_received_sctp_chunk_init_ack - total_received_sctp_chunk_pad - total_received_sctp_chunk_reconfig - total_received_sctp_chunk_sack - total_received_sctp_chunk_shutdown - total_received_sctp_chunk_shutdown_ack - total_received_sctp_chunk_shutdown_complete - total_received_sctp_chunk_unknown - total_received_unknown_sctp - total_sent_sctp - total_sent_sctp_byte_size - total_sent_sctp_chunk_abort - total_sent_sctp_chunk_asconf - total_sent_sctp_chunk_asconf_ack - total_sent_sctp_chunk_auth - total_sent_sctp_chunk_cookie_ack - total_sent_sctp_chunk_cookie_echo - total_sent_sctp_chunk_cwr - total_sent_sctp_chunk_data - total_sent_sctp_chunk_ecne - total_sent_sctp_chunk_error - total_sent_sctp_chunk_forward_tsn - total_sent_sctp_chunk_heartbeat - total_sent_sctp_chunk_heartbeat_ack - total_sent_sctp_chunk_i_data - total_sent_sctp_chunk_i_forward_tsn - total_sent_sctp_chunk_init - total_sent_sctp_chunk_init_ack - total_sent_sctp_chunk_pad - total_sent_sctp_chunk_reconfig - total_sent_sctp_chunk_sack - total_sent_sctp_chunk_shutdown - total_sent_sctp_chunk_shutdown_ack - total_sent_sctp_chunk_shutdown_complete - total_sent_sctp_chunk_unknown - total_enqueued_sent_chunk- SCTP 送信用キュー (sent_queue) に追加されたチャンク数 - total_dequeued_sent_chunk- SCTP 送信用キュー (sent_queue) から取り出されたチャンク数 - total_enqueued_outbound_chunk- SCTP 送信待ちキュー (outbound_queue) に追加されたチャンク数 - total_dequeued_outbound_chunk- SCTP 送信待ちキュー (outbound_queue) から取り出されたチャンク数 - total_increased_flight_size- SCTP フライトサイズの増加量の合計値 (バイト単位) - total_decreased_flight_size- SCTP フライトサイズの減少量の合計値 (バイト単位) - total_expired_t3_timer- SCTP T3 タイマーの満了回数 - cc- bwe_period - congestion_window - delay_based_estimated_bitrate - pacer_data_window - pacer_padding_window - round_trip_time - stable_target_bitrate - target_bitrate ## GetStatsConnection **x-sora-target**: Sora_20170529.GetStatsConnection 指定した接続の統計情報を取得します。 * - キー - 型 * - channel_id - string * - connection_id - string ```console $ curl -sS \ -X POST \ http://127.0.0.1:3000/ \ -H "x-sora-target: Sora_20170529.GetStatsConnection" \ --json '{"channel_id":"sora","connection_id":"KDBN2YD1A919V5BA2JX6TG2RP8"}' \ | jq . { "channel_id": "sora", "group_id": "FDYSGDVQ592CK5D4ZMC0W4XXDM", "session_id": "FDYSGDVQ592CK5D4ZMC0W4XXDM", "client_id": "KP8VZZ321D0A90RSVJC4RMGJ08", "bundle_id": "KP8VZZ321D0A90RSVJC4RMGJ08", "connection_id": "KP8VZZ321D0A90RSVJC4RMGJ08", "cc": { "bwe_period": 0, "congestion_window": 0, "delay_based_estimated_bitrate": 0, "pacer_data_window": 0, "pacer_padding_window": 0, "round_trip_time": 0, "stable_target_bitrate": 0, "target_bitrate": 0 }, "data_channel": { "#test": { "compress": false, "direction": "sendrecv", "ordered": true, "protocol": "", "total_data_channel_abandon_message": 0, "total_data_channel_ack_message": 0, "total_data_channel_open_message": 0, "total_data_channel_retransmit_message": 0, "total_received_data_channel_message": 1, "total_received_data_channel_message_byte_size": 1, "total_sent_data_channel_message": 1, "total_sent_data_channel_message_byte_size": 17 }, "notify": { "compress": true, "direction": "recvonly", "ordered": true, "protocol": "", "total_data_channel_abandon_message": 0, "total_data_channel_ack_message": 0, "total_data_channel_open_message": 0, "total_data_channel_retransmit_message": 0, "total_received_data_channel_message": 1, "total_received_data_channel_message_byte_size": 1, "total_sent_data_channel_message": 8, "total_sent_data_channel_message_byte_size": 627 }, "push": { "compress": true, "direction": "recvonly", "ordered": true, "protocol": "", "total_data_channel_abandon_message": 0, "total_data_channel_ack_message": 0, "total_data_channel_open_message": 0, "total_data_channel_retransmit_message": 0, "total_received_data_channel_message": 1, "total_received_data_channel_message_byte_size": 1, "total_sent_data_channel_message": 1, "total_sent_data_channel_message_byte_size": 16 }, "signaling": { "compress": true, "direction": "sendrecv", "ordered": true, "protocol": "", "total_data_channel_abandon_message": 0, "total_data_channel_ack_message": 0, "total_data_channel_open_message": 0, "total_data_channel_retransmit_message": 0, "total_received_data_channel_message": 1, "total_received_data_channel_message_byte_size": 1, "total_sent_data_channel_message": 1, "total_sent_data_channel_message_byte_size": 21 }, "stats": { "compress": true, "direction": "sendrecv", "ordered": true, "protocol": "", "total_data_channel_abandon_message": 0, "total_data_channel_ack_message": 0, "total_data_channel_open_message": 0, "total_data_channel_retransmit_message": 0, "total_received_data_channel_message": 3, "total_received_data_channel_message_byte_size": 30078, "total_sent_data_channel_message": 3, "total_sent_data_channel_message_byte_size": 73 } }, "dtls": { "total_received_dtls": 36, "total_sent_dtls": 37 }, "media_publish_worker": { "peak_count": 0, "total_started": 0, "total_stopped": 0, "total_unknown_subscriber": 0 }, "packet_loss_simulator": { "total_dropped_received_data_channel": 2, "total_dropped_received_rtp": 0, "total_dropped_sent_data_channel": 2, "total_dropped_sent_rtp": 0 }, "rtcp": { "total_generic_nack_cache_hit": 4, "total_generic_nack_cache_miss": 0, "total_pli_trigger": 0, "total_received_rtcp": 375, "total_received_rtcp_bye": 0, "total_received_rtcp_byte_size": 33260, "total_received_rtcp_psfb_afb": 278, "total_received_rtcp_psfb_fir": 0, "total_received_rtcp_psfb_pli": 0, "total_received_rtcp_rr": 73, "total_received_rtcp_rtpfb_generic_nack": 4, "total_received_rtcp_rtpfb_tmmbn": 0, "total_received_rtcp_rtpfb_tmmbr": 0, "total_received_rtcp_rtpfb_transport_wide": 0, "total_received_rtcp_sdes": 298, "total_received_rtcp_sr": 298, "total_received_rtcp_unknown": 0, "total_received_rtcp_xr": 0, "total_sent_rtcp": 184, "total_sent_rtcp_bye": 0, "total_sent_rtcp_byte_size": 14812, "total_sent_rtcp_psfb_afb": 79, "total_sent_rtcp_psfb_fir": 0, "total_sent_rtcp_psfb_pli": 0, "total_sent_rtcp_rr": 91, "total_sent_rtcp_rtpfb_generic_nack": 0, "total_sent_rtcp_rtpfb_tmmbn": 0, "total_sent_rtcp_rtpfb_tmmbr": 0, "total_sent_rtcp_rtpfb_transport_wide": 0, "total_sent_rtcp_sdes": 93, "total_sent_rtcp_sr": 93, "total_sent_rtcp_unknown": 0, "total_sent_rtcp_xr": 0 }, "rtp": { "total_decrypt_skipped_audio_srtp": 717, "total_decrypt_skipped_srtp": 1599, "total_decrypt_skipped_video_srtp": 882, "total_received": 5706, "total_received_byte_size": 1879672, "total_received_rtp": 5331, "total_received_rtp_byte_size": 1846412, "total_received_key_frame": 0, "total_received_rtp_padding": 0, "total_received_rtp_padding_size": 0, "total_received_rtp_payload_invalid": 0, "total_received_rtp_red": 0, "total_received_rtp_red_rtx": 0, "total_received_rtp_red_ulpfec": 0, "total_received_rtp_rtx": 79, "total_received_sounding_rtp": 0, "total_received_srtp_invalid": 0, "total_sent": 5548, "total_sent_byte_size": 2015913, "total_sent_rtp": 5364, "total_sent_rtp_byte_size": 2001101, "total_sent_rtp_sfu_delay_us": 0, "total_ulpfec_recovered": 0 }, "rtp_hdrext": { "total_received_rtp_hdrext_abs_capture_time": 0, "total_received_rtp_hdrext_abs_send_time": 5331, "total_received_rtp_hdrext_audio_level": 3187, "total_received_rtp_hdrext_av1_rtp_sepc": 2144, "total_received_rtp_hdrext_color_space": 0, "total_received_rtp_hdrext_inband_cn": 0, "total_received_rtp_hdrext_playout_delay": 0, "total_received_rtp_hdrext_sdes_mid": 0, "total_received_rtp_hdrext_sdes_repaired_rtp_stream_id": 0, "total_received_rtp_hdrext_sdes_rtp_stream_id": 0, "total_received_rtp_hdrext_toffset": 0, "total_received_rtp_hdrext_transport_wide_cc": 0, "total_received_rtp_hdrext_unknown": 0, "total_received_rtp_hdrext_video_content_type": 0, "total_received_rtp_hdrext_video_orientation": 0, "total_received_rtp_hdrext_video_timing": 0, "total_sent_rtp_hdrext_abs_capture_time": 0, "total_sent_rtp_hdrext_abs_send_time": 0, "total_sent_rtp_hdrext_audio_level": 3188, "total_sent_rtp_hdrext_av1_rtp_sepc": 2176, "total_sent_rtp_hdrext_color_space": 0, "total_sent_rtp_hdrext_inband_cn": 0, "total_sent_rtp_hdrext_playout_delay": 0, "total_sent_rtp_hdrext_sdes_mid": 0, "total_sent_rtp_hdrext_sdes_repaired_rtp_stream_id": 0, "total_sent_rtp_hdrext_sdes_rtp_stream_id": 0, "total_sent_rtp_hdrext_toffset": 0, "total_sent_rtp_hdrext_transport_wide_cc": 0, "total_sent_rtp_hdrext_unknown": 0, "total_sent_rtp_hdrext_video_content_type": 0, "total_sent_rtp_hdrext_video_orientation": 0, "total_sent_rtp_hdrext_video_timing": 0 }, "sctp": { "total_decreased_flight_size": 0, "total_dequeued_outbound_chunk": 0, "total_dequeued_sent_chunk": 0, "total_enqueued_outbound_chunk": 0, "total_enqueued_sent_chunk": 0, "total_expired_t3_timer": 0, "total_increased_flight_size": 0, "total_pruned_sctp_data_chunk": 0, "total_received_invalid_sctp": 0, "total_received_sctp": 32, "total_received_sctp_byte_size": 8244, "total_received_sctp_chunk_abort": 0, "total_received_sctp_chunk_asconf": 0, "total_received_sctp_chunk_asconf_ack": 0, "total_received_sctp_chunk_auth": 0, "total_received_sctp_chunk_cookie_ack": 0, "total_received_sctp_chunk_cookie_echo": 1, "total_received_sctp_chunk_cwr": 0, "total_received_sctp_chunk_data": 14, "total_received_sctp_chunk_ecne": 0, "total_received_sctp_chunk_error": 0, "total_received_sctp_chunk_forward_tsn": 0, "total_received_sctp_chunk_heartbeat": 0, "total_received_sctp_chunk_heartbeat_ack": 2, "total_received_sctp_chunk_i_data": 0, "total_received_sctp_chunk_i_forward_tsn": 0, "total_received_sctp_chunk_init": 1, "total_received_sctp_chunk_init_ack": 0, "total_received_sctp_chunk_pad": 19, "total_received_sctp_chunk_reconfig": 0, "total_received_sctp_chunk_sack": 15, "total_received_sctp_chunk_shutdown": 0, "total_received_sctp_chunk_shutdown_ack": 0, "total_received_sctp_chunk_shutdown_complete": 0, "total_received_sctp_chunk_unknown": 0, "total_received_sctp_zero_checksum": 0, "total_received_unknown_sctp": 0, "total_sent_sctp": 37, "total_sent_sctp_byte_size": 2060, "total_sent_sctp_chunk_abort": 0, "total_sent_sctp_chunk_asconf": 0, "total_sent_sctp_chunk_asconf_ack": 0, "total_sent_sctp_chunk_auth": 0, "total_sent_sctp_chunk_cookie_ack": 1, "total_sent_sctp_chunk_cookie_echo": 0, "total_sent_sctp_chunk_cwr": 0, "total_sent_sctp_chunk_data": 19, "total_sent_sctp_chunk_ecne": 0, "total_sent_sctp_chunk_error": 0, "total_sent_sctp_chunk_forward_tsn": 0, "total_sent_sctp_chunk_heartbeat": 2, "total_sent_sctp_chunk_heartbeat_ack": 0, "total_sent_sctp_chunk_i_data": 0, "total_sent_sctp_chunk_i_forward_tsn": 0, "total_sent_sctp_chunk_init": 0, "total_sent_sctp_chunk_init_ack": 1, "total_sent_sctp_chunk_pad": 0, "total_sent_sctp_chunk_reconfig": 0, "total_sent_sctp_chunk_sack": 14, "total_sent_sctp_chunk_shutdown": 0, "total_sent_sctp_chunk_shutdown_ack": 0, "total_sent_sctp_chunk_shutdown_complete": 0, "total_sent_sctp_chunk_unknown": 0, "total_sent_sctp_zero_checksum": 0 }, "signaling": { "total_received_signaling_pong": 0, "total_sent_signaling_ping": 0 }, "simulcast": { "r0": { "rtp": { "total_decrypt_skipped_srtp": 0, "total_received_rtp": 0, "total_received_rtp_byte_size": 0, "total_received_rtp_padding": 0, "total_received_rtp_padding_size": 0, "total_received_rtp_red": 0, "total_received_rtp_red_rtx": 0, "total_received_rtp_red_ulpfec": 0, "total_received_rtp_rtx": 0 }, "rtp_hdrext": { "total_received_rtp_hdrext_abs_send_time": 0, "total_received_rtp_hdrext_audio_level": 0, "total_received_rtp_hdrext_av1_rtp_sepc": 0, "total_received_rtp_hdrext_color_space": 0, "total_received_rtp_hdrext_inband_cn": 0, "total_received_rtp_hdrext_playout_delay": 0, "total_received_rtp_hdrext_sdes_mid": 0, "total_received_rtp_hdrext_sdes_repaired_rtp_stream_id": 0, "total_received_rtp_hdrext_sdes_rtp_stream_id": 0, "total_received_rtp_hdrext_toffset": 0, "total_received_rtp_hdrext_transport_wide_cc": 0, "total_received_rtp_hdrext_unknown": 0, "total_received_rtp_hdrext_video_content_type": 0, "total_received_rtp_hdrext_video_orientation": 0, "total_received_rtp_hdrext_video_timing": 0 } }, "r1": { "rtp": { "total_decrypt_skipped_srtp": 0, "total_received_rtp": 0, "total_received_rtp_byte_size": 0, "total_received_rtp_padding": 0, "total_received_rtp_padding_size": 0, "total_received_rtp_red": 0, "total_received_rtp_red_rtx": 0, "total_received_rtp_red_ulpfec": 0, "total_received_rtp_rtx": 0 }, "rtp_hdrext": { "total_received_rtp_hdrext_abs_send_time": 0, "total_received_rtp_hdrext_audio_level": 0, "total_received_rtp_hdrext_av1_rtp_sepc": 0, "total_received_rtp_hdrext_color_space": 0, "total_received_rtp_hdrext_inband_cn": 0, "total_received_rtp_hdrext_playout_delay": 0, "total_received_rtp_hdrext_sdes_mid": 0, "total_received_rtp_hdrext_sdes_repaired_rtp_stream_id": 0, "total_received_rtp_hdrext_sdes_rtp_stream_id": 0, "total_received_rtp_hdrext_toffset": 0, "total_received_rtp_hdrext_transport_wide_cc": 0, "total_received_rtp_hdrext_unknown": 0, "total_received_rtp_hdrext_video_content_type": 0, "total_received_rtp_hdrext_video_orientation": 0, "total_received_rtp_hdrext_video_timing": 0 } }, "r2": { "rtp": { "total_decrypt_skipped_srtp": 0, "total_received_rtp": 0, "total_received_rtp_byte_size": 0, "total_received_rtp_padding": 0, "total_received_rtp_padding_size": 0, "total_received_rtp_red": 0, "total_received_rtp_red_rtx": 0, "total_received_rtp_red_ulpfec": 0, "total_received_rtp_rtx": 0 }, "rtp_hdrext": { "total_received_rtp_hdrext_abs_send_time": 0, "total_received_rtp_hdrext_audio_level": 0, "total_received_rtp_hdrext_av1_rtp_sepc": 0, "total_received_rtp_hdrext_color_space": 0, "total_received_rtp_hdrext_inband_cn": 0, "total_received_rtp_hdrext_playout_delay": 0, "total_received_rtp_hdrext_sdes_mid": 0, "total_received_rtp_hdrext_sdes_repaired_rtp_stream_id": 0, "total_received_rtp_hdrext_sdes_rtp_stream_id": 0, "total_received_rtp_hdrext_toffset": 0, "total_received_rtp_hdrext_transport_wide_cc": 0, "total_received_rtp_hdrext_unknown": 0, "total_received_rtp_hdrext_video_content_type": 0, "total_received_rtp_hdrext_video_orientation": 0, "total_received_rtp_hdrext_video_timing": 0 } } }, "simulcast_auto": { "target_sender_count": 0, "total_history_not_ready": 0, "total_switched": 0, "total_up_trend": 0 }, "spotlight": { "total_spotlight_audible_to_focus_delay_us": 0, "total_spotlight_focus_failed": 0, "total_spotlight_focus_succeeded": 0, "total_spotlight_unfocus_audio_no_room": 0, "total_spotlight_unfocus_audio_out_packet": 0, "total_spotlight_unfocus_audio_publish": 0 }, "ice_connection_state": { "total_checking_ack": 1, "total_checking_duration_ms": 7, "total_checking_req": 1, "total_checking_to_connected": 1, "total_checking_to_disconnected": 0, "total_connected_ack": 12, "total_connected_req": 12, "total_connected_to_checking": 0, "total_disconnected_ack": 0, "total_disconnected_duration_ms": 0, "total_disconnected_req": 0, "total_disconnected_to_checking": 0, "total_disconnected_to_failed": 0 }, "network_status": { "unstable_level": 0, "total_unstable_level0": 2, "total_unstable_level1": 0, "total_unstable_level2": 0, "total_unstable_level3": 0 }, "timestamp": "2021-11-30T01:59:51.372062Z", "turn": { "total_received_allocate_request": 7, "total_received_binding_request": 0, "total_received_channel_bind_request": 1, "total_received_channel_data": 5802, "total_received_create_permission_request": 1, "total_received_expired_channel_number": 0, "total_received_invalid_channel_data": 0, "total_received_refresh_request": 4, "total_received_send_indication": 3, "total_received_stun_invalid": 0, "total_received_stun_unknown": 0, "total_received_turn_binding_error": 0, "total_received_turn_binding_request": 29, "total_received_turn_binding_success": 28, "total_received_turn_invalid_stun": 0, "total_received_turn_unknown": 0, "total_received_turn_unknown_stun": 0, "total_received_unknown_channel_number": 0, "total_received_unknown_packet": 0, "total_sent_allocate_error": 2, "total_sent_allocate_success": 2, "total_sent_binding_error": 0, "total_sent_binding_success": 0, "total_sent_channel_bind_error": 0, "total_sent_channel_bind_success": 1, "total_sent_channel_data": 5644, "total_sent_create_permission_error": 0, "total_sent_create_permission_success": 1, "total_sent_data_indication": 2, "total_sent_refresh_error": 0, "total_sent_refresh_success": 3, "total_sent_turn_binding_error": 0, "total_sent_turn_binding_request": 28, "total_sent_turn_binding_success": 1, "total_sent_turn_unknown": 0, "total_turn_udp_allocate_request_401_rate_limit_exceeded": 0 } } ``` ## GetStatsClient **x-sora-target**: Sora_20170529.GetStatsClient 指定したクライアントの統計情報を取得します。 * - キー - 型 * - channel_id - string * - client_id - string ```console $ curl -sS \ -X POST \ http://127.0.0.1:3000/ \ -H "x-sora-target: Sora_20170529.GetStatsClient" \ --json '{"channel_id":"sora","client_id":"82TKXKK1M15C76KTF192WVDSVC"}' \ | jq . [ { "channel_id": "sora", "group_id": "FDYSGDVQ592CK5D4ZMC0W4XXDM", "session_id": "FDYSGDVQ592CK5D4ZMC0W4XXDM", "client_id": "spam", "bundle_id": "DDG3V4NZPH04V02NKDMY97993W", "connection_id": "DDG3V4NZPH04V02NKDMY97993W", ... }, { "channel_id": "sora", "group_id": "FDYSGDVQ592CK5D4ZMC0W4XXDM", "session_id": "FDYSGDVQ592CK5D4ZMC0W4XXDM", "client_id": "spam", "bundle_id": "1RKMMEA10923N96N88S1GEKGYR", "connection_id": "1RKMMEA10923N96N88S1GEKGYR", ... } ] ``` ## GetStatsAllConnections **x-sora-target**: Sora_20171101.GetStatsAllConnections すべての接続の統計情報を取得します。 * - キー - 型 - デフォルト * - local (オプション) - boolean - true `local` はクラスター機能利用時に、全てのノードの情報を取得するかどうかを指定します。 ```console $ curl -sS \ -X POST \ http://127.0.0.1:3000/ \ -H "x-sora-target: Sora_20171101.GetStatsAllConnections" \ | jq . [ { "channel_id": "sora", "group_id": "FDYSGDVQ592CK5D4ZMC0W4XXDM", "session_id": "FDYSGDVQ592CK5D4ZMC0W4XXDM", "client_id": "spam", "bundle_id": "DDG3V4NZPH04V02NKDMY97993W", "connection_id": "DDG3V4NZPH04V02NKDMY97993W", ... }, { "channel_id": "sora", "group_id": "FDYSGDVQ592CK5D4ZMC0W4XXDM", "session_id": "FDYSGDVQ592CK5D4ZMC0W4XXDM", "client_id": "spam", "bundle_id": "1RKMMEA10923N96N88S1GEKGYR", "connection_id": "1RKMMEA10923N96N88S1GEKGYR", ... }, { "channel_id": "zakuro", "group_id": "JJJ5BFH7QN6DQBTKSS7JA8ZYQR", "session_id": "JJJ5BFH7QN6DQBTKSS7JA8ZYQR", "client_id": "EYYX5FGZN17VB647HGYZ27K8MM", "bundle_id": "EYYX5FGZN17VB647HGYZ27K8MM", "connection_id": "EYYX5FGZN17VB647HGYZ27K8MM", ... } ] ``` # ライセンス API 現在利用しているライセンス情報の取得や、新しいライセンスの適用を行うための API です。 ## GetLicense *バージョン 18.01.0 で追加。* **x-sora-target**: Sora_20171218.GetLicense 現在利用しているライセンス情報を取得します。 > **重要** > > `signature` は表示されません ```console $ curl -sS \ -X POST \ http://127.0.0.1:3000/ \ -H "x-sora-target: Sora_20171218.GetLicense" \ | jq . { "expired_at": "2023-03", "max_connections": 100, "product_name": "Sora", "serial_code": "123ABC-SRA-E001-202303-100", "type": "Experimental" } ``` ## UpdateLicense *バージョン 18.01.0 で追加。* **x-sora-target**: Sora_20171218.UpdateLicense ライセンスを更新します。 `sora.conf` の `license_file` に設定したファイルを新規のライセンスとして読み込みます。 ライセンスが壊れていたり、見つからない場合はエラーになります。 いずれの場合も接続中のクライアントへの影響はありません。 > **重要** > > `signature` は表示されません ```console $ curl -sS \ -X POST \ http://127.0.0.1:3000/ \ -H "x-sora-target: Sora_20171218.UpdateLicense" \ | jq . { "new_license": { "expired_at": "2023-03", "max_connections": 100, "product_name": "Sora", "serial_code": "123ABC-SRA-E001-202303-100", "type": "Experimental" }, "old_license": { "expired_at": "2024-03", "max_connections": 100, "product_name": "Sora", "serial_code": "123ABC-SRA-E002-202403-100", "type": "Experimental" } } ``` # モード API モードの詳細については [モード機能](MODE.html) をご確認ください。 ## ChangeMode *バージョン 2021.2.0 で追加。* **x-sora-target**: Sora_20211215.ChangeMode Sora のモードを変更します。 * - キー - 型 * - mode - string (normal | block_new_session | block_new_connection) `mode` はすべての新規コネクションを受け入れる `normal` 、新規セッションの受け入れを停止する `block_new_session` と新規コネクションの受け入れを停止する `block_new_connection` が指定できます。 ```console $ curl -sS \ -X POST \ http://127.0.0.1:3000/ \ -H "x-sora-target: Sora_20211215.ChangeMode" \ --json '{"mode":"block_new_connection"}' \ | jq . { "mode": "block_new_connection" } ``` ## GetMode *バージョン 2021.2.0 で追加。* **x-sora-target**: Sora_20211215.GetMode Sora のモードを取得します。 ```console $ curl -sS \ -X POST \ http://127.0.0.1:3000/ \ -H "x-sora-target: Sora_20211215.GetMode" \ | jq . { "mode": "normal" } ``` # 転送フィルター API 転送フィルター API は、チャネル単位やコネクション単位で音声や映像の転送をフィルタリングする機能です。 ## ListForwardingFilters *バージョン 2023.1.0 で追加。* **x-sora-target**: Sora_20230628.ListForwardingFilters 指定したチャネルについて、チャネル単位とコネクション単位両方の転送フィルターを表示します。 また、 `blocked` オプションの指定により音声と映像のブロック状況を表示します。 * - キー - 型 * - channel_id - string * - blocked (オプション) - boolean - `blocked` を指定しない場合は `false` が指定されます - `version` が指定されているフィルターに対しては `version` 項目が追加されます - `metadata` が指定されているフィルターに対しては `metadata` 項目が追加されます ``` $ curl -sS \ -X POST \ http://127.0.0.1:3000/ \ -H "x-sora-target: Sora_20230628.ListForwardingFilters" \ --json '{"channel_id":"sora","blocked":true}' \ | jq . { "channel_forwarding_filters": [ { "action": "block", "name": "default", "priority": 32767, "rules": [ [ { "field": "kind", "operator": "is_in", "values": [ "video", "audio" ] } ] ] } ], "connection_forwarding_filters": [ { "action": "allow", "name": "default", "priority": 32767, "connection_id": "6V9VANDZZH71HCQGVKBWKJ8GS0", "rules": [ [ { "field": "kind", "operator": "is_in", "values": [ "video" ] } ] ] }, { "action": "allow", "name": "default", "priority": 32767, "connection_id": "XEDQM589M520Z50KM7C6C5PRB0", "rules": [ [ { "field": "kind", "operator": "is_in", "values": [ "audio" ] } ] ] } ], "blocked": [ { "destination_connection_id": "6V9VANDZZH71HCQGVKBWKJ8GS0", "kind": "audio", "source_connection_id_list": [ "ASJDFJ1PF94JN6DV59JQZ1HNDR" ] }, { "destination_connection_id": "XEDQM589M520Z50KM7C6C5PRB0", "kind": "video", "source_connection_id_list": [ "ASJDFJ1PF94JN6DV59JQZ1HNDR", "6V9VANDZZH71HCQGVKBWKJ8GS0" ] } ] } ``` ### レスポンス レスポンスの内容は以下の通りです。転送フィルターについての詳細は [転送フィルタールールの仕様](FORWARDING_FILTER.html#86374f) をご確認ください。 - channel_forwarding_filters- 指定したチャネルに設定されているチャネル単位の転送フィルターをリストで表示します - connection_forwarding_filters- 指定したチャネルに設定されているコネクション単位の転送フィルターを配列で表示します - blocked- destination_connection_id- ブロックされている送信先のコネクション ID - kind- ブロックされているメディア (audio または video) - source_connection_id_list- ブロックされている送信元のコネクション ID の配列 ## CreateChannelForwardingFilter *バージョン 2023.1.0 で追加。* **x-sora-target**: Sora_20230628.CreateChannelForwardingFilter 指定したチャネルに対して転送フィルターを作成します。 チャネル単位での転送フィルター作成は、**送信元からの音声や映像を送信先に転送するかどうか** を制御します。 送信先はチャネルに参加しているすべてのコネクションです。 指定した送信先だけにブロックをさせたい場合は [CreateConnectionForwardingFilter](API_FORWARDING_FILTER.html#d80a51) を使用してください。 転送フィルターの指定方法についての詳細は [転送フィルタールールの仕様](FORWARDING_FILTER.html#86374f) をご確認ください。 * - キー - 型 * - channel_id - string * - action (オプション) - string (block | allow) * - rules - array of object * - version (オプション) - string * - metadata (オプション) - JSONValue * - name (オプション) - string (最大 255 バイト) * - priority (オプション) - integer (0-32767) - `action` の指定がない場合は `block` が指定されます - `name` と `priority` を指定することができます- 複数の転送フィルターを指定する場合は `name` と `priority` を指定する必要があります - `rules` は転送フィルターの対象を配列で指定します。 `rules` で指定する array of object の object の内容は以下の通りです * - キー - 型 * - field - string (connection_id | client_id | kind) * - operator - string (is_in | is_not_in) * - values - array of string ``` $ curl -sS \ -X POST \ http://127.0.0.1:3000/ \ -H "x-sora-target: Sora_20230628.CreateChannelForwardingFilter" \ --json '{"channel_id":"sora","action":"block","rules":[[{"field":"connection_id","operator":"is_in","values":["XEDQM589M520Z50KM7C6C5PRB0"]},{"field":"client_id","operator":"is_not_in","values":["screen-share"]},{"field":"kind","operator":"is_in","values":["video"]}]]}' \ | jq . { "action": "block", "channel_id": "sora", "rules": [ [ { "field": "connection_id", "operator": "is_in", "values": [ "XEDQM589M520Z50KM7C6C5PRB0" ] }, { "field": "client_id", "operator": "is_not_in", "values": [ "screen-share" ] }, { "field": "kind", "operator": "is_in", "values": [ "video" ] } ] ] } ``` ## UpdateChannelForwardingFilter *バージョン 2023.1.0 で追加。* **x-sora-target**: Sora_20230628.UpdateChannelForwardingFilter 指定したチャネルの転送フィルターの設定を、 `rules` と `action` の内容で置き換えます。 > **注意** > > この API を実行するには事前に指定したチャネル単位の転送フィルターが作成されている必要があります * - キー - 型 * - channel_id - string * - action (オプション) - string (block | allow) * - rules - array of object * - expected_version (オプション) - string * - desired_version (オプション) - string * - metadata (オプション) - JSONValue * - name (オプション) - string (最大 255 バイト) * - priority (オプション) - integer (0-32767) - `action` の指定がない場合は `block` が指定されます - `name` と `priority` を指定することができます- 指定しない場合は `name` には `default` 、 `priority` には `32767` が指定されます - `name` と `priority` のどちらかだけを指定することはできません - 複数の転送フィルターを指定する場合は `name` と `priority` を指定する必要があります - `rules` は転送フィルターの対象を配列で指定します。 `rules` で指定する array of object の object の内容は以下の通りです * - キー - 型 * - field - string (connection_id | client_id | kind) * - operator - string (is_in | is_not_in) * - values - array of string ``` $ curl -sS \ -X POST \ http://127.0.0.1:3000/ \ -H "x-sora-target: Sora_20230628.UpdateChannelForwardingFilter" \ --json '{"channel_id":"sora","action":"block","rules":[[{"field":"connection_id","operator":"is_in","values":["XEDQM589M520Z50KM7C6C5PRB0"]},{"field":"client_id","operator":"is_not_in","values":["screen-share"]},{"field":"kind","operator":"is_in","values":["video"]}]]}' \ | jq . { "action": "block", "channel_id": "sora", "rules": [ [ { "field": "connection_id", "operator": "is_in", "values": [ "XEDQM589M520Z50KM7C6C5PRB0" ] }, { "field": "client_id", "operator": "is_not_in", "values": [ "screen-share" ] }, { "field": "kind", "operator": "is_in", "values": [ "video" ] } ] ] } ``` ## DeleteChannelForwardingFilter *バージョン 2023.1.0 で追加。* **x-sora-target**: Sora_20230628.DeleteChannelForwardingFilter 指定したチャネルの転送フィルターの設定を削除します。 > **注意** > > この API を実行するには事前に指定したチャネル単位の転送フィルターが作成されている必要があります * - キー - 型 * - channel_id - string * - name (オプション) - string (最大 255 バイト) - `name` はマルチ転送フィルター機能が有効になっている場合に指定します ``` $ curl -sS \ -X POST \ http://127.0.0.1:3000/ \ -H "x-sora-target: Sora_20230628.DeleteChannelForwardingFilter" \ --json '{"channel_id":"sora"}' \ | jq . { "channel_id": "sora" } ``` ## CreateConnectionForwardingFilter *バージョン 2023.1.0 で追加。* **x-sora-target**: Sora_20230628.CreateConnectionForwardingFilter 指定したチャネルの特定コネクションに対して転送フィルターを作成します。 コネクション単位での転送フィルター作成は、**指定したコネクションに対して送信元からの音声や映像を転送するかどうか** を制御します。 指定した送信先だけをブロックしたい場合に利用します。 転送フィルターの指定方法についての詳細は [転送フィルタールールの仕様](FORWARDING_FILTER.html#86374f) をご確認ください。 * - キー - 型 * - channel_id - string * - connection_id - string * - action (オプション) - string (block | allow) * - rules - array of object * - version (オプション) - string * - metadata (オプション) - JSONValue * - name (オプション) - string * - priority (オプション) - integer - `action` の指定がない場合は `block` が指定されます - `name` と `priority` を指定することができます- `name` と `priority` のどちらかだけを指定することはできません - 複数の転送フィルターを指定する場合は `name` と `priority` を指定する必要があります - 指定しない場合は `name` には `default` 、 `priority` には `32767` が指定されます - `rules` は転送フィルターの対象を配列で指定します。 `rules` で指定する array of object の object の内容は以下の通りです * - キー - 型 * - field - string (connection_id | client_id | kind) * - operator - string (is_in | is_not_in) * - values - array of string ``` $ curl -sS \ -X POST \ http://127.0.0.1:3000/ \ -H "x-sora-target: Sora_20230628.CreateConnectionForwardingFilter" \ --json '{"channel_id":"sora","connection_id":"EQ13WT731S1EK452YRJVFGYAY8","action":"block","rules":[[{"field":"connection_id","operator":"is_in","values":["XEDQM589M520Z50KM7C6C5PRB0"]},{"field":"client_id","operator":"is_not_in","values":["screen-share"]},{"field":"kind","operator":"is_in","values":["video"]}]]}' \ | jq . { "action": "block", "channel_id": "sora", "connection_id": "EQ13WT731S1EK452YRJVFGYAY8", "rules": [ [ { "field": "connection_id", "operator": "is_in", "values": [ "XEDQM589M520Z50KM7C6C5PRB0" ] }, { "field": "client_id", "operator": "is_not_in", "values": [ "screen-share" ] }, { "field": "kind", "operator": "is_in", "values": [ "video" ] } ] ] } ``` ## UpdateConnectionForwardingFilter *バージョン 2023.1.0 で追加。* **x-sora-target**: Sora_20230628.UpdateConnectionForwardingFilter 指定したチャネルの特定コネクションに対する転送フィルターの設定を、 `rules` と `action` の内容で置き換えます。 > **注意** > > この API を実行するには事前に指定したコネクション単位の転送フィルターが作成されている必要があります * - キー - 型 * - channel_id - string * - connection_id - string * - action (オプション) - string (block | allow) * - rules - array of object * - expected_version (オプション) - string * - desired_version (オプション) - string * - metadata (オプション) - JSONValue * - name (オプション) - string (最大 255 バイト) * - priority (オプション) - integer (0-32767) - `action` の指定がない場合は `block` が指定されます - `name` と `priority` を指定することができます- `name` と `priority` のどちらかだけを指定することはできません - `rules` は転送フィルターの対象を配列で指定します。 `rules` で指定する array of object の object の内容は以下の通りです * - キー - 型 * - field - string (connection_id | client_id | kind) * - operator - string (is_in | is_not_in) * - values - array of string * - name (オプション) - string (最大 255 バイト) * - priority (オプション) - integer (0-32767) ``` $ curl -sS \ -X POST \ http://127.0.0.1:3000/ \ -H "x-sora-target: Sora_20230628.UpdateConnectionForwardingFilter" \ --json '{"channel_id":"sora","connection_id":"T9J5FM3NTH6JH4JKFGTSHB1BA0","action":"block","rules":[[{"field":"connection_id","operator":"is_in","values":["XEDQM589M520Z50KM7C6C5PRB0"]},{"field":"client_id","operator":"is_not_in","values":["screen-share"]},{"field":"kind","operator":"is_in","values":["video"]}]]}' \ | jq . { "action": "block", "channel_id": "sora", "connection_id": "EQ13WT731S1EK452YRJVFGYAY8", "rules": [ [ { "field": "connection_id", "operator": "is_in", "values": [ "XEDQM589M520Z50KM7C6C5PRB0" ] }, { "field": "client_id", "operator": "is_not_in", "values": [ "screen-share" ] }, { "field": "kind", "operator": "is_in", "values": [ "video" ] } ] ] } ``` ## DeleteConnectionForwardingFilter *バージョン 2023.1.0 で追加。* **x-sora-target**: Sora_20230628.DeleteConnectionForwardingFilter 指定したチャネルの特定コネクションの転送フィルターを削除します。 > **注意** > > この API を実行するには事前に指定したコネクション単位の転送フィルターが作成されている必要があります * - キー - 型 * - channel_id - string * - connection_id - string * - name (オプション) - string (最大 255 バイト) - `name` はマルチ転送フィルター機能が有効になっている場合に指定します ``` $ curl -sS \ -X POST \ http://127.0.0.1:3000/ \ -H "x-sora-target: Sora_20230628.DeleteConnectionForwardingFilter" \ --json '{"channel_id":"sora","connection_id":"T9J5FM3NTH6JH4JKFGTSHB1BA0"}' \ | jq . { "channel_id": "sora", "connection_id": "EQ13WT731S1EK452YRJVFGYAY8" } ``` # シグナリング通知メタデータ拡張 API ## ListSignalingNotifyMetadata **x-sora-target**: Sora_20201124.ListSignalingNotifyMetadata 指定したチャネルのすべての接続のメタデータをリストで返します。リストの中には `connection_id` と `bundle_id` と `client_id` と `metadata` をキーとしたオブジェクトがリストで入ってきます。順番保証はしません。 * - キー - 型 * - channel_id - string ```console $ curl -sS \ -X POST \ http://127.0.0.1:3000/ \ -H "x-sora-target: Sora_20201124.ListSignalingNotifyMetadata" \ --json '{"channel_id":"sora"}' \ | jq . [ { "client_id": "V3Q452QQBD5TQ6ZQDMTEDKA07C", "bundle_id": "V3Q452QQBD5TQ6ZQDMTEDKA07C", "connection_id": "V3Q452QQBD5TQ6ZQDMTEDKA07C", "metadata": { "abc": 10 } } ] ``` ## GetSignalingNotifyMetadata **x-sora-target**: Sora_20201124.GetSignalingNotifyMetadata 指定した接続のメタデータを取得します。 * - キー - 型 * - channel_id - string * - connection_id - string ```console $ curl -sS \ -X POST \ http://127.0.0.1:3000/ \ -H "x-sora-target: Sora_20201124.GetSignalingNotifyMetadata" \ --json '{"channel_id":"sora","connection_id":"0FQE5EA5YN3FS13P01QZ1JG8R0"}' \ | jq . { "abc": "efg" } ``` ## PutSignalingNotifyMetadata **x-sora-target**: Sora_20201124.PutSignalingNotifyMetadata 指定した接続のメタデータを作成します。 * - キー - 型 * - channel_id - string * - connection_id - string * - metadata - object * - push (オプション) - boolean 指定した接続のメタデータを作成します。メタデータがすでにあった場合は更新します。 追加したあとのメタデータが値として返ってきます。 ```console $ curl -sS \ -X POST \ http://127.0.0.1:3000/ \ -H "x-sora-target: Sora_20201124.PutSignalingNotifyMetadata" \ --json '{"channel_id":"sora","connection_id":"0FQE5EA5YN3FS13P01QZ1JG8R0","metadata":{"abc":"efg"},"push":true}' \ | jq . { "abc": "efg" } ``` push を有効にした場合は、そのチャネルのすべてのクライアントに以下のようなプッシュ通知が送られます。 ```javascript { "type": "push", "data": { "action": "PutMetadata", "connection_id": "0FQE5EA5YN3FS13P01QZ1JG8R0", "metadata": {"abc": "efg"}, "type": "signaling_notify_metadata_ext" } } ``` - action- "PutMetadata" 固定 - connection_id- シグナリング通知メタデータの項目が変更された接続の ID - metadata- 作成、または更新したメタデータ ## DeleteSignalingNotifyMetadata **x-sora-target**: Sora_20201124.DeleteSignalingNotifyMetadata 指定した接続のメタデータを削除します。 * - キー - 型 * - channel_id - string * - connection_id - string * - push (オプション) - boolean 指定した接続のメタデータを削除します。メタデータが空だったとしてもエラーにはなりません。 削除される **まえ** のメタデータが値として返ってきます。 ```console $ curl -sS \ -X POST \ http://127.0.0.1:3000/ \ -H "x-sora-target: Sora_20201124.DeleteSignalingNotifyMetadata" \ --json '{"channel_id":"sora","connection_id":"0FQE5EA5YN3FS13P01QZ1JG8R0","push":true}' \ | jq . { "abc": "efg" } ``` push を有効にした場合は、そのチャネルのすべてのクライアントに以下のようなプッシュ通知が送られます。 ```javascript { "type": "push", "data": { "action": "DeleteMetadata", "connection_id": "0FQE5EA5YN3FS13P01QZ1JG8R0", "metadata": {"abc": "efg"}, "type": "signaling_notify_metadata_ext" } } ``` - action- "DeleteMetadata" 固定 - connection_id- シグナリング通知メタデータの項目が変更された接続の ID - metadata- 削除したメタデータ ## PutSignalingNotifyMetadataItem **x-sora-target**: Sora_20201124.PutSignalingNotifyMetadataItem 指定した接続のメタデータ項目を作成または更新します。 * - キー - 型 * - channel_id - string * - connection_id - string * - key - string * - value - json * - push (オプション) - boolean key/value で指定したメタデータ項目を追加します。その項目が既にあった場合は更新します。 追加したあとのメタデータが値として返ってきます。 ```console $ curl -sS \ -X POST \ http://127.0.0.1:3000/ \ -H "x-sora-target: Sora_20201124.PutSignalingNotifyMetadataItem" \ --json '{"channel_id":"sora","connection_id":"0FQE5EA5YN3FS13P01QZ1JG8R0","key":"abc","value":"efg","push":true}' \ | jq . { "abc": "efg" } ``` push を有効にした場合は、そのチャネルのすべてのクライアントに以下のようなプッシュ通知が送られます。 ```javascript { "type": "push", "data": { "action": "PutMetadataItem", "connection_id": "0FQE5EA5YN3FS13P01QZ1JG8R0", "key": "abc", "value": "efg", "type": "signaling_notify_metadata_ext" } } ``` - action- "PutMetadataItem" 固定 - connection_id- シグナリング通知メタデータの項目が変更された接続の ID - key- シグナリング通知メタデータの項目が変更されたキー - value- シグナリング通知メタデータの項目が変更されたバリュー ## DeleteSignalingNotifyMetadataItem **x-sora-target**: Sora_20201124.DeleteSignalingNotifyMetadataItem 指定した接続のメタデータ項目を削除します。 * - キー - 型 * - channel_id - string * - connection_id - string * - key - string * - push (オプション) - boolean key で指定したメタデータ項目を削除します。その項目がなかったとしてもエラーにはなりません。 削除された **あと** のメタデータが値として返ってきます。 もしその項目がなかった場合は現状のメタデータが値として返ってきます。 ```console $ curl -sS \ -X POST \ http://127.0.0.1:3000/ \ -H "x-sora-target: Sora_20201124.DeleteSignalingNotifyMetadataItem" \ --json '{"channel_id":"sora","connection_id":"0FQE5EA5YN3FS13P01QZ1JG8R0","key":"abc","push":true}' \ | jq . {} ``` push を有効にした場合は、そのチャネルのすべてのクライアントに以下のようなプッシュ通知が送られます。 ```javascript { "type": "push", "data": { "action": "DeleteMetadataItem", "connection_id": "0FQE5EA5YN3FS13P01QZ1JG8R0", "key": "abc", "type": "signaling_notify_metadata_ext" } } ``` - action- "DeleteMetadataItem" 固定 - connection_id- シグナリング通知メタデータの項目が変更された接続の ID - key- シグナリング通知メタデータの項目が変更されたキー # 音声ストリーミング API ## StartAudioStreaming *バージョン 2022.2.0 で追加。* **x-sora-target**: Sora_20221221.StartAudioStreaming セッションが存在し、音声ストリーミングが開始していないチャネルに対して音声ストリーミングを開始します。 * - キー - 型 * - channel_id - string ```console $ curl -sS \ -X POST \ http://127.0.0.1:3000/ \ -H "x-sora-target: Sora_20221221.StartAudioStreaming" \ --json '{"channel_id":"sora"}' \ | jq . { "session_id": "MPXNY180M175Z69YY9FZFJ0QWR" } ``` ## StopAudioStreaming *バージョン 2022.2.0 で追加。* **x-sora-target**: Sora_20221221.StopAudioStreaming セッションが存在し、音声ストリーミングが開始しているチャネルに対して音声ストリーミングを停止します。 * - キー - 型 * - channel_id - string ```console $ curl -sS \ -X POST \ http://127.0.0.1:3000/ \ -H "x-sora-target: Sora_20221221.StopAudioStreaming" \ --json '{"channel_id":"sora"}' \ | jq . { "session_id": "MPXNY180M175Z69YY9FZFJ0QWR" } ``` ## SubscribeAudioStreamingResultPush *バージョン 2022.2.0 で追加。* **x-sora-target**: Sora_20221221.SubscribeAudioStreamingResultPush 音声ストリーミングサーバーからの戻り値のプッシュ通知を指定した接続が購読するよう設定します。 * - キー - 型 * - channel_id - string * - connection_id - string ```console $ curl -sS \ -X POST \ http://127.0.0.1:3000/ \ -H "x-sora-target: Sora_20221221.SubscribeAudioStreamingResultPush" \ --json '{"channel_id":"sora","connection_id":"AT10T0WHH94PHEM3M5F45QFGRW"}' \ | jq . { "channel_id": "sora", "connection_id": "AT10T0WHH94PHEM3M5F45QFGRW" } ``` ## UnsubscribeAudioStreamingResultPush *バージョン 2022.2.0 で追加。* **x-sora-target**: Sora_20221221.UnsubscribeAudioStreamingResultPush 音声ストリーミングサーバーからの戻り値のプッシュ通知を指定した接続が購読しないよう設定します。 * - キー - 型 * - channel_id - string * - connection_id - string ```console $ curl -sS \ -X POST \ http://127.0.0.1:3000/ \ -H "x-sora-target: Sora_20221221.UnsubscribeAudioStreamingResultPush" \ --json '{"channel_id":"sora","connection_id":"4D83B8APHS4JX03C8SZ3176SBM"}' \ | jq . { "channel_id": "sora", "connection_id": "4D83B8APHS4JX03C8SZ3176SBM" } ``` ## ListAudioStreamingResultPushState *バージョン 2023.1.0 で追加。* **x-sora-target**: Sora_20230628.ListAudioStreamingResultPushState 指定したチャネルのセッションにおける、コネクションごとのサブスクライブ状態を表示します。 * - キー - 型 * - channel_id - string ```console $ curl -sS \ -X POST \ http://127.0.0.1:3000/ \ -H "x-sora-target: Sora_20230628.ListAudioStreamingResultPushState" \ --json '{"channel_id":"sora"}' \ | jq . [ { "connection_id": "B2JPGFZPMD3H973Y811MF8ZZ70", "subscribe": true }, { "connection_id": "KT116Z11KX5Y547KA1V12HW8PG", "subscribe": false }, { "connection_id": "A5GYXGRYAX6590M3AFH7F9Z2H4", "subscribe": false } ] ``` # RTC 統計情報 API ## 統計情報更新のタイミングについて この統計情報は、クライアントからシグナリングで送信されてくる統計情報の最新の値を返します。 デフォルトでは WebSocket と DataChannel 経由のどちらも 60 秒間隔で更新されます。 間隔は以下で変更できます。 - [websocket_stats_timer_interval](SORA_CONF.html#67a631) - [data_channel_stats_timer_interval](SORA_CONF.html#217b39) ## ListRtcStats *バージョン 2024.1.0 で追加。* **x-sora-target**: Sora_20211215.ListRtcStats すべての RTC 統計情報の一覧を取得します。 * - キー - 型 - デフォルト * - local (オプション) - boolean - true `local` はクラスター機能利用時に、全てのノードの情報を取得するかどうかを指定します。 ```console $ curl -sS \ -X POST \ http://127.0.0.1:3000/ \ -H "x-sora-target: Sora_20211215.ListRtcStats" \ | jq . [ { "channel_id": "sora", "connection_id": "FNRGZ8VFSN3R98DK7NBA38MFNR", "timestamp": "2021-11-13T13:05:33.264Z", "rtc_stats": [ { "audioLevel": 0, "id": "RTCAudioSource_1", "kind": "audio", "timestamp": 1636808733258.573, "totalAudioEnergy": 0, "totalSamplesDuration": 90.08000000000918, "trackIdentifier": "222a181f-d0fe-4434-b7a1-a8e05e3abbb4", "type": "media-source" }, ... ] }, { "channel_id": "zakuro", "connection_id": "X019KW3ZT95WZ6T15S6HHTM59C", "timestamp": "2021-11-13T13:05:44.044Z", "rtc_stats": [ { "audioLevel": 0, "id": "RTCAudioSource_1", "kind": "audio", "timestamp": 1636808744029.488, "totalAudioEnergy": 0, "totalSamplesDuration": 31.070000000002057, "trackIdentifier": "9a84b996-d3ab-4cea-8131-04f96232dde5", "type": "media-source" }, ... ] } ] ``` ## ListChannelRtcStats *バージョン 2024.1.0 で追加。* **x-sora-target**: Sora_20211215.ListChannelRtcStats 指定したチャネルの RTC 統計情報の一覧を取得します。 * - キー - 型 * - channel_id - string ```console $ curl -sS \ -X POST \ http://127.0.0.1:3000/ \ -H "x-sora-target: Sora_20211215.ListChannelRtcStats" \ --json '{"channel_id":"sora"}' \ | jq . [ { "channel_id": "sora", "connection_id": "1BW6V4P6A14MZ0W2HHXV3M8MCW", "timestamp": "2021-11-13T13:10:25.736Z", "rtc_stats": [ { "audioLevel": 0, "id": "RTCAudioSource_1", "kind": "audio", "timestamp": 1636809025720.942, "totalAudioEnergy": 0, "totalSamplesDuration": 90.08000000000918, "trackIdentifier": "58c7f808-5b7f-4283-8816-0ac1f7d75387", "type": "media-source" }, ... ] }, { "channel_id": "sora", "connection_id": "VDH8HN6X6S4MZF2FCQJF3Z4M8G", "timestamp": "2021-11-13T13:10:30.643Z", "rtc_stats": [ { "audioLevel": 0, "id": "RTCAudioSource_1", "kind": "audio", "timestamp": 1636809030622.809, "totalAudioEnergy": 0, "totalSamplesDuration": 91.08000000000968, "trackIdentifier": "e6d3182d-706c-445f-9a91-c5951d55e000", "type": "media-source" }, ... ] } ] ``` ## GetRtcStats *バージョン 2024.1.0 で追加。* **x-sora-target**: Sora_20211215.GetRtcStats 指定した接続の RTC 統計情報を取得します。 * - キー - 型 * - channel_id - string * - connection_id - string ```console $ curl -sS \ -X POST \ http://127.0.0.1:3000/ \ -H "x-sora-target: Sora_20211215.GetRtcStats" \ --json '{"channel_id":"sora","connection_id":"VDH8HN6X6S4MZF2FCQJF3Z4M8G"}' \ | jq . { "channel_id": "sora", "connection_id": "VDH8HN6X6S4MZF2FCQJF3Z4M8G", "rtc_stats": [ { "audioLevel": 0, "id": "RTCAudioSource_1", "kind": "audio", "timestamp": 1636809090624.392, "totalAudioEnergy": 0, "totalSamplesDuration": 151.08000000000757, "trackIdentifier": "e6d3182d-706c-445f-9a91-c5951d55e000", "type": "media-source" }, ... ], "timestamp": "2021-11-13T13:11:30.647Z" } ``` # 実験的 API ## 概要 実験的 API とは、今後のアップデートで互換性を保証しない API です。 将来的には正式版としてリリースするか、または非推奨となり廃止するかのどちらかです。 ## その他の API > **注意** > > この API は実験的機能のため、正式版では仕様が変更される可能性があります。 ### ChangeUpstreamVideoBitRate **x-sora-target**: Sora_20190327.ChangeUpstreamVideoBitRate 指定した接続のビットレートを動的に変更します。 主に `role` が `sendonly` の **配信ビットレート** を動的に変更し固定することを目的としている API です。 > **注釈** > > これは接続後に映像ビットレートを強制的に変更する唯一の仕組みです。 * - キー - 型 * - channel_id - string * - connection_id - string * - bit_rate - integer (1 - 30000) ```console $ curl -sS \ -X POST \ http://127.0.0.1:3000/ \ -H "x-sora-target: Sora_20190327.ChangeUpstreamVideoBitRate" \ --json '{"channel_id":"sora","connection_id":"HMRVPQEXJX03D3B3WE778SJGRC","bit_rate":300}' \ | jq . { "bit_rate": 300, "channel_id": "sora", "connection_id": "HMRVPQEXJX03D3B3WE778SJGRC" } ``` # シグナリング API > **注意** > > この API は [実験的機能](EXPERIMENTAL.html) のため、正式版では仕様が変更される可能性があります。 ## ListChannels **x-sora-target**: Sora_20201013.ListChannels すべてのチャネル一覧を取得します。 * - キー - 型 - デフォルト * - local (オプション) - boolean - true `local` はクラスター機能利用時に、全てのノードの情報を取得するかどうかを指定します。 ```console $ curl -sS \ -X POST \ http://127.0.0.1:3000/ \ -H "x-sora-target: Sora_20201013.ListChannels" \ | jq . [ { "channel_id": "sora", "spotlight": false }, { "channel_id": "akane", "spotlight": false } ] ``` # RTP 転送 API > **注意** > > この API は [実験的機能](EXPERIMENTAL.html) のため、正式版では仕様が変更される可能性があります。 指定したチャネル ID の配信している映像または音声の RTP を指定した IP アドレスとポートに送信します。 ## 注意 - サイマルキャストの映像配信には対応していません ## StartForwardingRtp **x-sora-target**: Sora_20170814.StartForwardingRtp 指定したチャネルの RTP の転送を開始します。 * - キー - 型 * - channel_id - string * - connection_id - string * - ip_address - string * - audio_port - integer * - video_port - integer ```console $ curl -sS \ -X POST \ http://127.0.0.1:3000/ \ -H "x-sora-target: Sora_20170814.StartForwardingRtp" \ --json '{"channel_id":"sora","connection_id":"3X0W1C23KS1TQAAYMKA9TXJS4G","ip_address":"127.0.0.1","audio_port":60001,"video_port":60003}' \ | jq . { "sdp": "v=0\r\no=- 0 0 IN IP4 0.0.0.0\r\ns=-\r\nt=0 0\r\nm=audio 60001 RTP/SAVPF 109\r\nc=IN IP4 127.0.0.1\r\na=rtpmap:109 opus/48000/2\r\nm=video 60003 RTP/SAVPF 120\r\nc=IN IP4 127.0.0.1\r\na=rtpmap:120 VP9/90000\r\na=fmtp:120 max-fs=12288;max-fr=60\r\n" } ``` ## StopForwardingRtp **x-sora-target**: Sora_20170814.StopForwardingRtp 指定したチャネルの RTP の転送を停止します。 * - キー - 型 * - channel_id - string * - connection_id - string ```console $ curl -sS \ -X POST \ http://127.0.0.1:3000/ \ -H "x-sora-target: Sora_20170814.StopForwardingRtp" \ --json '{"channel_id":"sora","connection_id":"3X0W1C23KS1TQAAYMKA9TXJS4G"}' \ | jq . { "channel_id": "sora", "connection_id": "3X0W1C23KS1TQAAYMKA9TXJS4G" } ``` # サイマルキャスト API > **注意** > > この API は [実験的機能](EXPERIMENTAL.html) のため、正式版では仕様が変更される可能性があります。 ## ChangeSimulcastAuto **x-sora-target**: Sora_20251217.ChangeSimulcastAuto 指定した視聴者が受信するストリームの `rid` を視聴者の環境に合わせたものを配信するように変更します。 変更する際に自動で切り替わる rid のリストを指定します。 * - キー - 型 * - channel_id - string * - receiver_connection_id - string * - sender_connection_id (オプション) - string * - rids - string[none | r0 | r1 | r2, ...] - `rids` に指定したリストの中から視聴者の環境に合わせた rid で映像ストリームが配信されます - `rids` に `[]` を指定すると自動で rid の切り替えは無効化されます ```console $ curl -sS \ -X POST \ http://127.0.0.1:3000/ \ -H "x-sora-target: Sora_20251217.ChangeSimulcastAuto" \ --json '{"channel_id":"sora","receiver_connection_id":"4EVK3MN5Z17GB62RE5TGD045ZM","rids":["r0","r1"]}' \ | jq . { "channel_id": "sora", "receiver_connection_id": "4EVK3MN5Z17GB62RE5TGD045ZM", "rids": [ "r0", "r1" ] } ``` # 統計 API > **注意** > > この API は [実験的機能](EXPERIMENTAL.html) のため、正式版では仕様が変更される可能性があります。 ## GetStatsReport **x-sora-target**: Sora_20171010.GetStatsReport Sora が起動している間の Sora 全体の統計情報を取得できます。 この統計情報は Sora を止めたり再起動したりすることでクリアされますので注意してください。 ### レスポンス項目 - version- sora のバージョン - total_connection_created- 現在までの接続が作成された数 - total_connection_updated- 現在までの接続が更新された数 - total_connection_destroyed- 現在までの接続が破棄された数 - total_session_created- 現在までのセッションが作成された数 - total_session_destroyed- 現在までのセッションが破棄された数 - total_successful_connections- 現在までの接続が成功した数 - total_ongoing_connections- 現在接続している数 - total_failed_connections- 現在までの接続が失敗した数 - total_duration_sec- 現在までの合計接続時間 (秒) - total_turn_udp_connections- 現在までの TURN-UDP での接続数 - total_turn_tcp_connections- 現在までの TURN-TCP または TURN-TLS での接続数 - total_received_invalid_turn_tcp_packet- 現在までの TURN-TCP でパースできないパケットが送られてきた数 - total_auth_webhook_allowed- 認証ウェブフックで許可された数 - total_auth_webhook_denied- 認証ウェブフックで拒否された数 - total_successful_auth_webhook- 認証ウェブフックが成功した数 - total_failed_auth_webhook- 認証ウェブフックが失敗した数 - total_successful_session_webhook- セッションウェブフックが成功した数 - total_failed_session_webhook- セッションウェブフックが失敗した数 - total_ignored_session_webhook- 無視されたセッションウェブフックの合計数 - total_successful_event_webhook- イベントウェブフックが成功した数 - total_failed_event_webhook- イベントウェブフックが失敗した数 - total_ignored_event_webhook- 無視されたイベントウェブフックの合計数 - total_successful_stats_webhook- 統計ウェブフックが成功した数 - total_failed_stats_webhook- 統計ウェブフックが失敗した数 - total_ignored_stats_webhook- 無視された統計ウェブフックの合計数 - total_auth_webhook_response_time_ms- 認証ウェブフックの応答時間の累積合計 (ミリ秒) - auth_webhook_response_time_ms_buckets- 認証ウェブフックの応答時間ヒストグラム (上限値別の累積件数) - total_session_webhook_response_time_ms- セッションウェブフックの応答時間の累積合計 (ミリ秒) - session_webhook_response_time_ms_buckets- セッションウェブフックの応答時間ヒストグラム (上限値別の累積件数) - total_event_webhook_response_time_ms- イベントウェブフックの応答時間の累積合計 (ミリ秒) - event_webhook_response_time_ms_buckets- イベントウェブフックの応答時間ヒストグラム (上限値別の累積件数) - average_duration_sec- 平均接続時間 (秒) - average_setup_time_msec- 平均セットアップ時間 (ミリ秒) - セットアップ時間とはシグナリング接続開始から WebRTC が確立するまでにかかった時間です - total_received_srtp- 受信した SRTP パケットの数 - total_received_srtp_byte_size- 受信した SRTP パケットのバイト数 - total_sent_srtp- 送信した SRTP パケットの数 - total_sent_srtp_byte_size- 送信した SRTP パケットのバイト数 - Sora は暗号化したパケットは必ず送信します - total_decrypted_srtp- 復号した SRTP パケットの数 - Sora は誰も視聴していない音声や映像パケットを復号しません - total_decrypted_srtp_byte_size- 復号した SRTP パケットのバイト数 - total_received_sctp- 受信した SCTP パケットの数 - total_received_sctp_byte_size- 受信した SCTP パケットのバイト数 - total_sent_sctp- 送信した SCTP パケットの数 - total_sent_sctp_byte_size- 送信した SCTP パケットのバイト数 - cluster- クラスター機能の統計情報です - raft_commit_index- Raft ノードが最後にコミットしたログのインデックス番号 - raft_state- Raft ノードの現在の状態 - raft_term- Raft ノードの現在の term - total_force_sync_session_resource- セッションリソース情報を他ノードへ即時同期した回数 - cluster_relay- **この統計データは厳密なデータではないため、参考程度にご利用ください** - クラスターリレー機能が有効な場合この項目が追加されます - node_name- 対象ノード名 - total_sent_byte_size- 対象ノードへリレー機能で送信したバイト数 - total_received_byte_size- 対象ノードからリレー機能で受信したバイト数 - total_sent- 対象ノードからリレー機能で送信したパケット数 - total_received- 対象ノードからリレー機能で受信したパケット数 - 対象ノードが削除された場合でも再起動されるまでは統計情報は残ります - plumtree- 対象ノードが利用しているツリー構造の統計情報です - total_sent_gossip - total_received_gossip - total_received_gossip_hop - total_sent_ihave - total_received_ihave - total_sent_graft - total_received_graft - total_sent_prune - total_received_prune - total_graft_miss - total_skipped_send - total_ignored ウェブフックの成功は 2xx 系が戻ってきておりかつ、JSON がある場合は JSON のパースに失敗しない場合です。 それ以外は失敗としています。 応答時間に関する統計は統計ウェブフックを対象外としています。 ```console $ curl -sS \ -X POST \ http://127.0.0.1:3000/ \ -H "x-sora-target: Sora_20171010.GetStatsReport" \ | jq . { "auth_webhook_response_time_ms_buckets": [ {"upper_bound": 1250, "count": 0}, {"upper_bound": 2500, "count": 0}, {"upper_bound": 3750, "count": 0}, {"upper_bound": 5000, "count": 0} ], "average_duration_sec": 1450, "average_setup_time_msec": 879, "cluster": { "raft_commit_index": 98, "raft_state": "follower", "raft_term": 3, "total_force_sync_session_resource": 0 }, "cluster_relay": [ { "node_name": "sora2@192.0.2.13", "plumtree": { "total_graft_miss": 0, "total_ignored": 0, "total_received_gossip": 1036, "total_received_gossip_hop": 1037, "total_received_graft": 0, "total_received_ihave": 760, "total_received_prune": 1, "total_sent_gossip": 1731, "total_sent_graft": 0, "total_sent_ihave": 760, "total_sent_prune": 1, "total_skipped_send": 0 }, "total_received": 1797, "total_received_byte_size": 796839, "total_sent": 2492, "total_sent_byte_size": 1034225 }, { "node_name": "sora3@192.0.2.13", "plumtree": { "total_graft_miss": 0, "total_ignored": 0, "total_received_gossip": 1161, "total_received_gossip_hop": 1162, "total_received_graft": 0, "total_received_ihave": 1034, "total_received_prune": 1, "total_sent_gossip": 3556, "total_sent_graft": 0, "total_sent_ihave": 1034, "total_sent_prune": 1, "total_skipped_send": 0 }, "total_received": 2196, "total_received_byte_size": 763788, "total_sent": 4591, "total_sent_byte_size": 2134557 } ], "event_webhook_response_time_ms_buckets": [ {"upper_bound": 1250, "count": 0}, {"upper_bound": 2500, "count": 0}, {"upper_bound": 3750, "count": 0}, {"upper_bound": 5000, "count": 0} ], "session_webhook_response_time_ms_buckets": [ {"upper_bound": 1250, "count": 0}, {"upper_bound": 2500, "count": 0}, {"upper_bound": 3750, "count": 0}, {"upper_bound": 5000, "count": 0} ], "total_auth_webhook_allowed": 0, "total_auth_webhook_denied": 0, "total_auth_webhook_response_time_ms": 0, "total_connection_created": 1, "total_connection_destroyed": 0, "total_connection_updated": 2, "total_decrypted_srtp": 18029, "total_decrypted_srtp_byte_size": 4735559, "total_duration_sec": 0, "total_event_webhook_response_time_ms": 0, "total_failed_auth_webhook": 0, "total_failed_connections": 0, "total_failed_event_webhook": 0, "total_failed_session_webhook": 0, "total_failed_stats_webhook": 0, "total_ignored_event_webhook": 0, "total_ignored_session_webhook": 0, "total_ignored_stats_webhook": 0, "total_ongoing_connections": 1, "total_received_invalid_turn_tcp_packet": 0, "total_received_sctp": 0, "total_received_sctp_byte_size": 0, "total_received_srtp": 18029, "total_received_srtp_byte_size": 4735559, "total_sent_sctp": 0, "total_sent_sctp_byte_size": 0, "total_sent_srtp": 1343, "total_sent_srtp_byte_size": 643870, "total_sent_srtp_sfu_delay_us": 3940352, "total_session_created": 0, "total_session_destroyed": 0, "total_session_webhook_response_time_ms": 0, "total_successful_auth_webhook": 0, "total_successful_connections": 1, "total_successful_event_webhook": 0, "total_successful_session_webhook": 0, "total_successful_stats_webhook": 0, "total_turn_tcp_connections": 0, "total_turn_udp_connections": 1, "version": "2025.1.0" } ``` # 非推奨 API ## 概要 非推奨 API は廃止日が設定されている API です。 基本的には以下のルールで廃止をしますが、例外はあります。不明点がある場合はサポートまでご連絡ください。 - API が非推奨 API になった場合、代替 API がない場合は廃止までに少なくとも 1 年以上の期間を設けます - API が非推奨 API になった場合、代替 API がある場合は廃止までに少なくとも 6 ヶ月以上の期間を設けます ## ResetRtpStream API > **注意** > > [ResetRtpStream](DEPRECATED_API_SIMULCAST.html#afba6e) API は 2026 年 12 月リリース予定の Sora にて廃止します。 > 今後は [RequestSimulcastRid](API_SIMULCAST.html#7d26ab) API をご利用ください。 ## RequestRtpStream API > **注意** > > [RequestRtpStream](DEPRECATED_API_SIMULCAST.html#6fe0b3) API は 2027 年 12 月リリース予定の Sora にて廃止します。 > 今後は [RequestSimulcastRid](API_SIMULCAST.html#7d26ab) API をご利用ください。 # 非推奨 サイマルキャスト API ## RequestRtpStream **x-sora-target**: Sora_20201005.RequestRtpStream 指定した視聴者が受信する RTP ストリームの `rid` をリクエストします。 * - キー - 型 * - channel_id - string * - recv_connection_id - string * - send_connection_id (オプション) - string * - rid - string (r0 | r1 | r2) - `r1` までしか配信されていない場合、 `r2` をリクエストすると `r1` を受信し始めます ```console $ curl -sS \ -X POST \ http://127.0.0.1:3000/ \ -H "x-sora-target: Sora_20201005.RequestRtpStream" \ --json '{"channel_id":"sora","recv_connection_id":"4EVK3MN5Z17GB62RE5TGD045ZM","send_connection_id":"EKNQ103WRD4ZZ74B6TKRM9YK78","rid":"r1"}' \ | jq . { "channel_id": "sora", "recv_connection_id": "4EVK3MN5Z17GB62RE5TGD045ZM", "rid": "r1", "send_connection_id": "EKNQ103WRD4ZZ74B6TKRM9YK78" } ``` ## ResetRtpStream **x-sora-target**: Sora_20201005.ResetRtpStream 指定した視聴者が受信する RTP ストリームの rid をリセットします。 * - キー - 型 * - channel_id - string * - recv_connection_id - string * - send_connection_id (オプション) - string ```console $ curl -sS \ -X POST \ http://127.0.0.1:3000/ \ -H "x-sora-target: Sora_20201005.ResetRtpStream" \ --json '{"channel_id":"sora","recv_connection_id":"4EVK3MN5Z17GB62RE5TGD045ZM","send_connection_id":"EKNQ103WRD4ZZ74B6TKRM9YK78"}' \ | jq . { "channel_id": "sora", "recv_connection_id": "4EVK3MN5Z17GB62RE5TGD045ZM", "send_connection_id": "EKNQ103WRD4ZZ74B6TKRM9YK78" } ``` # 廃止 API ## 概要 廃止 API とはすでに廃止された API です。 ## レガシー録画 API > **注意** > > [レガシー録画機能 API](OBSOLETE_API_LEGACY_RECORDING.html) は 2025 年 12 月リリースの Sora にて廃止します。 > 今後は [録画機能 (セッション単位) API](API_RECORDING.html) をご利用ください。 ## RTP ストリーム停止/再開 API > **注意** > > [RTP ストリーム停止/再開 API](OBSOLETE_API_RTP_STREAM_PAUSE_RESUME.html) は 2025 年 12 月リリースの Sora にて廃止します。 > 今後は [転送フィルター API](API_FORWARDING_FILTER.html) をご利用ください。 ## 廃止ユーザーエージェント API *バージョン 2025.1.0 で削除。* [ユーザーエージェント統計 API](OBSOLETE_API_USER_AGENT_STATS.html) は 2025 年 6 月リリースの Sora にて廃止しました。 今後は [RTC 統計 API](API_RTC_STATS.html) をご利用ください。 ## 廃止クラスター API ### JoinCluster *バージョン 2024.2.0 で削除。* > **危険** > > この API は廃止しました。 全く同じ機能をもつ [RegisterClusterNode](API_CLUSTER.html#09ed96) API を利用してください。 **廃止**: 2024 年 12 月リリースの Sora にて廃止 **x-sora-target**: Sora_20211215.JoinCluster 指定したクラスターノードに参加します。 参加したいクラスターに属するノードのいずれかを `contact_node_name` で指定してください。 クラスターに属していれば、どのノードでもかまいません。 - 参加したいクラスターがすでに初期化されている必要があります。 - クラスターに参加するためには、参加したいクラスターの過半数のノードが正常に稼働している必要があります > **注釈** > > 新規にクラスターを作成する場合には、まず [InitCluster](API_CLUSTER.html#621990) API を使用してください。 * - キー - 型 * - contact_node_name - string ```console $ curl -sS \ -X POST \ http://127.0.0.1:3000/ \ -H "x-sora-target: Sora_20211215.JoinCluster" \ --json '{"contact_node_name":"node-03@10.99.0.8"}' \ | jq . { "node_name_list": [ "node-01@192.0.2.5", "node-02@192.0.2.7", "node-03@192.0.2.8", "node-04@192.0.2.9", "node-05@192.0.2.10" ] } ``` ## 廃止シグナリング API ### ListAllConnections *バージョン 2021.2.0 で削除。* > **危険** > > この API は廃止しました。 **廃止**: 2021 年 12 月リリースの Sora にて廃止 **代替 API**: Sora_20201013.ListConnections **x-sora-target**: Sora_20151104.ListAllConnections すべての接続一覧を取得します。 #### レスポンス項目 **リスト** - role - channel_id - client_id - connection_id - simulcast - spotlight ```console $ curl -sS \ -X POST \ http://127.0.0.1:3000/ \ -H "x-sora-target: Sora_20151104.ListAllConnections" \ | jq . [ { "channel_id": "sora", "client_id": "6DXMKHX8Q106K9YKN693C2D69C", "connection_id": "6DXMKHX8Q106K9YKN693C2D69C", "role": "sendrecv", "simulcast": true, "spotlight": false }, { "channel_id": "sora", "client_id": "QR3H6TYEA907B2HRDF6KCBGWYG", "connection_id": "QR3H6TYEA907B2HRDF6KCBGWYG", "role": "sendrecv", "simulcast": true, "spotlight": false }, { "channel_id": "sora1", "client_id": "K3VJGRFG614SV4RRF74QDEYHVC", "connection_id": "K3VJGRFG614SV4RRF74QDEYHVC", "role": "sendrecv", "simulcast": true, "spotlight": false } ] ``` ### ListChannelClients *バージョン 2021.2.0 で削除。* > **危険** > > この API は廃止しました。 **廃止**: 2021 年 12 月リリースの Sora にて廃止 **代替 API**: Sora_20201013.ListChannelConnections **x-sora-target**: Sora_20170814.ListChannelClients 指定したチャネルのクライアント情報を取得します。 * - キー - 型 * - channel_id - string #### レスポンス項目 **リスト** - role - channel_id - client_id - connection_id - audio - video - minutes- 分単位での接続経過時間 - event_metadata- 認証時に認証サーバーから指定した event_metadata ```console $ curl -sS \ -X POST \ http://127.0.0.1:3000/ \ -H "x-sora-target: Sora_20170814.ListChannelClients" \ --json '{"channel_id":"sora"}' \ | jq . [ { "audio": { "codec_type": "OPUS" }, "channel_id": "sora", "client_id": "6DXMKHX8Q106K9YKN693C2D69C", "connection_id": "6DXMKHX8Q106K9YKN693C2D69C", "minutes": 2, "role": "sendrecv", "video": { "bit_rate": 3000, "codec_type": "VP8" } }, { "audio": { "codec_type": "OPUS" }, "channel_id": "sora", "client_id": "QR3H6TYEA907B2HRDF6KCBGWYG", "connection_id": "QR3H6TYEA907B2HRDF6KCBGWYG", "minutes": 2, "role": "sendrecv", "video": { "bit_rate": 3000, "codec_type": "VP8" } } ] ``` ### DisconnectChannelUpstream *バージョン 2021.1.0 で削除。* > **危険** > > この API は廃止しました。 **廃止**: 2021 年 6 月リリースの Sora にて廃止 **代替 API**: 20201013.DisconnectChannelByRole **x-sora-target**: Sora_20151104.DisconnectChannelUpstream 指定したチャネルすべての配信者の接続を切断します。 * - キー - 型 * - channel_id - string * - reason (オプション) - object `reason` に値を指定した場合、イベントウェブフック `connection.destroyed` の `reason` に指定した値が入ってきます。 ```console $ curl -sS \ -X POST \ http://127.0.0.1:3000 \ -H "x-sora-target: Sora_20151104.DisconnectChannelUpstream" \ --json '{"channel_id":"sora"}' \ | jq . ``` ### DisconnectChannelDownstream > **危険** > > この API は廃止しました。 **廃止**: 2021 年 6 月リリースの Sora にて廃止 **代替 API**: 20201013.DisconnectChannelByRole **x-sora-target**: Sora_20151104.DisconnectChannelDownstream 指定したチャネルすべての視聴者の接続を切断します。 * - キー - 型 * - channel_id - string * - reason (オプション) - object reason に値を指定した場合、イベントウェブフック connection.destroyed の reason に指定した値が入ってきます。 ```console $ curl -sS \ -X POST \ http://127.0.0.1:3000 \ -H "x-sora-target: Sora_20151104.DisconnectChannelDownstream" \ --json '{"channel_id":"sora"}' \ | jq . ``` ### Disconnect > **危険** > > この API は廃止しました。 > **警告** > > sora.conf にて allow_client_id_assignment を true にしていた場合はこの API は利用できません **廃止**: 2021 年 6 月リリースの Sora にて廃止 **代替 API**: Sora_20151104.DisconnectClient **x-sora-target**: Sora_20151104.Disconnect 指定したクライアント ID の接続を切断する * - キー - 型 * - channel_id - string * - client_id - string * - reason (オプション) - object reason に値を指定した場合、イベントウェブフック connection.destroyed の reason に指定した値が入ってきます。 ``` $ curl -sS \ -X POST \ http://127.0.0.1:3000/ \ -H "x-sora-target: Sora_20151104.Disconnect" \ --json '{"channel_id":"sora","client_id":"HMRVPQEXJX03D3B3WE778SJGRC"}' \ | jq . ``` ### ListConnections > **危険** > > この API は廃止しました。 **廃止**: 2021 年 6 月リリースの Sora にて廃止 **代替 API**: Sora_20201013.ListChannelConnections **x-sora-target**: Sora_20151104.ListConnections 指定したチャネルの接続一覧を取得します。 * - キー - 型 * - channel_id - string ```console $ curl -sS \ -X POST \ http://127.0.0.1:3000/ \ -H "x-sora-target: Sora_20151104.ListConnections" \ --json '{"channel_id":"sora"}' \ | jq . [ { "channel_id": "sora", "client_id": "6DXMKHX8Q106K9YKN693C2D69C", "connection_id": "6DXMKHX8Q106K9YKN693C2D69C", "role": "sendrecv", "simulcast": true, "spotlight": false }, { "channel_id": "sora", "client_id": "QR3H6TYEA907B2HRDF6KCBGWYG", "connection_id": "QR3H6TYEA907B2HRDF6KCBGWYG", "role": "sendrecv", "simulcast": true, "spotlight": false } ] ``` ## 廃止サイマルキャスト API ### ChangeSimulcastQuality > **危険** > > この API は廃止しました。 **廃止**: 2021 年 6 月リリースの Sora にて廃止 **代替 API**: Sora_20201005.RequestRtpStream **x-sora-target**: Sora_20180820.ChangeSimulcastQuality 指定した参加者の視聴する映像の画質を変更する * - キー - 型 * - channel_id - string * - connection_id - string * - stream_id (オプション) - string * - quality - string (high | middle | low) ```console $ curl -sS \ -X POST \ http://127.0.0.1:3000/ \ -H "x-sora-target: Sora_20180820.ChangeSimulcastQuality" \ --json '{"channel_id":"sora","connection_id":"KD9N57E2RN5T1BDEA7S7SH038M","quality":"high"}' \ | jq . { "channel_id": "sora", "connection_id": "KD9N57E2RN5T1BDEA7S7SH038M", "quality": "high" } ``` ## 廃止統計 API ### GetStats > **危険** > > この API は廃止しました。 > **警告** > > sora.conf にて allow_client_id_assignment を true にしていた場合はこの API は利用できません **廃止**: 2021 年 6 月リリースの Sora にて廃止 **x-sora-target**: Sora_20170529.GetStats 指定したクライアントの統計情報を取得します。 * - キー - 型 * - channel_id - string * - client_id - string ```console $ curl -sS \ -X POST \ http://127.0.0.1:3000/ \ -H "x-sora-target: Sora_20170529.GetStats" \ --json '{"channel_id":"sora","client_id":"WZXPMM6K8113K83VB8G9XZDTFW"}' \ | jq . { "channel_id": "sora", "client_id": "WZXPMM6K8113K83VB8G9XZDTFW", "connection_id": "WZXPMM6K8113K83VB8G9XZDTFW", "dtls": { "total_received_dtls": 2, "total_sent_dtls": 2 }, "network_status": { "unstable_level": 0 }, "packet_loss_simulator": { "total_dropped_received_rtp": 0, "total_dropped_sent_rtp": 0 }, "rtp": { "total_generic_nack_cache_hit": 0, "total_generic_nack_cache_miss": 0, "total_pli_trigger": 0, "total_received": 1105, "total_received_byte_size": 845972, "total_received_rtcp": 20, "total_received_rtcp_bye": 0, "total_received_rtcp_byte_size": 1304, "total_received_rtcp_psfb_afb": 0, "total_received_rtcp_psfb_fir": 0, "total_received_rtcp_psfb_pli": 0, "total_received_rtcp_rr": 2, "total_received_rtcp_rtpfb_generic_nack": 0, "total_received_rtcp_rtpfb_tmmbn": 0, "total_received_rtcp_rtpfb_tmmbr": 0, "total_received_rtcp_rtpfb_transport_wide": 0, "total_received_rtcp_sdes": 18, "total_received_rtcp_sr": 18, "total_received_rtcp_unknown": 0, "total_received_rtcp_xr": 0, "total_received_rtp": 1085, "total_received_rtp_byte_size": 844668, "total_received_rtp_red": 0, "total_received_rtp_red_rtx": 0, "total_received_rtp_red_ulpfec": 0, "total_received_rtp_rtx": 0, "total_sent": 9, "total_sent_byte_size": 606, "total_sent_rtcp": 9, "total_sent_rtcp_bye": 0, "total_sent_rtcp_byte_size": 606, "total_sent_rtcp_psfb_afb": 8, "total_sent_rtcp_psfb_fir": 0, "total_sent_rtcp_psfb_pli": 0, "total_sent_rtcp_rr": 9, "total_sent_rtcp_rtpfb_generic_nack": 0, "total_sent_rtcp_rtpfb_tmmbn": 0, "total_sent_rtcp_rtpfb_tmmbr": 0, "total_sent_rtcp_rtpfb_transport_wide": 0, "total_sent_rtcp_sdes": 0, "total_sent_rtcp_sr": 0, "total_sent_rtcp_unknown": 0, "total_sent_rtcp_xr": 0, "total_sent_rtp": 0, "total_sent_rtp_byte_size": 0 }, "timestamp": "2020-06-09T05:42:40Z", "turn": { "total_received_allocate_request": 11, "total_received_binding_request": 0, "total_received_channel_bind_request": 1, "total_received_channel_data": 1113, "total_received_create_permission_request": 2, "total_received_expired_channel_number": 0, "total_received_refresh_request": 0, "total_received_send_indication": 7, "total_received_turn_binding_error": 0, "total_received_turn_binding_request": 7, "total_received_turn_binding_success": 6, "total_received_turn_invalid_stun": 0, "total_received_turn_unknown": 0, "total_received_turn_unknown_stun": 0, "total_received_unknown_channel_number": 0, "total_sent_allocate_error": 7, "total_sent_allocate_success": 2, "total_sent_binding_error": 0, "total_sent_binding_success": 0, "total_sent_channel_bind_error": 0, "total_sent_channel_bind_success": 1, "total_sent_channel_data": 19, "total_sent_create_permission_error": 0, "total_sent_create_permission_success": 2, "total_sent_data_indication": 5, "total_sent_refresh_error": 0, "total_sent_refresh_success": 0, "total_sent_turn_binding_error": 0, "total_sent_turn_binding_request": 6, "total_sent_turn_binding_success": 2, "total_sent_turn_unknown": 0 } } ``` ## 廃止プッシュ API ### PushUpstream > **危険** > > この API は廃止しました。 **廃止**: 2021 年 6 月リリースの Sora にて廃止 **代替 API**: Sora_20201120.PushChannelByRole **x-sora-target**: Sora_20160711.PushUpstream 指定したチャネルの配信クライアントにプッシュ通知を送ります。 * - キー - 型 * - channel_id - string * - data - object ```console $ curl -sS \ -X POST \ http://127.0.0.1:3000/ \ -H "x-sora-target: Sora_20160711.PushUpstream" \ --json '{"channel_id":"sora","data":{"spam":"egg"}}' \ | jq . { "data": { "spam": "egg" }, "type": "push" } ``` ### PushDownstream > **危険** > > この API は廃止しました。 **廃止**: 2021 年 6 月リリースの Sora にて廃止 **代替 API**: Sora_20201120.PushChannelByRole **x-sora-target**: Sora_20160711.PushDownstream 指定したチャネルの視聴クライアントにプッシュ通知を送ります。 * - キー - 型 * - channel_id - string * - data - object ``` $ curl -sS \ -X POST \ http://127.0.0.1:3000/ \ -H "x-sora-target: Sora_20160711.PushDownstream" \ --json '{"channel_id":"sora","data":{"spam":"egg"}}' \ | jq . { "data": { "spam": "egg" }, "type": "push" } ``` ## 廃止リモート統計情報 API ### 統計情報更新のタイミングについて この統計情報は、シグナリングで死活監視用の Pong メッセージに含まれてくるクライアント統計情報の最新の値を返します。 Ping メッセージは 5 秒間隔で Sora から送られるため、ネットワークが正常であれば Pong メッセージが返ってくるのは 5 秒間隔となります。 そのため、統計情報は 5 秒間隔で更新されます。 ### GetAllRemoteStats > **危険** > > この API は廃止しました。 **廃止**: 2022 年 6 月リリースの Sora にて廃止 **代替 API**: Sora_20211215.ListUserAgentStats **x-sora-target**: Sora_20200225.GetAllRemoteStats すべてのリモート統計情報を取得する。 ```console $ curl -sS \ -X POST \ http://127.0.0.1:3000/ \ -H "x-sora-target: Sora_20200225.GetAllRemoteStats" \ | jq . [ { "channel_id": "sora", "connection_id": "HMRVPQEXJX03D3B3WE778SJGRC", "remote_stats": [ { "audioLevel": 0, "id": "RTCAudioSource_1", "kind": "audio", "timestamp": 1586417492054.487, "totalAudioEnergy": 0, "totalSamplesDuration": 24.930000000001098, "trackIdentifier": "8de161d9-c93f-4c8a-ab0e-c4cb1ed45543", "type": "media-source" }, ... ], "timestamp": "2020-04-09T07:31:32.056Z" } ] ``` ### GetChannelRemoteStats > **危険** > > この API は廃止しました。 **廃止**: 2022 年 6 月リリースの Sora にて廃止 **代替 API**: Sora_20211215.ListChannelUserAgentStats **x-sora-target**: Sora_20200225.GetChannelRemoteStats 指定したチャネルのリモート統計情報を取得する。 * - キー - 型 * - channel_id - string ```console $ curl -sS \ -X POST \ http://127.0.0.1:3000/ \ -H "x-sora-target: Sora_20200225.GetChannelRemoteStats" \ --json '{"channel_id":"sora"}' \ | jq . [ { "channel_id": "sora", "connection_id": "HMRVPQEXJX03D3B3WE778SJGRC", "remote_stats": [ { "audioLevel": 0, "id": "RTCAudioSource_1", "kind": "audio", "timestamp": 1586417557067.526, "totalAudioEnergy": 0, "totalSamplesDuration": 89.95000000000911, "trackIdentifier": "8de161d9-c93f-4c8a-ab0e-c4cb1ed45543", "type": "media-source" }, ... ], "timestamp": "2020-04-09T07:32:37.069Z" } ] ``` ### GetConnectionRemoteStats > **危険** > > この API は廃止しました。 **廃止**: 2022 年 6 月リリースの Sora にて廃止 **代替 API**: Sora_20211215.GetUserAgentStats **x-sora-target**: Sora_20200225.GetConnectionRemoteStats 指定した接続のリモート統計情報を取得する。 * - キー - 型 * - channel_id - string * - connection_id - string ```console $ curl -sS \ -X POST \ http://127.0.0.1:3000/ \ -H "x-sora-target: Sora_20200225.GetConnectionRemoteStats" \ --json '{"channel_id":"sora","connection_id":"HMRVPQEXJX03D3B3WE778SJGRC"}' \ | jq . { "channel_id": "sora", "connection_id": "HMRVPQEXJX03D3B3WE778SJGRC", "stats": [ { "audioLevel": 0, "id": "RTCAudioSource_1", "kind": "audio", "timestamp": 1586417622080.464, "totalAudioEnergy": 0, "totalSamplesDuration": 154.96000000000404, "trackIdentifier": "8de161d9-c93f-4c8a-ab0e-c4cb1ed45543", "type": "media-source" }, ... ], "timestamp": "2020-04-09T07:33:42.081Z" } ``` ## 廃止スポットライト API ### CastSpotlight > **危険** > > この API は廃止しました。 **廃止**: 2021 年 12 月リリースの Sora にて廃止 **x-sora-target**: Sora_20180404.CastSpotlight 指定した参加者を強制的に画面に表示する。 * - キー - 型 * - channel_id - string * - connection_id - string ```console $ curl -sS \ -X POST \ http://127.0.0.1:3000/ \ -H "x-sora-target: Sora_20180404.CastSpotlight" \ --json '{"channel_id":"sora","connection_id":"KD9N57E2RN5T1BDEA7S7SH038M"}' \ | jq . { "channel_id": "sora", "connection_id": "KD9N57E2RN5T1BDEA7S7SH038M" } ``` ### CastAlwaysSpotlight > **危険** > > この API は廃止しました。 **廃止**: 2021 年 12 月リリースの Sora にて廃止 **x-sora-target**: Sora_20180404.CastAlwaysSpotlight 指定した参加者を常に画面に表示します。 * - キー - 型 * - channel_id - string * - connection_id - string * - spotlight_id (オプション) - string spotlight_id を指定しない場合はどこかのスポットライトに入ります。 ```console $ curl -sS \ -X POST \ http://127.0.0.1:3000/ \ -H "x-sora-target: Sora_20180404.CastAlwaysSpotlight" \ --json '{"channel_id":"sora","connection_id":"KD9N57E2RN5T1BDEA7S7SH038M","spotlight_id":"spotlight-1"}' \ | jq . { "channel_id": "sora", "connection_id": "KD9N57E2RN5T1BDEA7S7SH038M", "spotlight_id": "spotlight-1" } ``` ### CancelSpotlight > **危険** > > この API は廃止しました。 **廃止**: 2021 年 12 月リリースの Sora にて廃止 **x-sora-target**: Sora_20180404.CancelSpotlight 指定した参加者を常に画面に表示する状態を解除します。 * - キー - 型 * - channel_id - string * - connection_id - string ```console $ curl -sS \ -X POST \ http://127.0.0.1:3000/ \ -H "x-sora-target: Sora_20180404.CancelSpotlight" \ --json '{"channel_id":"sora","connection_id":"KD9N57E2RN5T1BDEA7S7SH038M"}' \ | jq . { "channel_id": "sora", "connection_id": "KD9N57E2RN5T1BDEA7S7SH038M" } ``` ### DowngradeSpotlightBitRate > **危険** > > この API は廃止しました。 **廃止**: 2021 年 12 月リリースの Sora にて廃止 **x-sora-target**: Sora_20181023.DowngradeSpotlightBitRate 指定したスポットライトチャネルのビットレートを下げる。 * - キー - 型 * - channel_id - string 現時点ではどの程度下げるかどうかは指定できません。 ``` $ curl -sS \ -X POST \ http://127.0.0.1:3000/ \ -H "x-sora-target: Sora_20181023.DowngradeSpotlightBitRate" \ --json '{"channel_id":"sora"}' \ | jq . ``` ### ResetSpotlightBitRate > **危険** > > この API は廃止しました。 **廃止**: 2021 年 12 月リリースの Sora にて廃止 **x-sora-target**: Sora_20181023.ResetSpotlightBitRate 指定したスポットライトチャネルのビットレートを戻します。 * - キー - 型 * - channel_id - string ``` $ curl -sS \ -X POST \ http://127.0.0.1:3000/ \ -H "x-sora-target: Sora_20181023.ResetSpotlightBitRate" \ --json '{"channel_id":"sora"}' \ | jq . { "channel_id": "sora", "connection_id": "DRPBMP6FEH49S5CSB04EDSTQ38", "quality": "low" } ``` ### RequestSpotlightQuality > **危険** > > この API は廃止しました。 **廃止**: 2020 年 12 月リリースの Sora にて廃止 **代替 API**: Sora_20201005.RequestRtpStream **x-sora-target**: Sora_20200807.RequestSpotlightQuality 指定した参加者の受信している映像ストリームのクオリティを変更します。 スポットライトのフォーカスとは別に、画質を受信ストリームすべて、またはストリームごと変更できます。 現時点では low か middle のみ指定できます。 * - キー - 型 * - channel_id - string * - connection_id - string * - stream_id (オプション) - string * - quality - string (low / middle / high) ```console $ curl -sS \ -X POST \ http://127.0.0.1:3000/ \ -H "x-sora-target: Sora_20200807.RequestSpotlightQuality" \ --json '{"channel_id":"sora","connection_id":"DRPBMP6FEH49S5CSB04EDSTQ38","quality":"low"}' \ | jq . { "channel_id": "sora", "connection_id": "DRPBMP6FEH49S5CSB04EDSTQ38", "quality": "low" } ``` ### ResetSpotlightQuality > **危険** > > この API は廃止しました。 **廃止**: 2020 年 12 月リリースの Sora にて廃止 **代替 API**: Sora_20201005.ResetRtpStream **x-sora-target**: Sora_20200807.ResetSpotlightQuality 指定した参加者の受信している映像ストリームのクオリティをリセットします。 RequestSpotlightQuality で変更された画質をリセットします。 * - キー - 型 * - channel_id - string * - connection_id - string * - stream_id (オプション) - string ```console $ curl -sS \ -X POST \ http://127.0.0.1:3000/ \ -H "x-sora-target: Sora_20200807.ResetSpotlightQuality" \ --json '{"channel_id":"sora","connection_id":"DRPBMP6FEH49S5CSB04EDSTQ38"}' \ | jq . { "channel_id": "sora", "connection_id": "DRPBMP6FEH49S5CSB04EDSTQ38" } ``` # テスト API > **注意** > > テスト API はテスト目的のためだけに利用してください ## 概要 テスト API は意図的に発生させるのが難しい状況を API 経由で発生させるための API です。 ## 設定 テスト API を利用するには `sora.conf` の [test_api](SORA_CONF.html#a2f020) を `true` に設定する必要があります。 デフォルトは `false` です。 ## 注意 - テスト API は利便性を最優先にするため破壊的変更を積極的に行います ## GenerateCrashLog **x-sora-target**: Sora_20380119.GenerateCrashLog 意図的に Sora のクラッシュログを発生させます。クラッシュログの監視のテストなどに利用してください。 この API はかならずステータスコード `500` を返します。 * - キー - 型 * - info - object ```console $ curl -sS \ -X POST \ http://127.0.0.1:3000/ \ -H "x-sora-target: Sora_20380119.GenerateCrashLog" \ --json '{"info":{"spam":"egg"}}' \ | jq . ``` ## FailArchive *バージョン 2024.1.0 で追加。* *バージョン 2024.2.0 で変更。* クラスターに対応しました **x-sora-target**: Sora_20380119.FailArchive 意図的に Sora の録画を失敗させます。 `archive.failed` ウェブフックを意図的に出力させたい場合に利用してください。 テストの利便性を考えランダムな値である `connection_id` ではなく、固定値として設定できる `client_id` を指定できるようにしています。 `client_id` は指定しなければ `connection_id` が設定されるので、 `client_id` を指定しない場合、 `client_id` に `connection_id` を指定しても動作します。 * - キー - 型 * - channel_id - string * - client_id - string ```console $ curl -sS \ -X POST \ http://127.0.0.1:3000/ \ -H "x-sora-target: Sora_20380119.FailArchive" \ --json '{"channel_id":"sora","client_id":"test"}' \ | jq . ``` ## SendSignalingNotify *バージョン 2024.1.0 で追加。* **x-sora-target**: Sora_20380119.SendSignalingNotify 指定した内容のシグナリング通知として送信します。シグナリング通知のテストなどに利用してください。 - 指定したチャネルの参加者全員に json に指定した値がそのまま通知されます - クラスター機能を利用していた場合、API を実行したノードでのみ通知されます * - キー - 型 * - channel_id - string * - json - object ```console $ curl -sS \ -X POST \ http://127.0.0.1:3000/ \ -H "x-sora-target: Sora_20380119.SendSignalingNotify" \ --json '{"channel_id":"sora","json":{"type":"notify","event_type":"audio-streaming-failed"}}' \ | jq . ``` ## LockIceConnectionState *バージョン 2024.2.0 で追加。* **x-sora-target**: Sora_20380119.LockIceConnectionState ICE コネクションステートの状態を指定した状態に変更しロックします。ICE コネクションステートのテストなどに利用してください。 一度でもこの API で状態を変更した場合は、ICE コネクションステート機能は機能しなくなりますので注意してください。 ただし状態を変更した際のシグナリング通知は通知されます。 * - キー - 型 * - channel_id - string * - connection_id - string * - state_name - string (connected | checking | disconnected) ```console $ curl -sS \ -X POST \ http://127.0.0.1:3000/ \ -H "x-sora-target: Sora_20380119.LockIceConnectionState" \ --json '{"channel_id":"sora","connection_id":"6V9VANDZZH71HCQGVKBWKJ8GS0","state_name":"checking"}' \ | jq . ``` # クラスター機能 ## 概要 これは複数の Sora でクラスターを構成し、冗長化、負荷分散を行うための仕組みです。 ひとつのチャネル ID をクラスターに参加している複数の Sora で共有することができます。 そのため、Sora をクラスターに追加で参加させることで 1 チャネル単位での配信をスケールアウトさせることができます。 ここではクラスター機能について説明しています。 - クラスター機能を動かしてみる場合は [クラスター機能のチュートリアル](CLUSTER_TUTORIAL.html) をご確認ください - クラスター機能の運用については [クラスター機能の運用](CLUSTER_OPS.html) をご確認ください - クラスター機能利用時の録画については [クラスター機能での録画機能](CLUSTER_RECORDING.html) をご確認ください ## 用語 **ノード** : クラスターに参加している Sora **レギュラーノード** : クラスター構成を維持するノード **テンポラリーノード** : クラスター構成を維持しないノード、ノードを停止すると強制的にクラスターから消去される **リレー** : ノード間で音声、映像、データを転送すること **アフィニティ** : 同一セッションの接続を同一ノードに集約すること ## クライアントへの複数シグナリング設定 Sora SDK にシグナリング URL を複数指定することで、いずれかの ノードが正常に動作していれば Sora に繋がります。 > **注釈** > > 最低 3 つ、レギュラーノードのシグナリング URL を渡すことを推奨しています。 ## リレー機能 > **重要** > > リレー機能を利用するには [最大ノード数ライセンス](LICENSE.html#aee259) が必要です。 > **注意** > > リレー機能を利用する際、ノード間通信には同一データセンター内のプライベートネットワークを利用してください。 Sora クラスターはリレーという仕組みで、 クラスターに参加しているノード同士で、クライアントの音声や映像、データを共有します。 例えば 3 ノードのクラスターがある場合、 すでに接続しているクライアントがいるノードとは異なるノードにクライアントが接続した場合、 Sora はその異なるノードにすでに接続しているクライアントの音声や映像、データをリレーします。 この機能を利用することで 1 チャネルでのスケールアウトを実現できるようになります。 リレー機能はクラスター機能が有効な場合に利用できます。 リレー機能はデフォルトで有効になっています。 無効にしたい場合は `sora.conf` の [cluster_relay](SORA_CONF.html#0ef660) を変更してください。 ```ini cluster_relay = false ``` ### リレー発生のタイミング リレー機能利用時、リレーが発生するタイミングは別ノードに同一チャネルへ参加しているクライアントがいる場合のみです。 同一ノードのみの場合は他のノードへのリレーは発生しません。 ### リレー終了のタイミング 一度リレーが発生した場合、セッションが破棄されるまではリレーが破棄されることは基本的にありません。 ### メッセージングのリレー リレー機能は音声と映像だけでなく、メッセージもリレーを行います。そのため、リレー機能ではメッセージング機能も利用できます。 ### 最大ノード数ライセンス リレー機能は [最大ノード数ライセンス](LICENSE.html#aee259) が必要です。もし [最大ノード数ライセンス](LICENSE.html#aee259) を利用せずに、 `sora.conf` の [cluster_relay](SORA_CONF.html#0ef660) を `true` にした場合、リレー機能は無効になります。 ### 接続したノードが最大同時接続数に達していた場合 もし接続したノードがライセンスの最大同時接続数に達している場合は、 余裕のある別ノードへのリダイレクトを試みます。 ## アフィニティ機能 > **重要** > > アフィニティ機能を利用するには [最大ノード数ライセンス](LICENSE.html#aee259) が必要です。 Sora クラスターはリレー機能利用時に、同一セッションの接続を同一ノードに集約するアフィニティ機能を提供します。 同一セッションへの接続を同一ノードに集約することでレイテンシーを低減し、より低遅延な通信を実現できます。 アフィニティ機能はデフォルトで有効になっています 無効にしたい場合は `sora.conf` の [default_cluster_affinity](SORA_CONF.html#95466d) を変更してください ```ini default_cluster_affinity = false ``` アフィニティはクラスター単位でのデフォルト値以外に、コネクション単位で指定することもできます。 コネクション単位の指定は `sora.conf` の [default_cluster_affinity](SORA_CONF.html#95466d) の値を上書きします この仕組みを利用することで特定のコネクションだけアフィニティを行わず、最初に接続したノードで WebRTC の確立を試みることができるようになります。 > **注釈** > > リレー機能を検証したい場合は `sora.conf` の [default_cluster_affinity](SORA_CONF.html#95466d) を `false` に設定してください。 ### 接続したノードが最大同時接続数に達していた場合 もし接続したノードがライセンスの最大同時接続数に達している場合は、 余裕のある別ノードへのリダイレクトを試みます。 ### コネクション単位でのアフィニティ指定 認証ウェブフックの認証成功時の払い出しで `cluster_affinity` を指定することができます。 ```javascript { "allowed": true, "cluster_affinity": "" } ``` `"cluster_affinity": true` を指定した場合は、接続したノードがセッションを集約しているノードでなければ、 `"type": "redirect"` をクライアントへ返し、集約しているノードへの再接続を要求します。 `"cluster_affinity": false` を指定した場合は、ノードへの集約を行わず、接続したノードでの WebRTC 確立を試みます。 ### クラスターアフィニティ利用時の 1 ノードセッション同時接続数基準値指定 > **注意** > > この設定を利用する場合は事前にサポートまでご相談ください 接続したノードのセッション単位での同時接続数が `sora.conf` の [cluster_affinity_threshold](SORA_CONF.html#2abc6a) で指定した基準値を超えていた場合、 他のノードへのリダイレクトを試みるようになります。 全てのノードで基準値を超えた場合は、ノード単位での同時接続数が最も少ないノードにリダイレクトを試みます。 この設定はチューニング向けのため、基本的にはデフォルトから変更する必要はありません。 ```ini cluster_affinity_threshold = 20 ``` ### リレー機能利用時の認証について リレー機能を利用している場合、認証成功時の払い出しでアフィニティを判断するため、 接続したノードで必ず認証を行います。 アフィニティが有効な場合は、別ノードへのリダイレクトが発生する場合があります。 その場合は別ノードでも認証が行われます。 アフィニティが無効な場合でも、接続を行ったノードがライセンスの上限に達していた場合で、 クラスター全体ではまだライセンスの上限に達していない場合は別ノードへのリダイレクトが発生します。 その場合は別ノードでも認証が行われます。 詳細は [クラスターリレー機能利用時に認証が 2 回行われる場合がある](AUTH_WEBHOOK.html#a1fc2c) をご確認ください。 ## アフィニティ機能の接続先ノード範囲指定機能 > **重要** > > 接続先ノード範囲指定機能を利用するには [最大ノード数ライセンス](LICENSE.html#aee259) が必要です。 > **注意** > > 接続先ノード範囲指定機能は実験的機能です。利用する際は、事前にサポートまでご相談ください。 Sora では、認証成功時の払い出しで `cluster_affinity_node_name_list` を指定することで、アフィニティ機能で接続先として利用するノードを限定できます。 この機能は、たとえば、セキュリティ要件により、ファイアウォールなどで接続先の Sora ノードの IP アドレスを制限したい場合や、同一地域のユーザーを指定したノードに集約させたい場合などに有効です。 ### アフィニティ機能無効との違い アフィニティ機能そのものを無効にすると、Sora は同一セッションの接続を特定のノードに集約しません。 そのため、クライアントが最初に接続したノードをそのまま利用しやすくなります。 ただし、接続先のノードがライセンスの上限に達している場合は、他のノードへのリダイレクトが発生します。 一方で、接続先ノード範囲指定機能は、接続先をあらかじめ指定した特定のノード範囲に限定する機能です。 指定した複数のノードがいずれも利用できない場合、Sora はリダイレクトせずに接続を失敗させます。 ### 仕様 - `cluster_affinity_node_name_list` を指定する際、 `cluster_affinity` は `true` を指定する必要があります - 認証成功時の払い出しで `cluster_affinity_node_name_list` を指定することで、接続先を特定のノード範囲に固定できます - 固定先の指定はコネクション単位で適用されます - 認証ウェブフックの認証成功時の戻り値でのみ指定できます - 複数のノードを指定した場合は、指定したノード範囲から接続先として利用できるノードが選択されます - 指定できるノードはクラスターに参加しているノードのみです - 指定するノードは 1 つ以上必要です - アクセスしたノードが `cluster_affinity_node_name_list` に含まれていない場合、含まれているノードへリダイレクトします - アクセスしたノードが `cluster_affinity_node_name_list` に含まれている場合でも、別の含まれているノードへリダイレクトされる場合があります ### 利用方法 認証ウェブフックの認証成功時の戻り値に `cluster_affinity` を `true` にして、 `cluster_affinity_node_name_list` を指定してください。 > **重要** > > [default_cluster_affinity](SORA_CONF.html#95466d) が `true` の場合でも、認証成功時の払い出しで `cluster_affinity` を `true` で払い出さない場合はこの機能は有効になりません。 `cluster_affinity_node_name_list` には固定対象とするノード名のリストを指定します。 この指定はコネクション単位で適用されます。ノード名は `sora.conf` の `node_name` で指定した値です。 ```javascript { "allowed": true, "cluster_affinity": true, "cluster_affinity_node_name_list": ["node-01@192.0.2.5", "node-02@192.0.2.7"] } ``` > **警告** > > 以下のケースでは `sora.jsonl` に警告ログが出力され、 `cluster_affinity_node_name_list` の指定は無視されます。 > > - `cluster_affinity` が `true` で指定されていない場合 > - [最大ノード数ライセンス](LICENSE.html#aee259) が取得されていない環境で `cluster_affinity: true` を払い出した場合 ### エラー #### invalid_affinity_node_name_list `invalid_affinity_node_name_list` は、 `cluster_affinity_node_name_list` の指定内容自体に問題がある場合のエラーです。 具体的には、以下のいずれかに該当する場合です。 - `cluster_affinity_node_name_list` に空のリストを指定した - クラスターリレー機能が無効な状態で指定した - 指定したノードのうち有効なノードが 1 つもない クライアントには WebSocket Close フレームで `code` に `4490`、 `reason` に `SERVICE-UNAVAILABLE` が通知されます。 このとき `signaling_error.jsonl` の `details.reason` には `invalid_affinity_node_name_list` が出力されます。 指定したノードのうち有効なノードが 1 つ以上ある場合は、 `sora.jsonl` に警告ログが出力されますが、処理は継続します。 #### no_acceptable_node `no_acceptable_node` は、 `cluster_affinity_node_name_list` に指定したノード自体には問題ないものの、 接続先として利用できるノードが 1 つもない場合のエラーです。 具体的には、以下のいずれかに該当する場合です。 - 指定したノードが全てライセンスの最大同時接続数に達している - 指定したノードが全て新しくコネクションが接続できない状態になっている この場合、クライアントには WebSocket Close フレームで `code` に `4490`、 `reason` に `SERVICE-UNAVAILABLE` が通知されます。 このとき `signaling_error.jsonl` の `details.reason` には `no_acceptable_node` が出力されます。 ### 運用 アクセス先の IP アドレスを固定して運用する場合でも、 `cluster_affinity_node_name_list` には少なくとも 2 つのノードを指定することを推奨します。 1 つのノードだけを指定すると、そのノードがダウンした場合やクラスターから離脱した場合に、 接続先として利用できるノードがなくなり、 `no_acceptable_node` により接続できなくなることがあります。 固定 IP と可用性を両立したい場合は、接続先として利用するノードを複数指定してください。 ## テンポラリーノード機能 > **重要** > > テンポラリーノード機能を利用するには [最大ノード数ライセンス](LICENSE.html#aee259) が必要です。 テンポラリーノードはクラスター構成を維持するためのノードとして認識されず、 ノードを停止すると強制的にクラスターから消去されます。 そのため、クラスターを気軽にスケールアウト/スケールインさせることができます。 注意点としてテンポラリーノードが何ノード稼働していたとしても、 生存しているレギュラーノードが過半数を下回った場合、クラスターは利用できなくなります。 ### 設定 `sora.conf` で `cluster_temporary_node` を `true` に設定することでテンポラリーノードとして扱われます。 ```ini cluster_temporary_node = true ``` ### 登録 クラスターへの登録はレギュラーノードと同様 [RegisterClusterNode](API_CLUSTER.html#09ed96) API を利用してください。 テンポラリーノードはノードを停止したタイミングで、クラスターから強制的に消去されます。 そのため、再度クラスターに登録するには [RegisterClusterNode](API_CLUSTER.html#09ed96) API を利用して登録してください。 ### 消去 テンポラリーノードはクラスターを維持するためのノードとして認識されず、 ノードを停止することでクラスターから強制的に消去されます。 そのためノード離脱時に [PurgeClusterNode](API_CLUSTER.html#13b35a) API でノードを消去する必要はありません。 ### ネットワーク障害時 テンポラリーノードがネットワーク障害でクラスターから切断されたとしても、 ノードを停止しなければ自動でクラスターに復帰します。 ### ノード障害時 テンポラリーノードが何かしらの障害で停止した場合は、必ず登録が必要です。 ### 注意 - テンポラリーノードを利用するには [最大ノード数ライセンス](LICENSE.html#aee259) が必要です - テンポラリーノードはクラスター構成を維持するためのノードとしては認識されません - テンポラリーノードに障害が発生してもライセンスで決められた最大同時接続数の合計を維持する機能による接続数の維持は行われません - テンポラリーノードはクラスターへの登録には [RegisterClusterNode](API_CLUSTER.html#09ed96) API を利用してください - テンポラリーノードは停止時にクラスターから消去されます - テンポラリーノードを再起動した場合、クラスターには自動で参加しません。再度 [RegisterClusterNode](API_CLUSTER.html#09ed96) API を利用して登録してください - テンポラリーノードだけでクラスターを構築することはできません - テンポラリーノードは [PurgeClusterNode](API_CLUSTER.html#13b35a) API でノードを消去することはできません - テンポラリーノードは [InitCluster](API_CLUSTER.html#621990) API で初期化することはできません ## シグナリングのリダイレクト機能 > **重要** > > Sora の SDK を利用している場合は、 > 基本的にここに書かれているリダイレクトの細かい仕様を把握する必要はありません。 `"type": "connect"` を送った際、認証処理前と認証処理後に、 `{"type": "redirect", "location": "wss://sora1.example.com/signaling"}` が Sora から送られてくる場合があります。 この場合は、送られてきた location の URL にシグナリング URL を切り替えて再度 `type: connect` を行ってください。 その際は `{type: connect, redirect: true}` のように `redirect: true` を追加情報として入れてください。 ### 接続したノードが最大同時接続数に達していた場合 - リレー機能が無効な場合、チャネルのセッションが接続したノードに生成されている場合は接続に失敗します - リレー機能が無効な場合、チャネルのセッションが接続したノードに生成されていない場合、余裕のあるノードへリダイレクトを試みます - リレー機能が有効な場合、余裕のあるノードへリダイレクトを試みます ## リダイレクト機能によるノード選択 ### リレー機能有効かつアフィニティ機能有効時 アフィニティ機能が有効な場合はできるだけ同一セッションを同一ノードに集約します。 すでに、そのチャネル ID がクラスター内部で利用されている場合は、 そのチャネル ID のセッションが存在するノードへ接続先の割り当てを試みます。 また、そのチャネル ID がクラスター内部で利用されているが、 そのチャネル ID のセッションが存在するノードのセッション単位の同時接続数が、 [cluster_affinity_threshold](SORA_CONF.html#2abc6a) の基準値を超えていた場合は、 他のノードへの割り当てを試みます。 ちなみに、全てのノードで [cluster_affinity_threshold](SORA_CONF.html#2abc6a) の基準値を超えた場合は、 一番余裕のあるノードへの割り当てを試みます。 割り当てられたノードの同時接続数がライセンスの上限に達していた場合、 一番余裕のあるノードへの割り当てを試みます。 ### リレー機能有効かつアフィニティ機能無効時 すでに、そのチャネル ID がクラスター内部で利用されている場合でも、 接続したノードへの割り当てを試みます。 接続したノードが同時接続数のライセンスの上限に達成していた場合、 一番余裕のあるノードへの割り当てを試みます。 ### リレー機能無効時 すでに、そのチャネル ID がクラスター内部で利用されている場合は、 そのチャネル ID のセッション ID が存在するノードへ割り当てを試みます。 ただし、そのノードの同時接続数がライセンスの上限に達していた場合、 接続に失敗します。 ## ロードバランス機能 クラスターを構築しているノードの中で `ライセンスの最大同時接続数` を `現在の同時接続数` で引いた値が一番小さいノードに、チャネル ID の新規セッションを割り当てます。 この値がすべて同じ場合は、接続しに行ったノード自身が新規チャネル ID のセッションを担当します。 また、接続したノードがライセンスの最大同時接続数に達していた場合、 他のノードへのリダイレクトを試みます。 ### アフィニティ機能を無効にしている場合 アフィニティ機能を無効にしている場合は接続を試みたノードに接続し、リダイレクトは一切発生しません。 ただし、ライセンスの最大同時接続数を超えていた場合、他のノードへのリダイレクトを試みます。 ## HTTP API のリダイレクト機能 チャネル ID を指定する HTTP API を利用する場合、リダイレクトが発生することがあります。 指定されたチャネル ID を他ノードが担当している場合に、ステータスコード 307 (Temporary Redirect)の HTTP 応答により、クライアントにそのノードへのリダイレクトを要求します。 ステータスコード 307 の HTTP 応答受信時の処理は、HTTP のクライアントとして使用するツールやライブラリにより異なります。 必要に応じて、リダイレクト応答の Location ヘッダーへアクセスを継続するようにしてください。 [curl](https://curl.se/) の場合は `--location` (`-L`) を指定することで、リダイレクト先への再要求を行います。 ## クラスターへの登録 クラスターへノードを登録する機能です。 既存のクラスターに登録する際に、クラスターに登録させるノードで [RegisterClusterNode](API_CLUSTER.html#09ed96) API を実行します。 また、そのノードが一度でもクラスターに参加したことがある場合は、クラスターへの参加を自動で試みます。 ## クラスター自動復旧 クラスターで利用しているネットワークに障害が発生した際には、個々のノードはクラスターを構成する他のノードへの接続を試みて、復旧処理を行います。 ## ネットワーク分断時の接続受け付けの停止 ネットワーク分断時には Sora のノード間で通信ができずに、クラスター内の情報の整合性が取れなくなる可能性があります。 この情報の不整合を回避するために、Sora は自分がクラスター内の半数以下のグループに属した場合には、既存の接続を切断し、 さらに新規接続の受け付けも停止します。 ## 特定ノードへの新規チャネル ID の割り当て停止 [モード機能](MODE.html) の [新規セッションブロックモード](MODE.html#041e1c) または [新規コネクションブロックモード](MODE.html#0b67d3) になっている場合は、 そのノードに対して新規チャネル ID の割り当てを行いません。 ## ライセンスで決められた最大同時接続数の合計を維持する機能 > **重要** > > ライセンスで決められた最大同時接続数の合計を維持する機能を利用するには [最大ノード数ライセンス](LICENSE.html#aee259) が必要です。 クラスターを構築している場合、特定のノードがハードウェア障害などで利用できなくなった場合、 残りのノードで障害が発生したレギュラーノードの同時接続数を引き継ぎます。 例えば 100 同時接続のレギュラーノードを 3 つでクラスターを構築している場合、 1 つのレギュラーノードに障害が発生した場合は 2 つのノードで 300 同時接続を維持できます。 割り当ては 1 つのノードが 150 までの同時接続数を許容できるようになります。 障害が発生したレギュラーノードが復旧したとしても 100 を超えている接続を切断することはありません。 ただし 1 ノードの最大同時接続数の 100 までに戻ります。 ### 切り上げ レギュラーノードが 3 ノード、テンポラリーノードが 1 ノードあり、 それぞれが 100 同時接続数をできる場合、 レギュラーノードが 1 ノード障害が発生した場合、残りの 3 ノードがそれぞれ +34 同時接続数を一時的に引き継ぎます。 残りのノード数で割った結果の小数点以下は切り上げます。 ### テンポラリーノード利用時の注意 この機能はテンポラリーノードには適用されません。 例えばレギュラーノードが 3 ノード、テンポラリーノードが 1 ノードあり、 それぞれが 100 同時接続数をできる場合、テンポラリーノードが 1 ノード障害が発生したとしても、 テンポラリノードの同時接続数分を維持することはありません。 レギュラーノード 1 ノードに障害が発生した場合、テンポラリーノードは同時接続数分の維持を行います。 ## 設定 クラスター機能を利用するには以下の設定を行ってください。 - [cluster](SORA_CONF.html#b2cd99) - [node_name](SORA_CONF.html#748d89) - [external_signaling_url](SORA_CONF.html#d6bf68) - [external_api_url](SORA_CONF.html#8b922a) ### cluster **必須設定** クラスター機能を利用する場合、 `sora.conf` にて [cluster](SORA_CONF.html#b2cd99) を `true` を設定する必要があります。 デフォルトでは `cluster` は有効になっていません。 > **重要** > > cluster = true にして Sora を起動した場合、 > Sora は [InitCluster](API_CLUSTER.html#621990) API を実行するか、クラスターに参加して過半数のグループになったタイミングでのみ利用可能になります。 ```ini cluster = true ``` ### node_name **必須設定** クラスター機能を利用する際のノード名を指定して下さい。 この名前はクラスター内のノードの識別に使われます。 具体的には、クラスターノード間の通信相手の特定や、 [RegisterClusterNode](API_CLUSTER.html#09ed96) API、 [PurgeClusterNode](API_CLUSTER.html#13b35a) API で指定する名前として利用します。 > **重要** > > `node_name` はクラスター内のすべてのノードでユニークである必要があります ノード名の @ の前には、正規表現 `[0-9A-Za-z_\\-]+` にマッチする任意の文字列を指定してください。 また @ の後ろには、他のノードからアクセス可能なこのノードのドメイン名(FQDN)や、IP アドレスを指定してください。 @ の後ろにホスト名("." を含まない文字列)のみを指定すると、ノード間で通信が行えなくなってしまいますので、ご注意ください。 ```ini # ドメイン名を指定する例 node_name = node01@node01.example.com ``` ```ini # IP アドレスを指定する例 node_name = node02@192.0.2.1 ``` ### external_signaling_url **必須設定** `sora.conf` にてシグナリングの URL を指定して下さい。 この URL はクラスター機能を利用した際に `"type": "redirect"` の `"location"` の値として払い出されます。 ```ini external_signaling_url = wss://node1.example.com/signaling ``` 例えば、上記の設定の場合は、シグナリングのリダイレクトが必要な際に Sora から `{"type": "redirect", "location": "wss://node1.example.com/signaling"}` として払い出されます。 ### external_api_url **必須設定** `sora.conf` にて API の URL を指定して下さい。 この URL はクラスター機能を利用した際に、API を適切なノードに HTTP 307 でリダイレクトさせる場合の HTTP の `location` ヘッダーの値として払い出されます。 この URL は外部に公開する必要はなく、プライベートなアドレスでも問題ありません。 ```ini # IP アドレスを指定する例 external_api_url = http://192.0.2.10:3000/ # ドメイン名を指定する例 external_api_url = https://node1.example.com/api ``` ### cluster_relay > **重要** > > クラスターリレー機能を利用する場合は [最大ノード数ライセンス](LICENSE.html#aee259) が必要です。 クラスターリレー機能を利用する場合、 `sora.conf` にて [cluster](SORA_CONF.html#b2cd99) を `true` を設定する必要があります。 `cluster_relay` のデフォルトは `true` になっています。 ```ini cluster = true ``` ### default_cluster_affinity > **重要** > > クラスターアフィニティ機能を利用する場合は [最大ノード数ライセンス](LICENSE.html#aee259) が必要です。 クラスターリレー機能でアフィニティ機能を利用する場合、 `sora.conf` にて [cluster](SORA_CONF.html#b2cd99) と [cluster_relay](SORA_CONF.html#0ef660) を `true` を設定する必要があります。 `default_cluster_affinity` のデフォルトは `true` になっています。 ```ini default_cluster_affinity = true ``` ### cluster_affinity_threshold クラスターリレー機能でアフィニティ機能で、他のノードへのリレーが発生する 1 ノード 1 セッションあたりの同時接続数を指定します。チューニング目的の設定となります。 - 片方向で大規模配信であれば 100 などの大きめの設定をお勧めします - 双方向で 1 チャネルで最大 5 接続までなら 5 を設定することをお勧めします ```ini cluster_affinity_threshold = 5 ``` ### cluster_listen_{min,max}_port `sora.conf` にてクラスター情報の同期に利用する TCP の受信ポートの範囲を指定してください。 デフォルトでは 49010 - 49020 が指定されています。 ```ini cluster_listen_min_port = 49010 cluster_listen_max_port = 49020 ``` ## API ### クラスター初期化 API クラスターを構築するときは、まずクラスターの初期化を行います。 > **重要** > > クラスターの初期化はクラスターを初めて構築する際と、クラスターが破綻した際に行う必要があります。 クラスターの初期化を実行する場合は `20221221.InitCluster` API をクラスター構築するいずれかのノードで実行します。 `node_name_list` にはクラスターを構成するノードを、 `20221221.InitCluster` API を実行するノードを含め指定してください。 API の詳細は [InitCluster](API_CLUSTER.html#621990) API をご確認ください。 ```console $ curl -sS \ -X POST \ http://127.0.0.1:3000/ \ -H "x-sora-target: Sora_20221221.InitCluster" \ --json '{"node_name_list":["node-02@192.0.2.7","node-03@192.0.2.8","node-01@192.0.2.5"]}' \ | jq . { "node_name_list": [ "node-02@192.0.2.7", "node-03@192.0.2.8", "node-01@192.0.2.5" ] } ``` > **重要** > > クラスターのノードが恒久的に破損し、クラスターを構成するノードが半数以下になった場合には、 > 全てのノードが接続を受け付けなくなるため、クラスターの再構築手順に従って、 > 再度クラスターの初期化を行う必要があります。 > > 詳しくは [クラスター破綻からの再構築手順](CLUSTER_OPS.html#7c3099) をご確認ください。 ### クラスター登録 API 初期化後のクラスターにノードを追加するときは、すでにクラスターに参加しているノードを指定して、登録するノードに API を実行します。 API の詳細は [RegisterClusterNode](API_CLUSTER.html#09ed96) API をご確認ください。 下記は、既存クラスター内の **node-01@192.0.2.5** ノードを `contact_node_name` に指定して、新規に登録するノードで [RegisterClusterNode](API_CLUSTER.html#09ed96) API を実行しています。 ```console $ curl -sS \ -X POST \ http://127.0.0.1:3000/ \ -H "x-sora-target: Sora_20211215.RegisterClusterNode" \ --json '{"contact_node_name":"node-01@192.0.2.5"}' \ | jq . { "node_name_list": [ "node-01@192.0.2.5", "node-02@192.0.2.7", "node-03@192.0.2.8" ] } ``` ### クラスターノード完全消去 API あるノードが障害で再度の参加が難しい、またはスケールインのためにノード破棄する場合は、 破棄するノードを停止後に [PurgeClusterNode](API_CLUSTER.html#13b35a) API を利用して、そのノード情報を完全消去してください。 `20220629.PurgeClusterNode` API は、クラスターに参加している破棄するノード以外のどのノードでもかまわないので 1 回だけ実行します。 この API で完全消去した結果はクラスター内部で共有されます。 > **警告** > > PurgeClusterNode API はクラスターからノードを完全に消去するための API です。 > 再度参加するノードに対しては基本的に使用しないでください。 > この API を含めた運用の手順は [クラスター機能運用](CLUSTER_OPS.html) をご確認ください。 詳細は [PurgeClusterNode](API_CLUSTER.html#13b35a) API をご確認ください。 ```console $ curl -sS \ -X POST \ http://127.0.0.1:3000/ \ -H "x-sora-target: Sora_20220629.PurgeClusterNode" \ --json '{"target_node_name":"node-01@192.0.2.5"}' \ | jq . { "target_node_name": "node-01@192.0.2.5" } ``` ### クラスターノード一覧 API 詳細は [ListClusterNodes](API_CLUSTER.html#a70901) API をご確認ください。 ```console $ curl -sS \ -X POST \ http://127.0.0.1:3000/ \ -H "x-sora-target: Sora_20211215.ListClusterNodes" \ | jq . [ { "external_api_url": "http://192.0.2.5:3000/", "license_max_connections": 600, "license_max_nodes": 10, "license_serial_code": "ABCDEF-SRA-E001-203801-400", "license_type": "Experimental", "node_name": "node-01@192.0.2.5", "connected": true, "mode": "normal", "external_signaling_url": "wss://node-01.example.com/signaling", "version": "2023.2.0" }, { "external_api_url": "http://192.0.2.7:3000/", "license_max_connections": 600, "license_max_nodes": 10, "license_serial_code": "ABCDEF-SRA-E002-203801-400", "license_type": "Experimental", "node_name": "node-02@192.0.2.7", "connected": true, "mode": "normal", "external_signaling_url": "wss://node-02.example.com/signaling", "version": "2023.2.0" }, { "external_api_url": "http://192.0.2.8:3000/", "license_max_connections": 600, "license_max_nodes": 10, "license_serial_code": "ABCDEF-SRA-E003-203801-500", "license_type": "Experimental", "node_name": "node-03@192.0.2.8", "connected": true, "mode": "normal", "external_signaling_url": "wss://node-03.example.com/signaling", "version": "2023.2.0" } ] ``` ### クラスターチャネル割り当て一覧 API 詳細は [ListClusterChannels](API_CLUSTER.html#0a4459) API をご確認ください。 ```console $ curl -sS \ -X POST \ http://127.0.0.1:3000/ \ -H "x-sora-target: Sora_20211215.ListClusterChannels" \ | jq . [ { "channel_id": "sora", "owners": [ { "node_name": "node-01@192.0.2.5", "connected": true } ] }, { "channel_id": "lemon", "owners": [ { "node_name": "node-01@192.0.2.5", "connected": true } ] }, { "channel_id": "hisui", "owners": [ { "node_name": "node-03@192.0.2.5", "connected": true } ] }, { "channel_id": "zakuro", "owners": [ { "node_name": "node-03@192.0.2.5", "connected": true } ] } ] ``` ## 接続時の挙動 ### リレーあり / アフィニティあり - 新規セッションでの接続- 一番空いてるノードへリダイレクト - 既存セッションへの接続- 既にセッションがあるノードへリダイレクト - 新規セッションでの接続 (接続したノードの同時接続数がライセンス上限に達している場合)- 一番空いてるノードへリダイレクト - 既存セッションへの接続 (接続したノードの同時接続数がライセンス上限に達している場合)- 一番空いてるノードへリダイレクト ### リレーあり / アフィニティなし - 新規セッションでの接続- 接続したノードを選択 - 既存セッションへの接続- 接続したノードを選択 - 新規セッションでの接続 (接続したノードの同時接続数がライセンス上限に達している場合)- 一番空いてるノードへリダイレクト - 既存セッションへの接続 (接続したノードの同時接続数がライセンス上限に達している場合)- 一番空いてるノードへリダイレクト ### リレーなし - 新規セッションでの接続- 一番空いてるノードへリダイレクト - 既存セッションへの接続- 既にセッションがあるノードへリダイレクト - 既にセッションがあるノードがライセンス上限に達していた場合、接続失敗 - 新規セッションでの接続 (接続したノードの同時接続数がライセンス上限に達している場合)- 一番空いてるノードへリダイレクト - 既存セッションへの接続 (接続したノードの同時接続数がライセンス上限に達している場合)- 既にセッションがあるノードへリダイレクト - 既にセッションがあるノードがライセンス上限に達していた場合、接続失敗 ### クラスターなし - 新規セッションでの接続- 接続したノードを選択 - 既存セッションへの接続- 接続したノードを選択 - 新規セッションでの接続 (接続したノードの同時接続数がライセンス上限に達している場合)- 接続失敗 - 既存セッションへの接続 (接続したノードの同時接続数がライセンス上限に達している場合)- 接続失敗 ## リレーの終了とアフィニティ機能 リレー機能を利用した場合、一度リレーがノード間で発生すると、セッションが破棄されるまでリレーが行われます。 ノードへの接続数が 0 になったとしてもリレーが発生します。これは Sora の仕様です。 アフィニティ機能を有効にした状態であれば、基本的に同一セッションのコネクションは同一ノードに割り当てられます。 もし別ノードにリレーが発生したとしても、そのリレーが発生したノードに割り当てるようになります。 アフィニティ機能を無効にして、接続を各ノードに分散させた場合は、 リレーが発生したノードで、接続数が 0 になったとしてもリレーが行われ続けますが、これは仕様です。 ## シーケンス図 > **注釈** > > 3 ノードのクラスターですが Sora3 を省略しています ### リレー機能かつアフィニティ機能が有効 - アフィニティ機能により寄せが発生し、リダイレクトを試みる場合がある - アフィニティ機能は認証成功時の払い出しで判断するため必ず認証は行う - リダイレクトが発生した場合は、リダイレクト先のノードでも認証を行う ```mermaid sequenceDiagram participant C1 as クライアント1 participant C2 as クライアント2 participant S1 as Sora1 participant S2 as Sora2 participant A as アプリケーションサーバー C1->>S1: "type": "connect" S1->>+A: 認証ウェブフック A-->>-S1: 200 OK
"allowed": true
"cluster_affinity": true S1->>+A: セッションウェブフック
"type": "session.created" A-->>-S1: 200 OK S1->>C1: "type": "offer" C1->>S1: "type": "answer" note over C1, S1: WebRTC 接続 S1->>+A: イベントウェブフック
"type": "connection.created" A-->>-S1: 200 OK C2->>S2: "type": "connect" S2->>+A: 認証ウェブフック A-->>-S2: 200 OK
"allowed": true
"cluster_affinity": true note left of S2: アフィニティ機能により Sora1 へリダイレクト S2->>C2: "type": "redirect" C2->>S1: "type": "connect", "redirect": true S1->>+A: 認証ウェブフック A-->>-S1: 200 OK
{"allowed": true} S1->>C2: "type": "offer" C2->>S1: "type": "answer" note over C2, S1: WebRTC 確立 S1->>+A: イベントウェブフック
"type": "connection.created" A-->>-S1: 200 OK ``` ### リレー機能が有効だが、アフィニティ機能が無効 - アフィニティ機能による寄せが発生しない ```mermaid sequenceDiagram participant C1 as クライアント1 participant C2 as クライアント2 participant S1 as Sora1 participant S2 as Sora2 participant A as アプリケーションサーバー C1->>S1: "type": "connect" S1->>+A: 認証ウェブフック A-->>-S1: 200 OK
"allowed": true
"cluster_affinity": false S1->>+A: セッションウェブフック
"type": "session.created" A-->>-S1: 200 OK S1->>C1: "type": "offer" C1->>S1: "type": "answer" note over C1, S1: WebRTC 接続 S1->>+A: イベントウェブフック
"type": "connection.created" A-->>-S1: 200 OK C2->>S2: "type": "connect" S2->>+A: 認証ウェブフック A-->>-S2: 200 OK
"allowed": true
"cluster_affinity": false S2->>C2: "type": "offer" C2->>S2: "type": "answer" note over C2, S2: WebRTC 確立 S2->>+A: イベントウェブフック
"type": "connection.created" A-->>-S2: 200 OK ``` ### リレー機能が有効で接続したノードがライセンスの上限 ```mermaid sequenceDiagram participant C1 as クライアント1 participant S1 as Sora1 participant S2 as Sora2 participant A as アプリケーションサーバー note over S1: ライセンス余裕なし C1->>S1: "type": "connect" S1->>+A: 認証ウェブフック A-->>-S1: 200 OK
"allowed": true
"cluster_affinity": false note over S1: ライセンス余裕なし S1->>C1: "type": "redirect", "location": "wss://sora2..." C1->>S2: "type": "connect", "redirect": true S2->>+A: 認証ウェブフック A-->>-S2: 200 OK
"allowed": true
"cluster_affinity": false note over S2: ライセンス余裕あり S2->>+A: セッションウェブフック
"type": "session.created" A-->>-S2: 200 OK S2->>C1: "type": "offer" C1->>S2: "type": "answer" note over C1, S2: WebRTC 確立 S2->>+A: イベントウェブフック
"type": "connection.created" A-->>-S2: 200 OK ``` ### リレー機能を利用しない場合 - 他のノードが余裕がある場合、新規セッションの場合はリダイレクトを試みる ```mermaid sequenceDiagram participant C as クライアント participant S1 as Sora1 participant S2 as Sora2 participant A as アプリケーションサーバー C->>S1: "type": "connect" note over S1: このノードは同時接続が多かったので、
Sora2 へリダイレクト提案 S1->>C: "type": "redirect" C->>S2: "type": "connect", "redirect": true S2->>+A: 認証ウェブフック A-->>-S2: 200 OK
{"allowed": true} S2->>C: "type": "offer" C->>S2: "type": "answer" note over C, A: WebRTC 確立 S2->>+A: イベントウェブフック
"type": "connection.created" A-->>-S2: 200 OK ``` # クラスター機能チュートリアル ## 概要 このチュートリアルでは、Sora のクラスター機能をひととおり使ってみるところまでを説明します。 ## 前提 クラスター特有ではない Sora の設定や起動方法、シグナリングで使用する NGINX の設定等については [チュートリアル](TUTORIAL.html) をご確認ください。 ### ライセンス ノード数分のライセンスが必要になります。 Sora 3 台でクラスターを構築する場合は通常のライセンスが 3 つ、もしくは 3 ノード以上に対応した [最大ノード数ライセンス](LICENSE.html#aee259) が 1 つ必要です。 > **注釈** > > クラスターを構築する場合はリレー機能やライセンスで決められた最大同時接続数の合計を維持する機能が利用できる [最大ノード数ライセンス](LICENSE.html#aee259) の利用をお勧めします。 ### リレー機能 どのノードに繋いでも同一チャネルに接続できるようになるリレー機能を利用する場合は、 [最大ノード数ライセンス](LICENSE.html#aee259) を利用する必要があります。 [最大ノード数ライセンス](LICENSE.html#aee259) を利用している場合、リレー機能はデフォルトで有効です。 ### アフィニティ機能 リレー機能を利用した際でも、できるだけ同一セッションは同一ノードへ接続することで、 ノード間の通信を最小限に抑えるアフィニティ機能を利用する場合は、 [最大ノード数ライセンス](LICENSE.html#aee259) を利用する必要があります。 [最大ノード数ライセンス](LICENSE.html#aee259) を利用している場合、アフィニティ機能はデフォルトで有効です。 ### ライセンスで決められた最大同時接続数の合計を維持する機能 クラスターのノードで障害が発生した際、 他のノードが同時接続数を引き受けるライセンスで決められた最大同時接続数の合計を維持する機能は、 [最大ノード数ライセンス](LICENSE.html#aee259) を利用する必要があります。 [最大ノード数ライセンス](LICENSE.html#aee259) を利用している場合、ライセンスで決められた最大同時接続数の合計を維持する機能はデフォルトで有効です。 ### テンポラリーノード機能 クラスター機能を利用した際に、クラスターの維持を目的とせず、 一時的なスケールアウトを目的にノードを追加するテンポラリーノード機能を利用する場合は、 [最大ノード数ライセンス](LICENSE.html#aee259) を利用する必要があります。 ## クラスターの構築 まず、ここでは 3 ノードの Sora クラスターを構築する手順を示します。 それぞれのノードのノード名は **sora1@192.0.2.101**, **sora2@192.0.2.102**, **sora3@192.0.2.103** とします。 > **重要** > > `ノード名(node_name)` はクラスター内のすべてのノードのそれぞれがユニークである必要があります `external_api_url` は HTTP API を叩いたノードにはそのセッションが存在しない場合に、 別のノードに転送するために `location` ヘッダーに指定する URL です。 そのためプライベートなアドレスでも問題ありません。 > **注釈** > > クラスターを構築する際、クラスター間の通信に使うネットワークは、 > 可能な限りプライベートネットワークを利用してください。 > > クラスター間の通信には各ノードの `node_name` で指定した @ 以下の IP アドレスまたはドメイン名を使用します。 ここでのクラスター構築では、3 台のサーバーがそれぞれ TCP/IP で通信できる状態になっていること、 そして Sora の tar.gz が展開されて `bin/sora` が実行できるようになっていることを前提としています。 1. クラスター間の通信に必要な TCP のポートをすべて開放します- TCP 4369- ポート番号の変更はできません、必ずこのポートを開放してください - TCP 49010-49020- `sora.conf` にて変更できますがデフォルトをお勧めします 2. 最初のノード(**sora1@192.0.2.101**)の `sora.conf` にクラスターの設定をします```ini node_name = sora1@192.0.2.101 cluster = true external_signaling_url = wss://sora-node1.example.com/signaling external_api_url = http://192.0.2.101:3000/ ``` 3. 最初のノード(**sora1@192.0.2.101**)の Sora を `bin/sora daemon` で起動します 4. 次のノード(**sora2@192.0.2.102**)の `sora.conf` も最初のノードと同様にクラスターの設定をします```ini node_name = sora2@192.0.2.102 cluster = true external_signaling_url = wss://sora-node2.example.com/signaling external_api_url = http://192.0.2.102:3000/ ``` 5. 次のノード(**sora2@192.0.2.102**)の Sora を `bin/sora daemon` で起動します 6. 最後のノード(**sora3@192.0.2.103**)の `sora.conf` にもクラスターの設定をします```ini node_name = sora3@192.0.2.103 cluster = true external_signaling_url = wss://sora-node3.example.com/signaling external_api_url = http://192.0.2.103:3000/ ``` 7. 最後のノード(**sora3@192.0.2.103**)の Sora を `bin/sora daemon` で起動します 8. 最初のノード(**sora1@192.0.2.101**)の Sora に [InitCluster](API_CLUSTER.html#621990) API を実行し、3 ノードのクラスターとして初期化します```console $ curl -sS \ -X POST \ http://127.0.0.1:3001/ \ -H "x-sora-target: Sora_20221221.InitCluster" \ --json '{"node_name_list":["sora1@192.0.2.101","sora2@192.0.2.102","sora3@192.0.2.103"]}' \ | jq . ``` 9. 最初のノード(**sora1@192.0.2.101**)の Sora に [ListClusterNodes](API_CLUSTER.html#a70901) API を実行し、ノード一覧を取得します```console $ curl -sS \ -X POST \ http://127.0.0.1:3001/ \ -H "x-sora-target: Sora_20211215.ListClusterNodes" \ | jq . [ { "connected": true, "external_api_url": "https://sora-node1.example.com/api", "external_signaling_url": "wss://sora-node1.example.com/signaling", "license_max_connections": 100, "license_max_nodes": 3, "license_serial_code": "DOC123-SRA-E002-201303-N3-100", "license_type": "Experimental", "mode": "normal", "node_name": "sora1@192.0.2.101", "temporary_node": false, "version": "2024.1.0" }, { "connected": true, "external_api_url": "https://sora-node2.example.com/api", "external_signaling_url": "wss://sora-node2.example.com/signaling", "license_max_connections": 100, "license_max_nodes": 3, "license_serial_code": "DOC123-SRA-E002-201303-N3-100", "license_type": "Experimental", "mode": "normal", "node_name": "sora2@192.0.2.102", "temporary_node": false, "version": "2024.1.0" }, { "connected": true, "external_api_url": "https://sora-node3.example.com/api", "external_signaling_url": "wss://sora-node3.example.com/signaling", "license_max_connections": 100, "license_max_nodes": 3, "license_serial_code": "DOC123-SRA-E002-201303-N3-100", "license_type": "Experimental", "mode": "normal", "node_name": "sora3@192.0.2.103", "temporary_node": false, "version": "2024.1.0" } ] ``` 結果として、 **sora1@192.0.2.101** から **sora3@192.0.2.103** の 3 ノードの一覧が取得できれば、クラスターの構築は完了です。 ### クラスター構築のトラブルシューティング クラスター構築時に躓きやすいポイントと確認事項を示します。 - ノード間通信ができない場合- Sora はノード間通信を行うため、ファイアウォールの開放が必要です - [クラスター構成情報ファイル](CLUSTER_OPS.html#9bed3b) にあるとおりに、EPMD と sora の Listen ポートの開放を確認してください - ライセンス違反のエラーが出る場合- [最大ノード数ライセンス](LICENSE.html#aee259) ではないライセンスを使っている場合には、すべてのノードで異なるライセンスが設定されている必要があります - [最大ノード数ライセンス](LICENSE.html#aee259) のライセンスを使っている場合には、指定されたノード数まで同じライセンスを利用できます - [最大ノード数ライセンス](LICENSE.html#aee259) とそうではないライセンスを混在させて利用することはできません - [RegisterClusterNode](API_CLUSTER.html#09ed96) API 実行時に `CONTACT-NODE-NOT-INITIALIZED` エラーが出る場合- 未初期化のノードを `contact_node_name` に指定した場合に発生します - `contact_node_name` に指定するノードは [InitCluster](API_CLUSTER.html#621990) で初期化したノードか、[RegisterClusterNode](API_CLUSTER.html#09ed96) API でクラスターに参加したノードを指定する必要があります ## クラスター操作 上記のクラスターの構築の手順で、クラスターの構築と初期化が完了していることを前提とします。 ### クラスターのノード一覧の取得 構築済みのクラスター内のノード名 **sora1@192.0.2.101**、 **sora2@192.0.2.102**、 **sora3@192.0.2.103** のいずれかで [ListClusterNodes](API_CLUSTER.html#a70901) API を実行して、 クラスター内のノード一覧を取得します。 ```console $ curl -sS \ -X POST \ http://127.0.0.1:3000/ \ -H "x-sora-target: Sora_20211215.ListClusterNodes" \ | jq . [ { "connected": true, "external_api_url": "https://sora-node1.example.com/api", "external_signaling_url": "wss://sora-node1.example.com/signaling", "license_max_connections": 100, "license_max_nodes": 3, "license_serial_code": "DOC123-SRA-E002-201303-N3-100", "license_type": "Experimental", "mode": "normal", "node_name": "sora1@192.0.2.101", "temporary_node": false, "version": "2024.1.0" }, { "connected": true, "external_api_url": "https://sora-node2.example.com/api", "external_signaling_url": "wss://sora-node2.example.com/signaling", "license_max_connections": 100, "license_max_nodes": 3, "license_serial_code": "DOC123-SRA-E002-201303-N3-100", "license_type": "Experimental", "mode": "normal", "node_name": "sora2@192.0.2.102", "temporary_node": false, "version": "2024.1.0" }, { "connected": true, "external_api_url": "https://sora-node3.example.com/api", "external_signaling_url": "wss://sora-node3.example.com/signaling", "license_max_connections": 100, "license_max_nodes": 3, "license_serial_code": "DOC123-SRA-E002-201303-N3-100", "license_type": "Experimental", "mode": "normal", "node_name": "sora3@192.0.2.103", "temporary_node": false, "version": "2024.1.0" } ] ``` ### クラスターチャネル割り当て一覧の取得 接続済みのチャネルのノードへの割り当てを確認するために、[ListClusterChannels](API_CLUSTER.html#0a4459) API を実行します。 まず、構築済みのクラスターに複数のチャネルで接続しておきます。 次に、クラスター内のいずれかのノードで [ListClusterChannels](API_CLUSTER.html#0a4459) API を実行して、クラスターのチャネル割り当ての一覧を取得し、チャネルと割り当てられているノードを確認します。 ```console $ curl -sS \ -X POST \ http://127.0.0.1:3000/ \ -H "x-sora-target: Sora_20211215.ListClusterChannels" \ | jq . [ { "channel_id": "hisui", "owners": [ { "connected": true, "node_name": "sora1@192.0.2.101" } ] }, { "channel_id": "kohaku", "owners": [ { "connected": true, "node_name": "sora2@192.0.2.102" } ] }, { "channel_id": "sora", "owners": [ { "connected": true, "node_name": "sora3@192.0.2.103" } ] }, { "channel_id": "zakuro", "owners": [ { "connected": true, "node_name": "sora3@192.0.2.103" } ] } ] ``` ### クラスターからノードを消去する 構築済みのクラスター内からノードを消去してみます。 ここでは、ノード名 **sora1@192.0.2.101**、 **sora2@192.0.2.102**、 **sora3@192.0.2.103** の 3 ノードで構築されているクラスターから、 **sora3@192.0.2.103** のノードを消去します。 ノードの消去には [PurgeClusterNode](API_CLUSTER.html#13b35a) API を使用します。 初めに、 **sora3@192.0.2.103** の Sora を `bin/sora stop` で停止します。 次に、 **sora3@192.0.2.103** ノードの `data/` ディレクトリを削除します。 **sora1@192.0.2.101** のノードで [ListClusterNodes](API_CLUSTER.html#a70901) API を実行して、 **sora3@192.0.2.103** のノードについて `"connected": false` になっていることを確認します。 ```console $ curl -sS \ -X POST \ http://127.0.0.1:3000/ \ -H "x-sora-target: Sora_20211215.ListClusterNodes" \ | jq . [ { "connected": true, "external_api_url": "https://sora-node1.example.com/api", "external_signaling_url": "wss://sora-node1.example.com/signaling", "license_max_connections": 100, "license_max_nodes": 3, "license_serial_code": "DOC123-SRA-E002-201303-N3-100", "mode": "normal", "node_name": "sora1@192.0.2.101", "temporary_node": false, "version": "2024.1.0" }, { "connected": true, "external_api_url": "https://sora-node2.example.com/api", "external_signaling_url": "wss://sora-node2.example.com/signaling", "license_max_connections": 100, "license_max_nodes": 3, "license_serial_code": "DOC123-SRA-E002-201303-N3-100", "license_type": "Experimental", "mode": "normal", "node_name": "sora2@192.0.2.102", "temporary_node": false, "version": "2024.1.0" }, { "connected": false, "license_max_connections": 100, "license_max_nodes": 3, "license_serial_code": "DOC123-SRA-E002-201303-N3-100", "license_type": "Experimental", "node_name": "sora3@192.0.2.103", "temporary_node": false } ] ``` クラスターから **sora3@192.0.2.103** ノードの情報を消去するために、 **sora1@192.0.2.101** または **sora2@192.0.2.102** ノードのいずれかで [PurgeClusterNode](API_CLUSTER.html#13b35a) API を実行します。 この API を実行する際の `target_node_name` には消去するノード名を指定します。 今回指定するノード名は、 **sora3@192.0.2.103** です。 ```console $ curl -sS \ -X POST \ http://127.0.0.1:3000/ \ -H "x-sora-target: Sora_20220629.PurgeClusterNode" \ --json '{"target_node_name":"sora3@192.0.2.103"}' \ | jq . { "target_node_name": "sora3@192.0.2.103" } ``` 再度 **sora1@192.0.2.101** のノードで [ListClusterNodes](API_CLUSTER.html#a70901) API を実行して、 クラスターのノードから **sora3@192.0.2.103** のノードが見えなくなっていることを確認します。 ```console $ curl -sS \ -X POST \ http://127.0.0.1:3000/ \ -H "x-sora-target: Sora_20211215.ListClusterNodes" \ | jq . [ { "connected": true, "external_api_url": "https://sora-node1.example.com/api", "external_signaling_url": "wss://sora-node1.example.com/signaling", "license_max_connections": 100, "license_max_nodes": 3, "license_serial_code": "DOC123-SRA-E002-201303-N3-100", "mode": "normal", "node_name": "sora1@192.0.2.101", "temporary_node": false, "version": "2024.1.0" }, { "connected": true, "external_api_url": "https://sora-node2.example.com/api", "external_signaling_url": "wss://sora-node2.example.com/signaling", "license_max_connections": 100, "license_max_nodes": 3, "license_serial_code": "DOC123-SRA-E002-201303-N3-100", "license_type": "Experimental", "mode": "normal", "node_name": "sora2@192.0.2.102", "temporary_node": false, "version": "2024.1.0" } ] ``` ### クラスターにノードを追加する 構築済みのクラスターにノードを追加してみます。 ノード名 **sora1@192.0.2.101**、 **sora2@192.0.2.102** の 2 ノードで構築されているクラスターへ、 API を使用して **sora4@192.0.2.104** ノードを追加します。 ノードの追加には [RegisterClusterNode](API_CLUSTER.html#09ed96) API を使用します。 クラスターに **sora4@192.0.2.104** ノードを追加するために、 **sora4@192.0.2.104** ノードで [RegisterClusterNode](API_CLUSTER.html#09ed96) API を実行します。 この API を実行する際の `contact_node_name` には既存のクラスターのノード名を指定します。 今回指定するノード名は、 **sora1@192.0.2.101** または **sora2@192.0.2.102** のいずれかです。 ```console $ curl -sS \ -X POST \ http://127.0.0.1:3000/ \ -H "x-sora-target: Sora_20211215.RegisterClusterNode" \ --json '{"contact_node_name":"sora1@192.0.2.101"}' \ | jq . { "node_name_list": [ "sora1@192.0.2.101", "sora2@192.0.2.102", "sora4@192.0.2.104" ] } ``` [ListClusterNodes](API_CLUSTER.html#a70901) API を使用して、クラスターに追加されていることを確認します。 ```console $ curl -sS \ -X POST \ http://127.0.0.1:3000/ \ -H "x-sora-target: Sora_20211215.ListClusterNodes" \ | jq . [ { "connected": true, "external_api_url": "https://sora-node1.example.com/api", "external_signaling_url": "wss://sora-node1.example.com/signaling", "license_max_connections": 100, "license_max_nodes": 3, "license_serial_code": "DOC123-SRA-E002-201303-N3-100", "license_type": "Experimental", "mode": "normal", "node_name": "sora1@192.0.2.101", "temporary_node": false, "version": "2024.1.0" }, { "connected": true, "external_api_url": "https://sora-node2.example.com/api", "external_signaling_url": "wss://sora-node2.example.com/signaling", "license_max_connections": 100, "license_max_nodes": 3, "license_serial_code": "DOC123-SRA-E002-201303-N3-100", "license_type": "Experimental", "mode": "normal", "node_name": "sora2@192.0.2.102", "temporary_node": false, "version": "2024.1.0" }, { "connected": true, "external_api_url": "https://sora-node4.example.com/api", "external_signaling_url": "wss://sora-node4.example.com/signaling", "license_max_connections": 100, "license_max_nodes": 3, "license_serial_code": "DOC123-SRA-E002-201303-N3-100", "license_type": "Experimental", "mode": "normal", "node_name": "sora4@192.0.2.104", "temporary_node": false, "version": "2024.1.0" } ] ``` # クラスター機能運用 不明点がある場合はサポートまでお問い合わせください。 ## クラスター利用時のファイル操作に問題が発生した場合 クラスター機能を利用している際に、ファイル操作に問題が発生した場合、 そのノードは [新規コネクションブロックモード](MODE.html#0b67d3) へ移行します。 ファイル操作とはログ出力だったり、録画ファイルアーカイブ出力だったりです。 この状態が発生した場合、 ディスク破損、ディスク容量不足、パーミッション間違いなど、 致命的な問題が発生している可能性が高いため、ノードを停止し、問題の解決を行ってください。 ### 問題があるノードを破棄する場合 レギュラーノードの場合は、 必ず [PurgeClusterNode](API_CLUSTER.html#13b35a) API を利用して対象のノードを消去し、新しいノードを追加してください。 テンポラリーノードの場合は、そのまま破棄して問題ありません。 ## クラスターのレギュラーノード数 ### 最低ノード数 Sora は最低 3 レギュラーノードのクラスターを構築してください。 - 1 レギュラーノードで構築されたクラスターはクラスターを構築していないのと同様です - 2 レギュラーノードで構築されたクラスターは片方のノードが停止すると、正常なノードも過半数の条件を満たさなくなるため接続を受け付けなくなってしまいます ### ノード数 3 レギュラーノードの次は 5 レギュラーノードのクラスターを構築してください。 4 レギュラーノードは 2 レギュラーノードがダウンした時点でクラスターが利用できなくなるため、3 レギュラーノードと可用性が変わらないためです。 5 レギュラーノード以上は、特に制限はありません。 ## クラスターのテンポラリーノード数 テンポラリーノードはレギュラーノードと違いクラスターの維持に影響しないため、最低ノード数の制限はありません。 ## 最大ノード数 クラスターを構築するノードの最大数は 100 ノードを想定しています。 これ以上のノード数を検討されている場合はサポートまでご連絡ください。 ## クラスター利用時のライセンス クラスターの 1 ノードにつき 1 ライセンスが必要になります。 3 台のノードでクラスターを構築する場合は 3 ライセンスが必要になります。 ### 最大ノード数ライセンス [最大ノード数ライセンス](LICENSE.html#aee259) を利用することで、同一ライセンスを複数ノードで利用できるようになります。 クラスターを利用する場合は [最大ノード数ライセンス](LICENSE.html#aee259) を利用することを推奨します。 [最大ノード数ライセンス](LICENSE.html#aee259) への切り替えはサポートまでご連絡ください。 > **注釈** > > レギュラーノードもテンポラリーノードも、それぞれ 1 ノードとしてカウントされます。 ### 最大ノード数ライセンスのみで利用できる機能 クラスター機能のいくつかの機能は [最大ノード数ライセンス](LICENSE.html#aee259) が必要です。 - リレー機能 - リレー機能利用時のアフィニティ機能 - ライセンスで決められた最大同時接続数の合計を維持する機能 - テンポラリーノード機能 > **重要** > > [最大ノード数ライセンス](LICENSE.html#aee259) を利用せずに `sora.conf` でリレー機能やアフィニティ機能を有効にしても起動はできます。 > ただし `sora.jsonl` に警告ログが出力されます。 ## ポートの開放 以下のポートを **クラスターを組むその他のノードにのみ** に対して開放してください。 > **危険** > > 絶対にパブリックインターネットへの公開はしないでください。 - epmd(Erlang Port Mapper Daemon)で利用する TCP ポート- 4369 - ノード間通信に利用する TCP ポート- 49010 - 49020 - `sora.conf` の `cluster_listen_{min,max}_port` にて範囲を指定できます ## ノード間通信 Sora のノード間通信は **TCP/IP を利用しています** 。 そのため、安定したプライベートネットワークの利用を強く推奨します。 もし、マルチクラウドなどでノード間通信がパブリックネットワークを利用したクラスターを構築する場合は、 輻輳が発生する可能性があります。 そのため、特別な理由がない限りはプライベートネットワークを利用してください。 ### リレー機能利用時のノード間通信 Sora クラスターリレー機能利用時のノード間通信では、大量のネットワーク帯域を消費します。 そのためリレー機能を利用する場合は **可能な限り** 同一データセンター内のプライベートネットワークを利用してください。 ## ノード間通信の暗号化 Sora のノード間通信は **暗号化されておりません** 。 そのため、安全なプライベートネットワークの利用を推奨します。 もし、マルチクラウドなどでノード間通信がパブリックネットワークを利用したクラスターを構築する場合は、 ノード間の通信を暗号化する必要があります。その場合は Tailscale などの利用をお勧めします。 [Tailscale · Best VPN Service for Secure Networks](https://tailscale.com/) 参考までに、下記は弊社の Tailscale 利用事例です。 [ベアメタルサーバーを利用したクラウドサービスで発生する課題を Tailscale で解決する · Tailscale](https://tailscale.com/ja/customers/shiguredo/) ### リレー機能利用時 > **重要** > > リレー機能を利用する際に、マルチクラウドでの利用は非推奨です。 リレー機能利用時にはノード間通信が大量に発生する場合があるため、暗号化に多くの CPU リソースを消費します。 そのため、プライベートネットワークを利用し、ノード間通信には暗号化を行わないことを推奨します。 ## テンポラリーノード機能の利用 3 ノードや 5 ノードのレギュラーノードで構築したクラスターを拡張する場合は、 テンポラリーノード機能の利用を検討してください。 テンポラリーノードは、クラスター維持に影響しないノードで、気軽に追加・削除できるノードです。 特にリレー機能利用時には、スケールアウト/スケールインが気軽に行えるようになるため、 レギュラーノードとテンポラリーノードを組み合わせてクラスターを構築することを推奨します。 ## クラスターからの一時的な離脱 モード切り替え API を利用し、 [新規セッションブロックモード](MODE.html#041e1c) または [新規コネクションブロックモード](MODE.html#0b67d3) に切り替えます。 その後、すべての接続がいなくなったタイミングでノードを終了してください。 一時的に離脱したノードは、再起動するとそのままクラスターに参加して動作します。 ## 一時的に離脱したノードを含めるクラスターノード一覧 [ListClusterNodes](API_CLUSTER.html#a70901) API では現在クラスターに登録している全てのノードの一覧が返ります。 > **注釈** > > 結果に一時的に離脱したレギュラーノードを含めない場合には、 `include_all_known_nodes` に `false` を指定して API を実行します。 ## クラスターからレギュラーノード情報の完全消去 > **重要** > > 恒久的にレギュラーノードを破棄する場合には、必ず、この作業を行ってください。 特定のレギュラーノードで障害が起きた後、復旧が難しい場合は [PurgeClusterNode](API_CLUSTER.html#13b35a) API を利用して、 クラスターに参加しているレギュラーノードから、障害が起きたレギュラーノードの情報を完全消去してください。 また、スケールインのためにレギュラーノードを破棄する場合も同様に [PurgeClusterNode](API_CLUSTER.html#13b35a) API を 利用して、破棄したレギュラーノードの情報を完全消去してください。 この作業はクラスターの新鮮さを保つために必要な作業となります。 この作業を行わないと存在していないレギュラーノードが残り続けることで過半数かどうかの判断を誤る場合があります。 > **警告** > > PurgeClusterNode API はクラスターからレギュラーノードを完全に消去するための API です。 > 近い将来に再び参加するレギュラーノードに対しては基本的に使用しないでください。 ## クラスターのローリングアップデート > **重要** > > ローリングアップデートは並列で行うのではなく必ず 1 台ずつ行ってください。 1. アップデート対象のノードを [ChangeMode](API_MODE.html#3af05f) API で [新規セッションブロックモード](MODE.html#041e1c)または [新規コネクションブロックモード](MODE.html#0b67d3) に切り替えます- 必要があれば [ListChannels](EXPERIMENTAL_API_SIGNALING.html#b27c42) API と [DisconnectChannel](API_SIGNALING.html#a87366) API を利用して既存接続を切断します 2. すべての接続がなくなったら Sora を停止させます 3. 新しいバージョンの Sora へ入れ替えます 4. 新しいバージョンの Sora を起動します 5. [ListClusterNodes](API_CLUSTER.html#a70901) API で新しいバージョンの Sora がクラスターに参加できているかを確認します > **警告** > > 自動でクラスターに参加する処理がエラーになる可能性もあるため、 > [ListClusterNodes](API_CLUSTER.html#a70901) API で新しいバージョンの Sora がクラスターに参加できているかを必ず確認してください。 > 確認せずに他ノードのローリングアップデートを行った場合、クラスターに参加できていないままのノードが出てしまう > 可能性があります。 > さらに、複数のノードが参加できずに過半数を割ってしまうと、クラスターがまったく稼働しなくなる可能性もあります。 上の手順を 1 ノードごとに繰り返してください。 ### アップデート対象のノードがローリングアップデートに成功したかどうかを確認する方法 [ヘルスチェック機能](OK.html) の `/.ok` を利用してください。 `200 OK` が返ってくればアップデートに成功し、クラスターへの再参加に成功しています。 成功を確認した後、 より詳細な状態が知りたい場合は [ListClusterNodes](API_CLUSTER.html#a70901) API を実行してクラスターの状態を確認してください。 ### ローリングアップデート時に一時的に `CLUSTER-NOT-INITIALIZED` になる場合 アップデート対象のノードのアップデート後に [ListClusterNodes](API_CLUSTER.html#a70901) API を実行した際に、 `CLUSTER-NOT-INITIALIZED` が返ってくる場合がありますが、これは一時的な状態です。 そのため、少し待って [ListClusterNodes](API_CLUSTER.html#a70901) API を再度実行してください。 ローリングアップデートに成功したかどうかには [ヘルスチェック機能](OK.html) の `/.ok` を利用してください。 ## クラスターのローリングアップデート中の挙動 ### リレー機能の無効化 クラスターをローリングアップデートの最中に、 クラスターに複数のバージョンが混在するノードが存在する場合、 リレー機能は同一バージョン同士でしか行えません。 そのため、アフィニティ機能が無効な場合でも別ノードへのリダイレクトを試みる場合があります。 ### 一部 API の local に false を指定することができない クラスターをローリングアップデートの最中に、 クラスターに複数バージョンが混在するノードが存在する場合、 以下 API に `local` に `false` を指定することができません。 - [ListConnections](API_SIGNALING.html#d3da2a) API - [ListChannels](EXPERIMENTAL_API_SIGNALING.html#b27c42) API - [GetStatsAllConnections](API_STATS.html#ef695a) API - [ListRtcStats](API_RTC_STATS.html#956f4b) API - [ListUserAgentStats](OBSOLETE_API_USER_AGENT_STATS.html#f9a4fe) API ## Sora のバージョンダウン [クラスターのローリングアップデート](CLUSTER_OPS.html#9dd5e5) の仕組みを使って、Sora のバージョンを下げることはできません。 そのため、クラスターのアップデート後に何らかの問題が発生し、 以前のバージョンに戻したい場合には、クラスターの再構築を行う必要があります。 再構築の際には、事前に全ノードを停止し、 `data/` ディレクトリを削除した上で、 以前のバージョンの Sora を使用してクラスターの構築を行ってください。 ## Sora のローリングアップデート失敗 [クラスターのローリングアップデート](CLUSTER_OPS.html#9dd5e5) に失敗した場合は、クラスターの再構築が必要になります。 再構築の際には、事前に全ノードを停止し、 `data/` ディレクトリを削除した上で、 新しいバージョンの Sora を使用してクラスターの再構築を行ってください。 ### ローリングアップデートの失敗判断 - 一定時間待っても [ListClusterNodes](API_CLUSTER.html#a70901) API の戻り値のノード数が一致しない場合 - 一定時間待っても [ListClusterNodes](API_CLUSTER.html#a70901) API の戻り値が `CLUSTER-NOT-MAJORITY` を返してくる場合 ## クラスター破綻からの再構築手順 クラスターのうち、過半数のノードが停止した場合、クラスターのすべてのノードは接続を受け付けなくなります。 この状態からでも、停止したノードを再開させ、過半数のノードが正常に戻ったタイミングで、接続を受け付け始めます。 その場合は、ここで書かれている手順は必要ありません。 ただし、停止したノードがディスク障害などで `data/` ディレクトリを失ってしまったときや、使っていた IP アドレスが使えなくなってしまうなどの理由で、再開できないこともあります。 ここでは、3 ノードクラスターを組んでいたものの、うち 2 つのサーバーがディスク障害で `data/` ディレクトリを失った状態からの再構築手順を示します。 > **注釈** > > `data/` ディレクトリを失ってしまうと、「未初期化」状態になるため、再度クラスターへの参加手順が必要です。 > **注釈** > > `node_name` に IP アドレスを使う場合、IP アドレスが変わると `node_name` も変える必要があります。 > その際は `data/` ディレクトリを削除する必要があります。 - まずすべての Sora プロセスを停止状態にします - ディスク障害がおきたサーバーでは- Sora をインストールしなおします - 必要に応じて sora.conf 設定を行います - ディスク障害がおきなかったサーバーでは- `data/` ディレクトリを削除します - これを忘れると正しい再構築ができません、必ず削除してください - ここまでで、完全にまっさらの Sora クラスターを構築する準備ができたことになります - すべてのノードを起動します - [InitCluster](API_CLUSTER.html#621990) API を発行し、クラスターを初期化します 以上の手順で、あたらしい 3 ノードのクラスターが動き始めます。 ## ノード名変更手順 sora.conf の `node_name` を変更する際の手順を示します。 この手順は、例えば Sora が動作するサーバーの IP アドレスが変わり、 `node_name` の IP アドレス部分を 変更する場合に必要になります。 - 対象のノードを停止します - `data/` ディレクトリを削除します- これを忘れるとノード名変更が正しく実行できません、必ず削除してください - クラスターの起動しているノードのいずれかに対し、 [PurgeClusterNode](API_CLUSTER.html#13b35a) API を発行し、対象のノードをクラスターから削除します - sora.conf の `node_name` を変更します - 対象のノードを起動します - [RegisterClusterNode](API_CLUSTER.html#09ed96) API でクラスターにあらたに登録します > **警告** > > この手順では、 `data/` ディレクトリの削除を含むため、対象のノードは「未初期化」状態になります。 > 複数のノードの名前変更が必要な場合には、1 ノードずつこの手順を実行することを推奨します。 > 1 ノードの変更のたびに、 [ListClusterNodes](API_CLUSTER.html#a70901) を使ってクラスターに正しく > 参加したことを確認して次のノードの手順に取り掛かってください。 ## ロードバランサーの導入 > **注意** > > ロードバランサーを導入する場合は事前にサポートまでご連絡ください。 クラスター機能を利用した場合は、シグナリング URL に対してロードバランサーが利用できます。 ただし、ロードバランス自体は Sora が行うため、 ロードバランサーの導入はシグナリング URL の 1 本化が目的となります。 - ロードバランサーは WebSocket に対応している必要があります - ロードバランサーで TLS 終端はせず TLS で Sora へ接続する必要があります - Sora はロードバランサー経由以外にクライアントと直接接続できる必要があります- これはリダイレクトが発生し、ロードバランサーを経由せずに接続する可能性があるためです - Sora の WebSocket 通信は 30 秒に 1 回通信を発生させるため、ロードバランサーのタイムアウトは 30 秒以上にする必要があります ```mermaid sequenceDiagram participant C as クライアント participant LB as ロードバランサー participant S1 as Sora1 participant S2 as Sora2 participant A as アプリケーションサーバー C->>LB: wss://sora.example.com/signaling LB->>S1: wss://0001.sora.example.com/signaling note over B,S1: WebSocket 確立 C->>+LB: "type": "connect" LB->>+S1: "type": "connect" S1-->>-LB: "type": "redirect"
"location": "wss://0002.sora.example.com/signaling" LB->>-C: "type": "redirect"
"location": "wss://0002.sora.example.com/signaling" note over B,S1: WebSocket 切断 C->>S2: wss://0002.sora.example.com/signaling note over B,S1: WebSocket 確立 C->>+S2: "type": "connect" S2->>+A: 認証ウェブフック A-->>-S2: "allowed": true S2->>-C: "type": "offer" C->>S2: "type": "answer" note over B,S2: WebRTC 確立 ``` もしシグナリング URL の 1 本化を検討している方で、不明点がある場合はサポートまでご連絡ください。 ## ログの出力 クラスターに関するログは `log/cluster.jsonl` に生成されます。 ログの詳細については [ログファイル](LOG.html) をご確認ください。 ## クラスター構成情報ファイル > **危険** > > このファイルは Sora が内部で利用するためのファイルのため、指示がある場合以外は触らないでください。 Sora でクラスターを利用する場合、クラスター参加後のノード情報を永続化するためのファイルを `data/` ディレクトリ以下に生成します。 ### Sora のバージョンアップ時 Sora をバージョンアップする際には `data/` ディレクトリをコピーを行わないでください。 このファイルが無い場合、 Sora の起動の際に生成されます。 ## クラスターからのレギュラーノードの完全消去について クラスターからレギュラーノードを完全に消去させる場合は `bin/sora stop` で停止させた後に、 クラスターを構成してる実行中のノードのいずれかに対して、 消去するノードのノード名を target_node_name に指定して [PurgeClusterNode](API_CLUSTER.html#13b35a) API を実行します。 > **警告** > > [PurgeClusterNode](API_CLUSTER.html#13b35a) API はクラスターからレギュラーノードを完全に消去するための API です。 > 再度参加するレギュラーノードに対しては基本的に使用しないでください。 ## PurgeClusterNode API で完全消去したレギュラーノードの再度の参加 > **警告** > > [PurgeClusterNode](API_CLUSTER.html#13b35a) API はクラスターからレギュラーノードを完全に消去するための API です。 > 通常は、再度参加するレギュラーノードに対しては使用しないでください。 > ここの説明は、長期間に渡ってクラスターに参加できないため、苦肉の策として > [PurgeClusterNode](API_CLUSTER.html#13b35a) API を使った場合の説明です。 > **警告** > > [PurgeClusterNode](API_CLUSTER.html#13b35a) API でクラスターから消去したレギュラーノードは、 > 以下に示す手順を経ずに再起動してはいけません。 クラスターからレギュラーノードを完全消去した場合、そのまま再度参加をすることはできません。 再度クラスターに参加する場合は `data/` ディレクトリを削除する必要があります。 [PurgeClusterNode](API_CLUSTER.html#13b35a) API を実行して、さらにそのレギュラーノードの `data/` ディレクトリを削除した場合、 そのレギュラーノードは完全に新規のレギュラーノードとして取り扱われます。 この状態になったレギュラーノードは新規レギュラーノードですので、 [RegisterClusterNode](API_CLUSTER.html#09ed96) API を利用してクラスターに登録できます。 ## クラスターから消去されたレギュラーノードを別クラスターに参加させたい場合 あるクラスター A に参加していたレギュラーノードを、A から削除して別のクラスター B に参加させたい状況を考えます。 > **警告** > > [PurgeClusterNode](API_CLUSTER.html#13b35a) API はクラスターからレギュラーノードを完全に消去するための API です。 > 現在参加しているクラスターで再利用するレギュラーノードに対しては使用しないでください。 > Sora が稼働するサーバーを再利用して、別のクラスター B に参加する新規レギュラーノードが欲しい場合には、 > Sora リリースの tar.gz を展開して、まっさらな状態からの新規レギュラーノード構築を推奨します。 > ここの説明は、どうしても既存の tar.gz 展開ディレクトリを再利用したい場合の説明です。 [PurgeClusterNode](API_CLUSTER.html#13b35a) API で消去されたレギュラーノードは `data/` ディレクトリ内のデータに以前参加していたクラスター A のノード群を覚えています。 そのため、再利用する場合には `data/` ディレクトリを削除して、クラスター A に関する情報を無くす必要があります。 > **警告** > > 以上の手順を踏まずに別クラスター B に参加させようとすると、最悪の場合には A と B がひとつになった > クラスターになってしまう場合があります。 上記の手順の後は Sora を起動し、クラスター参加の手順に従って、レギュラーノードをクラスターに参加させます。 ## ネットワーク障害やノード障害 Sora のクラスター機能はネットワーク障害やノード障害が発生した際に、 自動で新規接続の受け付けの停止とそこからの復旧を試みます。 ### 発生しうる問題と新規接続の受け付け停止 ネットワーク障害等が発生した場合には、 Sora のレギュラーノード間で通信ができず、クラスター内の情報の整合性が取れなくなる可能性があります。 たとえば、5 レギュラーノードのクラスターが 3 レギュラーノードからなるグループ A と 残りの 2 レギュラーノードからなるグループ B の 2 グループに分断されるということが起こりえます。 それぞれのグループ内では通信ができるものの、他グループへの通信ができないという状態です。 この状態ですべてのレギュラーノードが接続を受け付けると、同じチャネル ID を指定していても、 あるクライアントはグループ A に繋がり、別のクライアントは グルーブ B につながる可能性があり、 それぞれのクライアント間で音声と映像が届かなくなります。 このような状況を防止するため、Sora は自分が半数以下のグループに属した場合に、新規接続の受け付けを停止します。 また、レギュラーノード数が半数以下のクラスターに参加しているレギュラーノードは、接続中のすべての接続を切断し、その後は接続を受け入れません。 その後、クラスター自動復旧機能により、通信できるレギュラーノードが過半数のグループとなった場合には、自動で新規接続の受け付けを再開します。 ### 全ノードが半数以下のグループに所属した場合の挙動 ネットワーク障害等が発生したことで、いずれのグループも通信できるレギュラーノードが半数以下になった場合、 どのグループでも新規接続はまったく受け付けられない状態になります。 この状態でも Sora は、永続化しておいたレギュラーノード一覧を利用し自動でクラスターの復旧を試みます。 そして、クラスターが復旧して過半数のグループができた場合は新規接続が可能になります。 # クラスター機能録画 ## クラスターにおける録画機能 録画機能はどのノードで録画を開始しても、セッションが存在するノードで録画が行われます。 これはリレー機能を使い複数のノードにセッションがまたがっていても同様です。 すべてのノードでセッションが破棄されたタイミングで録画も終了します。 ## 録画ファイルの出力ノード `archive-.json`, `archive-.webm` の録画ファイルは、接続を担当するノードで 出力されます。 次のような場合には同一の `recording_id` に属する録画ファイルが、 複数ノードにまたがって出力されることがありますのでご注意ください。 1. [録画機能(セッション単位)](RECORDING.html) でチャネル ID を指定して録画開始 2. ノード A に指定したチャネル ID の接続が来てしばらくして切断、録画ファイルがノード A に作られる 3. ノード A が停止 4. ノード B に指定したチャネル ID に接続が来てしばらくして切断、録画ファイルがノード B に作られる ## `report-.json` ファイルの出力ノード あるチャネルに対して、 [StopRecording](API_RECORDING.html#fd0de5) API を実行した場合には録画が終了し、 `report-.json` ファイルが出力されます。 このファイルの出力ノードは次のとおりです。 - そのチャネルに接続したクライアントがひとつもなかった場合はどのノードで出力されるかは未定です- ただし、クラスター内のいずれかのノードで出力されます - そのチャネルに接続中のクライアントがいる場合は、チャネルの担当ノードで出力されます - そのチャネルに接続したクライアントが過去にいた場合は 2 パターンがありえます- クライアントが接続したノードが生存し続けている場合はそのノードで出力されます - ノードが落ちている、または停止した後に再起動した場合にはどのノードで出力されるかは未定です- ただし、クラスター内のいずれかのノードで出力されます ## `report-.json` ファイルが一時的に出力されない場合 全ノードが半数以下に所属した場合には `report-.json` ファイルが出力されません。 5 ノードのクラスターがあるとして、いくつか例を示します。 - ネットワーク障害が発生し、2 + 2 + 1 に分断された場合 - ノード障害(運用での停止も含む)が発生し、3 ノードが停止した場合 - ノード障害で 1 ノードが停止した状態でネットワーク障害が発生し、 2 + 2 に分断された場合 このあとに分断が解消し、過半数のグループができたあとに [StopRecording](API_RECORDING.html#fd0de5) API を 実行すると `report-.json` ファイルが出力されます。 ## `report-.json` ファイルの archives の内容と実際に出力される録画ファイルが一致しない場合 録画中のノードがクラスターから分離された場合に `report-.json` ファイルの `archives` にすべての録画ファイルが含まれないケースがあります。 録画中のノードがクラスターから分離された場合は別のノードが `report-.json` ファイルを出力しますが、クラスター分離前に共有された録画情報の内容で出力し、 分離直後に作成された録画ファイルは含まれないためです。 # クラスター API ## InitCluster *バージョン 2022.2.0 で追加。* **x-sora-target**: Sora_20221221.InitCluster クラスターを初期化する際に実行する必要がある API です。 クラスター初期化時に、参加させるいずれかのノードに対して行ってください。 `node_name_list` にはクラスターに参加するノードのリストを指定してください。 API が成功すると、そのリストのノードで構成されるクラスターが構築されます。 > **ヒント** > > InitCluster API の実行はひとつのクラスターにつき一度だけ必要です。 > InitCluster API 後に、そのクラスターにノードを追加する場合には [RegisterClusterNode](API_CLUSTER.html#09ed96) API を使います。 > > InitCluster API が次に必要になるのはクラスターが破綻した場合です。 > 詳細は [クラスター破綻からの再構築手順](CLUSTER_OPS.html#7c3099) を参照してください。 * - キー - 型 * - node_name_list - array of string ```console $ curl -sS \ -X POST \ http://127.0.0.1:3000/ \ -H "x-sora-target: Sora_20221221.InitCluster" \ --json '{"node_name_list":["node-02@192.0.2.7","node-03@192.0.2.8","node-01@192.0.2.5"]}' \ | jq . { "node_name_list": [ "node-02@192.0.2.7", "node-03@192.0.2.8", "node-01@192.0.2.5" ] } ``` ## RegisterClusterNode **x-sora-target**: Sora_20211215.RegisterClusterNode 指定したクラスターにノードを登録します。 登録したいクラスターに属するノードのいずれかを `contact_node_name` で指定してください。 クラスターに属していれば、どのノードでもかまいません。 - 登録したいクラスターがすでに初期化されている必要があります。 - クラスターに登録するためには、登録したいクラスターの過半数のノードが正常に稼働している必要があります > **注釈** > > 新規にクラスターを作成する場合には、まず [InitCluster](API_CLUSTER.html#621990) API を使用してください。 * - キー - 型 * - contact_node_name - string ```console $ curl -sS \ -X POST \ http://127.0.0.1:3000/ \ -H "x-sora-target: Sora_20211215.RegisterClusterNode" \ --json '{"contact_node_name":"node-03@192.0.2.8"}' \ | jq . { "node_name_list": [ "node-01@192.0.2.5", "node-02@192.0.2.7", "node-03@192.0.2.8", "node-04@192.0.2.9", "node-05@192.0.2.10" ] } ``` ## ListClusterNodes **x-sora-target**: Sora_20211215.ListClusterNodes クラスターのノード一覧を表示します。 一時的に離脱しているノードの場合は `connected` が `false` になります。 出力対象のノードが離脱中、またはノードの情報取得に失敗した場合には以下の項目は出力されません。 - external_api_url - external_signaling_url - version - mode **レスポンス JSON** * - キー - 型 - 内容 * - external_api_url - string - ``sora.conf`` の ``external_api_url`` * - license_max_nodes - integer - ライセンスの最大ノード数 * - license_max_connections - integer - ライセンスの最大同時接続数 * - license_serial_code - string - ライセンスのシリアルコード * - license_type - string - ライセンスのタイプ * - node_name - string - ``sora.conf`` の ``node_name`` * - error - string - API 実行ノードと正常に接続はできているが、情報の取得に失敗した際のエラー理由 * - connected - boolean - API 実行ノードと正常に接続できているかどうか * - external_signaling_url - string - ``sora.conf`` の ``external_signaling_url`` * - temporary_node - boolean - テンポラリーノードかどうか * - version - string - Sora のバージョン * - mode - string - モード (normal / block_new_session / block_new_connection) ```console $ curl -sS \ -X POST \ http://127.0.0.1:3000/ \ -H "x-sora-target: Sora_20211215.ListClusterNodes" \ | jq . [ { "external_api_url": "http://192.0.2.5:3000/", "license_max_connections": 500, "license_max_nodes": 10, "license_serial_code": "ABCDEF-SRA-E001-203801-N3-100", "license_type": "Experimental", "node_name": "node-01@192.0.2.5", "mode": "normal", "connected": true, "external_signaling_url": "wss://node-01.example.com/signaling", "version": "2024.1.0", "temporary_node": false }, { "api_url": "http://192.0.2.7:3000/", "license_max_connections": 500, "license_max_nodes": 10, "license_serial_code": "ABCDEF-SRA-E002-203801-N3-100", "license_type": "Experimental", "node_name": "node-02@192.0.2.7", "mode": "normal", "connected": true, "external_signaling_url": "wss://node-02.example.com/signaling", "version": "2024.1.0", "temporary_node": false }, { "license_max_connections": 500, "license_max_nodes": 10, "license_serial_code": "ABCDEF-SRA-E003-203801-N3-100", "license_type": "Experimental", "node_name": "node-03@192.0.2.11", "connected": false, "temporary_node": false }, { "error": "{error,{erpc,timeout}}", "license_max_connections": 500, "license_max_nodes": 10, "license_serial_code": "ABCDEF-SRA-E004-203801-N3-100", "license_type": "Experimental", "node_name": "node-04@192.0.2.9", "connected": false, "temporary_node": false } ] ``` ## ListClusterChannels **x-sora-target**: Sora_20211215.ListClusterChannels クラスターチャネル割り当て一覧を表示します。 * - キー - 型 - 内容 * - channel_id - string - チャネル ID * - owners - string - 担当ノード owners には以下が含まれます。 * - キー - 型 - 内容 * - node_name - string - ノード名 * - connected - boolean - 担当ノードが API 実行ノードと正常に接続できているかどうか ```console $ curl -sS \ -X POST \ http://127.0.0.1:3000/ \ -H "x-sora-target: Sora_20211215.ListClusterChannels" \ | jq . [ { "channel_id": "sora", "owners": [ { "node_name": "node-01@192.0.2.5", "connected": true } ] }, { "channel_id": "lemon", "owners": [ { "node_name": "node-01@192.0.2.5", "connected": true } ] }, { "channel_id": "hisui", "owners": [ { "node_name": "node-03@192.0.2.8", "connected": true } ] }, { "channel_id": "zakuro", "owners": [ { "node_name": "node-03@192.0.2.8", "connected": true } ] } ] ``` ## PurgeClusterNode **x-sora-target**: Sora_20220629.PurgeClusterNode 復旧がすぐには難しい障害が発生したノードや、縮退し再参加する予定が無いノードの情報をクラスターから完全に消去します。 この API は 1 クラスターにつき 1 回実行すればすべての参加ノードから指定したノード情報が完全に消去されます。 - この API の実行時には、消去対象のノードは停止している必要があります - この API が正常に完了するためには、過半数のノードが正常に稼働している必要があります - API を実行するノードは、クラスターに参加していて、正常に稼働しているノードであればどのノードでもかまいません > **警告** > > PurgeClusterNode API はクラスターからノードを完全に消去するための API です。 > 再参加するノードに対しては基本的に使用しないでください。 > この API を含めた運用の手順は [クラスター機能運用](CLUSTER_OPS.html) をご確認ください。 * - キー - 型 * - target_node_name - string ```console $ curl -sS \ -X POST \ http://127.0.0.1:3000/ \ -H "x-sora-target: Sora_20220629.PurgeClusterNode" \ --json '{"target_node_name":"node-03@192.0.2.8"}' \ | jq . { "target_node_name": "node-03@192.0.2.8" } ``` ```console $ curl -sS \ -X POST \ http://127.0.0.1:3001/ \ -H "x-sora-target: Sora_20220629.PurgeClusterNode" \ --json '{"target_node_name":"node-03@192.0.2.8"}' \ | jq . { "error_reason": { "target_node": "node-03@192.0.2.8" }, "error_type": "NODE-IS-ALIVE" } ``` # サイマルキャスト機能 ## 概要 サイマルキャスト (Simulcast) は、配信時に 1 つの RTCPeerConnection から複数種類のエンコードした映像を配信する技術です。 映像を配信する際、 Sora に対して、 1 つの RTCPeerConnection で複数種類のエンコードした映像を送信することにより、 受信者がどの映像を受信するかを選択できるようになります。 ## 注意 ### 現時点でのサイマルキャストの仕様 2026 年 6 月 時点で libwebrtc を利用したサイマルキャストで出力されるストリームの本数は解像度とビットレートに依存しています。 #### VP8 / H264 **解像度とビットレートとストリーム数の関係** * - 解像度 - ビットレート - ストリーム数 * - 1920x1080 - 5000 kbps - 3 * - 1280x720 - 2500 kbps - 3 * - 960x540 - 1200 kbps - 3 * - 640x360 - 700 kbps - 2 * - 480x270 - 450 kbps - 2 * - 320x180 - 200 kbps - 1 #### VP9 / AV1 / H265 **解像度とビットレートとストリーム数の関係** * - 解像度 - ビットレート - ストリーム数 * - 1920x1080 - 3367 kbps - 3 * - 1280x720 - 1524 kbps - 3 * - 960x540 - 879 kbps - 3 * - 640x360 - 420 kbps - 2 * - 480x270 - 257 kbps - 1 * - 320x180 - 142 kbps - 1 * - 240x135 - 101 kbps - 1 #### libwebrtc の仕様 この値は libwebrtc にハードコードされています。 VP8 (AV1/H264) と VP9(H265) で異なります。 ```cpp // These tables describe from which resolution we can use how many // simulcast layers at what bitrates (maximum, target, and minimum). // Important!! Keep this table from high resolution to low resolution. constexpr const SimulcastFormat kSimulcastFormatsVP8[] = { {.width = 1920, .height = 1080, .max_layers = 3, .max_bitrate = DataRate::KilobitsPerSec(5000), .target_bitrate = DataRate::KilobitsPerSec(4000), .min_bitrate = DataRate::KilobitsPerSec(800)}, {.width = 1280, .height = 720, .max_layers = 3, .max_bitrate = DataRate::KilobitsPerSec(2500), .target_bitrate = DataRate::KilobitsPerSec(2500), .min_bitrate = DataRate::KilobitsPerSec(600)}, {.width = 960, .height = 540, .max_layers = 3, .max_bitrate = DataRate::KilobitsPerSec(1200), .target_bitrate = DataRate::KilobitsPerSec(1200), .min_bitrate = DataRate::KilobitsPerSec(350)}, {.width = 640, .height = 360, .max_layers = 2, .max_bitrate = DataRate::KilobitsPerSec(700), .target_bitrate = DataRate::KilobitsPerSec(500), .min_bitrate = DataRate::KilobitsPerSec(150)}, {.width = 480, .height = 270, .max_layers = 2, .max_bitrate = DataRate::KilobitsPerSec(450), .target_bitrate = DataRate::KilobitsPerSec(350), .min_bitrate = DataRate::KilobitsPerSec(150)}, {.width = 320, .height = 180, .max_layers = 1, .max_bitrate = DataRate::KilobitsPerSec(200), .target_bitrate = DataRate::KilobitsPerSec(150), .min_bitrate = DataRate::KilobitsPerSec(30)}, // As the resolution goes down, interpolate the target and max bitrates down // towards zero. The min bitrate is still limited at 30 kbps and the target // and the max will be capped from below accordingly. {.width = 0, .height = 0, .max_layers = 1, .max_bitrate = DataRate::KilobitsPerSec(0), .target_bitrate = DataRate::KilobitsPerSec(0), .min_bitrate = DataRate::KilobitsPerSec(30)}}; ``` ```cpp // These tables describe from which resolution we can use how many // simulcast layers at what bitrates (maximum, target, and minimum). // Important!! Keep this table from high resolution to low resolution. constexpr const SimulcastFormat kSimulcastFormatsVP9[] = { {.width = 1920, .height = 1080, .max_layers = 3, .max_bitrate = DataRate::KilobitsPerSec(3367), .target_bitrate = DataRate::KilobitsPerSec(3367), .min_bitrate = DataRate::KilobitsPerSec(769)}, {.width = 1280, .height = 720, .max_layers = 3, .max_bitrate = DataRate::KilobitsPerSec(1524), .target_bitrate = DataRate::KilobitsPerSec(1524), .min_bitrate = DataRate::KilobitsPerSec(481)}, {.width = 960, .height = 540, .max_layers = 3, .max_bitrate = DataRate::KilobitsPerSec(879), .target_bitrate = DataRate::KilobitsPerSec(879), .min_bitrate = DataRate::KilobitsPerSec(337)}, {.width = 640, .height = 360, .max_layers = 2, .max_bitrate = DataRate::KilobitsPerSec(420), .target_bitrate = DataRate::KilobitsPerSec(420), .min_bitrate = DataRate::KilobitsPerSec(193)}, {.width = 480, .height = 270, .max_layers = 2, .max_bitrate = DataRate::KilobitsPerSec(257), .target_bitrate = DataRate::KilobitsPerSec(257), .min_bitrate = DataRate::KilobitsPerSec(121)}, {.width = 320, .height = 180, .max_layers = 1, .max_bitrate = DataRate::KilobitsPerSec(142), .target_bitrate = DataRate::KilobitsPerSec(142), .min_bitrate = DataRate::KilobitsPerSec(30)}, {.width = 240, .height = 135, .max_layers = 1, .max_bitrate = DataRate::KilobitsPerSec(101), .target_bitrate = DataRate::KilobitsPerSec(101), .min_bitrate = DataRate::KilobitsPerSec(30)}, // As the resolution goes down, interpolate the target and max bitrates down // towards zero. The min bitrate is still limited at 30 kbps and the target // and the max will be capped from below accordingly. {.width = 0, .height = 0, .max_layers = 1, .max_bitrate = DataRate::KilobitsPerSec(0), .target_bitrate = DataRate::KilobitsPerSec(0), .min_bitrate = DataRate::KilobitsPerSec(30)}}; ``` - VP8 向けが H.264 と VP8 に利用されます - VP9 向けが VP9 と AV1 と H.265 に利用されます ### SDK 対応状況 以下の SDK の最新版で、配信と視聴ともに VP8 と VP9 と AV1 と H.264 と H.265 に対応済みです。 - JavaScript SDK - iOS SDK - Android SDK - Unity SDK - C++ SDK - Python SDK ### 配信ブラウザの対応状況 配信側は Chrome と Edge と Safari の最新バージョンに対応しています。 > **警告** > > Firefox は配信に対応していません。 ### 視聴ブラウザの対応状況 視聴側は Chrome と Safari と Firefox と Edge の最新バージョンに対応しています。 > **警告** > > Firefox は AV1 に対応していません。 ### 映像コーデック 配信時に利用できる映像コーデックは VP8 と VP9 と AV1 と H.264 と H.265 です。 ### 映像ビットレート 利用するコーデックと解像度に合わせてビットレートを選択してください。 - 1080p AV1 を利用し、デフォルトのサイマルキャストの設定- 解像度が 1080p / 540p / 270p の 3 種類の映像を配信します - 指定すべきビットレートは 3367 + 879 + 257 = 4503 kbps です - 1080p の映像は 3367 kbps で配信され、540p の映像は 879 kbps で配信され、270p の映像は 257 kbps で配信されます - 720p H.264 を利用し、デフォルトのサイマルキャストの設定- 解像度が 720p / 360p / 180p の 3 種類の映像を配信します - 指定すべきビットレートは 2500 + 700 + 450 = 3650 kbps です - 720p の映像は 2500 kbps で配信され、360p の映像は 700 kbps で配信され、180p の映像は 450 kbps で配信されます ### VP9 と AV1 でのサイマルキャスト > **注意** > > Safari 26.0 ではまだ VP9 と AV1 のサイマルキャストに対応していません VP9 や AV1 でサイマルキャストを行う場合、ブラウザでは配信側が Chrome 113 / Edge 113 以降である必要があります。 また設定では `scalabilityMode` と `scaleResolutionDownBy` または `scaleResolutionDownTo` のどちらかの 2 つを設定する必要があります。 詳細は [scalabilityMode](SIMULCAST.html#918c4d) をご確認ください。 ### H.265 でのサイマルキャスト H.265 でサイマルキャストを行う場合、 ブラウザでは配信側が Chrome 137 か Safari 18.0 以降を利用する必要があり、 視聴側も同様に Chrome 137 か Safari 18.0 以降を利用する必要があります。 ### 非対応機能 **以下は今後対応予定です** - ULPFEC 機能には対応していません ## 映像の優先度 サイマルキャストでは 1 つのクライアントからの同じ映像を複数のエンコードで配信できます。 Sora では 1 つのクライアントから最大 3 種類のエンコードで映像を受信する仕組みが入っています。 この 3 種類の映像のそれぞれに r0 / r1 / r2 の 3 つの値を定義しています。 この値は rid と呼ばれています。 配信継続の優先度は r0 > r1 > r2 です。 例えば、回線が不安定だったりマシンの負荷が高かった場合、rid が `r2` の映像の配信が最初に停止します。 さらに配信状況が悪化した場合は rid が `r1` の映像の配信が停止します。 `r0` の映像は必ず配信されます。 ## 映像の種類のデフォルト Sora ではサイマルキャストで配信する映像の種類にデフォルト値を設定しています。 ```javascript [ {"rid": "r0", "active": true, "scaleResolutionDownBy": 4.0, "scalabilityMode": "L1T1"}, {"rid": "r1", "active": true, "scaleResolutionDownBy": 2.0, "scalabilityMode": "L1T1"}, {"rid": "r2", "active": true, "scaleResolutionDownBy": 1.0, "scalabilityMode": "L1T1"} ] ``` ### r0 `rid` が `r0` の場合は通常の解像度と比べて、一辺 が 1/4 の解像度の映像になるように設定されています。 ### r1 `rid` が `r1` の場合は通常の解像度と比べて、一辺 が 1/2 の解像度の映像になるように設定されています。 ### r2 `rid` が `r2` の場合は通常の解像度のままの映像に設定されています。 ## rid: none Sora ではシグナリング開始時、認証成功時、および API で `rid` を `none` にリクエストすることができます。 `rid` に `none` を指定した場合、視聴側に映像ストリームが配信されなくなります。 - シグナリング開始時の `simulcast_request_rid` で `none` を指定することができます - 認証成功時の `simulcast_request_rid` で `none` を指定することができます - [RequestSimulcastRid](API_SIMULCAST.html#7d26ab) API の `rid` で `none` を指定することができます > **注意** > > `sora.conf` の [simulcast_encodings_file](SORA_CONF.html#dead73) や認証成功時に払いだす `simulcast_encodings` では `rid` に `none` を指定することはできません。 ## 視聴側の自動 rid ストリーム切り替え機能 *バージョン 2025.2.0 で追加。* > **注意** > > この機能は [実験的機能](EXPERIMENTAL.html) のため、正式版では仕様が変更される可能性があります。 従来の Sora では、視聴側がどの `rid` ストリームを受信するかは、アプリケーション側が API を利用して明示的に切り替える必要がありました。 Sora 2025.2.0 では新たに、視聴側の環境に合わせて Sora が自動的に `rid` ストリームを切り替えて配信する機能を追加しました。 この機能をデフォルトで有効にする場合は、 `sora.conf` の [default_simulcast_auto_rids](SORA_CONF.html#97a674) に、自動切り替えに利用する rid をリストで指定してください。 接続ごとに設定を指定する場合は、認証成功時に `simulcast_auto_rids` を指定することができます。これは `sora.conf` の [default_simulcast_auto_rids](SORA_CONF.html#97a674) 設定を上書きします。 `simulcast_auto_rids` で `rid` が指定されている状態で、 `simulcast_request_rid` で指定した `rid` が視聴環境の制約により利用できないと判断された場合、 Sora は自動でより低いビットレートの `rid` に切り替えます。 `simulcast_auto_rids` には、 `["r0", "r1"]` のように複数の rid を指定することができます ## シグナリング通知での rid 切り替えイベント `sora.conf` の `signaling_notify_simulcast_switched` を `true` に設定することで、視聴側の自動 rid 切り替えが発生した際にシグナリング通知が送信されます。 ## 映像のエンコーディングパラメーターのカスタマイズ Sora ではサイマルキャストで配信する映像のエンコーディングパラメーターを自由に設定できます。 - sora.conf のファイルで指定することで全体のサイマルキャストのエンコーディングパラメーターが指定できます - 認証成功時に simulcast_encodings で払い出すことで個別にサイマルキャストのエンコーディングパラメーターが指定できます ### sora.conf でファイル指定 sora.conf にて `simulcast_encodings_file` で JSON を指定してください。 ```ini simulcast_encodings_file = etc/simulcast_encodings.json ``` ### sora.conf で指定する JSON ファイルの記述方法 ```javascript [ {"rid": "r0", "active": true, "scaleResolutionDownBy": 2.0, "maxFramerate": 5.0}, {"rid": "r1", "active": true, "scaleResolutionDownBy": 2.0, "maxFramerate": 20.0}, {"rid": "r2", "active": true, "scaleResolutionDownBy": 1.0, "maxFramerate": 30.0} ] ``` ### 認証成功時に simulcast_encodings で払い出す記述方法 ```javascript { "allowed": true, "simulcast_encodings": [ {"rid": "r0", "active": true, "scaleResolutionDownBy": 2.0, "maxFramerate": 5.0}, {"rid": "r1", "active": true, "scaleResolutionDownBy": 2.0, "maxFramerate": 20.0}, {"rid": "r2", "active": true, "scaleResolutionDownBy": 1.0, "maxFramerate": 30.0} ] } ``` ### カスタマイズの設定 - rid- 必須 - string (r0 / r1 / r2) - active- このエンコーディングパラメーターを有効にします - オプション - boolean - scaleResolutionDownBy- オプション - 1 以上の number (float または integer) - maxBitrate- オプション - 最大ビットレートを指定する - 0 以上の integer - maxFramerate- オプション - 最大フレームレートを指定する - 0 以上の number (float または integer) - scaleResolutionDownTo- **この設定は Chrome 131 / Edge 131 以降でしか利用できません** - オプション - `{"maxHeight": 1080, "maxWidth": 1920}` のような JSON Object - `maxHeight` と `maxWidth` は 0 よりも大きい整数 - `scaleResolutionDownBy` よりも優先されます - `maxHeight` と `maxWidth` の両方が指定されている場合に有効です - adaptivePtime- **この設定は Chrome でしか利用できません** - オプション - boolean - priority- **この設定は Chrome でしか利用できません** - オプション - string (`very-low` / `low` / `medium` / `high`) - networkPriority- **この設定は Chrome でしか利用できません** - オプション - string (`very-low` / `low` / `medium` / `high`) - scalabilityMode- **この設定は Chrome / Edge でしか利用できません** - オプション - string ### active: false の挙動 r1 の active を false にカスタマイズしている配信で r1 を受信をリクエストした場合、r0 が配信されます。 ```javascript [ {"rid": "r0", "active": true}, {"rid": "r1", "active": false}, {"rid": "r2", "active": true} ] ``` r0 の active を false にカスタマイズしている配信で r0 を受信をリクエストした場合、r1 が配信されます。 ```javascript [ {"rid": "r0", "active": false}, {"rid": "r1", "active": true}, {"rid": "r2", "active": true} ] ``` r0 と r1 の active を false にカスタマイズしている配信で r0 を受信をリクエストした場合、r2 が配信されます。 ```javascript [ {"rid": "r0", "active": false}, {"rid": "r1", "active": false}, {"rid": "r2", "active": true} ] ``` ### scalabilityMode **この設定は Chrome / Edge M113 以降でのみ有効です** > **注釈** > > [PSA: VP9/AV1 simulcast support in M113](https://groups.google.com/g/discuss-webrtc/c/-QQ3pxrl-fw?pli=1) VP9 または AV1 でサイマルキャストを利用する場合の条件として、 `scalabilityMode` と `scaleResolutionDownBy` または `scaleResolutionDownTo` のどちらかをすべての rid に対して設定する必要があります。 サイマルキャスト利用時に `scalabilityMode` に設定可能な値は `L1T1` 、 `L1T2` 、 `L1T3` のみです。 デフォルトでは `L1T1` が指定されています。特に理由がなければ `L1T1` を利用してください。 > **重要** > > AV1 でサイマルキャストやスポットライトを利用し、録画をする場合は `L1T1` を利用してください。 > L1T1 以外では正常に録画がされません。 #### 例 ```javascript [ {"rid": "r0", "active": true, "scaleResolutionDownBy": 4.0, "scalabilityMode": "L1T1"}, {"rid": "r1", "active": true, "scaleResolutionDownBy": 2.0, "scalabilityMode": "L1T1"}, {"rid": "r2", "active": true, "scaleResolutionDownBy": 1.0, "scalabilityMode": "L1T1"} ] ``` ## 配信側の利用方法 シグナリング開始時に指定できます。 ### シグナリング開始時 シグナリングの `"type": "connect"` 時に `"simulcast": true` を指定することで、有効になります。 映像コーデックは `VP8` または `H264` を選択してください。 ```javascript { "type": "connect":, "role": "sendonly", "channel_id": "sora", "video": {"codec_type": "VP8"}, "simulcast": true } ``` ## 視聴側の利用方法 シグナリング開始時に指定できます。 ### シグナリング開始時 - シグナリング `"type": "connect"` 時に `"simulcast": true` を指定することで、有効になります - `simulcast_request_rid` には `none` / `r0` / `r1` / `r2` が指定できます- `simulcast_request_rid` を指定しない場合は `r0` が指定されます - この値は **サイマルキャストで配信されている映像を受信する際のデフォルト値** です - この値は `sora.conf` の `default_simulcast_rid` で変更できます - `none` を指定した場合、映像は配信されません - 映像コーデックは `VP8` または `H264` を選択してください ```javascript { "type": "connect":, "role": "recvonly", "channel_id": "sora", "video": {"codec_type": "VP8"}, "simulcast": true, "simulcast_request_rid": "r2" } ``` ## 視聴側のストリームの変更 API 詳細は [サイマルキャスト API](API_SIMULCAST.html) をご確認ください ## scalabilityMode - scalabilityMode は Chrome と Edge でのみ利用できます。 - Edge では H.265 が利用できないため、H.265 の結果は Chrome の結果となります。 - VP8 と H.264 では L1T1 / L1T2 / L1T3 のみが利用できます - H.265 では L1T1 のみが利用できます - scalabilityMode の詳細に付いては [Scalable Video Coding (SVC) Extension for WebRTC](https://w3c.github.io/webrtc-svc/) をご確認ください。 **scalabilityMode 対応状況** * - Mode - VP8 - VP9 - AV1 - H.264 - H.265 * - L1T1 - o - o - o - o - o * - L1T2 - o - o - o - o - x * - L1T3 - o - o - o - o - x * - L2T1 - x - o - o - x - x * - L2T2 - x - o - o - x - x * - L2T3 - x - o - o - x - x * - L3T1 - x - o - o - x - x * - L3T2 - x - o - o - x - x * - L3T3 - x - o - o - x - x * - L2T1h - x - o - o - x - x * - L2T2h - x - o - o - x - x * - L2T3h - x - o - o - x - x * - L3T1h - x - o - o - x - x * - L3T2h - x - o - o - x - x * - L3T3h - x - o - o - x - x * - S2T1 - x - o - o - x - x * - S2T2 - x - o - o - x - x * - S2T3 - x - o - o - x - x * - S2T1h - x - o - o - x - x * - S2T2h - x - o - o - x - x * - S2T3h - x - o - o - x - x * - S3T1 - x - o - o - x - x * - S3T2 - x - o - o - x - x * - S3T3 - x - o - o - x - x * - S3T1h - x - o - o - x - x * - S3T2h - x - o - o - x - x * - S3T3h - x - o - o - x - x * - L2T2_KEY - x - o - o - x - x * - L2T2_KEY_SHIFT - x - o - o - x - x * - L2T3_KEY - x - o - o - x - x * - L2T3_KEY_SHIFT - x - x - x - x - x * - L3T1_KEY - x - o - o - x - x * - L3T2_KEY - x - o - o - x - x * - L3T2_KEY_SHIFT - x - x - x - x - x * - L3T3_KEY - x - o - o - x - x * - L3T3_KEY_SHIFT - x - x - x - x - x ## シーケンス図 ```mermaid sequenceDiagram participant C1 as クライアント1 participant S as WebRTC SFU Sora participant C2 as クライアント2 C1->>S: "type": "connect",
"role": "sendonly",
"simulcast":"true" note over C1, S: クライアント1 WebRTC 確立 C2->>S: "type": "connect",
"role": "recvonly",
"simulcast":"true",
"simulcast_rid": "r1" note over C2, S: クライアント2 WebRTC 確立 par C1-)S: 映像
rid: r0 and C1-)S: 映像
rid: r1 S-)C2: 映像
rid: r1 and C1-)S: 映像
rid: r2 end ``` # サイマルキャストマルチコーデック機能 > **注意** > > この機能を利用する場合は事前にサポートまでご連絡ください > **警告** > > この機能は [実験的機能](EXPERIMENTAL.html) のため、正式版では仕様が変更される可能性があります ## 概要 サイマルキャストマルチコーデックは、複数のコーデックを同時に使用して、サイマルキャストを実現する仕組みです。 ## 注意 この機能は実験的機能として提供しており、かつブラウザ側の実装が未定のため、 将来的に仕様が大きく変更する可能性があります。それを踏まえてご利用ください。 不明点がある場合はサポートまでお問い合わせください。 ## 制限 ### ブラウザでの配信 > **重要** > > 2026 年 6 月 現在、ブラウザでサイマルキャストマルチコーデック機能を利用することはできません。 ### ブラウザでの視聴 一部ブラウザでサイマルキャストマルチコーデックで配信された映像を視聴することはできます。 視聴時のコーデック切り替えにも対応しています。 動作が確認できているブラウザは Chrome と Edge と Safari Technology Preview です。 それ以外のブラウザでは正常に動作しない可能性があります。 ### 録画機能の利用 **将来的に対応予定です** サイマルキャストマルチコーデックが有効なクライアントでは録画機能を利用することはできません。 ### 映像コーデック指定の無視 サイマルキャストマルチコーデックを指定した場合、 クライアントや認証時の払い出しでのコーデック指定は無視されます。 ## 利用方法 サイマルキャストマルチコーデックを利用する ### sora.conf で simulcast_multicodec を有効にする サイマルキャストマルチコーデック機能を利用するには `sora.conf` で [simulcast_multicodec](SORA_CONF.html#a8cf0f) を `true` に設定します。 ```ini simulcast_multicodec = true ``` ### シグナリング接続時に `"simulcast": true` と `"simulcast_multicodec": true` を指定する マルチコーデックサイマルキャストを利用するにはシグナリング接続時に `"simulcast": true` と `"simulcast_multicodec": true` を指定します。 この際、 `"video": {"codec_type": "VP8"}` などのコーデック指定は無視されます。 ```javascript { "type": "connect", "role": "sendrecv", "channel_id": "sora", "simulcast": true, "simulcast_multicodec": true } ``` ### サイマルキャストマルチコーデックのデフォルト値 サイマルキャストマルチコーデック用のコーデックには以下のデフォルト値が設定されています。 ```javascript [ {"rid": "r0", "codec_type": "AV1", "codec_params": {"profile": 0}}, {"rid": "r1", "codec_type": "AV1", "codec_params": {"profile": 0}}, {"rid": "r2", "codec_type": "H264", "codec_params": {"profile_level_id": "42e02a"}} ] ``` ### サイマルキャストマルチコーデックのデフォルト値を変更する `sora.conf` の [simulcast_codecs_file](SORA_CONF.html#cc4473) でサイマルキャストマルチコーデックで利用するコーデックのデフォルトを指定することができます。 ```ini simulcast_codecs_file = etc/simulcast_codecs.json ``` ```javascript [ {"rid": "r0", "codec_type": "H264", "codec_params": {"profile_level_id": "42e02a"}}, {"rid": "r1", "codec_type": "H264", "codec_params": {"profile_level_id": "42e02a"}}, {"rid": "r2", "codec_type": "H265"} ] ``` ### 認証成功時の払い出しで指定する サイマルキャストマルチコーデックを利用する場合 `simulcast` と `simulcast_multicodec` を認証成功時に払い出すことができます。 ```javascript { "allowed": true, "simulcast": true, "simulcast_multicodec": true } ``` r0 と r1 に H264 、r2 に H265 を利用する場合の例です。 ```javascript { "allowed": true, "simulcast": true, "simulcast_multicodec": true, "simulcast_codecs": [ {"rid": "r0", "codec_type": "H264", "codec_params": {"profile_level_id": "42e02a"}}, {"rid": "r1", "codec_type": "H264", "codec_params": {"profile_level_id": "42e02a"}}, {"rid": "r2", "codec_type": "H265"} ] } ``` ### simulcast_encodings の指定 サイマルキャストマルチコーデックのサイマルキャストエンコード部分は `simulcast_encodings` のデフォルト値を利用します。 そのため、サイマルキャストマルチコーデック向けに `simulcast_encodings` を指定したい場合は、 認証成功時に払い出す必要があります。 ```javascript { "allowed": true, "simulcast": true, "simulcast_multicodec": true, "simulcast_encodings": [ {"rid": "r0", "active": true, "scaleResolutionDownBy": 4.0, "maxFramerate": 10.0}, {"rid": "r1", "active": true, "scaleResolutionDownBy": 1.0, "maxFramerate": 30.0}, {"rid": "r2", "active": true, "scaleResolutionDownBy": 1.0, "maxFramerate": 30.0} ], "simulcast_codecs": [ {"rid": "r0", "codec_type": "H264", "codec_params": {"profile_level_id": "42e02a"}}, {"rid": "r1", "codec_type": "H264", "codec_params": {"profile_level_id": "42e02a"}}, {"rid": "r2", "codec_type": "H265"} ] } ``` ### type: offer 時に払い出される内容 `simulcast_encodings` と `simulcast_codecs` に指定された値から、 W3C WebRTC 準拠の [RTCRtpEncodingParameters](https://w3c.github.io/webrtc-pc/#dom-rtcrtpencodingparameters) を生成し、 `"type": "offer"` の `"encodings"` として追加します。 `"codec"` については [W3C WebRTC RTCRtpCodecParameters](https://w3c.github.io/webrtc-pc/#rtcrtpcodecparameters) と [W3C WebRTC Extension RTCRtpEncodingParameters](https://w3c.github.io/webrtc-extensions/#rtcrtpencodingparameters) に準拠しています。 ```javascript { "type": "offer", "simulcast": true, "simulcast_multicodec": true, "encodings": [ { "rid": "r0", "active": true, "scaleResolutionDownBy": 4.0, "maxFramerate": 10.0, "codec": { "mimeType": "video/H264", "clockRate": 90000, "sdpFmtpLine": "level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42e02a" } }, { "rid": "r1", "active": true, "scaleResolutionDownBy": 1.0, "maxFramerate": 30.0, "codec": { "mimeType": "video/H264", "clockRate": 90000, "sdpFmtpLine": "level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42e02a" } }, { "rid": "r2", "active": true, "scaleResolutionDownBy": 1.0, "maxFramerate": 30.0, "codec": { "mimeType": "video/H265", "clockRate": 90000, "sdpFmtpLine": "profile-id=1;level-id=93" } } ] } ``` # スポットライト機能 ## 概要 WebRTC SFU サーバーを利用して 20 名で会議を行う場合、各参加者は自分以外の 19 名分の音声と映像を常に受信し続ける必要があります。 また、WebRTC SFU サーバーも、常に 20 名分の音声や映像を受信し、配信し続ける必要があります。 ところが実際は 20 名の会議であっても、ひとつのトピックに対して発言している人はせいぜい 2 名から 3 名です。 また、映像も常に参加者全員のものを高画質で配信しなくとも、その時点でアクティブに発言している人の映像がクリアであれば十分というケースも多いです。 この **スポットライト機能** を利用すると、発言していない大多数の参加者の音声は配信せず、低画質の映像のみを配信できます。ある参加者が発言し始めると、自動でその参加者の音声の配信を開始し、さらにあらかじめ設定した秒数が経過すると、映像の画質も自動で高画質に切り替えることができます。 この仕組を使うことで、クライアントやサーバーの負荷を抑えながら大人数で会議できるようになります。 この機能は、発言している参加者のみの音声と高画質の映像が配信されることから、スポットライトが当たるイメージに見立てて、スポットライト機能と名付けています。 ## 仕組み 開始前に、フォーカスする人数を決めます。 フォーカスする人数とは、会議の参加者のうち、最大何人分の映像を高画質で配信するかの数です。 ここではフォーカスする人数を 1 人とします。 この機能を利用した場合は、発言していない参加者の映像は低画質で配信され、音声は配信されません。 最初に A さんが発言し始めると、 A さんの映像が高画質になって配信されます。 次に B さんが発言すると、 B さんの映像が高画質になって配信されます。 このタイミングで A さんの映像は低画質になります。 その後は同じように、直近で発言した 1 人分の映像が高画質で配信され、音声も配信されます。 それ以外の参加者の映像は低画質で配信され、音声は配信されません。 このように、高画質で配信する人数を限定することで、クライアントやサーバーの負荷を抑えながら大人数での会議が実現できます。 ただし、上記のような自動切り替えでは、参加者の映像が頻繁に入れ替わると逆に負荷が高くなってしまいます。 それを抑えるため、Sora では、参加者が発言し始めるとまずは音声だけを配信し始め、映像の切り替えはしばらく時間が経ってから行うことができます。 この時、映像が切り替わる前に、先に音声を配信することをフォーカスなし音声配信と呼びます。 これにより、映像の切り替わりの有無に関わらず、短い発言、あいづちなども配信し、スムーズな会話を成立させられます。 また、音声よりも遅れて映像を切り替えることを遅延フォーカスと呼びます。 映像の切り替えを遅延させることにより、ちょっとした雑音や短い発言のたびに映像が切り替わることを抑制できます。 これらのフォーカスなし音声配信や遅延フォーカス機能を利用すれば、スポットライト機能でフォーカスする人数は 1 〜 2 人で十分です。多くても 3 人です。 ## 注意 ### スポットライト機能はサイマルキャスト機能を活用した機能です デフォルトであれば解像度が VGA 以上のサイズであれば 2 つの画質の映像を配信します。 - 高画質 (r1)- 解像度の縮小比が 1 で 30 fps - 低画質 (r0)- 解像度の縮小比が 4 で 5 fps > **注釈** > > スポットライト機能はデフォルトで r2 をエンコードを行いません。 ### Chrome 、 Edge 、 Safari で動作します 現時点では Chrome と Edge と Safari の最新版に対応しています。 > **注釈** > > Firefox ではサイマルキャスト機能ができないため、 > Firefox を利用する場合はサイマルキャスト機能を無効にして接続する必要があります。 > > 詳細は [サイマルキャスト機能を無効にして接続する](SPOTLIGHT.html#ae2845) をご確認ください。 ## サイマルキャストとの違い サイマルキャストを利用する場合、 受信する映像の種類を切り替えるには [RequestRtpStream](DEPRECATED_API_SIMULCAST.html#6fe0b3) API を利用する必要があります。 スポットライトはこの API の切り替え部分を Sora が自動で判断します。判断には参加者の音量を利用します。 例えば、音量が閾値を下回った場合は rid は r0 、閾値を超えた場合は rid は r1 のように、他の参加者が受信する映像の rid を切り替えます。 - マルチストリームの詳細は [マルチストリーム機能](MULTISTREAM.html) をご確認ください - サイマルキャストの詳細は [サイマルキャスト機能](SIMULCAST.html) をご確認ください ## SDK 対応状況 - 最新版の JavaScript SDK- 対応済みです - 最新版の iOS SDK- 対応済みです - 最新版の Android SDK- 対応済みです - 最新版の Unity SDK- 対応済みです - 最新版の C++ SDK- 対応済みです - 最新版の Python SDK- 対応済みです ## スポットライト利用時の映像の種類のデフォルト Sora ではスポットライトで配信する映像の種類にデフォルト値を設定しています。 ```javascript [ {"rid": "r0", "active": true, "maxFramerate": 5.0, "scaleResolutionDownBy": 4.0, "scalabilityMode": "L1T1"}, {"rid": "r1", "active": true, "maxFramerate": 30.0, "scaleResolutionDownBy": 1.0, "scalabilityMode": "L1T1"}, {"rid": "r2", "active": false} ] ``` ### r0 rid が r0 の場合は通常の解像度から解像度(一辺) が 1/4 で、 フレームレートが 5 になるようなエンコードがされるように設定されています。 ### r1 rid が r1 の場合は通常の解像度のままで、 フレームレートが 30 でエンコードがされるように設定されています。 ### r2 rid が r2 の場合はエンコードがされないように設定されています。 ## スポットライト利用時の映像のエンコーディングパラメーターのカスタマイズ Sora ではスポットライトでの映像のエンコーディングパラメーターを自由に設定できます。 - `sora.conf` のファイルで指定することで全体のスポットライトのエンコーディングパラメーターが指定できます - 認証成功時に `spotlight_encodings` で払い出すことで個別にスポットライトのエンコーディングパラメーターが指定できます ### sora.conf でファイル指定 `sora.conf` にて スポットライトの場合は [spotlight_encodings_file](SORA_CONF.html#6115fb) で JSON ファイルを指定してください。 ```ini spotlight_encodings_file = etc/spotlight_encodings.json ``` ### sora.conf で指定する JSON ファイルの記述方法 ```javascript [ {"rid": "r0", "active": true, "scaleResolutionDownBy": 4.0, "maxFramerate": 5.0}, {"rid": "r1", "active": true, "scaleResolutionDownBy": 1.0, "maxFramerate": 10.0}, {"rid": "r2", "active": true, "scaleResolutionDownBy": 1.0, "maxFramerate": 30.0} ] ``` ### 認証成功時に spotlight_encodings で払い出す記述方法 ```javascript { "allowed": true, "spotlight_encodings": [ {"rid": "r0", "active": true, "scaleResolutionDownBy": 2.0, "maxFramerate": 5.0}, {"rid": "r1", "active": true, "scaleResolutionDownBy": 2.0, "maxFramerate": 20.0}, {"rid": "r2", "active": true, "scaleResolutionDownBy": 1.0, "maxFramerate": 30.0} ] } ``` ### カスタマイズの設定 スポットライトでの映像のエンコーディングパラメーターのカスタマイズの設定方法はサイマルキャスト機能と同様です。 サイマルキャスト機能の [カスタマイズの設定](SIMULCAST.html#439977) をご確認ください。 ## フォーカスする配信数 フォーカスする配信数はチャネル ID ごとに 1 から 8 までのいずれかを選択できます。 同一チャネル ID へ接続しているクライアント全てが同じ値を指定する必要があります。 デフォルトのフォーカス数は 1 です。 `sora.conf` の [default_spotlight_number](SORA_CONF.html#41c42b) でデフォルトの値を変更することができます。 > **注釈** > > 遅延フォーカスやフォーカスなしでの音声配信を有効にしていればフォーカス数は 1 で十分です。 フォーカスする配信数を途中で変更するには [ChangeSpotlightNumber](API_SPOTLIGHT.html#17e930) API を利用してください。 ### シグナリング接続時の指定 > **警告** > > この機能は非推奨です。 > セッションウェブフック [session.created](SESSION_WEBHOOK.html#1d1984) の払い出しを利用してください。 シグナリング接続時に `spotlight_number` を指定することで、フォーカスする配信数を指定することができます。 そのチャネルのセッションが存在しない状態で、一番最初に接続したクライアントの `spotlight_number` が適用されます。 未指定であれば `sora.conf` の [default_spotlight_number](SORA_CONF.html#41c42b) の値が適用されます。 この値は [default_spotlight_number](SORA_CONF.html#41c42b) の値を上書きします。 ### 認証成功時の払い出しの指定 > **警告** > > この機能は非推奨です。 > セッションウェブフック [session.created](SESSION_WEBHOOK.html#1d1984) の払い出しを利用してください。 認証ウェブフック成功時の払い出しに `spotlight_number` を指定することで、フォーカスする配信数を指定することができます。 この値は [default_spotlight_number](SORA_CONF.html#41c42b) やシグナリング接続時の値を上書きします。 ### セッション生成時の払い出し指定 セッションウェブフック [session.created](SESSION_WEBHOOK.html#1d1984) の払い出しに `spotlight_number` を指定することで、 フォーカスする配信数を指定することができます。 この値は [default_spotlight_number](SORA_CONF.html#41c42b) やシグナリング接続時、認証成功時の払い出しの値を上書きします。 ## 遅延フォーカス ちょっとした物音でフォーカスをしないようにするため、フォーカスを遅延させる機能です。 この機能を有効にした場合、フォーカスされる場合に一定時間以上、音が出続けている必要があります。 ### [sora_conf-default_spotlight_delayed_focus](SPOTLIGHT.html#da30b6) `sora.conf` で遅延フォーカスを有効にするかどうかを指定してください。デフォルトで `true` です。 ### [sora_conf-default_spotlight_delayed_focus_interval](SPOTLIGHT.html#a5df3b) `sora.conf` でフォーカスを遅延させる時間を指定してください。デフォルトは `2000 ms` です。 ## 遅延アンフォーカス スポットライトの数が少ないときに、フォーカスの奪い合いが発生しないように、フォーカスが発生してからアンフォーカスするまで遅延させる機能です。 ### [sora_conf-default_spotlight_focus_min_interval](SPOTLIGHT.html#9ba866) `sora.conf` でフォーカスしてからアンフォーカスされるまでの最低時間間隔を指定します。デフォルトは `2000 ms` です。 ## フォーカスなし音声配信 フォーカスがない状態でも音声を配信するかを指定する機能です。 この機能を有効にすると、フォーカスが他の配信者にとられても音声を配信し続けます。 配信するレートの上限も指定できます。 ### [sora_conf-default_spotlight_unfocus_audio](SPOTLIGHT.html#3bd7f7) `sora.conf` でフォーカスなし音声を有効にするかどうかを指定してください。デフォルトで `true` です。 ### [sora_conf-default_spotlight_unfocus_audio_rate_limit](SPOTLIGHT.html#27c5ad) `sora.conf` でフォーカスなし音声を配信する上限レートを指定してください。デフォルトは `2` です。 レートの単位は `1 音声ストリーム = 50 packets / s` です。 ## 自動アンフォーカス 無音状態が一定時間続くとフォーカスを自動で外す機能です。この機能を利用するとフォーカス数が 0 になることもあります。 クライアントが受信するパケット、Sora が配信するパケットを減らすことができます。 ### [sora_conf-default_spotlight_auto_unfocus](SPOTLIGHT.html#d57acb) `sora.conf` で音がない場合に自動でアンフォーカスするかどうかを指定してください。デフォルトは `true` です。 ### [sora_conf-default_spotlight_auto_unfocus_interval](SPOTLIGHT.html#fcf07a) `sora.conf` で自動でアンフォーカスする無音時間を指定してください。デフォルトは `10 s` です。 ## サイマルキャスト機能を無効にして接続する > **注釈** > > サイマルキャストを無効にして接続すると常にフォーカスされ続けます。 スポットライト機能でサイマルキャスト機能を無効にして利用できます。 無効にする場合はシグナリング接続時または認証成功時に `"simulcast": "false"` を指定する必要があります。 サイマルキャスト機能を無効にしてスポットライトを利用した場合、 そのクライアントは常にフォーカスされている状態となります。 そのため `spotlight_focus_rid` や `spotlight_unfocus_rid` の影響も受けません。 サイマルキャスト機能を無効にした利用は、 画面共有やサイマルキャストが利用できないクライアントでの利用を想定しています。 ## シグナリング - シグナリングの `"type": "connect"` で `spotlight` を `true` に設定してください- これは必須です - シグナリングの `"type": "connect"` で `simulcast` を設定してください- これはオプションです - サイマルキャストを無効にする場合は [サイマルキャスト機能を無効にして接続する](SPOTLIGHT.html#ae2845) をご確認ください - シグナリングの `"type": "connect"` で `spotlight_number` で 1..8 の値を指定してください- 1 から 3 の間がお勧めです - これはオプションです その他の項目は [シグナリング](SIGNALING.html) を参照ください。以下に シグナリング `"type": "connect"` の例を示します。 ### "type": "connect" #### simulcast: false サイマルキャスト無効。 ```javascript { "type": "connect", "channel_id": "sora", "role": "sendrecv", "spotlight": true, "simulcast": false, "video": { "codec_type": "VP8", "bit_rate": 800 } } ``` #### spotlight_number > **重要** > > `spotlight_number` は同一セッションで同じ値を指定する必要があります。 `spotlight_number` はセッションウェブフック [session.created](SESSION_WEBHOOK.html#1d1984) の戻り値で指定することをお勧めします。 フォーカス数はデフォルトの 1 ```javascript { "type": "connect", "channel_id": "sora", "role": "sendrecv", "spotlight": true, "simulcast": true, "video": { "codec_type": "VP8", "bit_rate": 800 } } ``` フォーカス数は指定した値の 5 ```javascript { "type": "connect", "channel_id": "sora", "role": "sendrecv", "spotlight": true, "spotlight_number": 5, "simulcast": true, "video": { "codec_type": "VP8", "bit_rate": 800 } } ``` #### spotlight_focus_rid / spotlight_unfocus_rid シグナリング接続時、認証成功時にフォーカスした場合とフォーカスしていない場合に受信する映像の rid を接続ごとに指定できます。 例えば、映像は特に受け取らなくていい場合は、両方の設定で none を指定することで参加者全員の映像を受信しなくなります。 また、話している人は rid は r1 で受信し、それ以外は受信しない (rid に none を指定) といった設定もできます。 ```javascript { "type": "connect", "channel_id": "sora", "role": "sendrecv", "spotlight": true, "spotlight_focus_rid": "r0", "spotlight_unfocus_rid": "none", "simulcast": true, "video": { "codec_type": "VP8", "bit_rate": 800 } } ``` `sora.conf` で [default_spotlight_focus_rid](SORA_CONF.html#c71c97) と [default_spotlight_unfocus_rid](SORA_CONF.html#a7cd9b) を指定することで、個別ではなくサーバー全体の設定もできます。 ## シグナリング通知 シグナリング通知の詳細は [スポットライト機能のシグナリング通知](SIGNALING_NOTIFY.html#dcfbb9) をご確認ください。 フォーカスされたタイミングとフォーカスが外れたタイミングでシグナリング通知をクライアントに送ります。 クライアントはこの通知を利用することで、配信が切り替わったことを知ることができるようになります。 ## セッションウェブフック セッションウェブフック [session.created](SESSION_WEBHOOK.html#1d1984) の払い出しで `spotlight_number` を指定することができます。 この値はセッション単位で適用され、シグナリング接続時や認証成功時の払い出しの値を上書きします。 この `spotlight_number` の値を変更するには [ChangeSpotlightNumber](API_SPOTLIGHT.html#17e930) API を利用してください。 ## イベントウェブフック フォーカスされたタイミングとフォーカスが外れたタイミングでウェブフックリクエストが送信されます。 `sora.conf` の [ignore_spotlight_changed_webhook](SORA_CONF.html#7f5ed5) で指定できます。 デフォルトではイベントウェブフックのリクエスト送信は無効になっています。 - [spotlight.focused](EVENT_WEBHOOK.html#d79712) イベントウェブフック - [spotlight.unfocused](EVENT_WEBHOOK.html#41715c) イベントウェブフック ## API API の詳細は [スポットライト API](API_SPOTLIGHT.html) をご確認ください。 - [FocusSpotlightFixed](API_SPOTLIGHT.html#beaf88) API- 特定のクライアントにフォーカスし続ける API - [FocusSpotlight](API_SPOTLIGHT.html#90a256) API- 特定のクライアントにフォーカスする API - [UnfocusSpotlight](API_SPOTLIGHT.html#1390bc) API- 特定のクライアントからアンフォーカスする API - [ChangeSpotlightNumber](API_SPOTLIGHT.html#17e930) API- フォーカスする数を変更する API - [RequestSpotlightRid](API_SPOTLIGHT.html#5c2650) API- 特定のクライアントのフォーカス/アンフォーカス時の rid を変更する API - [ResetSpotlightRid](API_SPOTLIGHT.html#680344) API- 特定のクライアントのフォーカス/アンフォーカス時の rid をリセットする API - [BatchRequestSpotlightRid](API_SPOTLIGHT.html#a2e06c) API- フォーカス/アンフォーカス時の rid を一括で変更する API ## シーケンス図 ```mermaid sequenceDiagram participant C1 as クライアント1 participant S as WebRTC SFU Sora participant C2 as クライアント2 C1->>S: "type": "connect",
"role": "sendrecv"
"spotlight": true,
"simulcast": true note over C1,S: クライアント1 WebRTC 確立 par C1-)S: 映像
rid: r0 and C1-)S: 映像
rid: r1 end C2->>S: "type": "connect",
"role": "sendrecv"
"spotlight": true,
"simulcast": true note over C2,S: クライアント2 WebRTC 確立 par C2-)S: 映像
rid: r0 and C2-)S: 映像
rid: r1 end par S-)C2: クライアント1映像
rid: r0 and S-)C1: クライアント2映像
rid: r0 end note over C1: クライアント1が話し始める S-)C2: クライアント1音声 note over C1: しゃべり初めて 2 秒経過 note right of S: r0 の代わりに r1 映像を配信 S-)C2: クライアント1映像
rid: r1 ``` # WHIP 機能 ## 概要 Sora は [RFC 9725](https://datatracker.ietf.org/doc/html/rfc9725) で定義されている WHIP (WebRTC-HTTP Ingestion Protocol) の仕様に準拠した WHIP 機能を提供しています。 ただし、 [OBS Studio](https://obsproject.com/) での WHIP での動作を優先しています。そのため、 [RFC 9725](https://datatracker.ietf.org/doc/html/rfc9725) で定義されている WHIP の仕様とは異なる場合があります。 ## 注意 - Sora SDK は WHIP へ対応していません - 現時点では WHIP を利用した接続の統計ウェブフックの送信には対応していません ### WHIP クライアントのお問い合わせについて WHIP クライアントに関する質問などの報告は Discord の利用をお願いします。 **URL**: Sora の WHIP クライアントについての質問やバグ報告は Discord の `#sora-sdk-faq` チャンネルにお願いします。 ### 映像コーデックパラメータについて WHIP では映像コーデックのパラメーターを認証払い出し時に指定しても有効になりません。 ## WHIP とは何か > **参考** > > [WebRTC-HTTP ingestion protocol (WHIP)](https://datatracker.ietf.org/doc/html/draft-ietf-wish-whip) WHIP は WebRTC-HTTP ingestion protocol の略で、 WebRTC では標準化されていないシグナリングをブロードキャスト/ストリーミング系の配信ツール向けに規定した規格です。 WHIP は仕様を小さくして、実装を簡単にすることで配信ツールが取り込みやすくしています。 クライアントが HTTP POST で Offer SDP を送信して、Answer SDP を受け取るというシンプルなシグナリング規格です。 ### WHIP のシーケンス図 ```mermaid sequenceDiagram participant OBS as "OBS Studio" participant WE as WHIP Endpoint participant MS as Media Server participant WS as WHIP Session OBS->>+WE: HTTP POST (SDP Offer) WE-->>-OBS: HTTP 201 Created (SDP Answer) note over OBS,MS: WebRTC Connection OBS->>+WS: HTTP DELETE WS->>-OBS: HTTP 200 OK ``` ### Sora の WHIP のシーケンス図 Sora では WHIP エンドポイント、WHIP セッション、メディアサーバーすべてを Sora が担当します。 ```mermaid sequenceDiagram participant OBS as "OBS Studio" participant S as Sora participant A as App OBS->>+S: HTTP POST (SDP Offer) S->>+A: 認証ウェブフック A-->>-S: 200 OK
allowed : true S-->>-OBS: HTTP 201 Created (SDP Answer) note over OBS,S: WebRTC Connection S->>+A: イベントウェブフック
connection.created A-->>-S: 200 OK OBS->>+S: HTTP DELETE S->>+A: イベントウェブフック
connection.destroyed A-->>-S: 200 OK S->>-OBS: HTTP 200 OK ``` ## OBS Studio の WHIP 対応について > **警告** > > OBS Studio の WHIP 対応については Discord の #sora-sdk-faq にてご相談ください。 2023 年 12 月リリースの [OBS Studio 30.0](https://github.com/obsproject/obs-studio/releases/tag/30.0.0) にて WebRTC/WHIP が正式にサポートされました。 最新版は以下からダウンロードができます。 2026 年 6 月 時点での OBS Studio の WHIP 対応では輻輳制御が実装されていません。 これは OBS Studio が WHIP 対応のために利用している [libdatachannel](https://libdatachannel.org/) が輻輳制御に対応していないためです。 そのため、回線が不安定になったとしても、ビットレートを下げたりするといったことは行いません。 ## OBS Studio の WHIP サイマルキャスト対応について *バージョン 2026.1.0 で追加。* > **警告** > > Sora の WHIP サイマルキャストは OBS Studio の WHIP サイマルキャストにのみ対応しています。 Sora は、2026 年 3 月リリースの [OBS Studio 32.1](https://github.com/obsproject/obs-studio/releases/tag/32.1.0) 以降で利用できる OBS Studio の WHIP サイマルキャスト機能に対応しています。 Sora の OBS Studio 向けの WHIP サイマルキャスト機能はデフォルトで有効です。無効にしたい場合は [whip_simulcast](SORA_CONF.html#5a85ec) を `false` に設定してください。 OBS Studio で WHIP サイマルキャストを利用する場合は合計レイヤー数を 2 または 3 に指定してください。 合計レイヤー数に 1 を指定した場合は、WHIP サイマルキャストではなく通常の WHIP として扱われます。 OBS Studio の WHIP サイマルキャストは合計レイヤー数を 4 まで指定できますが、 Sora では合計レイヤー数 4 には対応していません。 - サイマルキャストのエンコーディングに [simulcast_encodings_file](SORA_CONF.html#dead73) を設定しても、 OBS Studio 側の設定が採用されるため適用されません - 認証成功時に [simulcast_encodings の払い出し](AUTH_WEBHOOK_RETURN.html#eebbba) を指定しても、 OBS Studio 側の設定が採用されるため適用されません - OBS Studio の WHIP サイマルキャスト利用時には、認証ウェブフックで `whip` と `simulcast` が `true` で送られてきます - OBS Studio の WHIP サイマルキャスト利用時に認証成功時の払い出しで `simulcast` に `false` を指定すると、 Sora の接続に失敗します - OBS Studio の WHIP サイマルキャスト利用時に合計レイヤー数に 4 を指定すると、 Sora の接続に失敗します - [whip_simulcast](SORA_CONF.html#5a85ec) が `false` の場合、 OBS Studio の WHIP サイマルキャストを利用すると、 Sora の接続に失敗します ## OBS Studio 以外の WHIP クライアントへの対応について > **重要** > > Sora の WHIP 実装は OBS Studio の WHIP 対応を優先しています。 新しい WHIP クライアントへの対応は有償での優先実装として対応を検討できますので、 対応希望の WHIP クライアントと優先実装については、サポートまでメールにてご連絡ください。 ### ブラウザでの WHIP 対応 ブラウザからの WHIP 接続は条件付きでサポートしています。 - 音声は `Opus` のみ - 映像は `AV1` / `H.264` / `H.265` のみ - コーデックは音声、映像ともに 1 つのみ- `setCodecPreferences` を利用して 1 つのみを指定してください - `mode` は `sendonly` のみ- `offer` は `a=sendonly` のみ - `Link` ヘッダーを利用した TURN 接続のみ ### FFmpeg での WHIP 対応 > **重要** > > 現時点で Sora は FFmpeg での WHIP には対応していません。 FFmpeg の WHIP 対応は仕様がとても古く RFC 9725 に準拠していないため、2026 年 6 月 時点での実装では対応は難しいと考えています。 ## Sora での利用方法 `sora.conf` にて [whip](SORA_CONF.html#615414) を `true` に指定してください。 ```ini whip = true ``` ### Bearer トークンを利用した認証機能を利用する場合 `sora.conf` にて [whip_bearer_token_metadata_key](SORA_CONF.html#699f57) を指定してください。 ```ini whip_bearer_token_metadata_key = whip_access_token ``` 例えば、 `access_token` という文字列を指定した場合、 WHIP 接続時、認証ウェブフックに `"metadata": {"access_token": ""}` が入ってきます。 `whip_token` を指定した場合は `"metadata": {"whip_token": ""}` が入ってきます。 `whip_bearer_token_metadata_key` が未指定の場合は、 Bearer トークンが WHIP 接続時に送られてきたとしても Sora は無視して、 `metadata` も生成しません。 ## OBS Studio での WHIP 利用方法 OBS Studio での利用方法は以下の通りです。 ![image](https://i.gyazo.com/f68934ea04634b0b845f3ae0d17ca4b3.jpg) 1. サービスに WHIP を選ぶ 2. サーバーに Sora が提供する WHIP エンドポイント URL を指定する- デフォルトでは `http://127.0.0.1:5000/whip/` 3. Bearer トークンには好きな文字列を指定する- Sora の認証ウェブフックの項目 `whip_bearer_token_metadata_key` で指定した値をキーとして、`"metadata": {"": ""}` が認証サーバーに送信されます ### 切断方法 `Location` ヘッダーに入ってくるセッション URL に DELETE リクエストを送ることで切断できます。 OBS Studio は配信終了することで切断リクエストを送りますので、意識する必要はありません。 ## Sora の OBS Studio (WHIP) の挙動 - Sora は WHIP エンドポイント URL を提供します- デフォルトでは `http://127.0.0.1:5000/whip/` です - Sora の WHIP エンドポイントからの配信は、マルチストリームかつ配信のみ(sendonly)として扱われます - Sora の WHIP エンドポイントを利用した配信では、シグナリング通知は現時点では利用できません - Sora の WHIP セッション URL は WHIP エンドポイントのレスポンスに含まれる Location ヘッダーにて払い出されます ## WHIP エンドポイント URL Sora の OBS Studio (WHIP) 対応は `"role": "sendonly"` として機能します。 ### チャネル ID の指定 OBS Studio ではリクエスト時に JSON でチャネル ID を指定することができません。そのため WHIP エンドポイント URL に `channel_id` を含めて指定します。 channel_id に URL に利用できない文字が含まれている場合は URL エンコードしてください。 `HTTP POST https://sora.example.com/whip/` `channel_id` が sora の WHIP エンドポイント URL 例: ``` https://sora.example.com/whip/sora ``` WHIP エンドポイントへの HTTP リクエストに対するレスポンスコードは 201 Created です。 ## WHIP セッション URL Sora では WHIP セッション URL は WHIP エンドポイントのレスポンスに含まれる Location ヘッダーにて払い出されます。 以下は切断する例です。 `HTTP DELETE https://sora.example.com/whip-session//` 以下は Trickle ICE を利用する例です。 `HTTP PATCH https://sora.example.com/whip-session//` `` は 32 バイトのランダムな値を base32 でエンコードした文字列です。 WHIP セッション URL 例: ``` https://sora.example.com/whip-session/sora/QBF6AFDWZGWM97BNS5YCBSXM54M01D0TFQ48MC9Z3ZJG8YPRQ1Z0 ``` > **注釈** > > OBS Studio に Bearer トークンを指定した場合は、WHIP セッション URL にも Bearer トークンは送られます ## 認証仕様 WHIP では認証に Bearer トークンを指定することができます。 OBS Studio でも認証情報に Bearer トークンを指定できます。 Sora は `sora.conf` で `whip_bearer_token_metadata_key` に文字列を指定していた場合、 OBS Studio の HTTP POST 時に Authentication ヘッダーで送られてきた Bearer トークンを、 認証ウェブフックの `metadata` に `{"": ""}` を設定して認証サーバーに送信します。 Sora 自体は Bearer トークンのチェックやデコードなどは行いません。これらは認証ウェブフックのリクエストを受信した認証サーバーが行う必要があります。 ## ウェブフック仕様 ### whip `true` が入ってきます。 ### ignore_disconnect_websocket `false` が入ってきます。 ### metadata `sora.conf` にて `whip_bearer_token_metadata_key` に指定した文字列をキーとして `metadata` に入ってきます。 ```ini whip_bearer_token_metadata_key = whip_bearer_token ``` もし文字列を `whip_bearer_token` にしていた場合は、 `"metadata": {"whip_bearer_token": ""}` が送られてきます。 OBS Studio 側に設定した Bearer Token の値がそのまま入ってきます。 ### role `sendonly` が入ってきます。 ### channel_id WHIP エンドポイント URL に渡した値が利用されます。 > **注釈** > > URL デコード済みの値が入ります ### client_id WHIP エンドポイント URL にクエリ文字列として `client_id=` を指定した場合、その値が利用されます。 > **注釈** > > URL デコード済みの値が入ります ### bundle_id WHIP エンドポイント URL にクエリ文字列として `bundle_id=` を指定した場合、その値が利用されます。 > **注釈** > > URL デコード済みの値が入ります ### simulcast 通常の WHIP 利用時には `false` が含まれます。 OBS Studio の WHIP サイマルキャスト利用時に、合計レイヤー数に 2 または 3 を指定し、 [whip_simulcast](SORA_CONF.html#5a85ec) が `false` に指定されていない場合には `true` が含まれます。 ### spotlight WHIP エンドポイント URL にクエリ文字列として `spotlight=` を指定した場合、その値が利用されます。 既知の問題として `spotlight = true` を指定して接続した場合、音声がそのままでは配信されません。 [FocusSpotlightFixed](API_SPOTLIGHT.html#beaf88) API を利用して OBS Studio の接続にフォーカスを当てる必要があります。 詳細は [既知の問題 - OBS Studio 対応機能](KNOWN_ISSUES.html#275fa8) をご確認ください。 > **注釈** > > URL デコード済みの値が入ります ### audio / video OBS Studio 側で指定した値を利用します。 OBS Studio では音声は Opus のみ、映像は AV1 と H.264 と H.265 が利用できます。 - `audio: true` - `audio_codec_type: "OPUS"` - `video: true` - `video_codec_type: "AV1" | "H264" | "H265"` OBS Studio 利用時にはビットレートの指定できないため、 Sora のデフォルトの値が入ってきますが、 OBS Studio の WHIP 実装では SDP での最大ビットレートを無視します。 そのため OBS Studio 側で設定したビットレートで配信が行われます。 > **注釈** > > H.265 は [OBS Studio 30.2](https://github.com/obsproject/obs-studio/releases/tag/30.2.0) から利用できます ### simulcast OBS Studio 32.1.0 以降からの WHIP サイマルキャストに対応しています。 WHIP 利用時に 2 以上のレイヤーを利用した場合で、 [whip_simulcast](SORA_CONF.html#5a85ec) が有効な場合は `simulcast` が `true` で入ってきます。 それ以外の場合は `false` が入ってきます。 ### sora_client OBS Studio WHIP で User-Agent として送られてくる情報を `sora_client` に含めています。 ```javascript "sora_client": { "raw": "Mozilla/5.0 (OBS-Studio/30.1.0; Mac OS X; ja-JP)", "type": "OBS-Studio-WHIP", "version": "30.1.0", "environment": "Mozilla/5.0 (OBS-Studio/30.1.0; Mac OS X; ja-JP)" }, ``` ### その他 - `e2ee: false` - `spotlight: false` - `data_channel_signaling: false` - `ignore_disconnect_webhook: false` - `turn_transport_type: udp`- [OBS Studio 30.2](https://github.com/obsproject/obs-studio/releases/tag/30.2.0) での TURN 対応は TURN-UDP のみのため `tcp` になることはありません ## 認証ウェブフック成功時の払い出し 基本的には OBS Studio で指定した値がそのまま利用されますので、 以下の値以外は指定しないでください。 - client_id - bundle_id - event_metadata - recording_block - signaling_notify_metadata - connection_lifetime - cluster_affinity - playout_delay_min_delay - playout_delay_max_delay - rtp_packet_loss_simulator_incoming - turn_tcp_only- ただし 2026 年 6 月 現在では OBS Studio WHIP は TURN-TCP には対応していません - turn_tls_only- ただし 2026 年 6 月 現在では OBS Studio WHIP は TURN-TLS には対応していません ## クラスター利用時の認証ウェブフックの挙動 クラスター利用時に、 WHIP で接続したノードではないノードに接続を振り分ける場合、 Sora は認証情報を担当ノードに Proxy を行います。 接続は接続したノードで行われますが、認証ウェブフックは担当ノードから送信されます。 その後 WebRTC 接続確立は担当ノードと行います。 ### シーケンス図 ```mermaid sequenceDiagram participant O as "OBS Studio (WHIP)" participant S1 as Sora 1 participant S2 as Sora 2 participant A as App O->>+S1: HTTP POST
https://sora-02.example.com/whip/sora
Offer SDP Note over S1: 担当ノードは Sora 2 S1->>+S2: ノード間通信で認証処理を Proxy S2->>+A: 認証ウェブフック
"channel_id": "sora"
"role": "sendonly" A-->>-S2: "allowed": true S2-->>-S1: Sora 2 の IP アドレス S1-->>-O: HTTP 201 Created
Answer SDP
Candidate: Sora 2 IP アドレス note over O,S2: WebRTC 確立 S1->>+A: イベントウェブフック
"connection.created" A-->>-S2: HTTP 200 OK O-)S2: SRTP O-)S2: SRTP O->>+S2: HTTP DELETE
https://sora-02.example.com/whip/sora/ S2-->>-O: HTTP 200 OK note over O,S2: WebRTC 終了 ``` ## TURN の利用 Sora はデフォルトで WHIP 利用時に `Link` ヘッダーに TURN URLs を払い出し、 **TURN のみの通信** を行います。 TURN の利用を無効にすることはできません。 > **注釈** > > 今後 TURN の仕組みを実装していないクライアント向けにシグナリングの query-string に `turn=false` を追加することで、TURN を無効にすることができるようにすることを検討しています。 ### OBS Studio の TURN 機能 OBS Studio は 2024 年 7 月にリリースされた [OBS Studio 30.2](https://github.com/obsproject/obs-studio/releases/tag/30.2.0) で TURN に対応しており、Sora の WHIP は TURN を前提としているため、これより古い OBS Studio は利用できません。 > **警告** > > OBS Studio で WebRTC を実現している libdatachannel が利用している ICE ライブラリの [libjuice](https://github.com/paullouisageneau/libjuice) は、TURN-UDP のみに対応しています。そのため TURN-TCP や TURN-TLS には対応していません。 ## 録画利用時の注意 - OBS Studio WHIP で H.264 を利用し、 Sora で録画を行う場合、エンコーダーには x264 以外を利用することを推奨します。x264 を利用すると、録画時に期待どおりに処理できない場合があります。 ## クラスター利用時の挙動 クラスター利用時に、接続したノードが指定した `channel_id` の担当ノードではない場合、 担当ノードの TURN URLs を Link ヘッダーにて払い出します。 ## シーケンス図 ### 単独 ```mermaid sequenceDiagram participant O as "OBS Studio" participant S as Sora participant A as App O->>+S: HTTP POST https://sora.example.com/whip/
Offer SDP S->>+A: 認証ウェブフック

"channel_id": """role": "sendonly" A-->>-S: "allowed": true S-->>-O: HTTP 201 Created
Answer SDP Note left of S: このタイミングで Link ヘッダーで、
TURN URLs を払い出す note over O,S: ICE 確立 note over O,S: DTLS 確立 note over O,S: WebRTC 確立 S->>+A: イベントウェブフック
"connection.created" A-->>-S: HTTP 200 OK O-)S: SRTP O-)S: SRTP O->>+S: HTTP DELETE https://sora.example.com/whip// S-->>-O: HTTP 200 OK note over O,S: WebRTC 終了 ``` ### クラスターかつロードバランサー クラスターを利用する場合、OBS Studio に設定する WHIP エンドポイントはロードバランサーが提供するエンドポイントをお勧めしています。 このシーケンス図では Sora が 2 ノードになっていますが、最低 3 ノード必要です。 ```mermaid sequenceDiagram participant O as "OBS Studio (WHIP)" participant B as ブラウザ participant LB as LB participant S1 as Sora 1 participant S2 as Sora 2 participant A as App B->>LB: WSS
https://sora.example.com/signaling
LB->>S1: WSS
https://node1.sora.example.com/signaling
note over B,S1: WebSocket 確立 B->>+S1: WSS "type": "connect" S1->>+A: 認証ウェブフック
"channel_id": "sora"
"role": "recvonly" A-->>-S1: "allowed": true S1-)-B: "type": "offer" B-)S1: "type": "answer" note over B,S2: WebRTC 確立 O->>+LB: HTTP POST
https://sora.example.com/whip/sora
Offer SDP LB->>+S2: HTTP POST
https://node2.sora.example.com/whip/sora
Offer SDP S2-->>-LB: HTTP 307 Temporary Redirect
location: https://node1.sora.example.com/whip/sora LB-->>-O: HTTP 307 Temporary Redirect
location: https://node1.sora.example.com/whip/sora O->>+LB: HTTP POST
https://node1.sora.example.com/whip/sora
Offer SDP LB->>+S1: HTTP POST
https://node1.sora.example.com/whip/sora
Offer SDP S1->>+A: 認証ウェブフック
"channel_id": "sora"
"role": "sendonly" A-->>-S1: "allowed": true S1-->>-LB: HTTP 201 Created
Answer SDP LB-->>-O: HTTP 201 Created
Answer SDP %% Note left of S2: このタイミングで Link ヘッダーで、
TURN URLs を払い出す note over O,S2: WebRTC 確立 S1->>+A: イベントウェブフック
"connection.created" A-->>-S1: HTTP 200 OK O-)S1: SRTP S1-)B: SRTP O-)S1: SRTP S1-)B: SRTP O->>+S1: HTTP DELETE
https://node2.sora.example.com/whip-resource/sora/ S1-->>-O: HTTP 200 OK note over O,S2: WebRTC 終了 ``` # WHEP 機能 > **注意** > > この機能を利用する場合は事前にサポートまでご連絡ください > **警告** > > この機能は [実験的機能](EXPERIMENTAL.html) のため、正式版では仕様が変更される可能性があります ## 概要 Sora は [WHEP](https://datatracker.ietf.org/doc/html/draft-ietf-wish-whep) で定義されている WHEP (WebRTC-HTTP Egress Protocol) の仕様に準拠した WHEP 機能を提供しています。 ただし、 [OBS Studio](https://obsproject.com/) での WHEP での動作を優先しています。そのため、 [WHEP](https://datatracker.ietf.org/doc/html/draft-ietf-wish-whep) で定義されている WHEP の仕様とは異なる場合があります。 ## 注意 - OBS Studio の WHEP での動作を優先しており RFC ドラフトの WHEP 仕様とは異なる可能性があります - Sora SDK は WHEP へ対応していません - OBS Studio の WHEP 実装では Opus と **H.264** の組み合わせでのみ利用できます - 現時点では WHEP を利用した接続の統計ウェブフックの送信には対応していません - Sora の WHEP 対応は `406 Not Acceptable` を利用したサーバーからのカウンター Offer には現時点では対応していません ### WHEP クライアントのお問い合わせについて WHEP クライアントに関する質問などの報告は Discord の利用をお願いします。 **URL**: Sora の WHEP クライアントについての質問やバグ報告は Discord の `#sora-sdk-faq` チャンネルにお願いします。 ## WHEP とは何か > **参考** > > [WebRTC-HTTP Egress Protocol (WHEP)](https://datatracker.ietf.org/doc/html/draft-ietf-wish-whep) WHEP は WebRTC-HTTP Egress Protocol の略で、 WebRTC では標準化されていないシグナリングをブロードキャスト/ストリーミング系のツール向けに規定した規格です。 WHEP は仕様を小さくして、実装を簡単にすることで配信ツールが取り込みやすくしています。 クライアントが HTTP POST で Offer SDP を送信して、Answer SDP を受け取るというシンプルなシグナリング規格です。 将来的に OBS Studio で WebRTC/WHEP がサポートされる予定です。 ### WHEP のシーケンス図 ```mermaid sequenceDiagram participant OBS as "OBS Studio" participant WE as WHEP Endpoint participant MS as Media Server participant WS as WHEP Session OBS->>+WE: HTTP POST (SDP Offer) WE-->>-OBS: HTTP 201 Created (SDP Answer) note over OBS,MS: WebRTC Connection OBS->>+WS: HTTP DELETE WS->>-OBS: HTTP 200 OK ``` ### Sora の WHEP のシーケンス図 Sora では WHEP エンドポイント、WHEP セッション、メディアサーバーすべてを Sora が担当します。 ```mermaid sequenceDiagram participant OBS as "OBS Studio" participant S as Sora participant A as App OBS->>+S: HTTP POST (SDP Offer) S->>+A: 認証ウェブフック A-->>-S: 200 OK
allowed : true S-->>-OBS: HTTP 201 Created (SDP Answer) note over OBS,S: WebRTC Connection S->>+A: イベントウェブフック
connection.created A-->>-S: 200 OK OBS->>+S: HTTP DELETE S->>+A: イベントウェブフック
connection.destroyed A-->>-S: 200 OK S->>-OBS: HTTP 200 OK ``` ## OBS Studio の WHEP 対応について > **警告** > > OBS Studio の WHEP 対応については Discord の #sora-sdk-faq にてご相談ください。 2026 年 6 月 時点での最新版である [OBS Studio 32.1](https://github.com/obsproject/obs-studio/releases/tag/32.1.0) では WHEP に対応していません。 以下の Pull-Request がマージされ、正式リリースされることで WHEP に対応予定です。 WHEP は `WHEP ソース` として利用できるようになります。 ![image](https://i.gyazo.com/d201cb2c8eea99d29a02e6f6a57f9180.jpg) ## OBS Studio 以外の WHEP クライアントへの対応について > **重要** > > Sora の WHEP 実装は OBS Studio の WHEP 対応を優先しています。 新しい WHEP クライアントへの対応は有償での優先実装として対応を検討できますので、 対応希望の WHEP クライアントと優先実装については、サポートまでメールにてご連絡ください。 ## Sora での利用方法 ### WHEP `sora.conf` にて [whep](SORA_CONF.html#5a91bb) を `true` に指定してください。 ```ini whep = true ``` ### Bearer トークンを利用した認証機能を利用する場合 `sora.conf` にて [whep_bearer_token_metadata_key](SORA_CONF.html#f857c6) を指定してください。 ```ini whep_bearer_token_metadata_key = whep_access_token ``` 例えば、 `access_token` という文字列を指定した場合、 WHEP 接続時、認証ウェブフックに `"metadata": {"access_token": ""}` が入ってきます。 `whep_token` を指定した場合は `"metadata": {"whep_token": ""}` が入ってきます。 `whep_bearer_token_metadata_key` が未指定の場合は、 Bearer トークンが WHIP/WHEP 接続時に送られてきたとしても Sora は無視して、 `metadata` も生成しません。 ## OBS Studio での WHEP 利用方法 OBS Studio での利用方法は以下の通りです。 1. シーンのソースに WHEP ソースを追加する 2. WHEP ソースに Sora が提供する WHEP エンドポイント URL を指定する- デフォルトでは `http://127.0.0.1:5000/whep/` です 3. Bearer トークンには好きな文字列を指定する- Sora の認証ウェブフックの項目 `whep_bearer_token_metadata_key` で指定した値をキーとして、`"metadata": {"": ""}` が認証サーバーに送信されます ### 切断方法 `Location` ヘッダーに入ってくるセッション URL に DELETE リクエストを送ることで切断できます。 OBS Studio は配信終了することで切断リクエストを送りますので、意識する必要はありません。 ## Sora の OBS Studio (WHEP) の挙動 - Sora は WHEP エンドポイント URL を提供します- デフォルトでは `http://127.0.0.1:5000/whep/` です - Sora の WHEP エンドポイントからの配信は、マルチストリームかつ視聴のみ(recvonly)として扱われます - Sora の WHEP エンドポイントを利用した配信では、シグナリング通知は現時点では利用できません - Sora の WHEP セッション URL は WHEP エンドポイントのレスポンスに含まれる Location ヘッダーにて払い出されます - 同一チャネルに複数の配信が存在する場合、 WHEP での接続を認証前に接続を拒否します - 同一チャネルに複数の配信が始まった場合、 WHEP での接続を切断します ## WHEP エンドポイント URL Sora の OBS Studio (WHEP) 対応は `"role": "recvonly"` として機能します。 ### チャネル ID の指定 OBS Studio ではリクエスト時に JSON でチャネル ID を指定することができません。そのため WHEP エンドポイント URL に `channel_id` を含めて指定します。 channel_id に URL に利用できない文字が含まれている場合は URL エンコードしてください。 `HTTP POST https://sora.example.com/whep/` `channel_id` が sora の WHEP エンドポイント URL 例: ``` https://sora.example.com/whep/sora ``` WHEP エンドポイントへの HTTP リクエストに対するレスポンスコードは 201 Created です。 ## WHEP セッション URL Sora では WHEP セッション URL は WHEP エンドポイントのレスポンスに含まれる Location ヘッダーにて払い出されます。 以下は切断する例です。 `HTTP DELETE https://sora.example.com/whep-session//` 以下は Trickle ICE を利用する例です。 `HTTP PATCH https://sora.example.com/whep-session//` `` は 32 バイトのランダムな値を base32 でエンコードした文字列です。 WHEP セッション URL 例: ``` https://sora.example.com/whep-session/sora/QBF6AFDWZGWM97BNS5YCBSXM54M01D0TFQ48MC9Z3ZJG8YPRQ1Z0 ``` > **注釈** > > OBS Studio に Bearer トークンを指定した場合は、WHEP セッション URL にも Bearer トークンは送られます ## 認証仕様 WHEP では認証に Bearer トークンを指定することができます。 OBS Studio でも認証情報に Bearer トークンを指定できます。 Sora は `sora.conf` で `whep_bearer_token_metadata_key` に文字列を指定していた場合、 OBS Studio の HTTP POST 時に Authentication ヘッダーで送られてきた Bearer トークンを、 認証ウェブフックの `metadata` に `{"": ""}` を設定して認証サーバーに送信します。 Sora 自体は Bearer トークンのチェックやデコードなどは行いません。これらは認証ウェブフックのリクエストを受信した認証サーバーが行う必要があります。 ## 認証成功時の払い出し 基本的には OBS Studio で指定した値がそのまま利用されますので、 以下の値以外は指定しないでください。 - client_id - bundle_id - event_metadata - connection_lifetime - playout_delay_min_delay - playout_delay_max_delay - turn_tcp_only- ただし 2026 年 6 月 現在では OBS Studio WHEP は TURN-TCP には対応していません - turn_tls_only- ただし 2026 年 6 月 現在では OBS Studio WHEP は TURN-TLS には対応していません ## ウェブフック仕様 ### whep `true` が入ってきます。 ### ignore_disconnect_websocket `false` が入ってきます。 ### metadata `sora.conf` にて `whep_bearer_token_metadata_key` に指定した文字列をキーとして `metadata` に入ってきます。 ```ini whep_bearer_token_metadata_key = whep_bearer_token ``` もし文字列を `whep_bearer_token` にしていた場合は、 `"metadata": {"whep_bearer_token": ""}` が送られてきます。 OBS Studio 側に設定した Bearer Token の値がそのまま入ってきます。 ### role `recvonly` が入ってきます。 ### channel_id WHEP エンドポイント URL に渡した値が利用されます。 > **注釈** > > URL デコード済みの値が入ります ### client_id WHEP エンドポイント URL にクエリ文字列として `client_id=` を指定した場合、その値が利用されます。 > **注釈** > > URL デコード済みの値が入ります ### bundle_id WHEP エンドポイント URL にクエリ文字列として `bundle_id=` を指定した場合、その値が利用されます。 > **注釈** > > URL デコード済みの値が入ります ### spotlight WHEP エンドポイント URL にクエリ文字列として `spotlight=` を指定した場合、その値が利用されます。 > **注釈** > > URL デコード済みの値が入ります ### audio / video OBS Studio 側で指定した値を利用します。 OBS Studio では音声は Opus のみ、映像は H.264 が利用できます。 - `audio: true` - `audio_codec_type: "OPUS"` - `video: true` - `video_codec_type: "H264"` ### simulcast `false` が入ってきます。 ### sora_client OBS Studio WHEP で User-Agent として送られてくる情報を `sora_client` に含めています。 ```javascript "sora_client": { "raw": "Mozilla/5.0 (OBS-Studio/30.1.0; Mac OS X; ja-JP)", "type": "OBS-Studio-WHEP", "version": "30.1.0", "environment": "Mozilla/5.0 (OBS-Studio/30.1.0; Mac OS X; ja-JP)" }, ``` ### その他 - `e2ee: false` - `spotlight: false` - `data_channel_signaling: false` - `ignore_disconnect_webhook: false` - `turn_transport_type: udp`- TURN が利用不可能な WHEP 実装の場合は udp が割り当てられます - TURN が利用可能な WHEP 実装の場合は udp または tcp が適切に割り当てられます ## TURN の利用 [WHIP](WHIP.html) と同様の挙動です。 [TURN の利用](WHIP.html#bc676e) をご確認ください。 ## クラスター利用時の挙動 [WHIP](WHIP.html) と同様の挙動です。 [クラスター利用時の挙動](WHIP.html#2e159a) をご確認ください。 ## シーケンス図 ### シングルノード ```mermaid sequenceDiagram participant WHIP as WHIP participant WHEP as WHEP participant S as Sora participant A as App note over WHIP, S: WebRTC 確立 WHEP->>+S: HTTP POST https://sora.example.com/whep/
Offer SDP S->>+A: 認証ウェブフック

"channel_id": ""
"role": "recvonly" A-->>-S: "allowed": true S-->>-WHEP: HTTP 201 Created
Answer SDP Note left of S: このタイミングで Link ヘッダーで、
TURN URLs を払い出す note over WHEP,S: ICE 確立 note over WHEP,S: DTLS 確立 note over WHEP,S: WebRTC 確立 S->>+A: イベントウェブフック
"connection.created" A-->>-S: HTTP 200 OK S-)WHEP: SRTP S-)WHEP: SRTP WHEP->>+S: HTTP DELETE https://sora.example.com/whep// S-->>-WHEP: HTTP 200 OK note over WHEP,S: WebRTC 終了 ``` # 組み込み TURN 機能 Sora は TURN 機能が組み込まれています。そのため TURN サーバーを別途立てる必要はありません。 ## 推奨設定 一番接続率が高くなる設定は以下の通りです。 - TURN-TCP を 443 番ポートで待ち受け - TURN-TLS を 443 番ポートで待ち受け 上記設定をしたい場合は [TURN-TLS、TURN-TCP、シグナリングで 443 番ポートを使用する](PRODUCTION.html#14258d) をご確認ください。 ## TURN はすべて同時に試される **TURN の経路を決定するのはクライアント側の実装に依存します** 基本的に TURN 利用時には TURN-UDP と TURN-TCP と TURN-TLS をすべて同時に試みて、 確立が早かった経路を利用する仕組みが多いです。 ## ブラウザの TURN 対応状況 Chrome、Firefox、Edge、Safari は TURN-UDP / TURN-TCP / TURN-TLS に対応しています。 ## 注意 Firefox では TURN の urls を 5 個より多く送るとエラーがコンソールに表示されます。 ## 設定 TURN 機能は常に有効です。 ```ini ## TURN 機能で利用するレルムを指定してください # turn_realm = sora-turn.example.com ## TURN 機能で TURN URL 払い出し機能で利用する FQDN (最後の . なし)を指定してください # turn_fqdn = sora-turn.example.com ## TURN 機能で TURN-TCP を有効にするかどうかを指定してください # turn_tcp = true ## TURN 機能で TURN-TCP を有効にした際に利用するポート番号を指定してください # turn_tcp_listen_port = 3478 ## TURN 機能で TURN-TCP URL 払い出し時のポート番号を指定してください # turn_tcp_port = 3478 ## TURN 機能で TURN-TLS URL 払い出し機能を有効にするかどうかを指定してください # turn_tls = true ## TURN 機能で TURN-TLS URL 払い出し機能で利用する FQDN (最後の . なし)を指定してください ## turn_tls_fqdn は turn_fqdn の値を上書きします # turn_tls_fqdn = sora-turn.example.com ## TURN 機能で TURN-TLS URL 払い出し機能を有効にした際に利用するポート番号を指定してください # turn_tls_port = 5349 ``` ### 設定の優先順位 Sora では TURN 用の URL を生成する優先順位が存在します。 1. 認証時に外部サーバーから払い出される `ipv4_address` が採用されます- `sora.conf` で [ipv6](SORA_CONF.html#3202ce) が `true` の場合は払い出された `ipv6_address` も採用されます 2. 外部サーバーから `ipv4_address` が払い出されなかった場合は `sora.conf` の [ipv4_address](SORA_CONF.html#04becc) が採用されます- `sora.conf` で [ipv6](SORA_CONF.html#3202ce) が `true` の場合は `sora.conf` の [ipv6_address](SORA_CONF.html#30f40f) も採用されます 3. TURN-TLS を有効にしている場合、外部サーバーから払い出される `turn_tls_fqdn` が払い出されなかった場合は `sora.conf` の [turn_tls_fqdn](SORA_CONF.html#3bfd30) が採用されます。さらに `turn_tls_fqdn` が指定されてない場合は `turn_fqdn` が採用されます。 #### 設定例 1 ```ini ipv4_address = 192.0.2.10 ipv6 = false turn_realm = sora-turn.example.com turn_fqdn = sora-turn.example.com turn_tcp = true turn_tcp_listen_port = 3478 turn_tcp_port = 3478 turn_tls = true turn_tls_fqdn = sora-turn.example.com turn_tls_port = 5349 ``` 外部サーバーから払い出された `turn_tls_fqdn` が `"sora-turn.example.com"` の場合、払い出される TURN の urls は 3 つです。 UDP のポートは動的に決まるためここでは 54321 としています。 - turn:sora-turn.example.com:54321?transport=udp - turn:sora-turn.example.com:3478?transport=tcp - turns:sora-turn.example.com:5349?transport=tcp #### 設定例 2 - sora.conf- すべてデフォルト - 収集された IP アドレスは 192.0.2.10 と 192.0.2.20 - 外部サーバーから払い出し- なし - sora.conf の auth_webhook_url がコメントアウトされている この場合、払い出される TURN の urls は 4 つです。 UDP のポートは動的に決まるためここでは 54321 としています。 - turn:192.0.2.10:54321?transport=udp - turn:192.0.2.10:3478?transport=tcp - turn:192.0.2.20:54321?transport=udp - turn:192.0.2.20:3478?transport=tcp ## 内蔵 TURN 機能のメリット - Sora との通信経路を強制的に TURN 経由に固定することで、効率よく接続の確立が行えます- `"type": "candidate"` を待つ必要がなく、 Answer さえ受け取ってしまえば接続の確立まで進めます - 接続ごとに TURN に使用する Username や Credential を意識する必要がなくなります - TURN-TCP や TURN-TLS 機能を使用することで UDP が使用できない環境でも WebRTC を利用できるようになります ## Sora の TURN 機能 - TURN-UDP での TURN 機能- 動的なポートでの TURN-UDP にのみ対応しています - TURN-TCP での TURN 機能 - TURN-TLS での TURN URL 払い出し機能- NGINX の利用を前提とした機能です - ワンタイムな Username や Credential、TURN の URL の自動払い出し- Sora がすべて自動で行ってくれます - Sora は TURN 機能に必要な Username や Credential をクライアントごとにワンタイムで生成します - TURN-UDP / TURN-TCP の IPv6 対応- TURN で払い出す urls も IPv6 に対応します - TURN-TLS での IPv6 対応については NGINX 依存となります - TURN-TCP の Proxy Protocol 対応- NGINX などを利用したリバースプロキシが前段にいて Proxy Protocol を利用する場合でも対応ができます ## Sora の TURN-TCP 機能 - デフォルトでは有効になっていますので、無効にしたい場合は `sora.conf` の [turn_tcp](SORA_CONF.html#500b14) を `false` に指定してください - TURN-TCP で受信するポート番号を指定したい場合は `sora.conf` の [turn_tcp_listen_port](SORA_CONF.html#7c335c) を `3478` に指定してください - TURN-TCP の設定で払い出すポート番号を指定したい場合は `sora.conf` の [turn_tcp_port](SORA_CONF.html#7211a6) を `443` に指定してください ## Sora の TURN-TLS URL 払い出し機能 Sora では TURN-TLS 機能は直接提供していません。 TLS の終端には NGINX を利用します。 つまり NGINX 側で TURN-TLS の TLS を終端して、 TURN-TCP として Sora に送られます。 > **重要** > > 必ず turn_tcp の設定を有効にしてください デフォルトでは無効になっていますので、有効にしたい場合は `sora.conf` で [turn_tls](SORA_CONF.html#63e4bb) を `true` に指定してください。 TURN-TLS で使用するポート番号を指定したい場合は `sora.conf` で [turn_tls_port](SORA_CONF.html#205b72) を `5349` のように指定してください。 さらに TURN-TLS を使用する場合はかならず証明書の FQDN を指定する必要があります。 sora-turn.example.com の証明書を使用する場合は `sora.conf` で [turn_tls_fqdn](SORA_CONF.html#3bfd30) を `sora-turn.example.com` のように指定してください。 詳細は [TURN-TLS、TURN-TCP、シグナリングで 443 番ポートを使用する](PRODUCTION.html#14258d) をご確認ください。 ## Sora の TURN IPv6 対応 IPv6 のアドレスが使用できる場合、クライアントに送られる TURN UDP/TCP サーバー機能も IPv6 で提供します。 ## TURN-TCP / TURN-TLS の検証 `sora.conf` の [turn_tcp_only](SORA_CONF.html#479c51) を `true` や [turn_tls_only](SORA_CONF.html#58d702) を `true` に設定することで強制的に TURN-TCP や TURN-TLS を利用できるようになります。 こちらは、あくまで検証のみで利用していただくことを想定している機能です。そのため有効にしている場合は `sora.jsonl` に `warning` メッセージが出力されます。 ## Sora TURN 機能の制限 Sora の TURN 機能には一部制限があります。 - TURN で使用される UDP のポート番号の固定ができない- TURN のポート番号は個々のクライアントに対して動的に生成されるため、固定できません。 ## シーケンス図 ### TURN への接続は同時に試す TURN-UDP のポートは動的に決まります。 ```mermaid sequenceDiagram autonumber participant C as クライアント participant NGINX participant S as Sora C->>NGINX: "type": "connect" over WSS note right of NGINX: TLS 終端 NGINX->>S: "type": "connect" over WS S->>NGINX: "type": "offer" over WS NGINX->>C: "type": "offer" over WSS C->>NGINX: "type": "answer" over WSS note right of NGINX: TLS 終端 NGINX->>S: "type": "answer" over WS par C->>S: TURN-UDP Allocate-Request port=52520 and C->>NGINX: TURN-TCP Allocate-Request port=443 NGINX->>S: TURN-TCP Allocate-Request port=3478 and C->>NGINX: TURN-TLS Allocate-Request port=443 note right of NGINX: TLS 終端 NGINX->>S: TURN-TCP Allocate-Request port=3478 end S->>C: TURN-UDP Allocate-Success C->>+S: TURN-UDP Permission-Request port=52520 S-->>-C: TURN-UDP Permission-Success C->>+S: TURN-UDP Channel-Request port=52520 S-->>-C: TURN-UDP Channel-Success C->>S: DTLS ClientHello over TURN port=52520 ``` # 録画機能 (セッション単位) ## 概要 Sora では、配信している映像や音声を録画、録音して保存できます。 配信されている映像をできるかぎりそのまま保存するため、CPU リソースを最小限に抑えることができます。 出力される録画ファイルは MP4 または WebM 形式です。映像のみの録画、音声のみの録音にも対応しています。 録画時には一切トランスコードを行っていません。配信された映像や音声をそのままに記録します。 ## 用語 **一括録画ファイル** : 切断または [StopRecording](API_RECORDING.html#fd0de5) API が実行されるか、録画期限が切れるか、セッションが破棄された場合に一つのファイルとして出力される動画ファイル **分割録画ファイル** : `split_duration` で指定した時間ごとに区切られ分割されて出力される動画ファイル ## 録画の開始方法 録画の開始方法には色々なパターンがあります。用途によって使い分けてください。 ### セッション生成時の録画開始 セッション生成時に録画を開始することができます。その場合は [session.created](SESSION_WEBHOOK.html#1d1984) の払い出しで `"recording": true` を指定してください。 常に録画を有効にしていたい場合、この機能を利用してください。 ### 認証成功時の録画開始 認証成功時の払い出しで録画を開始することができます。その場合は `"recording": true` を指定してください。 特定の接続がチャネルに接続した際に録画を開始したい場合、この機能を利用してください。 詳細は [録画機能の払い出し](AUTH_WEBHOOK_RETURN.html#8a1586) をご確認ください。 ### API 経由での録画開始 API 経由で録画を開始することができます。その場合は [StartRecording](API_RECORDING.html#c5b527) API を利用してください。 好きなタイミングで録画を開始したい場合、この機能を利用してください。 ## 録画の終了方法 録画の終了にも色々なパターンがあります。用途によって使い分けてください。 ### セッション破棄での録画停止 録画が開始されているセッションが破棄されたタイミングで録画を停止します。 ### 録画期限切れでの録画停止 録画開始時に録画期限(秒)を指定した場合、その期限が切れたタイミングで録画を停止します。 ### API 経由での録画停止 API 経由で録画を停止することができます。その場合は [StopRecording](API_RECORDING.html#fd0de5) API を利用してください。 ## 録画ファイルの出力 録画ファイルの出力には 3 パターンあります。 ### 一括録画ファイルのみ出力 - `split_only` が未指定、または `false` に設定されている - `split_duration` が未指定 - `expire_time` は指定されていてもよい 上記を満たした場合、1 接続で 1 つ録画ファイルが出力されます。 ### 分割録画ファイルのみ出力 - `split_only` が `true` に指定されている - `split_duration` が指定されている - `expire_time` は指定されていてもよい 上記を満たした場合、分割された録画ファイルのみが出力されます。 ### 一括録画ファイルと分割録画ファイルの両方が出力 - `sora.conf` で `recording_dual_output` が `true` に指定されている - `split_only` が未指定、または `false` に指定されている - `split_duration` が指定されている - `expire_time` は指定されていてもよい 上記を満たした場合、 1 接続で 1 つの録画ファイルと分割された録画ファイルの両方が出力されます。 イベントウェブフックも一括録画、分割録画、両方のイベントウェブフックリクエストが送信されます。 ## 録画ファイルの出力形式 MP4 と WebM 形式の 2 種類があります。 ### デフォルト設定 `sora.conf` で [default_recording_format](SORA_CONF.html#f9fa7d) を指定することで、 録画ファイルのデフォルト出力形式を指定できます。 未指定の場合は **MP4 形式** で出力します。 ### MP4 **MP4 形式を推奨します** Sora 2024.2.0 から対応しました。 H.265 の録画は MP4 形式のみ対応しています。 ### WebM Google が開発した動画フォーマットです。 H.265 コーデックには非対応です。 ## 制限 ### コーデック 録画 (録音) は、映像コーデックに VP8 と VP9 と AV1 と H.264 と H.265 、また音声コーデックに Opus を選択した場合のみ利用できます。 > **警告** > > - H.265 の録画は MP4 形式のみ対応しています > - B フレームの録画には非対応です > - VP8 と Opus の組み合わせの MP4 形式は Firefox で再生できません ### 解像度 WebRTC では配信側の CPU リソースが不足した場合や、 回線の品質が悪化した場合に解像度を動的に変更します。 そのため録画したデータの途中で解像度が低くなる可能性があります。 ### 音声や映像のクライアント側でのトラック削除 クライアント側でシグナリング接続時に音声や映像を有効にした状態で、 クライアント側で音声トラック、または映像トラックのどちらかを削除した場合でも録画は行われます。 さらに追加して戻した形であれば録画側も戻ります。 ただし、音声と映像両方のトラックを削除した場合は正常に録画が行われません。 ### マルチストリーム機能での録画 対応しています。 ### サイマルキャスト機能での録画 対応しています。 サイマルキャストを利用している際の録画は **一番優先度が低い** ストリーム、すなわちデフォルトでは最も高い画質の映像を録画します。 詳細はサイマルキャストの [映像の優先度](SIMULCAST.html#36c708) をご確認下さい。 ### スポットライト機能での録画 対応しています。 サイマルキャストを利用している際の録画は **一番優先度が低い** ストリーム、すなわちデフォルトでは最も高い画質の映像を録画します。 詳細はサイマルキャストの [映像の優先度](SIMULCAST.html#36c708) をご確認下さい。 ### キーフレーム要求間隔 録画機能利用時の Sora からのキーフレーム要求間隔は以下の通りです。 - WebM 形式の場合 20 秒固定 - MP4 形式の場合 [default_recording_mp4_pli_interval](SORA_CONF.html#874e5b) で指定した秒数 (デフォルトは 20 秒) 録画時のキーフレーム要求間隔を変更したい場合は、MP4 形式の録画を行ってください。 ### 分割録画ファイルの録画時間 分割録画ファイルの時間はキーフレームの到着タイミングにより前後するため、 `split_duration` に指定した時間から前後することがあります。 ## 無変換録画 WebRTC 経由で流れてきている映像や音声を変換せず、 そのまま録画するファイルの形式に組み立て直してファイルを保存します。 そのため、CPU リソースを最小限に抑えられます。 ブラウザでの録画など、通常の録画は変換が入るため CPU に多くの負荷がかかります。 変換を行わないため、録画を終了した数秒後には録画したファイルを取得できます。 解像度は送られてきた映像の最大値を録画ファイルの解像度として使用します。 ## コネクション単位の録画ブロックについて 認証成功時に `"recording_block": true` を払い出すことでコネクション単位で録画をブロックし、録画ファイルの出力を行わないようにすることができます。 録画ブロックは認証成功時の払い出し時のみ指定ができます。それ以外では指定できません。 そのため、録画ブロックの途中解除はできません。 コネクションごとの録画ブロックの設定状況は [ListConnections](API_SIGNALING.html#d3da2a) API の `recording_block` または [ListChannelConnections](API_SIGNALING.html#d388f3) の `recording_block` で確認できます。 ### シーケンス図 ```mermaid sequenceDiagram autonumber participant C as クライアント participant S as Sora participant A as アプリケーションサーバー C->>+S: "type": "connect" S->>+A: 認証ウェブフック A-->>-S: 200 OK
"recording_block": true S-->>-C: "type": "offer" C->>S: "type": "answer" note over C,A: WebRTC 確立 S->>+A: セッションウェブフック: "session.created" A-->>-S: 200 OK
"recording": true note over C,A: 録画開始 S->>+A: セッションウェブフック
"type": "recording.started" A-->>-S: 200 OK note over C,A: 録画ブロックしているため "archive.started" が飛ばない
さらに録画ファイルは出力されない ``` ## sora.conf の設定による録画指定制限 録画ファイルが大きくならないように、sora.conf の指定で録画開始時のオプションを制限することができます。 設定の詳細は以下をご確認ください。 - [recording_max_expire_time](SORA_CONF.html#f3ff8d) - [recording_max_split_duration](SORA_CONF.html#927da9) - [recording_expire_time_required](SORA_CONF.html#fcfa2d) - [recording_dual_output](SORA_CONF.html#4cc9c0) ## MP4 形式のキーフレーム要求間隔の変更 録画時には一定間隔で Sora からクライアントへキーフレーム要求 (PLI) を送ります。 WebM 形式ではキーフレームの間隔が最大でも 31 秒までという制約がありましたが、 MP4 形式ではこの制約がなくなりました。 そのため、 MP4 形式ではこの間隔を [default_recording_mp4_pli_interval](SORA_CONF.html#874e5b) で変更することができます。 デフォルトは `20 s` で、最小が `1 s` で、最大が `240 s` です。 ```ini default_recording_mp4_pli_interval = 100 s ``` ## 録画情報の API 経由での取得 録画情報を取得するには [セッション](API_SESSION.html) API を利用します。 ### 指定したセッションの録画情報を取得する [GetSession](API_SESSION.html#427a59) API を利用することで、指定したセッションの録画状態を取得することができます。 録画が開始されているセッションは `recording` 項目が存在します。 ```javascript { "label": "WebRTC SFU Sora", "node_name": "sora@127.0.0.1", "version": "2024.1.0", "channel_id": "sora", "group_id": "JJJ5BFH7QN6DQBTKSS7JA8ZYQR", "session_id": "JJJ5BFH7QN6DQBTKSS7JA8ZYQR", "session_metadata": {"spam": "egg"}, "created_time": 1638337454, "created_timestamp": "2021-12-01T05:44:14.523736Z", "spotlight": false, "max_connections": 4, "total_connections": 4, "external_signaling_url": "wss://node-01.example.com/signaling", "recording": { "recording_id": "WHEJ888HQ55KDCFE3TZ4VPFQHR", "recording_metadata": {"spam": "egg"}, "expire_time": 3600, "expired_at": 1615527737, "split_duration": 3600, "split_only": false, "start_timestamp": "2021-03-12T04:42:17.455668Z", "format": "mp4" } } ``` ### 全てのセッションの録画情報を取得する [ListSessions](API_SESSION.html#748f19) API を利用することで、全てのセッションの録画状態を取得することができます。 録画が開始されているセッションは `recording` 項目が存在します。 ```javascript [ { "label": "WebRTC SFU Sora", "node_name": "sora@127.0.0.1", "version": "2024.1.0", "channel_id": "sora", "group_id": "JJJ5BFH7QN6DQBTKSS7JA8ZYQR", "session_id": "JJJ5BFH7QN6DQBTKSS7JA8ZYQR", "session_metadata": {"spam": "egg"}, "created_time": 1638337454, "created_timestamp": "2021-12-01T05:44:14.523736Z", "spotlight": false, "max_connections": 4, "total_connections": 4, "connections": [ { "audio": true, "audio_codec_type": "OPUS", "client_id": "W9QE86Z0BS1QFFPZ2QB5DRZ2HC", "bundle_id": "W9QE86Z0BS1QFFPZ2QB5DRZ2HC", "connection_id": "W9QE86Z0BS1QFFPZ2QB5DRZ2HC", "connection_created_timestamp": "2021-12-01T05:44:23.051704Z", "connection_destroyed_timestamp": "2021-12-01T05:44:56.878019Z", "role": "sendrecv", "simulcast": false, "video": true, "video_bit_rate": 1000, "video_codec_type": "VP9", "video_vp9_params": { "profile_id": 0 }, }, { "audio": true, "audio_codec_type": "OPUS", "client_id": "JXMYW6GPX54EH0HGA5X4130FBM", "bundle_id": "JXMYW6GPX54EH0HGA5X4130FBM", "connection_id": "JXMYW6GPX54EH0HGA5X4130FBM", "connection_created_timestamp": "2021-12-01T05:44:23.051704Z", "connection_destroyed_timestamp": "2021-12-01T05:44:56.878019Z", "role": "sendrecv", "simulcast": false, "video": true, "video_bit_rate": 1000, "video_codec_type": "VP9", "video_vp9_params": { "profile_id": 0 }, } ], "recording": { "recording_id": "WHEJ888HQ55KDCFE3TZ4VPFQHR", "recording_metadata": {"spam": "egg"}, "expire_time": 3600, "expired_at": 1615527737, "split_duration": 3600, "split_only": false, "start_timestamp": "2021-03-12T04:42:17.455668Z", "format": "mp4" } } ] ``` ## 録画関連のウェブフックについて ### session.created ウェブフック > **注意** > > [sora.conf の設定による録画指定制限](RECORDING.html#a56297) を行っていた場合、制限に該当する指定を行っている場合は録画が開始されません。 払い出し時に以下の項目が指定できます。 - recording- boolean - そのセッションでの録画を開始するかどうかを指定します - オプション - recording_expire_time- integer - そのセッションでの録画期限を指定します - デフォルト値は未定義で、期限なしです - 指定する場合 0 より大きな値を指定してください - 単位は秒です - オプション - recording_split_only- boolean - そのセッションでの録画を分割のみにするかを指定します - デフォルト値は false で、分割を行いません - オプション - recording_split_duration- integer - そのセッションでの録画を分割する場合の分割時間を指定します - recording_split_only が true の場合は指定が必須です - オプション - recording_metadata- JSONValue - そのセッションでの録画メタデータを指定します - オプション - recording_format- string - そのセッションでの録画ファイルのフォーマットを指定します - `webm` と `mp4` が指定できます - オプション ### recording.started セッションウェブフック 録画開始 API が実行されたタイミングで `recording.started` リクエストを送信します。 詳しくは [recording.started](SESSION_WEBHOOK.html#9b5c58) をご確認ください。 ### recording.report セッションウェブフック 録画終了 API が実行されたか、 録画の期限が切れたか、 セッションが破棄されたタイミングで `recording.report` リクエストを送信します。 > **注釈** > > セッションが破棄されたタイミングでの `recording.report` は `session.destroyed` の **後** に送信されます。 詳しくは [recording.report](SESSION_WEBHOOK.html#920a02) をご確認ください。 ### archive.started ウェブフック 録画ファイルを保存しはじめたタイミングで `archive.started` リクエストを送信します。 詳しくは [archive.started](EVENT_WEBHOOK.html#462c97) をご確認ください。 ### archive.available イベントウェブフック 一括録画ファイルが出力されたタイミングで `archive.available` リクエストを送信します。 詳しくは [archive.available](EVENT_WEBHOOK.html#de9132) をご確認ください。 ### split-archive.available イベントウェブフック 録画ファイル分割出力機能を有効にした場合、 分割された録画ファイルが出力されたタイミングで `split-archive.available` リクエストを送信します。 詳しくは [split-archive.available](EVENT_WEBHOOK.html#555071) をご確認ください。 ### split-archive.end イベントウェブフック 録画ファイル分割出力機能を有効にした場合、 分割された録画が終了したタイミングで `split-archive.end` リクエストを送信します。 詳しくは [split-archive.end](EVENT_WEBHOOK.html#31be7a) をご確認ください。 ### archive.failed イベントウェブフック 録画ファイルの保存に失敗した場合、 `archive.failed` リクエストを送信します。 詳しくは [archive.failed](EVENT_WEBHOOK.html#5006f8) をご確認ください。 ### 認証ウェブフック `sora.conf` にて [auth_webhook_recording](SORA_CONF.html#24d27d) が `true` に設定することで、認証成功時の払い出し時に以下の項目が指定できます。 - 既に録画が開始されている場合はこの払い出しは無視されます - `"recording": false` を指定しても録画は停止せず、無視されます 払い出せる項目は [session.created ウェブフック](RECORDING.html#3cec61) と同じです。 #### 払い出せる項目 - recording - recording_expire_time - recording_split_only - recording_split_duration - recording_metadata - recording_format ## 一括録画ファイル出力のみ 一括録画ファイル出力のみの場合は `sora.conf` の [archive_dir](SORA_CONF.html#ad2156) に指定したディレクトリに `recording_id` 名のディレクトリ以下にファイルが出力されます。 `recording_id` は録画開始 API を実行したときに戻ってくる値で、 Base32 でエンコードされた UUIDv4 となります。 ディレクトリ構造: ``` ├── archive │ ├── 1CS9QJ0XPN4C76HBGBN6MGMK5M │ │ ├── archive-A4756MXP914ZB265E92JE3ZMWC.json │ │ ├── archive-A4756MXP914ZB265E92JE3ZMWC.mp4 │ │ ├── archive-H2NDA2YCGH7S1E9CVMFMXMA34R.json │ │ ├── archive-H2NDA2YCGH7S1E9CVMFMXMA34R.mp4 │ │ ├── archive-PBVZQQN3JS3MQF8XHVFXDMCEEC.json │ │ ├── archive-PBVZQQN3JS3MQF8XHVFXDMCEEC.mp4 │ │ └── report-1CS9QJ0XPN4C76HBGBN6MGMK5M.json │ └── CZZ8A8KZB16A1DF5PKERBHGFNR │ ├── archive-3B7AFF8ZRX6VNEYV40B35Z9S2C.json │ ├── archive-3B7AFF8ZRX6VNEYV40B35Z9S2C.mp4 │ ├── archive-DGSN3TC0E91RSCZT5KVPRWCDHR.json │ ├── archive-DGSN3TC0E91RSCZT5KVPRWCDHR.mp4 │ └── report-CZZ8A8KZB16A1DF5PKERBHGFNR.json ``` > **注意** > > `archive_dir` と `archive_tmp_dir` は違うディレクトリを指定して下さい ### archive- #### 一括録画ファイル 一括録画ファイルは `/archive-.{mp4,webm}` に WebM または MP4 形式で出力されます。 #### 一括録画メタデータファイル 一括録画メタデータファイルは `/archive-.json` に JSON 形式で出力されます。 メタデータファイルには WebM または MP4 ファイルがいつ出力され、どんな形式なのか、開始時刻や終了時刻などの情報が含まれています。 - start_timestamp- この録画が開始した時刻を RFC 3339 (UTC) で表しています - stop_timestamp- この録画が終了した時刻を RFC 3339 (UTC) で表しています - start_time- この録画が開始された時刻を UNIX 時間で表しています - stop_time- この録画が終了した時刻を UNIX 時間で表しています **stats は省略しています** ```javascript { "audio": true, "audio_codec_type": "OPUS", "channel_id": "sora", "group_id": "JA8FB89ZJS1H9CV5GN3NCT5RA0", "session_id": "JA8FB89ZJS1H9CV5GN3NCT5RA0", "client_id": "GK2R6PSDYX68VDQPRX4FVVFN8W", "bundle_id": "GK2R6PSDYX68VDQPRX4FVVFN8W", "connection_id": "GK2R6PSDYX68VDQPRX4FVVFN8W", "created_at": 1615524156, "file_path": "/path/to/sora/archive/WHEJ888HQ55KDCFE3TZ4VPFQHR/archive-GK2R6PSDYX68VDQPRX4FVVFN8W.mp4", "filename": "WHEJ888HQ55KDCFE3TZ4VPFQHR/archive-GK2R6PSDYX68VDQPRX4FVVFN8W.mp4", "metadata_file_path": "/path/to/sora/archive/WHEJ888HQ55KDCFE3TZ4VPFQHR/archive-GK2R6PSDYX68VDQPRX4FVVFN8W.json", "metadata_filename": "WHEJ888HQ55KDCFE3TZ4VPFQHR/archive-GK2R6PSDYX68VDQPRX4FVVFN8W.json", "recording_id": "WHEJ888HQ55KDCFE3TZ4VPFQHR", "size": 0, "start_time": 1615524137, "start_time_offset": 7, "start_timestamp": "2021-03-12T04:42:17.455668Z", "stats": {}, "stop_time": 1615524154, "stop_time_offset": 24, "stop_timestamp": "2021-03-12T04:42:34.094375Z", "label": "WebRTC SFU Sora", "node_name": "node1@192.0.2.10", "event_metadata": {"spam": "egg"}, "video": true, "video_bit_rate": 1000, "video_codec_type": "VP9", "video_vp9_params": { "profile_id": 0 }, "video_height": 480, "video_width": 640, "format": "mp4" } ``` ### report- 録画終了時に、それまでにそのセッションで録画したファイル一覧が記載されているレポートファイルが JSON 形式で出力されます。 録画終了は [StopRecording](API_RECORDING.html#fd0de5) API を使用して指定したチャネルに対する録画を停止するか、 録画の期限が切れるか、セッションが破棄されるかの 3 つのパターンがあります。 このファイルは主にマルチストリームや途中で切れてしまった場合などを考慮しており、 録画ファイルのグルーピングを目的としたファイルです。 ファイルは `/report-.json` に出力されます。 - トップレベルの start_timestamp- [StartRecording](API_RECORDING.html#c5b527) API を受け付た時刻を RFC 3339 (UTC) で表しています - トップレベルの stop_timestamp- [StopRecording](API_RECORDING.html#fd0de5) API を受け付た時刻か、 [StartRecording](API_RECORDING.html#c5b527) API で設定された期限の時刻を RFC 3339 (UTC) で表しています - archives 内の start_time_offset- [StartRecording](API_RECORDING.html#c5b527) API を叩いてから何秒経過した後にこの録画が開始したかを表しています - archives 内の stop_time_offset- [StartRecording](API_RECORDING.html#c5b527) API を叩いてから何秒経過した後にこの録画が終了したかを表しています ```javascript { "archives": [ { "client_id": "GK2R6PSDYX68VDQPRX4FVVFN8W", "bundle_id": "GK2R6PSDYX68VDQPRX4FVVFN8W", "connection_id": "GK2R6PSDYX68VDQPRX4FVVFN8W", "file_path": "/path/to/sora/archive/WHEJ888HQ55KDCFE3TZ4VPFQHR/archive-GK2R6PSDYX68VDQPRX4FVVFN8W.mp4", "filename": "WHEJ888HQ55KDCFE3TZ4VPFQHR/archive-GK2R6PSDYX68VDQPRX4FVVFN8W.mp4", "metadata_file_path": "/path/to/sora/archive/WHEJ888HQ55KDCFE3TZ4VPFQHR/archive-GK2R6PSDYX68VDQPRX4FVVFN8W.json", "metadata_filename": "WHEJ888HQ55KDCFE3TZ4VPFQHR/archive-GK2R6PSDYX68VDQPRX4FVVFN8W.json", "size": 0, "start_time_offset": 0, "start_timestamp": "2021-03-12T04:42:17.455668Z", "stop_time_offset": 17, "stop_timestamp": "2021-03-12T04:42:34.094375Z", "label": "WebRTC SFU Sora", "node_name": "node1@192.0.2.10" } ], "channel_id": "sora", "created_at": 1615524137, "expire_time": 3600, "expired_at": 1615527737, "file_path": "/path/to/sora/archive/WHEJ888HQ55KDCFE3TZ4VPFQHR/report-WHEJ888HQ55KDCFE3TZ4VPFQHR.json", "filename": "WHEJ888HQ55KDCFE3TZ4VPFQHR/report-WHEJ888HQ55KDCFE3TZ4VPFQHR.json", "recording_metadata": {"spam": "egg"}, "recording_id": "WHEJ888HQ55KDCFE3TZ4VPFQHR", "split_only": false, "start_timestamp": "2021-03-12T04:42:17.455668Z", "stop_timestamp": "2021-03-12T04:42:34.094375Z", "format": "mp4" } ``` ## 分割録画ファイル出力のみ Sora では [StartRecording](API_RECORDING.html#c5b527) API 実行時に `split_only: true` と `split_duration` の 2 つを指定することで、 録画ファイルを指定した間隔で出力する機能を提供しています。 > **重要** > > 分割の最小単位はキーフレームから次のキーフレームまでです。例えば `split_duration` を 1 秒に設定した場合は、1 秒経過後に次のキーフレームが来たタイミングで分割出力されます。 録画が完了したファイルは `sora.conf` の [archive_dir](SORA_CONF.html#ad2156) に指定したディレクトリに `recording_id` 名のディレクトリ以下にファイルが出力されます。 `recording_id` は [StartRecording](API_RECORDING.html#c5b527) API を実行したときに戻ってくる値です。 ### 録画ファイル分割出力のみを行う 録画開始 API 実行時に `split_only: true` と `split_duration` の 2 つを指定することで、 録画ファイル分割出力 **のみ** を行うことが可能になります。 ディレクトリ構造: ``` ├── archive │ ├── 1CS9QJ0XPN4C76HBGBN6MGMK5M │ │ ├── split-archive-end-A4756MXP914ZB265E92JE3ZMWC.json │ │ ├── split-archive-A4756MXP914ZB265E92JE3ZMWC_0001.json │ │ ├── split-archive-A4756MXP914ZB265E92JE3ZMWC_0001.mp4 │ │ ├── split-archive-A4756MXP914ZB265E92JE3ZMWC_0002.json │ │ ├── split-archive-A4756MXP914ZB265E92JE3ZMWC_0002.mp4 │ │ ├── split-archive-A4756MXP914ZB265E92JE3ZMWC_0003.json │ │ ├── split-archive-A4756MXP914ZB265E92JE3ZMWC_0003.mp4 │ │ ├── split-archive-A4756MXP914ZB265E92JE3ZMWC_0003.json │ │ ├── split-archive-A4756MXP914ZB265E92JE3ZMWC_0003.mp4 │ │ └── report-1CS9QJ0XPN4C76HBGBN6MGMK5M.json │ └── CZZ8A8KZB16A1DF5PKERBHGFNR │ ├── split-archive-end-3B7AFF8ZRX6VNEYV40B35Z9S2C.json │ ├── split-archive-end-DGSN3TC0E91RSCZT5KVPRWCDHR.json │ ├── split-archive-3B7AFF8ZRX6VNEYV40B35Z9S2C_0001.json │ ├── split-archive-3B7AFF8ZRX6VNEYV40B35Z9S2C_0001.mp4 │ ├── split-archive-DGSN3TC0E91RSCZT5KVPRWCDHR_0001.json │ ├── split-archive-DGSN3TC0E91RSCZT5KVPRWCDHR_0001.mp4 │ ├── split-archive-DGSN3TC0E91RSCZT5KVPRWCDHR_0002.json │ ├── split-archive-DGSN3TC0E91RSCZT5KVPRWCDHR_0002.mp4 │ └── report-CZZ8A8KZB16A1DF5PKERBHGFNR.json ``` ### split-archive-_ #### 分割録画ファイル 分割録画ファイルは `/split-archive-_.{mp4,webm}` に WebM または MP4 形式で出力されます。 #### 分割録画メタデータファイル 分割録画メタデータファイルは `/split-archive-_.json` に JSON 形式で出力されます。 - split_index- ファイル名につくインデックスです - 0001 から始まり 9999 の後は 10000 となります **stats は省略しています** ```javascript { "audio": true, "audio_codec_type": "OPUS", "recording_id": "CZZ8A8KZB16A1DF5PKERBHGFNR", "file_path": "/path/to/sora/archive/CZZ8A8KZB16A1DF5PKERBHGFNR/split-archive-3B7AFF8ZRX6VNEYV40B35Z9S2C_001.mp4", "filename": "CZZ8A8KZB16A1DF5PKERBHGFNR/split-archive-3B7AFF8ZRX6VNEYV40B35Z9S2C_001.mp4", "metadata_file_path": "/path/to/sora/split-archive/CZZ8A8KZB16A1DF5PKERBHGFNR/archive-3B7AFF8ZRX6VNEYV40B35Z9S2C_001.json", "metadata_filename": "CZZ8A8KZB16A1DF5PKERBHGFNR/split-archive-3B7AFF8ZRX6VNEYV40B35Z9S2C_001.json", "channel_id": "sora", "group_id": "JA8FB89ZJS1H9CV5GN3NCT5RA0", "session_id": "JA8FB89ZJS1H9CV5GN3NCT5RA0", "client_id": "3B7AFF8ZRX6VNEYV40B35Z9S2C", "bundle_id": "3B7AFF8ZRX6VNEYV40B35Z9S2C", "connection_id": "3B7AFF8ZRX6VNEYV40B35Z9S2C", "split_index": "0001", "created_at": 1604656364, "size": 823263, "start_time": 1604656354, "start_time_offset": 4, "start_timestamp": "2020-11-06T09:52:34.696758Z", "stats": {}, "stop_time": 1604656364, "stop_time_offset": 14, "stop_timestamp": "2020-11-06T09:52:44.493179Z", "label": "WebRTC SFU Sora", "node_name": "node1@192.0.2.10", "event_metadata": {"spam": "egg"}, "video": true, "video_bit_rate": 1000, "video_codec_type": "VP9", "video_vp9_params": { "profile_id": 0 }, "video_height": 480, "video_width": 640, "format": "mp4" } ``` ### split-archive-end- #### 分割録画終了メタデータファイル 分割録画終了メタデータファイルは `/split-archive-end-.json` に JSON 形式で出力されます。 **stats は省略しています** ```javascript { "audio": true, "audio_codec_type": "OPUS", "split_last_index": "0042", "recording_id": "CZZ8A8KZB16A1DF5PKERBHGFNR", "file_path": "/path/to/sora/archive/CZZ8A8KZB16A1DF5PKERBHGFNR/split-archive-end-3B7AFF8ZRX6VNEYV40B35Z9S2C.json", "filename": "CZZ8A8KZB16A1DF5PKERBHGFNR/split-archive-end-3B7AFF8ZRX6VNEYV40B35Z9S2C.json", "channel_id": "sora", "group_id": "JA8FB89ZJS1H9CV5GN3NCT5RA0", "session_id": "JA8FB89ZJS1H9CV5GN3NCT5RA0", "client_id": "3B7AFF8ZRX6VNEYV40B35Z9S2C", "bundle_id": "3B7AFF8ZRX6VNEYV40B35Z9S2C", "connection_id": "3B7AFF8ZRX6VNEYV40B35Z9S2C", "start_time": 1604656354, "start_time_offset": 4, "start_timestamp": "2020-11-06T09:52:34.696758Z", "stats": {}, "stop_time": 1604656364, "stop_time_offset": 14, "stop_timestamp": "2020-11-06T09:52:44.493179Z", "label": "WebRTC SFU Sora", "node_name": "node1@192.0.2.10", "event_metadata": {"spam": "egg"}, "video": true, "video_bit_rate": 1000, "video_codec_type": "VP9", "video_vp9_params": { "profile_id": 0 }, "format": "mp4" } ``` #### 録画ファイル分割出力終了時 コネクション単位での録画が終了したタイミングでイベントウェブフックリクエスト `split-archive.end` がリクエスト送信されます。 詳細は [split-archive.end](EVENT_WEBHOOK.html#31be7a) をご確認ください。 ### report- 録画終了時に、それまでにそのチャネルで録画したファイル一覧が記載されているレポートファイルが JSON 形式で出力されます。 録画終了は [StopRecording](API_RECORDING.html#fd0de5) API を使用して指定したチャネルに対する録画を停止するか、 録画の期限が切れるか、セッションが破棄されるかの 3 つのパターンがあります。 このファイルは主にマルチストリームや途中で切れてしまった場合などを考慮しており、 録画ファイルのグルーピングを目的としたファイルです。 ファイルは `/report-.json` に出力されます。 分割録画ファイル出力のみの場合は archives には `connection_id` や `client_id` といった接続情報と、 分割録画ファイルの最後のインデックス番号のみが含まれます。 - トップレベルの start_timestamp- [StartRecording](API_RECORDING.html#c5b527) API を受け付た時刻を RFC 3339 (UTC) で表しています - トップレベルの stop_timestamp- [StopRecording](API_RECORDING.html#fd0de5) API を受け付た時刻か、 [StartRecording](API_RECORDING.html#c5b527) API で設定された期限の時刻を RFC 3339 (UTC) で表しています - archives 内の start_time_offset- [StartRecording](API_RECORDING.html#c5b527) API を叩いてから何秒経過した後にこの録画が開始したかを表しています - archives 内の stop_time_offset- [StartRecording](API_RECORDING.html#c5b527) API を叩いてから何秒経過した後にこの録画が終了したかを表しています ```javascript { "archives": [ { "client_id": "GK2R6PSDYX68VDQPRX4FVVFN8W", "bundle_id": "GK2R6PSDYX68VDQPRX4FVVFN8W", "connection_id": "GK2R6PSDYX68VDQPRX4FVVFN8W", "split_last_index": "0042", "start_time_offset": 4, "start_timestamp": "2020-11-06T09:52:34.696758Z", "stop_time_offset": 14, "stop_timestamp": "2020-11-06T09:52:44.493179Z", "label": "WebRTC SFU Sora", "node_name": "node1@192.0.2.10" } ], "channel_id": "sora", "created_at": 1615524137, "expire_time": 3600, "expired_at": 1615527737, "file_path": "/path/to/sora/archive/WHEJ888HQ55KDCFE3TZ4VPFQHR/report-GK2R6PSDYX68VDQPRX4FVVFN8W.json", "filename": "WHEJ888HQ55KDCFE3TZ4VPFQHR/report-GK2R6PSDYX68VDQPRX4FVVFN8W.json", "recording_id": "WHEJ888HQ55KDCFE3TZ4VPFQHR", "split_duration": 3600, "split_only": false, "recording_metadata": {"spam": "egg"}, "start_timestamp": "2020-11-06T09:52:34.696758Z", "stop_timestamp": "2020-11-06T09:52:44.493179Z", "format": "mp4" } ``` ## 一括録画ファイルと分割録画ファイル [StartRecording](API_RECORDING.html#c5b527) API 実行時に `split_only` を有効にしない限り、 単一ファイルと分割ファイルの二つが出力されます。 一括録画ファイルと分割録画ファイルのいいところ取りですが、その分ストレージの容量も 2 倍消費します。 出力されるファイルは単一と分割のファイルが混ざった形式になります。 ディレクトリ構造: ``` ├── archive │ ├── 1CS9QJ0XPN4C76HBGBN6MGMK5M │ │ ├── split-archive-end-A4756MXP914ZB265E92JE3ZMWC.json │ │ ├── split-archive-A4756MXP914ZB265E92JE3ZMWC_0001.json │ │ ├── split-archive-A4756MXP914ZB265E92JE3ZMWC_0001.mp4 │ │ ├── split-archive-A4756MXP914ZB265E92JE3ZMWC_0002.json │ │ ├── split-archive-A4756MXP914ZB265E92JE3ZMWC_0002.mp4 │ │ ├── split-archive-A4756MXP914ZB265E92JE3ZMWC_0003.json │ │ ├── split-archive-A4756MXP914ZB265E92JE3ZMWC_0003.mp4 │ │ ├── split-archive-A4756MXP914ZB265E92JE3ZMWC_0004.json │ │ ├── split-archive-A4756MXP914ZB265E92JE3ZMWC_0004.mp4 │ │ ├── archive-A4756MXP914ZB265E92JE3ZMWC.json │ │ ├── archive-A4756MXP914ZB265E92JE3ZMWC.mp4 │ │ └── report-1CS9QJ0XPN4C76HBGBN6MGMK5M.json │ └── CZZ8A8KZB16A1DF5PKERBHGFNR │ ├── split-archive-end-3B7AFF8ZRX6VNEYV40B35Z9S2C.json │ ├── split-archive-3B7AFF8ZRX6VNEYV40B35Z9S2C_0001.json │ ├── split-archive-3B7AFF8ZRX6VNEYV40B35Z9S2C_0001.mp4 │ ├── split-archive-end-DGSN3TC0E91RSCZT5KVPRWCDHR.json │ ├── split-archive-DGSN3TC0E91RSCZT5KVPRWCDHR_0001.json │ ├── split-archive-DGSN3TC0E91RSCZT5KVPRWCDHR_0001.mp4 │ ├── split-archive-DGSN3TC0E91RSCZT5KVPRWCDHR_0002.json │ ├── split-archive-DGSN3TC0E91RSCZT5KVPRWCDHR_0002.mp4 │ ├── archive-3B7AFF8ZRX6VNEYV40B35Z9S2C.json │ ├── archive-3B7AFF8ZRX6VNEYV40B35Z9S2C.mp4 │ ├── archive-DGSN3TC0E91RSCZT5KVPRWCDHR.json │ ├── archive-DGSN3TC0E91RSCZT5KVPRWCDHR.mp4 │ └── report-CZZ8A8KZB16A1DF5PKERBHGFNR.json ``` ### report- 出力される report ファイルは単一と分割が混ざった形式になります。 - トップレベルの start_timestamp- [StartRecording](API_RECORDING.html#c5b527) API を受け付た時刻を RFC 3339 (UTC) で表しています - トップレベルの stop_timestamp- [StopRecording](API_RECORDING.html#fd0de5) API を受け付た時刻か、 [StartRecording](API_RECORDING.html#c5b527) API で設定された期限の時刻を RFC 3339 (UTC) で表しています - archives 内の start_time_offset- [StartRecording](API_RECORDING.html#c5b527) API を叩いてから何秒経過した後にこの録画が開始したかを表しています - archives 内の stop_time_offset- [StartRecording](API_RECORDING.html#c5b527) API を叩いてから何秒経過した後にこの録画が終了したかを表しています ```javascript { "archives": [ { "client_id": "GK2R6PSDYX68VDQPRX4FVVFN8W", "bundle_id": "GK2R6PSDYX68VDQPRX4FVVFN8W", "connection_id": "GK2R6PSDYX68VDQPRX4FVVFN8W", "file_path": "/path/to/sora/archive/WHEJ888HQ55KDCFE3TZ4VPFQHR/archive-GK2R6PSDYX68VDQPRX4FVVFN8W.mp4", "filename": "WHEJ888HQ55KDCFE3TZ4VPFQHR/archive-GK2R6PSDYX68VDQPRX4FVVFN8W.mp4", "metadata_file_path": "/path/to/sora/archive/WHEJ888HQ55KDCFE3TZ4VPFQHR/archive-GK2R6PSDYX68VDQPRX4FVVFN8W.json", "metadata_filename": "WHEJ888HQ55KDCFE3TZ4VPFQHR/archive-GK2R6PSDYX68VDQPRX4FVVFN8W.json", "size": 0, "start_time_offset": 0, "start_timestamp": "2021-03-12T04:42:17.455668Z", "stop_time_offset": 17, "stop_timestamp": "2021-03-12T04:42:34.094375Z", "split_last_index": "0042", "label": "WebRTC SFU Sora", "node_name": "node1@192.0.2.10" } ], "channel_id": "sora", "created_at": 1615524137, "expire_time": 3600, "expired_at": 1615527737, "file_path": "/path/to/sora/archive/WHEJ888HQ55KDCFE3TZ4VPFQHR/report-WHEJ888HQ55KDCFE3TZ4VPFQHR.json", "filename": "WHEJ888HQ55KDCFE3TZ4VPFQHR/report-WHEJ888HQ55KDCFE3TZ4VPFQHR.json", "recording_id": "WHEJ888HQ55KDCFE3TZ4VPFQHR", "label": "WebRTC SFU Sora", "node_name": "node1@192.0.2.10", "split_duration": 3600, "split_only": false, "recording_metadata": {"spam": "egg"}, "start_timestamp": "2021-03-12T04:42:17.455668Z", "stop_timestamp": "2021-03-12T04:42:34.094375Z", "format": "mp4" } ``` ## 録画ファイル出力失敗時の録画一時ファイル 何らかの理由で録画ファイル出力が失敗した場合、 `archive_tmp_dir` で指定したディレクトリに録画一時ファイルが削除されずに残ります。そのため、定期的な削除が必要です。 この録画一時ファイルは WebM または MP4 形式のためそのまま再生できます。 ## シグナリング通知 シグナリング通知で録画開始と終了を通知できます。 詳細は [録画のシグナリング通知](SIGNALING_NOTIFY.html#7ce275) をご確認ください。 ## 録画ファイル合成ツール マルチストリームを録画した場合はそれぞれの接続に対して録画ファイルが出力されます。このそれぞれ分かれた録画ファイルを合成して一つにするツールをオープンソースとして公開しています。 詳細は [WebRTC 録画合成ツール Hisui](HISUI.html) をご確認ください。 ## 録画ファイルアップロードツール 録画ファイルを S3 または S3 互換オブジェクトストレージにアップロードするツールをオープンソースとして公開しています。 詳細は [Sora Archive Uploader](SORA_ARCHIVE_UPLOADER.html) をご確認ください ## 試してみる Sora では録画機能を試すための開発ツールを提供しています。 [開発ツール](DEVTOOLS.html) を参照の上、開発ツールを有効にしてください。 ここでは Sora が立っているサーバーは example.com としています。 ### 録画開始 録画を開始するにはセッションウェブフックで `"recording": true` を払い出すか録画開始 [StartRecording](API_RECORDING.html#c5b527) API を叩く必要があります。 ここでは API を叩いて録画を開始してみましょう。 録画を開始するにはセッションが存在する必要があるため、API を叩く前にクライアントの接続を行い、セッションを作成してください。 ```console $ curl -sS \ -X POST \ http://example.com:3000/ \ -H "x-sora-target: Sora_20231220.StartRecording" \ --json '{"channel_id":"sora"}' \ | jq . ``` その後 `https://example.com/sendonly.html` を開き、 connect ボタンを押して配信を開始します。 切断またはチャネルの録画終了、もしくはチャネルの録画期限が来たタイミングでクライアント単位の録画は終了します。 セッションが破棄されたタイミングで録画は終了します。 ### 録画終了 録画を終了するには全ての参加者が離脱し、セッションが破棄されるか、 API を叩く必要があります。 ここでは API を叩いて録画を終了してみましょう。 ```console $ curl -sS \ -X POST \ http://example.com:3000/ \ -H "x-sora-target: Sora_20231220.StopRecording" \ --json '{"channel_id":"sora"}' \ | jq . ``` その後 archive/ ディレクトリに WebM または MP4 形式のファイルが出力されます。 Chrome または Firefox にドラッグアンドドロップして、動作を確認してください。 ## シーケンス図 ### 録画 API ```mermaid sequenceDiagram autonumber participant C as クライアント participant S as Sora participant A as アプリケーションサーバー note over C,A: 認証成功 S->>+A: セッションウェブフック: "session.created" A-->>-S: 200 OK S->>+C: "type": "offer" C->>-S: "type": "answer" note over C,A: WebRTC 確立 S->>+A: イベントウェブフック: "connection.created" A-->>-S: 200 OK A->>+S: HTTP API StartRecording S-->>-A: 200 OK note over C,A: 録画開始 S->>+A: セッションウェブフック
"type": "recording.started" A-->>-S: 200 OK S->>+A: イベントウェブフック
"type": "archive.started" A-->>-S: 200 OK A->>+S: HTTP API StopRecording S-->>-A: 200 OK note over C,A: 録画終了 S->>+A: イベントウェブフック
"type": "archive.available" A-->>-S: 200 OK S->>+A: セッションウェブフック
"type": "recording.report" A-->>-S: 200 OK ``` ### セッションウェブフック `"recording": true` で録画開始 ```mermaid sequenceDiagram autonumber participant C as クライアント participant S as Sora participant A as アプリケーションサーバー note over C,A: 認証成功 S->>+A: セッションウェブフック: "session.created" A-->>-S: 200 OK
"recording": true note over C,A: 録画開始 S->>+A: セッションウェブフック
"type": "recording.started" A-->>-S: 200 OK S->>+C: "type": "offer" C->>-S: "type": "answer" note over C,A: WebRTC 確立 S->>+A: イベントウェブフック: "connection.created" A-->>-S: 200 OK S->>+A: イベントウェブフック
"type": "archive.started" A-->>-S: 200 OK ``` ### 録画期限切れ ```mermaid sequenceDiagram autonumber participant C as クライアント participant S as Sora participant A as アプリケーションサーバー note over C,A: 認証成功 S->>+A: セッションウェブフック: "session.created" A-->>-S: 200 OK
"recording": true,
"recording_expire_time": 3600 note over C,A: 録画開始 S->>+A: セッションウェブフック
"type": "recording.started" A-->>-S: 200 OK S->>+C: "type": "offer" C->>-S: "type": "answer" note over C,A: WebRTC 確立 S->>+A: イベントウェブフック: "connection.created" A-->>-S: 200 OK S->>+A: イベントウェブフック
"type": "archive.started" A-->>-S: 200 OK note over C,A: 期限切れにより録画終了 S->>+A: イベントウェブフック
"type": "archive.available" A-->>-S: 200 OK S->>+A: セッションウェブフック
"type": "recording.report" A-->>-S: 200 OK ``` ### クライアント切断 ```mermaid sequenceDiagram autonumber participant C as クライアント participant S as Sora participant A as アプリケーションサーバー note over C,A: 認証成功 S->>+A: セッションウェブフック: "session.created" A-->>-S: 200 OK
"recording": true note over C,A: 録画開始 S->>+A: セッションウェブフック
"type": "recording.started" A-->>-S: 200 OK S->>+C: "type": "offer" C->>-S: "type": "answer" note over C,A: WebRTC 確立 S->>+A: イベントウェブフック: "connection.created" A-->>-S: 200 OK S->>+A: イベントウェブフック
"type": "archive.started" A-->>-S: 200 OK C->>S: "type": "disconnect" S->>+A: イベントウェブフック
"type" :"connection.destroyed" A-->-S: 200 OK S->>C: WebSocket Close note over C,A: クライアント切断に伴いクライアントの録画終了 S->>+A: イベントウェブフック
"type": "archive.available" A-->>-S: 200 OK ``` ### セッション破棄 ```mermaid sequenceDiagram autonumber participant C as クライアント participant S as Sora participant A as アプリケーションサーバー note over C,A: 認証成功 note over C,A: セッション生成 S->>+A: セッションウェブフック: "session.created" A-->>-S: 200 OK
"recording": true note over C,A: 録画開始 S->>+A: セッションウェブフック
"type": "recording.started" A-->>-S: 200 OK S->>+C: "type": "offer" C->>-S: "type": "answer" note over C,A: WebRTC 確立 S->>+A: イベントウェブフック: "connection.created" A-->>-S: 200 OK S->>+A: イベントウェブフック
"type": "archive.started" A-->>-S: 200 OK C->>S: "type": "disconnect" S->>+A: イベントウェブフック
"type" :"connection.destroyed" A-->-S: 200 OK S->>C: WebSocket Close note over C,A: クライアント切断に伴いクライアントの録画終了 S->>+A: イベントウェブフック
"type": "archive.available" A-->>-S: 200 OK note over C,A: セッション破棄 S->>+A: セッションウェブフック: "session.destroyed" A-->>-S: 200 OK note over C,A: セッション破棄に伴いセッションの録画終了 S->>+A: セッションウェブフック: "recording.report" A-->>-S: 200 OK ``` # リアルタイムメッセージング機能 ## 概要 リアルタイムメッセージング機能は DataChannel の互換性を維持しつつ、 超低遅延で同じチャネル参加者へメッセージを送る仕組みです。 ## 注意 - リアルタイムメッセージング機能を利用するためには、 `data_channel_signaling` が有効になっている必要があります - リアルタイムメッセージング機能は DataChannel プロトコル互換性を維持しつつ Sora 独自の仕組みを追加しています ## 制限 ### メッセージサイズ制限 > **注意** > > 1 回のメッセージで送れる値には制限がありますのでご注意ください。 詳しくは DataChannel シグナリングの [推奨メッセージサイズ](DATA_CHANNEL_SIGNALING.html#2b27d3) をご確認ください ## SDK 対応状況 - 最新版の JavaScript SDK- 対応済みです - 最新版の iOS SDK- 対応済みです - 最新版の Android SDK- 対応済みです - 最新版の Unity SDK- 対応済みです - 最新版の C++ SDK- 対応済みです - 最新版の Python SDK- 対応済みです ## DataChannel を利用したリアルタイムメッセージング機能を有効にする DataChannel を利用したリアルタイムメッセージングを利用する場合、 DataChannel シグナリングが有効になっている必要があります。 その上で `sora.conf` にて [data_channel_messaging](SORA_CONF.html#1d5746) を `true` に指定してください。 利用する場合は `"type": "connect"` 時に `data_channels` を指定してください。 ## リアルタイムメッセージング用 DataChannel の作成 > **重要** > > DataChannel を利用したリアルタイムメッセージングを利用する場合は、DataChannel シグナリングが有効になっている必要があります Sora では、Sora がシグナリングで使用する DataChannel 以外にも、リアルタイムメッセージング用の DataChannel を作成できます。 利用する場合は `"type": "connect"` 時に定義するか、認証成功時の払い出しで定義する必要があります。 Sora のリアルタイムメッセージング用 DataChannel は、DataChannel の属性である `label` を定義する際に `#` から始める必要があります。 ## data_channels 仕様 > **重要** > > メッセージは **送信者以外** の同一 `label` 、かつ、 `direction` が `sendrecv` > または `recvonly` のクライアントに送信されます。 ### label メッセージのラベルを指定します。先頭に `#` が付いている必要があります。 - `label` は `#` を含めて 32 文字まで指定できます - `label` には小文字大文字のアルファベットと `-` (ハイフン) しか利用できません- `#` の次の文字に `-` は指定できません - `^#[a-zA-Z0-9][a-zA-Z0-9-]{1,30}$` - 1 接続においてラベルは最大で 1024 まで指定できます ### compress メッセージを zlib にて圧縮するかどうかを指定します。 - `compress` が `true` の場合、圧縮/展開に `zlib.deflate` を利用します- 圧縮方式を変更することはできません ### direction メッセージの方向を指定します。 - `direction` には `sendrecv` / `sendonly` / `recvonly` が設定できます- `sendrecv` 時に **自分が送ったメッセージ** は自分には送られてきません クライアントからみた方向になります。 - `sendrecv` が設定されたラベルは送受信で利用できます - `sendonly` が設定されたラベルは送信のみが利用できます - `recvonly` が設定されたラベルは受信のみが利用できます ### ordered 順序保証を行うかどうか指定します。デフォルトでは `true` に設定され、順序保証を行います。 ### max_retransmits > **注意** > > max_retransmits と max_packet_life_time はどちらかしか指定できません。 最大再送回数を指定します。デフォルトでは未指定で、無制限に再送します。 ### max_packet_life_time > **注意** > > max_retransmits と max_packet_life_time はどちらかしか指定できません。 最大再送時間をミリ秒で指定します。デフォルトでは未指定で、無制限に再送します。 ### header メッセージングにヘッダーを追加します。ヘッダーは Sora 側で付与します。 - `header` は `direction` が `sendrecv` または `recvonly` の場合に指定できます - `header` を指定したメッセージの受信者にヘッダーが付与されるようになります - `header` はオプションです - `header` のデフォルトは `[]` です - `header` には `{"type": "sender_connection_id"}` を指定できます- `sender_connection_id` はメッセージングの送信元の `connection_id` です - 先頭 26 バイトが `sender_connection_id` になります - クライアントから Sora が受信するメッセージ- `[message (variable length)]` - Sora から `header` を指定したクライアントへ送信するメッセージ- `[sender_connection_id (26 bytes)][message (variable length)]` ```javascript "data_channels": [ { "label": "#spam", "max_packet_life_time": 5000, "ordered": true, "protocol": "efg", "compress": false, "direction": "recvonly", "header": [{"type": "sender_connection_id"}] }, { "label": "#egg", "max_retransmits": 0, "ordered": false, "protocol": "abc", "compress": false, "direction": "recvonly" } ] ``` ### JavaScript SDK 利用時の注意 - `max_retransmits` は `maxRetransmits` に変更してください - `max_packet_life_time` は `maxPacketLifeTime` に変更してください ## "type": "connect" 時の "data_channels" > **注釈** > > protocol は特に指定する必要はありません。 * - 項目名 - 型 - 必須 / オプション - デフォルト - 備考 * - label - string - 必須 - - ^#[a-zA-Z0-9][a-zA-Z0-9-]{1,30}$ * - direction - string - 必須 - - "sendrecv" / "sendonly" / "recvonly" * - ordered - boolean - オプション - true - * - max_packet_life_time - integer - オプション - 未指定 - * - max_retransmits - integer - オプション - 未指定 - * - protocol - string - オプション - "" - * - compress - boolean - オプション - false - * - header - array[object] - オプション - [] - "sender_connection_id" > **注意** > > Sora JS SDK や Sora DevTools で `max_packet_life_time` と `max_retransmits` を指定する場合は > `maxPacketLifeTime` と `maxRetransmits` となります。 ```javascript { "type": "connect", "data_channels": [ { "label": "#spam", "max_packet_life_time": 5000, "ordered": true, "protocol": "efg", "compress": false, "direction": "recvonly", "header": [{"type": "sender_connection_id"}] }, { "label": "#egg", "max_retransmits": 0, "ordered": false, "protocol": "abc", "compress": false, "direction": "recvonly" } ] } ``` ## 認証成功時の戻り値 認証ウェブフックの認証成功時に `data_channels` を指定できます。 ```javascript { "allowed": true, "data_channels": [ { "label": "#spam", "max_packet_life_time": 5000, "ordered": true, "protocol": "efg", "compress": false, "direction": "recvonly", "header": [{"type": "sender_connection_id"}] }, { "label": "#egg", "max_retransmits": 0, "ordered": false, "protocol": "abc", "compress": false, "direction": "recvonly" } ] } ``` ## "type": "offer" 時の "data_channels" > **注釈** > > Sora SDK を利用する場合はこれを意識する必要はありません。 接続時か認証成功時に指定された `data_channels` は `{"type": "offer"}` に含まれます。 ```javascript { "type": "offer", "data_channels": [ { "label": "signaling", "ordered": true, "protocol": "signaling", "compress": true, "direction": "sendrecv" }, { "label": "notify", "ordered": true, "protocol": "notify", "compress": true, "direction": "recvonly" }, { "label": "push", "ordered": true, "protocol": "push", "compress": true, "direction": "recvonly" }, { "label": "stats", "ordered": true, "max_retransmits": 1, "protocol": "stats", "compress": true, "direction": "sendrecv" }, { "label": "rpc", "ordered": true, "protocol": "rpc", "compress": true, "direction": "sendrecv" }, { "label": "#spam", "max_packet_life_time": 5000, "ordered": true, "protocol": "efg", "compress": false, "direction": "recvonly", // header の長さが type: offer 時の data_channels には含まれるようになります "header": [{"type": "sender_connection_id", "length": 26}] }, { "label": "#egg", "max_retransmits": 0, "ordered": false, "protocol": "abc", "compress": false, "direction": "recvonly" } ] } ``` ## DataChannel を利用したメッセージングのみで接続する DataChannel を利用したメッセージングのみを有効にするには以下を満たす必要があります。 > **注釈** > > role は sendrecv / sendonly / recvonly のどれでも問題ありませんが、 sendrecv / recvonly の場合、相手から送られてきた音声や映像を受信しますので、sendonly で接続することをお勧めします。 - `sora.conf` の [default_data_channel_signaling](SORA_CONF.html#adceef) を `true` にする - `sora.conf` の [data_channel_messaging_only](SORA_CONF.html#93c61c) を `true` にする - `sora.conf` の [data_channel_messaging](SORA_CONF.html#1d5746) を `true` にする - `"type": "connect"` 時に `audio` を `false` にする- 認証成功時の払い出しでも可 - `"type": "connect"` 時に `video` を `false` にする- 認証成功時の払い出しでも可 - `"type": "connect"` 時に `data_channels` を指定する- 認証成功時の払い出しでも可 - `"type": "connect"` 時に `data_channel_signaling` を `true` にする- 認証成功時の払い出しでも可 これで **音声や映像を送らず** DataChannel を利用したメッセージングのみを利用できるようになります。 ## シーケンス図 ### シンプル 1. クライアント 1 が `label`: `spam`, `direction`: `sendrecv` と、`label`: `#egg`, `direction`: `sendonly` でメッセージング利用開始```javascript { "type": "connect", "data_channels": [ {"label": "#spam", "direction": "sendrecv"}, {"label": "#egg": "direction": "sendonly"} ] } ``` 2. クライアント 2 が `label`: `#spam`, `direction`: `recvonly` でメッセージング利用開始```javascript { "type": "connect", "data_channels": [ {"label": "#spam", "direction": "recvonly"} ] } ``` 3. クライアント 1 が `label`: `#spam` へメッセージ `"abc"` を送信 4. クライアント 2 が Sora から `label`: `#spam` へのメッセージ `"abc"` を受信 5. クライアント 1 が `label`: `#egg` へメッセージ `"xyz"` を送信- 誰も受け取る人がいない 6. クライアント 3 が `label`: `#spam`, `direction`: `sendrecv` でメッセージング利用開始```javascript { "type": "connect", "data_channels": [ {"label": "#spam", "direction": "sendrecv"} ] } ``` 7. クライアント 1 が Sora へ `label`: `#spam` のメッセージ `"123"` を送信 8. クライアント 2 が Sora から `label`: `#spam` のメッセージ `"123"` を受信 9. クライアント 3 が Sora から `label`: `#spam` のメッセージ `"123"` を受信 ```mermaid sequenceDiagram autonumber participant C1 as クライアント1 participant C2 as クライアント2 participant C3 as クライアント3 participant S as Sora C1->>S: "type": "connect" note over C1,S: クライアント1 WebRTC 確立 C2->>S: "type": "connect" note over C2,S: クライアント2 WebRTC 確立 C1-)S: label: #35;spam "abc" send S-)C2: label: #35;spam "abc" send C3->>S: "type": "connect" note over C3,S: クライアント3 WebRTC 確立 C1-)S: label: #35;spam "xyz" send S-)C2: label: #35;spam "xyz" send S-)C3: label: #35;spam "xyz" send ``` # ICE コネクションステート機能 ## 概要 ICE コネクションステート機能は Sora に ICE コネクションによる状態管理を持たせた機能です。 ## 前提 この機能はクライアント側が意識する必要はありません。 ## 挙動 Sora は WebRTC が確立した後に TURN 上で ICE コネクションステートを更新し続けます。 ステートの更新には `STUN Binding-Request` と `STUN Binding-Success` を利用します。 - Sora は 2.5 秒間隔で `STUN Binding-Request` をクライアントへ送ります- `STUN Binding-Success` が 2.5 秒以内に一度も返ってこない場合、状態を `connected` から `checking` へ遷移します - 状態が `checking` へ遷移した場合、 Sora は 1 秒間隔で `STUN Binding-Request` をクライアントへ送ります- `STUN Binding-Success` が 5 秒以内に一度も返ってこない場合、状態を `checking` から `disconnected` へ遷移します - この 5 秒は `sora.conf` にて [default_ice_connection_state_disconnected_timeout](SORA_CONF.html#420a1e) で変更できます - さらに認証ウェブフック成功時の [ice_connection_state_disconnected_timeout_ms の払い出し](AUTH_WEBHOOK_RETURN.html#38a86f) で上書きできます - 状態が `disconnected` に遷移した場合、 Sora は 50 ミリ秒間隔で `STUN Binding-Request` をクライアントへ送ります- `STUN Binding-Success` が 10 秒以内に一度も返ってこない場合、状態を `disconnected` から `failed` へ遷移します - この 10 秒は `sora.conf` にて [default_ice_connection_state_failed_timeout](SORA_CONF.html#d6f965) で変更できます - さらに認証ウェブフック成功時の [ice_connection_state_failed_timeout_ms の払い出し](AUTH_WEBHOOK_RETURN.html#1f5eb9) で上書きできます - このタイミングで `sora.jsonl` に `warning` として `ICE-CONNECTION-STATE-DISCONNECTED` が出力されます - 状態が `failed` に遷移した場合、Sora はクライアントの接続を切断します- このタイミングで `sora.jsonl` に `error` として `ICE-CONNECTION-STATE-FAILED` が出力されます ## 設定 ICE コネクションステート機能は無効にすることはできません。 ただし、切断や失敗までの判定時間を `sora.conf` にてデフォルト値から変更できます。 ### default_ice_connection_state_disconnected_timeout この値は Sora が ICE コネクションステートを disconnected へと遷移する際にクライアントからの応答を待つ時間です。 デフォルトでは `5 s` が設定されています。 詳細は [default_ice_connection_state_disconnected_timeout](SORA_CONF.html#420a1e) をご確認ください。 ### default_ice_connection_state_failed_timeout この値は Sora が ICE コネクションステートを failed へと遷移する際にクライアントからの応答を待つ時間です。 デフォルトでは `10 s` が設定されています。 詳細は [default_ice_connection_state_failed_timeout](SORA_CONF.html#d6f965) をご確認ください。 ## シグナリング通知 > **警告** > > この機能は実験的機能です。 シグナリング通知経由で、それぞれのクライアントの ICE コネクションステートの変更を送信する機能です。 この機能を有効にするには `sora.conf` の [signaling_notify_ice_connection_state](SORA_CONF.html#e65192) を `true` に設定してください。 機能を有効にした場合、ICE コネクションの状態変更時に、自分を含むチャネル参加者全員に対して、 シグナリング通知 `ice-connection-state.changed` が送信されるようになります。 さらに `connection.created` の `data` に `ice_connection_state` が含まれるようになり、 既にチャネルに参加しているクライアントの `ice_connection_state` を取得できるようになります。 ### 認証成功時の `signaling_notify_ice_connection_state` の払い出し シグナリング通知 `ice-connection-state.changed` を送信するかどうかは、 [signaling_notify_ice_connection_state](SORA_CONF.html#e65192) の値が採用されますが、 認証成功時の払い出しに `signaling_notify_ice_connection_state` を指定することで変更できます。 > **注釈** > > [signaling_notify_ice_connection_state](SORA_CONF.html#e65192) を `false` に設定したとしても、 > 認証成功時の払い出しに `signaling_notify_ice_connection_state` を `true` で指定した場合は、 > シグナリング通知 `ice-connection-state.changed` が送信されます。 ### シグナリング通知 `ice-connection-state.changed` 自分が接続した時は `connection.created` のシグナリング通知の後に、 シグナリング通知 `ice-connection-state.changed` が送信されます。 以下の 4 つのタイミングで通知がチャネルに参加している他のコネクションへ送信されます。 1. connected から checking になった時- `ice-connection-state.changed` で `current_state` に `checking` 、 `previous_state` に `connected` が入ります 2. checking から connected になった時- `ice-connection-state.changed` で `current_state` に `connected` 、 `previous_state` に `checking` が入ります 3. checking から disconnected になった時- `ice-connection-state.changed` で `current_state` に `disconnected` 、 `previous_state` に `checking` が入ります 4. disconnected から checking になった時- `ice-connection-state.changed` で `current_state` に `checking` 、 `previous_state` に `disconnected` が入ります ```javascript { "connection_id": "JA0H99CB490C9EEV8AAVBNSBWG", "timestamp": "2024-10-15T01:04:50.039752Z", "type": "notify", "event_type": "ice-connection-state.changed", "current_state": "connected", "previous_state": "checking" } ``` ### `connection.created` の `data` の `ice_connection_state` シグナリング通知 `connection.created` の `data` に `ice_connection_state` が含まれるようにするには、 `sora.conf` の [signaling_notify_ice_connection_state](SORA_CONF.html#e65192) を `true` に設定する必要があります。 ```javascript { // 色々省略 "connection_id": "ZE6QPYMF1N4473AN1AH5KY6T3C", "data": [ { "connection_id": "JA0H99CB490C9EEV8AAVBNSBWG", "timestamp": "2024-10-15T01:04:50.036927Z", "bundle_id": "JA0H99CB490C9EEV8AAVBNSBWG", "client_id": "JA0H99CB490C9EEV8AAVBNSBWG", // 既存参加者の ice_connection_state が含まれる "ice_connection_state": "connected" } ], "timestamp": "2024-10-15T01:05:17.317571Z", "type": "notify", "session_id": "HC3DTTQH1946DC9HYKAE2AAHS8", "role": "sendrecv", "event_type": "connection.created", } ``` ## 認証成功時の払い出し Sora は、認証成功時のタイミングで `ice_connection_state_disconnected_timeout_ms` と `ice_connection_state_failed_timeout_ms` を認証サーバーから払い出すことができます。 ### ice_connection_state_disconnected_timeout_ms の払い出し ice_connection_state_disconnected_timeout_ms の値は `sora.conf` の [default_ice_connection_state_disconnected_timeout](SORA_CONF.html#420a1e) の値を上書きします。 ```javascript { "allowed": true, "ice_connection_state_disconnected_timeout_ms": 10000, } ``` ### ice_connection_state_failed_timeout_ms の払い出し ice_connection_state_failed_timeout_ms の値は `sora.conf` の [default_ice_connection_state_failed_timeout](SORA_CONF.html#d6f965) の値を上書きします。 ```javascript { "allowed": true, "ice_connection_state_failed_timeout_ms": 20000, } ``` ## ウェブフック コネクションの状態が `checking` と `disconnected` だった合計時間をイベントウェブフックで取得できます。 - 取得可能なイベントウェブフック- `connection.created` - `connection.updated` - `connection.destroyed` - `data.ice_connection_state.total_checking_duration_ms` に `checking` だった合計時間(ミリ秒)の合計が入ります - `data.ice_connection_state.total_disconnected_duration_ms` に `disconnected` だった合計時間(ミリ秒)の合計が入ります ```javascript { // 色々省略してます "type": "connection.destroyed", "channel_id": "sora", "connection_id": "GS4Q8PQ5PS3EXC30T6PM2R7Y20", "timestamp": "2023-08-16T05:42:13.970729Z", "bundle_id": "GS4Q8PQ5PS3EXC30T6PM2R7Y20", "client_id": "GS4Q8PQ5PS3EXC30T6PM2R7Y20", "data": { "ice_connection_state": { "total_checking_duration_ms": 5002, "total_disconnected_duration_ms": 10002 } } } ``` ## テスト ICE コネクションステートのテストをしたい場合は [LockIceConnectionState](TEST_API.html#8b5622) API を利用してください。 ## ステート図 > **重要** > > 図のタイムアウト値はデフォルト値を採用しています。 ```mermaid stateDiagram New --> Checking Checking --> Connected: 応答あり Checking --> Disconnected: 5 秒間応答なし Disconnected --> Failed: 10 秒間応答なし Connected --> Checking: 2.5 秒応答なし Disconnected --> Checking: 応答あり Connected --> Closed: 正常終了 ``` ## シーケンス図 > **重要** > > 図のタイムアウト値はデフォルト値を採用しています。 ### connected 正常な接続状態である connected を継続しているシーケンス図です。 ```mermaid sequenceDiagram participant C as クライアント participant S as Sora note over C,S: WebRTC 確立 note over S: ICE State connected S->>+C: STUN Binding-Request C-->>-S: STUN Binding-Success note left of S: 2.5 秒経過 S->>+C: STUN Binding-Request C-->>-S: STUN Binding-Success note left of S: 2.5 秒経過 S->>+C: STUN Binding-Request C-->>-S: STUN Binding-Success ``` ### connected -> checking 正常な接続状態である connected から一時的に反応が無く checking 状態へ切り替わるシーケンス図です。 ```mermaid sequenceDiagram participant C as クライアント participant S as Sora note over C,S: WebRTC 確立 note over S: ICE State connected S->>C: STUN Binding-Request note left of S: 2.5 秒経過したが反応がない note over S: ICE State checking S->>C: STUN Binding-Request note left of S: 1.0 秒経過 S->>C: STUN Binding-Request note left of S: 1.0 秒経過 S->>C: STUN Binding-Request ``` ### checking -> disconnected 一時的に反応が無い checking の状態が続いたため、 切断判断をするために短い間隔で疎通パケットを送信する disconnected 状態へ切り替わるシーケンス図です。 ```mermaid sequenceDiagram participant C as クライアント participant S as Sora note over C,S: WebRTC 確立 note over S: ICE State connected S->>C: STUN Binding-Request note left of S: 2.5 秒経過したが反応がない note over S: ICE State checking S->>C: STUN Binding-Request note left of S: 1.0 秒間隔で 5 秒間送り続けてるが反応がない note over S: ICE State disconnected S->>C: STUN Binding-Request note left of S: 50 ミリ秒 S->>C: STUN Binding-Request ``` ### disconnected -> failed 切断判断をするため短い間隔で疎通パケットを送り続けたが、反応が無かったため failed へと切り替わるシーケンス図です。 ```mermaid sequenceDiagram participant C as クライアント participant S as Sora note over C,S: WebRTC 確立 note over S: ICE State connected S->>C: STUN Binding-Request note left of S: 2.5 秒経過したが反応がない note over S: ICE State checking S->>C: STUN Binding-Request note left of S: 1 秒間隔で 5 秒間送り続けてるが反応がない note over S: ICE State disconnected S->>C: STUN Binding-Request note left of S: 50 ミリ秒間隔で 10 秒間送り続けてるが反応がない note over S: ICE State failed note left of S: S はクライアントを切断したと見なし切断処理を行う ``` ### disconnected -> checking -> connected 一定時間、不通になっていたため状態が disconnected になっていましたが、 checking を経て connected まで状態が戻るシーケンス図です。 ```mermaid sequenceDiagram participant C as クライアント participant S as Sora note over C,S: WebRTC 確立 note over S: ICE State connected S->>C: STUN Binding-Request note left of S: 2.5 秒経過したが反応がない note over S: ICE State checking S->>C: STUN Binding-Request note left of S: 1 秒間隔で 5 秒間送り続けてるが反応がない note over S: ICE State disconnected S->>C: STUN Binding-Request note left of S: 50 ミリ秒間隔で 10 秒間送り続ける C-->>S: STUN Binding-Success note over S: ICE State checking S->>C: STUN Binding-Request note left of S: 1 秒間隔で 5 秒間送り続ける C-->>S: STUN Binding-Success note over S: ICE State connected S->>C: STUN Binding-Request note left of S: 2.5 秒間隔で送り続ける C-->>S: STUN Binding-Success ``` # モード機能 ## 概要 モード機能 は、指定されているモードごとに Sora の挙動を変更する機能です。 ## 目的 Sora 自体は認証の機能を持っていないため、メンテナンス時に一時的に接続をブロックするといった仕組みがありません。 接続をブロックする場合は、認証サーバー側で処理をすることになり不便でした。 そこで、Sora 側にモード機能を持たせることで、モードを切り替えることで接続を気軽にブロックできる機能を追加します。 ## モード ### ノーマルモード このモードは何もせず、すべての新規接続を受け入れます。 ### 新規コネクションブロックモード このモードは新規の接続をブロックします。すでに接続しているコネクションはそのままです。 ### 新規セッションブロックモード このモードは新規セッションの作成をブロックします。すでに接続しているセッションやコネクションはそのままです。 そのためセッション(チャネルに 1 人以上接続しているアクティブな状態)が存在する場合は接続できますが、セッションが存在しない場合は新規の接続をブロックします。 ## API ### ChangeMode API モード変更 API です。指定するモードには 3 種類あります。 - normal - block_new_session - block_new_connection ```console $ curl -sS \ -X POST \ http://127.0.0.1:3000 \ -H "x-sora-target: Sora_20211215.ChangeMode" \ --json '{"mode":"block_new_session"}' \ | jq . { "mode": "block_new_session" } ``` ```console $ curl -sS \ -X POST \ http://127.0.0.1:3000 \ -H "x-sora-target: Sora_20211215.ChangeMode" \ --json '{"mode":"block_new_connection"}' \ | jq . { "mode": "block_new_connection" } ``` 詳細は [ChangeMode](API_MODE.html#3af05f) をご確認ください。 ### GetMode API モード取得 API です。 ```console $ curl -sS \ -X POST \ http://127.0.0.1:3000 \ -H "x-sora-target: Sora_20211215.GetMode" \ | jq . { "mode": "normal" } ``` 詳細は [GetMode](API_MODE.html#c0c2e7) をご確認ください。 ## クラスター機能 ### チャネル ID のノード割り当て クラスター機能を利用した場合、 `mode` が [新規セッションブロックモード](MODE.html#041e1c) または [新規コネクションブロックモード](MODE.html#0b67d3) のノードに対して、 新規のチャネル ID を割り当てません。 ## シーケンス図 ### block_new_connection ```mermaid sequenceDiagram participant C1 as クライアント1 participant C2 as クライアント2 participant S as Sora participant A as アプリケーションサーバー note over S: Sora 起動 note over S: モード: normal C1->>S: "type": "connect" note over C1,S: クライアント1 WebRTC 確立 A->>S: ChangeMode API
mode=block_new_connection note over S: モード: block_new_connection break 接続失敗 C2->>S: "type": "connect" end A->>S: ChangeMode API
mode=normal note over S: モード: normal C2->>S: "type": "connect" note over C2,S: クライアント2 WebRTC 確立 ``` ### block_new_session ```mermaid sequenceDiagram participant C1 as クライアント1 participant C2 as クライアント2 participant C3 as クライアント3 participant S as Sora participant A as アプリケーションサーバー note over S: Sora 起動 note over S: モード: normal C1->>S: "type": "connect"
channel_id=spam note over C1,S: クライアント1 WebRTC 確立 A->>S: ChangeMode API
mode=block_new_session note over S: モード: block_new_session break 接続失敗 C2->>S: "type": "connect"
channel_id=ham end C3->>S: "type": "connect"
channel_id=spam note over C3,S: クライアント3 WebRTC 確立 ``` # ヘルスチェック機能 ## 概要 Sora にはヘルスチェック機能を搭載しています。 URL は固定で `/.ok` で、ポート番号はシグナリングに利用するポートでデフォルトは 5000 番です。 ポート番号を変更する場合は `sora.conf` の [signaling_port](SORA_CONF.html#4a4f57) を変更してください。 ## 確認 ```console $ curl \ http://192.0.2.1:5000/.ok ``` ## 単体利用時 問題が無ければ `200 OK` が返ります。 ## クラスター利用時 ### 200 - 問題が無ければ `200 OK` が返ります - ローリングアップデート時にアップデートに成功しクラスターへの参加が成功してれば `200 OK` が返ります ### 503 - ノードがクラスターに参加していない場合 `503 Service Unavailable` が返ります - `block_new_connection` モード時に `503 Service Unavailable` が返ります # RPC 機能 *バージョン 2025.2.0 で追加。* > **警告** > > この機能は [実験的機能](EXPERIMENTAL.html) のため、正式版では仕様が変更される可能性があります ## 概要 Sora では、 [DataChannel 経由のシグナリング](DATA_CHANNEL_SIGNALING.html) 利用時に、 JSON-RPC 2.0 over DataChannel で一部の HTTP API をクライアントから直接呼び出すことができます。 この RPC 機能を利用することで、アプリケーションサーバー経由で Sora の HTTP API を呼び出す場合と比べて、より低遅延に同等の操作を行えます。 ## RPC 機能を利用する条件 - `sora.conf` で [data_channel_rpc](SORA_CONF.html#26f332) が `true` に設定されていること - コネクションが [DataChannel 経由のシグナリング](DATA_CHANNEL_SIGNALING.html) を利用していること - 認証成功時に [rpc_methods の払い出し](AUTH_WEBHOOK_RETURN.html#a2e307) で利用できる RPC メソッド名一覧が払い出されていること ## JSON-RPC 2.0 仕様 - JSON-RPC 2.0 の仕様に準拠しています - `method` には HTTP API で指定するヘッダー名とは異なる形式で指定する必要があります- `2025.2.0/RequestSimulcastRid` のように `{RPC 経由での HTTP API の呼出が導入された Sora のバージョン}/{HTTP API 名}` の形式で指定します - `params` には HTTP API 利用時の JSON を指定します- `params` に不要な項目が含まれている場合はエラーになります - `channel_id` と `connection_id` は Sora 側で現在接続しているコネクションの値を利用するため指定不要です - `receiver_connection_id` も同様に Sora 側で現在接続しているコネクションの値を利用するため指定不要です - `id` を付けないことでレスポンスを返さない `Notification` として利用できます- これは Sora 側がレスポンスを返さないことを意味します ### RPC の型定義 ```typescript // @ts-check /* data_channel_rpc = true の場合に送信される RPC の型定義 JSON-RPC 2.0 準拠 https://www.jsonrpc.org/specification DataChannel シグナリング label: "rpc" */ // 2025.2.0 以降で利用可能な RPC メソッド type rpcMethod = | "2025.2.0/RequestSimulcastRid" | "2025.2.0/RequestSpotlightRid" | "2025.2.0/ResetSpotlightRid" | "2025.2.0/PutSignalingNotifyMetadata" | "2025.2.0/PutSignalingNotifyMetadataItem"; type JSONRPCRequest = { jsonrpc: "2.0"; // null 非推奨 id?: number | string; method: rpcMethod; params?: Record | unknown[]; }; type JSONRPCSuccess = { jsonrpc: "2.0"; id: number | string; result: unknown; }; // 予約済みエラーコード type JSONRPCErrorCode = // JSON パースエラー | -32700 // 不正なリクエスト | -32600 // メソッドが見つからない | -32601 // 不正なパラメータ | -32602 // 内部エラー | -32603 // -32000 ~ -32099: サーバーエラー、その他: アプリケーション定義 | number; type JSONRPCError = { jsonrpc: "2.0"; id: number | string | null; error: { code: number; message: string; data?: unknown; }; }; ``` ## メソッド一覧 > **注釈** > > method は `{RPC 経由での HTTP API の呼出が導入された Sora のバージョン}/{HTTP API 名}` という形式になります。 ### 2025.2.0/RequestSimulcastRid [RequestSimulcastRid](API_SIMULCAST.html#7d26ab) API ```javascript { "jsonrpc": "2.0", "method": "2025.2.0/RequestSimulcastRid", "params": { "sender_connection_id": "example_sender_connection_id", "rid": "r1" }, "id": 1 } ``` `channel_id` と `receiver_connection_id` は Sora 側で設定するため指定不要です。また `sender_connection_id` はオプションです。 このメソッドを利用するには認証時の払い出しで `simulcast` と `simulcast_rpc_rids` を指定する必要があります。 RPC 経由で切り替えられる `rid` を `simulcast_rpc_rids` で指定してください。 ```javascript { "allowed": true, "simulcast": true, "simulcast_rpc_rids": ["none", "r0", "r1"], "rpc_methods": [ "2025.2.0/RequestSimulcastRid" ] } ``` ### 2025.2.0/RequestSpotlightRid [RequestSpotlightRid](API_SPOTLIGHT.html#5c2650) API ```javascript { "jsonrpc": "2.0", "method": "2025.2.0/RequestSpotlightRid", "params": { "send_connection_id": "example_send_connection_id", "spotlight_focus_rid": "r1", "spotlight_unfocus_rid": "none" }, "id": 1 } ``` `channel_id` と `recv_connection_id` は Sora 側で設定するため指定不要です。また `send_connection_id` はオプションです。 ### 2025.2.0/ResetSpotlightRid [ResetSpotlightRid](API_SPOTLIGHT.html#680344) API ```javascript { "jsonrpc": "2.0", "method": "2025.2.0/ResetSpotlightRid", "params": { "send_connection_id": "example_send_connection_id" }, "id": 1 } ``` `channel_id` と `recv_connection_id` は Sora 側で設定するため指定不要です。また `send_connection_id` はオプションです。 ### 2025.2.0/PutSignalingNotifyMetadata [PutSignalingNotifyMetadata](API_SIGNALING_NOTIFY_METADATA_EXT.html#a20c95) API ```javascript { "jsonrpc": "2.0", "method": "2025.2.0/PutSignalingNotifyMetadata", "params": { "push": true, "metadata": { "example_key_1": "example_value_1", "example_key_2": "example_value_2" } }, "id": 1 } ``` `channel_id` と `connection_id` は Sora 側で設定するため指定不要です。また、 `push` はオプションです。 ### 2025.2.0/PutSignalingNotifyMetadataItem [PutSignalingNotifyMetadataItem](API_SIGNALING_NOTIFY_METADATA_EXT.html#387c9c) API ```javascript { "jsonrpc": "2.0", "method": "2025.2.0/PutSignalingNotifyMetadataItem", "params": { "push": true, "key": "example_key", "value": "example_value" }, "id": 1 } ``` `channel_id` と `connection_id` は Sora 側で設定するため指定不要です。また、 `push` はオプションです。 ## 利用できる RPC の指定 この機能を利用するには認証時の払い出しで RPC 機能で利用できるメソッド一覧を指定する必要があります。 ```javascript { "allowed": true, "rpc_methods": [ "2025.2.0/RequestSpotlightRid", "2025.2.0/ResetSpotlightRid" ] } ``` ## "type": "offer" シグナリングメッセージでの確認 クライアントから利用できる RPC メソッド一覧は `"type": "offer"` のシグナリングメッセージの `rpc_methods` で確認することができます。 ```javascript { "type": "offer", "rpc_methods": [ "2025.2.0/RequestSpotlightRid", "2025.2.0/ResetSpotlightRid" ] } ``` ## シーケンス図 ```mermaid sequenceDiagram participant C1 as Client1 participant C2 as Client2 participant S as Sora note over C1,S: C1, C2 共に WebRTC 確立済み C1 ->> S: JSON-RPC 2.0 Request
PutSignalingNotifyMetadataItem
push: true
over DataChannel note over S: シグナリング通知メタデータ拡張に項目を追加 S ->> C1: JSON-RPC 2.0 Success Response
over DataChannel note over S: シグナリング通知メタデータ拡張によるプッシュ通知が発生 S ->> C1: type: push
over DataChannel S ->> C2: type: push
over DataChannel ``` # 音声ストリーミング機能 ## 概要 Sora に WebRTC で送られてきた音声を、接続ごとに HTTP/2 で外部へ出力し、外部から受信した結果をクライアントへプッシュで通知する機能です。 ## 注意 ### OBS (WHIP) 機能利用時の Opus の設定 OBS の Opus のビットレートがデフォルトの場合は正常に動作しない場合があります。 その場合はビットレートを 128 kbps まで下げて見てください。 ### IPv6 非対応 現時点で、音声ストリーミングは IPv6 を利用できません。 ### 音声ストリーミングの送信単位 音声ストリーミングを [audio_streaming_url](SORA_CONF.html#6b5dd6) へ送信するのは、 コネクション単位であり、セッション単位ではありません。 ## HTTP/2 - 音声ストリーミングゲートウェイは HTTP/2 に対応している必要があります - h2c と h2 の両方に対応しています - `http://` から始めると h2c を利用します - `https://` から始めると h2 を利用します ## 音声ストリーミングの配信 音声ストリーミング機能はセッション単位で有効になります。 実際に音声ストリーミングで音声が外部に配信されるのは、 `role` が `sendrecv` または `sendonly`、かつ `audio` が `true` になっている場合のみ有効になります。 > **注釈** > > 外部から受信した結果はロールなどは関係なく、サブスクライブしているすべてのクライアントが受信できます。 ## 音声ストリーミングのヘッダー 音声ストリーミング機能において、HTTP/2 経由で送信する音声パケットに Sora 側でヘッダーを追加する機能です。 `sora.conf` の [audio_streaming_header](SORA_CONF.html#3edcef) を `true` に設定するとヘッダーが追加されます。 ```mermaid --- title: "音声ストリーミングヘッダーフォーマット" --- packet-beta 0-63: "Timestamp" 64-127: "SeqNum" 128-159: "Length" ``` - `Timestamp` は音声パケット送信時の UTC 時間マイクロ秒の整数です- RTP のタイムスタンプとは異なります - 64 ビット符号なし整数です - `SequenceNumber` は音声パケットのシーケンス番号で、 1 から始まります- RTP のシーケンス番号とは異なります - 64 ビット符号なし整数です - `Length` はヘッダーを除いた音声パケットの長さです- 32 ビット符号なし整数です ## 言語コードの指定 音声ストリーミングを利用する場合、 言語コードを指定する必要があります。 シグナリング接続時、または認証成功時の払い出しで `{"audio_streaming_language_code": "ja-JP"}` のように指定してください。 指定するのは **文字列であればなんでもかまいません** 。Sora 自体は言語コードには関与しません。あくまでただの文字列として扱います。 > **注意** > > 言語コードが指定されていない接続は、音声ストリーミングが開始している場合でも音声ストリーミングを行いません。 > 言語コードは音声を解析するにあたり必要になるためこのような仕様になっています。 ## セッションウェブフック経由での開始 音声ストリーミングはセッション単位で開始、終了します。 セッション生成時から音声ストリーミングを開始したい場合、 セッションウェブフックの戻り値に `{"audio_streaming": true}` を指定することで音声ストリーミングが開始します。 そのセッションに参加してきた言語コードが指定されているクライアントはすべて音声ストリーミングが行われます。 ## セッション破棄時の音声ストリーミング終了 チャネルのセッションが破棄したタイミングで音声ストリーミングは終了します。 ## API 経由での開始と終了 セッションの途中で音声ストリーミングを開始する場合は [StartAudioStreaming](API_AUDIO_STREAMING.html#0f1087) API を利用する必要があります。 また、セッションの途中で音声ストリーミングを終了する場合は [StopAudioStreaming](API_AUDIO_STREAMING.html#bad1bb) API を利用する必要があります。 ## 自動開始/停止機能 サブスクライブ中のコネクション数が 1 つ以上に増えたとき、自動的に音声ストリーミングが開始します。 逆に、サブスクライブ中のコネクション数が 0 になったときには、音声ストリーミングが自動的に停止します。 この機能を有効にすることで、サブスクライブが 0 の時は音声ストリーミングを行わなくなり、 転送量などを抑えることができます。 以下の方法でこの機能を有効にできます: - セッションウェブフックの `session.created` 時の払い出しで `{"audio_streaming": true, "audio_streaming_auto": true}` を指定した場合 > **注意** > > この機能が有効化されているときには、 > [StartAudioStreaming](API_AUDIO_STREAMING.html#0f1087) API と [StopAudioStreaming](API_AUDIO_STREAMING.html#bad1bb) API は利用できません。 > > この機能を停止するにはセッションを破棄する必要があります。 > API を使用してセッションを破棄する場合には、 [TerminateSession](API_SESSION.html#ba022b) API を利用してください。 ## リトライ条件 Sora は音声ストリーミングゲートウェイへの接続が失敗した際、リトライを行います。 リトライを行うには [audio_streaming_max_retries](SORA_CONF.html#9fd67a) と [audio_streaming_retry_interval](SORA_CONF.html#15f73d) に `0` 以外の値を指定してある必要があります。 ### リトライを行う - 音声ストリーミングゲートウェイへ接続ができなかった場合 - 音声ストリーミングゲートウェイへ接続時に 5xx 系のステータスコードが返された場合 ### リトライを行わない - 接続時に 4xx 系が送られてきた場合 - 接続後に `"type": "error"` が送られてきた場合 ## audio_streaming 関連の払い出し設定の組み合わせによる動作 ### 音声ストリーミングゲートウェイへの接続 セッションウェブフックの session.created 時に払い出した、 `audio_streaming`, `audio_streaming_auto` の組み合わせごとの `配信者接続時` の音声ストリーミングゲートウェイへの接続の有無は下記の通りです。 * - audio_streaming の指定 - audio_streaming_auto の指定 - subscribe 数 - 音声ストリーミングゲートウェイへの接続 * - true - true [#f1]_ - 0 - 無し * - true - true [#f1]_ - 1 以上 - 有り * - true - false - 0 - 有り [#f2]_ * - true - false - 1 以上 - 有り [#f2]_ * - true - 指定なし - 0 - 有り [#f2]_ * - true - 指定なし - 1 以上 - 有り [#f2]_ * - false - false - 0 - 無し * - false - false - 1 以上 - 無し [#f3]_ * - false - 指定なし - 0 - 無し [#f3]_ * - false - 指定なし - 1 以上 - 無し [#f3]_ * - 指定なし - false - 0 - 無し * - 指定なし - false - 1 以上 - 無し [#f3]_ * - 指定なし - 指定なし - 0 - 無し [#f3]_ * - 指定なし - 指定なし - 1 以上 - 無し [#f3]_ [^#f1]: .. [#f1] audio_streaming_auto に true を指定する場合には、audio_streaming にも true を指定する必要があります [^#f2]: .. [#f2] 音声ストリーミングゲートウェイへの接続有無はサブスクライブの数に依存しません [^#f3]: .. [#f3] 接続には StartAudioStreaminga API の実行が必要です > **注意** > > audio_streaming_auto に true を指定したにもかかわらず、audio_streaming を指定しないか、または false を指定した場合は、不正な組み合わせのため audio_streaming_auto、audio_streaming の指定は無視されます ### クライアントへの解析結果の送信 セッションウェブフックの session.created 時に払い出した、 `audio_streaming`, `audio_streaming_auto` の組み合わせごとの subscribe しているクライアントへの解析結果の送信有無は下記の通りです。 * - audio_streaming の指定 - audio_streaming_auto の指定 - subscribe 数 - クライアントへの解析結果の送信 * - true - true [#f4]_ - 0 - 無し * - true - true [#f4]_ - 1 以上 - 有り * - true - false - 0 - 無し * - true - false - 1 以上 - 有り * - true - 指定なし - 0 - 無し * - true - 指定なし - 1 以上 - 有り * - false - false - 0 - 無し * - false - false - 1 以上 - 無し * - false - 指定なし - 0 - 無し * - false - 指定なし - 1 以上 - 無し * - 指定なし - false - 0 - 無し * - 指定なし - false - 1 以上 - 無し * - 指定なし - 指定なし - 0 - 無し * - 指定なし - 指定なし - 1 以上 - 無し [^#f4]: .. [#f4] audio_streaming_auto に true を指定する場合には、audio_streaming にも true を指定する必要があります > **注意** > > audio_streaming_auto に true を指定したにもかかわらず、audio_streaming を指定しないか、または false を指定した場合は、不正な組み合わせのため audio_streaming_auto、audio_streaming の指定は無視されます ## 1 コネクション 1 HTTP/2 コネクション 音声ストリーミングが開始している状態でそのチャネルに新規クライアントが参加すると、 `audio_streaming_url` 宛てに新しく HTTP/2 コネクションが張られ、 クライアントから送られてきた Opus のバイナリデータがそのまま送られます。 HTTP/2 コネクションを張る際のヘッダーには以下の値が入ります。 - sora-channel-id- クライアントのチャネル ID - sora-connection-id- クライアントのコネクション ID - sora-audio-streaming-language-code- クライアントの言語コード ## プッシュ通知経由での戻り値の通知 シグナリングのプッシュ通知経由で外部サーバーからの戻り値を通知します。 ```javascript { "type": "push", "data": { "type": "audio_streaming_result", "connection_id": "", "result": "レスポンスがそのまま含まれる" } } ``` ## ウェブフック 音声ストリーミングの開始、終了時にウェブフックを通知します。 このウェブフックはデフォルト無効です。 もし利用する場合は `sora.conf` の [ignore_audio_streaming_webhook](SORA_CONF.html#8f086b) を `false` にして通知を有効にしてください。 ### audio-streaming.started - セッションで音声ストリーミングが開始した場合に通知されます - 自動開始/停止が有効の場合は `"audio_streaming_auto": true` が入ってきます - 音声ストリーミングを開始した時間が `"audio_streaming_started_timestamp"` に入ってきます - このウェブフックはかならず `session.created` よりも後に送信されます ```javascript { "data": { "audio_streaming_auto": false, "audio_streaming_started_timestamp": "2023-05-01T08:23:58.489262Z" }, "id": "VWGZ8NK2C55XBCGQ54SECK7J08", "label": "WebRTC SFU Sora", "timestamp": "2023-05-01T08:24:20.757279Z", "type": "audio-streaming.started", "version": "2023.2.0", "max_connections": 1, "node_name": "sora@127.0.0.1", "session_id": "DYPX8R6F4D11ZEG6XCX6N8EEWM", "channel_id": "sora", "spotlight": false, "created_time": 1682929437, "total_connections": 1, "created_timestamp": "2023-05-01T08:23:57.274844Z" } ``` ### audio-streaming.stopped - セッションで音声ストリーミング停止した場合に通知されます - 自動開始/停止が有効な場合は `"audio_streaming_auto": true` が入ってきます - 音声ストリーミングを開始した時間が `"audio_streaming_started_timestamp"` に入ってきます - 音声ストリーミングを停止した時間が `"audio_streaming_stopped_timestamp"` に入ってきます - このウェブフックはかならず `session.destroyed` よりも前に送信されます ```javascript { "data": { "audio_streaming_auto": false, "audio_streaming_started_timestamp": "2023-05-01T08:23:58.489262Z", "audio_streaming_stopped_timestamp": "2023-05-01T08:24:20.756785Z" }, "id": "VWGZ8NK2C55XBCGQ54SECK7J08", "label": "WebRTC SFU Sora", "timestamp": "2023-05-01T08:24:20.757279Z", "type": "audio-streaming.stopped", "version": "2023.2.0", "max_connections": 1, "node_name": "sora@127.0.0.1", "session_id": "DYPX8R6F4D11ZEG6XCX6N8EEWM", "channel_id": "sora", "spotlight": false, "created_time": 1682929437, "total_connections": 1, "created_timestamp": "2023-05-01T08:23:57.274844Z" } ``` ### audio-streaming.failed > **重要** > > このウェブフックは **イベントウェブフック** として送信されます。 このウェブフックは、Sora が接続する音声ストリーミングゲートウェイが利用するサービスに不具合があったことを、Sora に伝える仕組みです。 - `sora.conf` の [audio_streaming_max_retries](SORA_CONF.html#9fd67a) が `0` では無い場合に有効になります - `sora.conf` の [ignore_audio_streaming_failed_webhook](SORA_CONF.html#80d7fb) が `false` の場合にウェブフックが送られるようになります- `true` にした場合でも `event_webhook.jsonl` にログは出力されます リトライが発生する場合は最大リトライ数を超えている場合に、以下の状況でウェブフックが送信されます。 - 音声ストリーミングゲートウェイに接続した際 5xx 系のエラーが返ってきた場合に送信します - 音声ストリーミングゲートウェイに接続した際 4xx 系のエラーが返ってきた場合に送信します - 音声ストリーミングゲートウェイから `"type": "error"` が返ってきた場合に送信します - 音声ストリーミングゲートウェイへの接続確立がタイムアウト以外で失敗した場合に送信します 音声ストリーミングを再開したい場合は、再接続をしてください。 音声ストリーミングゲートウェイへの接続がタイムアウトになった場合にはウェブフックは送信されません。 > **注釈** > > 音声ストリーミングゲートウェイへの接続は HTTP/2 で行われます。 > そのため接続の途中で問題が起きた場合は HTTP ステータスコードを受け取ることはできません。 > その代わりに音声ストリーミングゲートウェイが送ってくる `"type": "error"` メッセージでエラーを検知します。 ```javascript { "data": { "failed_reason": "" }, "id": "VWGZ8NK2C55XBCGQ54SECK7J08", "label": "WebRTC SFU Sora", "timestamp": "2023-05-01T08:24:20.757279Z", "type": "audio-streaming.failed", "role": "sendrecv", "version": "2024.1.0", "node_name": "sora@127.0.0.1", "client_id": "B2JPGFZPMD3H973Y811MF8ZZ70", "connection_id": "B2JPGFZPMD3H973Y811MF8ZZ70", "bundle_id": "B2JPGFZPMD3H973Y811MF8ZZ70", "session_id": "DYPX8R6F4D11ZEG6XCX6N8EEWM", "channel_id": "sora", "simulcast": false, "spotlight": false, "log_written": true } ``` ## シグナリング通知経由で audio-streaming.failed をクライアントへ通知する このシグナリング通知は、Sora が接続する音声ストリーミングゲートウェイが利用するサービスに不具合があったことを、 そのチャネルに参加している全てのクライアントへ通知する仕組みです。 `sora.conf` にて [signaling_notify_audio_streaming_failed](SORA_CONF.html#d13e38) に `true` を指定した場合、 [audio_streaming_url](SORA_CONF.html#6b5dd6) への接続を諦めた際、セッションに参加している全てのコネクションにシグナリング通知 `audio-streaming.failed` を送信します。 この設定はデフォルトで `false` です。 ```javascript { "type": "notify", "event_type": "audio-streaming.failed", "failed_connection_id": "" } ``` ## 設定 ### audio_streaming_url **デフォルト**: 指定なし 音声ストリーミングゲートウェイの URL を指定してください。 音声ストリーミングゲートウェイは HTTP/2 に対応している必要があります。 https または http から始まる URL を指定してください。 詳細は [audio_streaming_url](SORA_CONF.html#6b5dd6) をご確認ください。 ### audio_streaming_max_retries **デフォルト**: 0 **範囲**: 0..10 音声ストリーミングゲートウェイへの接続が失敗した場合の最大リトライ回数を指定してください。 詳細は [audio_streaming_max_retries](SORA_CONF.html#9fd67a) をご確認ください。 ### audio_streaming_retry_interval **デフォルト**: 5 s **範囲**: 0..60 s 音声ストリーミングゲートウェイへの接続が失敗した場合のリトライ間隔を指定してください。 詳細は [audio_streaming_retry_interval](SORA_CONF.html#15f73d) をご確認ください。 ### default_audio_streaming_result_push **デフォルト**: true 音声ストリーミングゲートウェイからのレスポンスをシグナリングプッシュ通知で送ることをデフォルトで行うかを指定してください。 詳細は [default_audio_streaming_result_push](SORA_CONF.html#0b4a07) をご確認ください。 ### default_audio_streaming_language_code **デフォルト**: 指定なし 音声ストリーミングゲートウェイ接続時に HTTP ヘッダー `sora-audio-steraming-language-code` にデフォルトで含める文字列を指定してください。 詳細は [default_audio_streaming_language_code](SORA_CONF.html#856531) をご確認ください。 ### audio_streaming_tls_fullchain_file **デフォルト**: 指定なし 音声ストリーミングゲートウェイとの通信に HTTPS で mTLS を利用するための設定です。 中間証明書を含む PEM 形式 のクライアント証明書のパスを設定して下さい。 詳細は [audio_streaming_tls_fullchain_file](SORA_CONF.html#e5459b) をご確認ください。 ### audio_streaming_tls_privkey_file **デフォルト**: 指定なし 音声ストリーミングゲートウェイとの通信に HTTPS で mTLS を利用するための設定です。 PEM 形式のクライアント証明書秘密鍵のパスを設定して下さい。 詳細は [audio_streaming_tls_privkey_file](SORA_CONF.html#5f8e61) をご確認ください。 ### audio_streaming_tls_verify_cacert_file **デフォルト**: 指定なし 音声ストリーミングゲートウェイとの通信に HTTPS を利用する際に、 サーバー証明書のチェックを行う PEM 形式の CA ファイルのパスを設定して下さい。 詳細は [audio_streaming_tls_verify_cacert_file](SORA_CONF.html#feef99) をご確認ください。 > **注釈** > > CA 証明書を指定しない場合、OS 組み込みの証明書を利用します。詳細は [ウェブフックリクエストなどの送信先サーバー証明書の検証に利用する OS 組み込みのルート CA 証明書について](WEBHOOK.html#e8a845) をご確認ください。 ## API ### StartAudioStreaming API セッションが存在し、音声ストリーミングが開始していないチャネルに対して音声ストリーミングを開始します。 詳細は [StartAudioStreaming](API_AUDIO_STREAMING.html#0f1087) をご確認ください。 > **注釈** > > この API は audio_streaming_auto が true の場合は利用できません。 ### StopAudioStreaming API セッションが存在し、音声ストリーミングが開始しているチャネルに対して音声ストリーミングを停止します。 > **注釈** > > 音声ストリーミングを終了すると、すべての接続のサブスクライブしている状態は初期化され、デフォルトの値に戻ります。 詳細は [StopAudioStreaming](API_AUDIO_STREAMING.html#bad1bb) をご確認ください。 > **注釈** > > この API は audio_streaming_auto が true の場合は利用できません。 ### SubscribeAudioStreamingResultPush API 指定した接続が、音声ストリーミングゲートウェイからの戻り値のプッシュ通知をサブスクライブするよう設定します。 詳細は [SubscribeAudioStreamingResultPush](API_AUDIO_STREAMING.html#d26262) をご確認ください。 > **注釈** > > デフォルトの値は `sora.conf` の [default_audio_streaming_result_push](SORA_CONF.html#0b4a07) が適用されます。 ### UnsubscribeAudioStreamingResultPush API 指定した接続が、音声ストリーミングゲートウェイからの戻り値のプッシュ通知をサブスクライブしないよう設定します。 > **注釈** > > デフォルトの値は `sora.conf` の [default_audio_streaming_result_push](SORA_CONF.html#0b4a07) が適用されます。 詳細は [UnsubscribeAudioStreamingResultPush](API_AUDIO_STREAMING.html#b63656) をご確認ください。 ### ListAudioStreamingResultPushState API 指定したチャネルのセッションのコネクションごとのサブスクライブの状態を確認します。 ```javascript [ { "connection_id": "B2JPGFZPMD3H973Y811MF8ZZ70", "subscribe": true }, { "connection_id": "KT116Z11KX5Y547KA1V12HW8PG", "subscribe": false }, { "connection_id": "A5GYXGRYAX6590M3AFH7F9Z2H4", "subscribe": false } ] ``` 詳細は [ListAudioStreamingResultPushState](API_AUDIO_STREAMING.html#70450f) をご確認ください。 ## Audio Streaming Gateway Suzu > **重要** > > Audio Streaming Gateway Suzu は Sora サポートの対象外です [shiguredo/suzu: Audio Streaming Gateway Suzu](https://github.com/shiguredo/suzu) Sora から HTTP/2 経由で送られてくるヘッダーや Opus 音声データを Ogg 形式に変換して、 音声からテキストに変換するサービスへ送信し、サービスから受信した解析結果を Sora に返すゲートウェイです。 時雨堂が開発し、 OSS として公開しています。 ### 対応サービス - [Amazon Transcribe](https://aws.amazon.com/jp/transcribe/) - [Google Cloud Speech-to-Text](https://cloud.google.com/speech-to-text) ## シーケンス図 ### Suzu + AWS Transcribe ```mermaid sequenceDiagram autonumber participant C as クライアント participant S as Sora participant Suzu participant AWS Transcribe C->>S: SRTP C->>S: SRTP C->>S: SRTP note over C, AWS Transcribe: StartAudioStreaming API 実行 C->>S: SRTP S->>Suzu: Opus over HTTP/2 Suzu->>AWS Transcribe: Ogg over HTTP/2 C->>S: SRTP S->>Suzu: Opus over HTTP/2 Suzu->>AWS Transcribe: Ogg over HTTP/2 C->>S: SRTP S->>Suzu: Opus over HTTP/2 Suzu->>AWS Transcribe: Ogg over HTTP/2 AWS Transcribe->>Suzu: JSON over HTTP/2 Suzu->>S: JSON over HTTP/2 S->>C: シグナリングプッシュ通知 ``` ### 自動開始/停止 ```mermaid sequenceDiagram autonumber participant C as クライアント participant S as Sora participant A as アプリケーションサーバー participant Suzu S->>+A: セッションウェブフック
session.created A-->>-S: "audio_streaming": true
"audio_streaming_auto": true C->>S: SRTP C->>S: SRTP C->>S: SRTP A-->>+S: SubscribeAudioStreamingResultPush API 実行 S->>-A: 200 OK note right of S: Subscribe している C が 1 になった S->>+A: セッションウェブフック
audio-streaming.started A-->>-S: 200 OK note over S, Suzu: Suzu への HTTP/2 コネクション接続 C->>S: SRTP S->>Suzu: Opus over HTTP/2 C->>S: SRTP S->>Suzu: Opus over HTTP/2 Suzu->>S: JSON over HTTP/2 S->>C: シグナリングプッシュ通知 C->>S: SRTP S->>Suzu: Opus over HTTP/2 A-->>+S: UnsubscribeAudioStreamingResultPush API 実行 S->>-A: 200 OK note right of S: Subscribe しているクライアントが 0 になった note over S, Suzu: Suzu への HTTP/2 コネクション切断 C->>S: SRTP ``` # 転送フィルター機能 > **注釈** > > 転送とは Sora がクライアントから受信した音声や映像を他のクライアントに送信することを意味します。 ## 概要 転送フィルター機能は、Sora 側でクライアントへ転送する音声や映像のパケットをフィルターする機能です。 ## 目的 転送フィルター機能を使うことで、Sora から音声や映像のパケットをクライアントへ転送しなくなるため、 クライアントやサーバー側の負荷を減らすことができます。 また、接続直後に音声や映像を転送しなくすることもできます。 そのため、何らかのアクションを取ってから音声と映像を流し始めることができるようになります。 ## 注意 ### 利用可能なロール この機能は `role` が `sendrecv` または `recvonly` の場合にのみ利用できます。 ### データチャネルを利用したメッセージング データチャネルを利用したメッセージング機能は転送フィルター機能の対象外です。 ## 機能 > **注釈** > > チャネル単位、コネクション単位でフィルターが設定できます。 - 転送フィルターのルール指定は、チャネル単位、コネクション単位で指定できます - 転送フィルターのルールにはコネクション ID とクライアント ID と種類 (音声、映像) が指定できます - **転送フィルタールール** に指定するコネクション ID は 音声や映像の **送信元の** コネクション ID です。 - **転送フィルタールール** に指定するクライアント ID は 音声や映像の **送信元の** クライアント ID です。 - シグナリング指定時や認証成功時に **そのコネクションに対するフィルター** を指定できます - 転送フィルター更新時に転送フィルターのバージョンを確認し、一致した場合のみ更新することができます - 転送フィルターにメタデータを持たせることができます ## 転送フィルタールールの仕様 シグナリング、認証成功時の払い出し、セッション払い出し、API で共通のフィルタールールについて説明します。 フィルターは AND と OR が指定できます。ルールはリストとオブジェクトを利用して設定します。 > **重要** > > 転送フィルターのルールでは転送先のコネクション ID やクライアント ID を指定することはできません。 > 指定できるのは Sora に音声や映像を送信しているコネクションやクライアントの ID のみです。 ### チャネル単位でフィルターを設定する [CreateChannelForwardingFilter](API_FORWARDING_FILTER.html#fe98d1) API またはセッション生成時の払い出しを利用することで、 指定したチャネルに参加している **すべてのコネクションへ音声や映像を送信するかどうか** を設定できます。 ### コネクション単位でフィルター設定する [CreateConnectionForwardingFilter](API_FORWARDING_FILTER.html#d80a51) API 、シグナリング接続時の指定、または認証成功時の払い出しを利用することで、 指定したチャネルの **指定したコネクションへ音声や映像を送信するかどうか** を設定できます。 特定のコネクションに対してあるコネクションの映像を送りたくないなどができるようになります。 ### 1 チャネルや 1 コネクションに複数の転送フィルターを設定する 複数のフィルターを設定したい場合は [マルチ転送フィルター機能](MULTI_FORWARDING_FILTER.html) をご確認ください。 ### OR と AND トップレベルリストは OR を表しており、リストのリストでは AND を表しています。 `[[rule_1], [rule_2, rule_3]]` この場合は `(rule_1 OR (rule_2 AND rule_3))` という転送フィルタールールが適用されます。 `[[rule_1, rule_2]]` この場合は `(rule_1 AND rule_2)` という転送フィルタールールが適用されます。 > **警告** > > `[[[rule_1, rule_2], [rule_3]], [rule_5]]` のような 3 階層のルールは定義できません。 > 転送フィルターのルールで利用できるリストの階層は 2 階層までとなります。 ### action について 転送フィルターには `action` を指定できます。 アクションには `block` と `allow` が指定できます。 - `block` を指定した場合は、 rules にマッチした条件でのみ転送をブロックします - `allow` を指定した場合は、 rules にマッチした条件でのみ転送を許可します デフォルトでは `block` になります。 > **重要** > > `block` と `allow` では `allow` が優先されます。 > * チャネルで `block` 、コネクションで `allow` が指定されていた場合、コネクションの `allow` のみが適用されます > * チャネルで `allow` 、コネクションで `block` が指定されていた場合、チャネルの `allow` のみが適用されます > * チャネルで `allow` 、コネクションで `allow` が指定されていた場合、両方の `allow` が適用されます #### ケース 1 チャネル単位の転送フィルターでは映像を `block` にして設定している状態で、 ある接続の転送フィルターでは映像を `allow` に設定した場合、 その接続では `allow` の転送フィルターだけが有効になり、その接続に映像が転送されます。 #### ケース 2 チャネル単位の転送フィルターでは映像を `allow` にして設定している状態で、 ある接続の転送フィルターでは音声を `allow` に設定した場合、 その接続には音声と映像が転送されます。 ### version について 転送フィルターに文字列でバージョンを `version` 項目で指定することができます。これはオプションです。 転送フィルター作成時に `version` を指定した場合、 転送フィルターを更新するには `expected_version` と `desired_version` を指定する必要があります。 `expected_version` は更新する転送フィルターの `version` を指定します。 転送フィルターのバージョンが異なった場合、転送フィルターの更新は失敗します。 転送フィルターのバージョンが一致した場合、転送フィルターの更新は成功します。 `desired_version` の値が、新しい `version` の値となります。 `version` を利用することで転送フィルターを並列で実行されても期待した値に変更することができるようになります。 ### metadata について 転送フィルターにはメタデータを `metadata` 項目を指定することができます。これはオプションです。 転送フィルター作成、または更新時に `metadata` に JSON 値を指定することができます。 この `metadata` は転送フィルターの挙動には影響せず、転送フィルターの情報を自由に書き込める項目です。 `metadata` を利用することで転送フィルターに関する情報を自由に管理することができるようになります。 ### rules の書き方 **すべての項目は必須です** - field- フィールドには `connection_id` と `client_id` と `kind` が指定できます - `connection_id`- フィルターの対象となる音声や映像の **送信元の** コネクション ID を指定してください - `client_id`- フィルターの対象となる音声や映像の **送信元の** クライアント ID を指定してください - `kind`- フィルターに音声や映像を指定できます - operator- オペレーターには `is_in` と `is_not_in` が指定できます - `is_in`- values に指定されたリストに含まれる値にマッチしている場合は転送フィルターの対象とする - `is_not_in`- values に指定されたリストに含まれる値にマッチしていない場合は転送フィルターの対象とする - values- バリューにはかならず文字列のリスト `["string", ...]` を指定してください - `field` に合った値を指定してください - `field` が `kind` の場合は `"audio"` または `"video"` を指定してください ```javascript { "action": "block", "rules": [ // チャネルに接続しているすべてのクライアントへ connection_id "S8YEN0TSE13JDC2991NG4XZ150" からの音声と映像をブロックし転送しない // また // チャネルに接続しているすべてのクライアントへ client_id が "screen-share" の音声をブロックし転送しない [ { "field": "connection_id", "operator": "is_in", "values": ["S8YEN0TSE13JDC2991NG4XZ150"] } ], [ { "field": "client_id", "operator": "is_in", "values": ["screen-share"] }, { "field": "kind", "operator": "is_in", "values": ["audio"] } ] ] } ``` ### field に `connection_id` を指定した場合 `kind` を指定しなくても `audio` と `video` がブロックされます。 ```javascript { "action": "block", "rules": [ // チャネルに接続しているすべてのコネクションへ connection_id "S8YEN0TSE13JDC2991NG4XZ150" からの音声と映像をブロックし転送しない [ { "field": "connection_id", "operator": "is_in", "values": ["S8YEN0TSE13JDC2991NG4XZ150"] } ] ] } ``` ### 送信元の指定をせずすべての音声と映像をブロックする `kind` を指定することで送信元の指定がないフィルターを作成できます。 音声と映像の両方をブロックするので `values` に `audio` と `video` 両方を指定しています。 ```javascript { "action": "block", "rules": [ // チャネルに接続しているすべてのコネクションに対して音声と映像をブロックし転送しない [ { "field": "kind", "operator": "is_in", "values": ["audio", "video"] } ] ] } ``` ## フィルタールールの適用 - チャネル単位でのフィルター- 転送フィルターのルールにマッチした条件で、すべてのコネクションに対して転送するかどうか - コネクション単位でのフィルター- 転送フィルターのルールでマッチした条件で、指定した `connection_id` に対して転送するかどうか - フィルターの優先度- チャネル単位でフィルターとコネクション単位でのフィルターに優先度はない - 優先度は `allow` と `block` にだけあり `allow` が優先される ## 転送フィルター共通 API の仕様 ### ListForwardingFilters API 指定したチャネルのチャネルとコネクション両方の転送フィルターを確認できます。 - channel_id- string - 必須 - blocked- boolean - オプション - ブロック状況を表示するかどうかを指定します ``` $ curl -sS \ -X POST \ http://127.0.0.1:3000/ \ -H "x-sora-target: Sora_20230628.ListForwardingFilters" \ --json '{"channel_id":"sora","blocked":true}' \ | jq . { "channel_forwarding_filters": [ { "action": "block", "rules": [ [{"field": "kind", "operator": "is_in", "values": ["audio", "video"]}] ] } ], "connection_forwarding_filters": [ { "connection_id": "9PZ98RZV1H3RSEZ82SBBC289F8", "action": "allow", "rules": [ [{"field": "kind", "operator": "is_in", "values": ["audio"]}] ] }, { "connection_id": "8QA9YX7ZJX3150ZJ87874TBFMG", "action": "allow", "rules": [ [{"field": "kind", "operator": "is_in", "values": ["audio"]}] ] } ], "blocked": [ { "destination_connection_id": "9PZ98RZV1H3RSEZ82SBBC289F8", "source_connection_id_list": [ "2VJPS671HH1EH3HNY13SXHS5RG" ], "kind": "audio" }, { "destination_connection_id": "9PZ98RZV1H3RSEZ82SBBC289F8", "source_connection_id_list": [ "2VJPS671HH1EH3HNY13SXHS5RG", "C4D50FG8Q16BF4YCTT0V8YGSXM" ], "kind": "video" } ] } ``` ## チャネル単位の転送フィルター API の仕様 ### CreateChannelForwardingFilter API 指定したチャネルに対して Sora の転送フィルターを作成する API です。 - channel_id- string - 必須 - rules- `[[object, ...], [object, ...]]` - 必須 - 転送フィルターのルールを指定します - action - string - オプション - `block` または `allow` - デフォルトは `block` - version- string - オプション - 転送フィルターのバージョンを指定します - metadata- JSONValue - オプション - 転送フィルターのメタデータを指定します - name- string (最大 255 バイト) - オプション - 転送フィルターの名前を指定します - priority- integer (0-32767) - オプション - 転送フィルターの優先度を指定します ``` $ curl -sS \ -X POST \ http://127.0.0.1:3000/ \ -H "x-sora-target: Sora_20230628.CreateChannelForwardingFilter" \ --json '{"channel_id":"sora","rules":[[{"field":"client_id","operator":"is_in","values":["screen-share"]},{"field":"kind","operator":"is_in","values":["video"]}]]}' \ | jq . ``` ### UpdateChannelForwardingFilter API 指定したチャネルの転送フィルターを更新します。 - channel_id- string - 必須 - rules- `[[object, ...], [object, ...]]` - 必須 - 転送フィルターのルールを指定します - action - string - オプション - `block` または `allow` - デフォルトは `block` - expected_version- string - オプション - 転送フィルターの期待するバージョンを指定します - desired_version- string - オプション - 転送フィルターの更新成功後のバージョンを指定します - metadata- JSONValue - オプション - 転送フィルターのメタデータを指定します - name- string (最大 255 バイト) - オプション - 転送フィルターの名前を指定します - priority- integer (0-32767) - オプション - 転送フィルターの優先度を指定します ``` $ curl -sS \ -X POST \ http://127.0.0.1:3000/ \ -H "x-sora-target: Sora_20230628.UpdateChannelForwardingFilter" \ --json '{"channel_id":"sora","rules":[[{"field":"connection_id","operator":"is_in","values":["RAV7EG7Z693NDCZFGGXZS7WBRC"]}],[{"field":"client_id","operator":"is_in","values":["screen-share"]},{"field":"kind","operator":"is_in","values":["video"]}]]}' \ | jq . ``` ### DeleteChannelForwardingFilter API 指定したチャネルの転送フィルターを削除します。 - channel_id- string - 必須 - name- string (最大 255 バイト) - オプション - 転送フィルターの名前を指定します ``` $ curl -sS \ -X POST \ http://127.0.0.1:3000/ \ -H "x-sora-target: Sora_20230628.DeleteChannelForwardingFilter" \ --json '{"channel_id":"sora"}' \ | jq . ``` ## コネクション単位の転送フィルター API の仕様 ### CreateConnectionForwardingFilter API 指定したチャネルの特定のコネクションの転送フィルターを作成します。 - channel_id- string - 必須 - connection_id- string - 必須 - rules- `[[object, ...], [object, ...]]` - 必須 - 転送フィルターのルールを指定します - action - string - オプション - `block` または `allow` - デフォルトは `block` - version- string - オプション - 転送フィルターのバージョンを指定します - metadata- JSONValue - オプション - 転送フィルターのメタデータを指定します - name- string (最大 255 バイト) - オプション - 転送フィルターの名前を指定します - priority- integer (0-32767) - オプション - 転送フィルターの優先度を指定します ``` $ curl -sS \ -X POST \ http://127.0.0.1:3000/ \ -H "x-sora-target: Sora_20230628.CreateConnectionForwardingFilter" \ --json '{"channel_id":"sora","connection_id":"T9J5FM3NTH6JH4JKFGTSHB1BA0","rules":[[{"field":"client_id","operator":"is_in","values":["screen-share"]},{"field":"kind","operator":"is_in","values":["video"]}]]}' \ | jq . ``` ### UpdateConnectionForwardingFilter API 指定したチャネルの特定のコネクションの転送フィルターを更新します。 - channel_id- string - 必須 - connection_id- string - 必須 - rules- `[[object, ...], [object, ...]]` - 必須 - 転送フィルターのルールを指定します - action - string - オプション - `block` または `allow` - デフォルトは `block` - expected_version- string - オプション - 転送フィルターの期待するバージョンを指定します - desired_version- string - オプション - 転送フィルターの更新成功後のバージョンを指定します - metadata- JSONValue - オプション - 転送フィルターのメタデータを指定します - name- string (最大 255 バイト) - オプション - 転送フィルターの名前を指定します - priority- integer (0-32767) - オプション - 転送フィルターの優先度を指定します ``` $ curl -sS \ -X POST \ http://127.0.0.1:3000/ \ -H "x-sora-target: Sora_20230628.UpdateConnectionForwardingFilter" \ --json '{"channel_id":"sora","connection_id":"T9J5FM3NTH6JH4JKFGTSHB1BA0","rules":[[{"field":"connection_id","operator":"is_in","values":["RX1GD666HD53F3M36PB7KEZMBR"]},{"field":"kind","operator":"is_in","values":["video"]}]]}' \ | jq . ``` ### DeleteConnectionForwardingFilter API 指定したチャネルの特定のコネクションの転送フィルターを削除します。 - channel_id- string - 必須 - connection_id- string - 必須 - name- string (最大 255 バイト) - オプション - 転送フィルターの名前を指定します ``` $ curl -sS \ -X POST \ http://127.0.0.1:3000/ \ -H "x-sora-target: Sora_20230628.DeleteConnectionForwardingFilter" \ --json '{"channel_id":"sora","connection_id":"T9J5FM3NTH6JH4JKFGTSHB1BA0"}' \ | jq . ``` ## セッション生成時のチャネル単位転送フィルター仕様 セッション生成時に転送フィルターを指定することができます。 > **重要** > > セッション生成時の払い出しで転送フィルターがエラーになった場合、接続に失敗します。 以下はセッション接続時には音声しか転送しないフィルター例です。 ```javascript { "forwarding_filters": [ { "action": "allow", "rules": [ [ {"field": "kind", "operator": "is_in", "values": ["audio"]} ] ] } ] } ``` - `version` や `metadata` も指定できます - `name` や `priority` も指定できます > **注釈** > > セッション生成時に転送フィルターを指定した場合、 > API 経由で変更するには UpdateChannelForwardingFilter API を利用する必要があります。 ## シグナリング時のコネクション単位転送フィルター仕様 シグナリング接続時に **コネクション単位での転送フィルター** を指定することができます。 この転送フィルターは接続したコネクションにのみ影響します。 > **重要** > > シグナリング接続時に転送フィルターを指定する場合は `sora.conf` にて、 > [signaling_forwarding_filters](SORA_CONF.html#bf0e30) を `true` に設定する必要があります。 以下は接続時に映像を転送せずに音声だけを自分に転送するフィルター例です。 ```javascript { "type": "connect", "role": "sendrecv", "channel_id": "sora", "forwarding_filters": [ { "action": "allow", "rules": [ [ {"field": "kind", "operator": "is_in", "values": ["audio"]} ] ] } ] } ``` > **注釈** > > シグナリング時に転送フィルターを指定した場合、 > API 経由で変更するには UpdateConnectionForwardingFilter API を利用する必要があります。 ## 認証成功時払い出し時のコネクション単位転送フィルターの仕様 認証成功時に、コネクション単位の転送フィルターを指定することができます。 > **重要** > > 認証成功時の払い出しの転送フィルターがエラーになった場合、接続に失敗します。 以下は映像を転送せずに音声だけをそのコネクションに転送するフィルター例です。 ```javascript { "allowed": true, "forwarding_filters": [ { "action": "allow", "rules": [ [ {"field": "kind", "operator": "is_in", "values": ["audio"]} ] ] } ] } ``` `version` や `metadata` も指定できます。 > **注釈** > > 認証成功払い出し時に転送フィルターを作成した場合、 > API 経由で変更するには UpdateConnectionForwardingFilter API を利用する必要があります。 ## シグナリング通知 転送フィルターを作成、更新、削除したタイミングで、 転送フィルターによって転送されていないかどうかを、シグナリング経由で通知します。 転送フィルターが影響する範囲にのみ通知されます。 通知は送信側と受信側の両方に送られます。 - destination は映像または音声の送信先です - source は映像または音声の送信元です - destination_connection_id は映像または音声の送信先の connection_id です - source_connection_id は映像または音声の送信元の connection_id です ### forwarding.blocked 転送フィルターによりブロックが有効になったタイミングで送信側と受信側に通知されます。 以下の通知は、 `source_connection_id` の送信元から `destination_connection_id` の送信先へ送信した音声をブロックすることを表しています。 ```javascript { "type": "notify", "kind": "audio", "event_type": "forwarding.blocked", "destination_connection_id": "14P91M6B5526928T14WGPW9H6G", "source_connection_id": "GHRNJAQ40S15KCF3MZF0N7QS8R" } ``` ### forwarding.allowed 転送フィルターによりブロックが解除されたタイミングで送信側と受信側に通知されます。 以下の通知は、 `source_connection_id` の送信元から `destination_connection_id` の送信先へ送信した音声のブロックが解除されたことを表しています。 ```javascript { "type": "notify", "kind": "audio", "event_type": "forwarding.allowed", "destination_connection_id": "14P91M6B5526928T14WGPW9H6G", "source_connection_id": "GHRNJAQ40S15KCF3MZF0N7QS8R" } ``` ## フィルター例 ### 特定のクライアントにだけ音声と映像を転送しない `CreateConnectionForwardingFilter` API で音声と映像を転送したくないクライアントに対してフィルターを設定してください ``` $ curl -sS \ -X POST \ http://127.0.0.1:3000/ \ -H "x-sora-target: Sora_20230628.CreateConnectionForwardingFilter" \ --json '{"channel_id":"sora","connection_id":"T9J5FM3NTH6JH4JKFGTSHB1BA0","action":"block","rules":[[{"field":"kind","operator":"is_in","values":["audio","video"]}]]}' \ | jq . ``` このフィルターは指定したコネクションに転送するパケットのフィルターを設定しています。 `kind` で `audio` と `video` が `is_in` に設定されており、 すべてのクライアントから Sora に送信されてくる audio と video を指定したクライアントに転送しなくなります。 ### 特定の connection_id の送信元以外の音声や映像を転送しない `CreateChannelForwardingFilter` API で音声と映像の転送を許可する送信元のコネクション ID を指定してください。 ``` $ curl -sS \ -X POST \ http://127.0.0.1:3000/ \ -H "x-sora-target: Sora_20230628.CreateChannelForwardingFilter" \ --json '{"channel_id":"sora","action":"block","rules":[[{"field":"connection_id","operator":"is_not_in","values":["S8YEN0TSE13JDC2991NG4XZ150"]}]]}' \ | jq . ``` このフィルターでは指定したチャネルに転送するパケットのフィルターを設定しています。 `operator` に `is_not_in` を指定することで指定したコネクション ID の送信元以外からのパケットの送信をブロックします。 ### 全体をブロックしているが、一時的に特定の connection_id の送信先だけには全クライアントの音声と映像を転送する `CreateChannelForwardingFilter` API で音声と映像の転送をブロックしてください。 ``` $ curl -sS \ -X POST \ http://127.0.0.1:3000/ \ -H "x-sora-target: Sora_20230628.CreateChannelForwardingFilter" \ --json '{"channel_id":"sora","action":"block","rules":[[{"field":"kind","operator":"is_in","values":["audio","video"]}]]}' \ | jq . ``` `CreateConnectionForwardingFilter` API で一時的にブロックしない送信先の connection_id を指定してください。 ポイントはコネクション単位で `action` に `allow` を指定します。 `allow` は `block` を上書きします。 ``` $ curl -sS \ -X POST \ http://127.0.0.1:3000/ \ -H "x-sora-target: Sora_20230628.CreateConnectionForwardingFilter" \ --json '{"channel_id":"sora","connection_id":"T9J5FM3NTH6JH4JKFGTSHB1BA0","action":"allow","rules":[[{"field":"kind","operator":"is_in","values":["audio","video"]}]]}' \ | jq . ``` これで全体をブロックした状態で、指定した connection_id の送信先にだけ音声や映像が転送されます。 ## FAQ ### チャネルとコネクションの転送フィルターはどちらが優先されますか? チャネルとコネクションで優先度は特にありません。 ただしアクションの `allow` が優先されます。 チャネルのアクションが `block` でコネクションのアクションが `allow` で、 同じコネクション ID を指定した場合は `allow` が優先されます。 ### 転送フィルターでブロックされたときの挙動を教えてください Sora は転送フィルターでブロックされた音声や映像パケットをクライアントに転送しません。 そのため受信側ではパケットが「何も送られてこない」という状態になります。 転送フィルターが更新、または削除や `allow` で転送される状態になるとパケットの転送を開始します。 ### 1 チャネルや 1 コネクションに複数の転送フィルターを指定できますか? 指定できます。 [マルチ転送フィルター機能](MULTI_FORWARDING_FILTER.html) をご確認ください。 ### 転送フィルターを有効にした場合は ontrack は SDK 側で発火しますか? 発火します。転送フィルターはあくまで **本来転送する音声や映像を Sora でフィルターする機能** のため、 SDK 側の ontrack 自体は発火します。 ### フィルターでブロックされたりブロック解除されたタイミングをクライアント側で知ることはできますか? Sora はシグナリング通知経由でブロック/ブロック解除されたタイミングで通知します。 これはブロックされた送信側と受信側両方に通知が飛びます。 ## シーケンス図 ### チャネル単位のブロック例 ```mermaid sequenceDiagram autonumber participant C1 as クライアント1 participant C2 as クライアント2 participant C3 as クライアント3 participant S as Sora participant A as アプリケーションサーバー note over C1,S: クライアント1: WebRTC 確立 note over C2,S: クライアント2: WebRTC 確立 par C1-)S: SRTP S-)C1: SRTP (C2) and C2-)S: SRTP S-)C2: SRTP (C1) and A->>+S: CreateChannelForwardingFilter
channel_id=sora
block,kind(audio,video) S-->>-A: 200 OK note right of S: 音声と映像をこのチャネル内で転送しない end note over C1,S: ブロックフィルターで転送がブロックされる par C1-)S: SRTP and C2-)S: SRTP and note over C3,S: クライアント3: WebRTC 確立 end par C1-)S: SRTP and C2-)S: SRTP and C3-)S: SRTP end A->>+S: DeleteChannelForwardingFilter
channel_id=sora S-->>-A: 200 OK note over C1,S: ブロックフィルターが削除された par C1-)S: SRTP S-)C1: SRTP (C2) S-)C1: SRTP (C3) and C2-)S: SRTP S-)C2: SRTP (C1) S-)C2: SRTP (C3) and C3-)S: SRTP S-)C3: SRTP (C2) S-)C3: SRTP (C1) end note over C1,S: 音声と映像の転送がブロックされなくなった ``` ### チャネルフィルターとコネクションフィルター組み合わせ例 - 音声と映像がブロックされる - connection_id 1 にだけ映像が転送される ```mermaid sequenceDiagram autonumber participant C1 as クライアント1
connection_id: 1 participant C2 as クライアント2
connection_id: 2 participant S as Sora participant A as アプリケーションサーバー note over C1,S: クライアント1: WebRTC 確立 note over C2,S: クライアント2: WebRTC 確立 par C1-)S: SRTP (音声) S-)C2: SRTP (音声) and C1-)S: SRTP (映像) S-)C2: SRTP (映像) and C2-)S: SRTP (音声) S-)C1: SRTP (音声) and C2-)S: SRTP (映像) S-)C1: SRTP (映像) and note right of S: 音声と映像をこのチャネル内で転送しない A->>+S: CreateChannelForwardingFilter
channel_id=sora
block,kind(audio,video) S-->>-A: 200 OK note right of S: 映像を connection_id=1 にだけ転送する A->>+S: CreateConnectionForwardingFilter
channel_id=sora
connection_id: 1
allow,kind(video) S-->>-A: 200 OK end note over C1,S: チャネル単位フィルターで音声と映像の転送がブロックされる note over C1,S: コネクション単位フィルターで映像の転送が connection_id: 1 には許可される par note right of S: ブロックされる C1-)S: SRTP (音声) and note right of S: ブロックされる C1-)S: SRTP (映像) and note right of S: ブロックされる C2-)S: SRTP (音声) and C2-)S: SRTP (映像) note right of S: 許可されているので転送する S-)C1: SRTP (映像) end A->>+S: DeleteConnectionForwardingFilter
channel_id=sora
connection_id: 1 S-->>-A: 200 OK note over C1,S: コネクション単位のフィルターが削除された par C1-)S: SRTP (音声) and C1-)S: SRTP (映像) and C2-)S: SRTP (音声) and C2-)S: SRTP (映像) end note over C1,S: 全員が音声と映像の転送がブロックされている ``` ### version を利用した変更保証 並列に転送フィルター更新 API が叩かれてもバージョンチェックをすることで更新結果を保証する。 ```mermaid sequenceDiagram participant S as Sora participant A as アプリケーションサーバー par A->>+S: UpdateChannelForwardingFilters API
{"expect_version": "spam", "desire_version": "ham", ...} S-->>-A: 200 OK note over A: 更新成功 and A->>+S: UpdateChannelForwardingFilters API
{"expect_version": "spam", "desire_version": "beacon", ...} S-->>-A: 400 Bad Request
{"message": "INVALID-VERSION", "version": "ham"} note over A: 更新失敗 end ``` # マルチ転送フィルター機能 ## 概要 マルチ転送フィルター機能は、転送フィルターに名前 (`name`) と優先度 (`priority`) を指定することで、 1 チャネルや 1 コネクションに複数の転送フィルターを設定できる機能です。 ## 認証接続時と認証成功時・セッション生成時の払い出しの注意点 - `forwarding_filters` で `name` が重複した場合はエラーになります - `forwarding_filters` で `name` と `priority` が未指定の場合は `default` と `32767` として扱われます- ただし未指定が複数ある場合は `name` の `default` が重複していると判断されエラーになります ## 仕様 - マルチ転送フィルターは 1 チャネルや 1 コネクションに対して複数の転送フィルターを設定できる機能です - 複数の転送フィルターを設定する場合は、 `name` と `priority` を指定して転送フィルターを追加します- `name` はすでに設定済みの転送フィルターと重複することはできません - `name` と `priority` のどちらかだけを指定することはできません - 転送フィルターは転送を判定するタイミングで、指定されている全ての転送フィルターを判定します- ただし判定するタイミングで、優先度が高いものから判定します - 転送フィルター追加時に名前 (`name`) と優先度 (`priority`) を指定することができます - 転送フィルター更新時に名前 (`name`) と優先度 (`priority`) を指定することができます - 転送フィルター削除時に名前 (`name`) を指定して削除することができます - 名前は任意の文字列 (最大 255 バイト) が指定できます - 名前は重複できません- `channel_id` または `connection_id` 単位で一意な名前が必要 - 名前が重複している場合はエラーになります - 優先度は 0-32767 (16#7FFF) の間で指定してください - 優先度が一番高いのは 0 で、数値が大きいほど優先度が低くなります - 優先度は重複できます- 優先度が同じ場合は `allow` が優先されます - `block` のみの場合は OR で判定します - `allow` のみの場合は OR で判定します - `block` / `block` / `allow` なら `allow` のみで判定します - `name` と `priority` を指定しない場合はデフォルト値が設定されます- `name` は `"default"` です - `priority` は `32767` です ## 性能 1 チャネルや 1 コネクションに対して数千個などのフィルターを設定しない限り、性能が劣化することはありません。 ## 認証成功時の払い出し ```javascript forwarding_filters: [ { "name": "client-id-carol-allow", "priority": 0, "action": "allow", "rules": [ [ { "field": "client_id", "operator": "is_in", "values": [ "carol" ] } ] ] }, { "name": "default", "priority": 32767, "action": "block", "rules": [ [ { "field": "kind", "operator": "is_in", "values": [ "audio", "video" ] } ] ] } ] ``` ## セッション生成時の払い出し ```javascript forwarding_filters: [ { "action": "block", "name": "client-id-alice-block", "priority": 0, "rules": [ [ { "field": "client_id", "operator": "is_in", "values": [ "alice" ] } ] ] }, { "action": "block", "name": "client-id-bob-block", "priority": 0, "rules": [ [ { "field": "client_id", "operator": "is_in", "values": [ "bob" ] } ] ] }, { "action": "block", "name": "default", "priority": 32767, "rules": [ [ { "field": "kind", "operator": "is_in", "values": [ "audio" ] } ] ] } ] ``` # プレイアウト遅延機能 ## 概要 プレイアウト遅延機能は映像フレームを視聴側がどれくらい早く再生する必要があるかどうかを WebRTC SFU Sora 側から指定する仕組みです。 WebRTC はレイテンシーを優先する仕組みですが、 プレイアウト遅延機能を利用することで、再生までの間にバッファを持たせることができるようになります。 これにより、映像の安定性を向上させることができます。また、リップシンクなどを諦めてとにかく映像の低遅延化を優先することもできるようになります。 ### 注意 この機能はベストエフォートです。視聴側は、可能な限り配信側が指定した範囲内に収まるように映像を再生するように努力しますが、 ネットワークの状況によっては、指定した範囲外で再生されることがあります。 ## 仕組み この機能は [プレイアウト遅延を制御するための RTP ヘッダー拡張](https://webrtc.googlesource.com/src/+/refs/heads/main/docs/native-code/rtp-hdrext/playout-delay) を利用して実現しています。 ただし、 プレイアウト遅延を制御するための RTP ヘッダー拡張 は本来、 P2P 利用時に配信側が視聴側に対して再生遅延量を一定の範囲内に制限できるようにするための機能であり、フレームをどのくらいの速さでレンダリングする必要があるかについての送信者の意図を受信者に伝えることを目的としています。 そのため、 WebRTC SFU Sora のプレイアウト遅延機能は本来の プレイアウト遅延を制御するための RTP ヘッダー拡張 利用目的とは異なります。 ## 注意 プレイアウト遅延機能はロールによって適用される範囲が異なります。 ### sendrecv 受信するストリーム全てに適用されます。 ### sendonly 適用されません。 ### recvonly 受信するストリーム全てに適用されます。 ## 設定 プレイアウト遅延では視聴側の再生遅延の最小値と最大値を指定できます。 指定できる範囲は 0 ミリ秒から 40950 ミリ秒の間です。 ## 利用方法 プレイアウト遅延機能は [rtp_hdrext_playout_delay](SORA_CONF.html#d34a4b) が `true` である必要があります。 [rtp_hdrext_playout_delay](SORA_CONF.html#d34a4b) はデフォルトで `true` です。 ### sora.conf でのデフォルト値での指定 全ての接続のデフォルト値を指定したい場合、 sora.conf にて [default_playout_delay_min_delay](SORA_CONF.html#194218) と [default_playout_delay_max_delay](SORA_CONF.html#c1b0ab) を指定してください。 ### 認証成功時の指定 もしコネクション単位でプレイアウト遅延を指定したい場合、 認証成功時に `playout_delay_min_delay` と `playout_delay_max_delay` を指定してください。 詳細は [playout_delay_min_delay と playout_delay_max_delay の払い出し](AUTH_WEBHOOK_RETURN.html#3f11db) をご確認ください。 ## 設定例 **実際には環境に合わせて調整してください** ### オーディオのないリモートデスクトップ **min_delay**: 0 ms **max_delay**: 0 ms リモートデスクトップはできるだけ早く再生したいことが多いため、 プレイアウト遅延を 0 に設定することをお勧めします。 > **注釈** > > とにかく低遅延で映像を表示したい場合の設定です。 ### ミーティング **双方向** **min_delay**: 100 ms **max_delay**: 200 ms ミーティングは少しの遅延が存在しても、問題ない場合が多いため、100 ミリ秒の遅延を設定することをお勧めします。 ### ビデオストリーミング **min_delay**: 400 ms **max_delay**: 1000 ms 一方向のビデオストリーミングでは、低遅延で配信しつつも、映像が止まったり乱れたりすることを防ぐために、 400 ミリ秒の遅延を設定することをお勧めします。 # ノード単位での最大同時接続数制限機能 ## 概要 ノード単位での最大同時接続数制限機能を使用すると、Sora 1 ノードでライセンスの最大同時接続数制限とは別に最大同時接続数を制限することができます。 これにより、ノードのリソース使用量を管理し、過負荷を防止することができます。 ## 設定方法 `sora.conf` の [max_connections](SORA_CONF.html#498be9) を設定します。例えば、最大同時接続数を 50 に設定する場合は、以下のように設定します。 ```ini max_connections = 50 ``` # セッション単位での最大同時接続数制限機能 ## 概要 セッション単位での最大同時接続数制限機能を使用すると、特定のセッションに対して同時に確立できる接続数の上限を厳格に制限することができます。 ## 利用方法 セッションウェブフック [session.created](SESSION_WEBHOOK.html#1d1984) のレスポンスに `max_connections` を払い出してください。 `max_connections` フィールドには、そのセッションに対して許可される最大同時接続数を整数値で指定します。 ```javascript { "max_connections": 10 } ``` ## セッション単位での最大同時接続数を無視する機能 セッション作成時の `max_connections` にてセッション単位の最大同時接続数を制限できますが、 特定のクライアントは制限を無視して接続を許可することができます。 セッション単位の最大同時接続数制限が指定されている場合、 認証成功時の払い出しにて `ignore_max_connections` を `true` に設定することで、 そのクライアントはセッション単位の最大同時接続数制限を無視して接続が許可されます。 ```javascript { "ignore_max_connections": true } ``` # セッション単位でのクライアント ID 重複時の既存接続の追い出し機能 ## 概要 セッション単位でのクライアント ID 重複時の既存接続の追い出し機能を使用すると、同一セッション内で同じクライアント ID を持つ新しい接続が確立された場合に、既存の接続を強制的に切断することができます。これにより、特定のクライアント ID に対して同時に複数の接続が存在することを防止できます。 ## 利用方法 [session.created](SESSION_WEBHOOK.html#1d1984) のタイミングで、 クライアント ID が重複した場合の挙動を `duplicate_client_id` に指定してください。 `duplicate_client_id` に `evict` を指定した場合、 既に接続している同一クライアント ID の接続を破棄するような挙動になります。 `duplicate_client_id` には `allow` または `evict` を指定できます。 - `allow` は `client_id` の重複を許容します - `evict` は新規接続を受け入れて、既存接続を追い出します 未指定の場合は `sora.conf` の [default_duplicate_client_id](SORA_CONF.html#c8b57b) の値を利用します。 ```javascript { "duplicate_client_id": "evict" } ``` # レガシー録画機能 *バージョン 2025.2.0 で削除。* > **注意** > > レガシー録画機能は 2025 年 12 月リリースの Sora にて廃止しました。 > 今後は [録画機能 (セッション単位)](RECORDING.html) をご利用ください。 > **注意** > > レガシー録画機能は MP4 形式でのファイル出力に対応していません。 > MP4 形式でのファイル出力を利用する場合は [録画機能 (セッション単位)](RECORDING.html) をご利用ください。 > **重要** > > レガシー録画機能と録画機能 (セッション単位) はチャネル単位で異なる仕組みを同時に利用できます。 > 例えば、channel_id a ではレガシー録画機能、channel_id b では録画機能(セッション単位)のように利用することができます。 ## 概要 Sora では、配信している映像や音声を録画、録音して保存できます。 配信されている映像をできるかぎりそのまま保存するため、CPU リソースを最小限に抑えることができます。 出力される録画ファイルは WebM 形式です。映像のみの録画、音声のみの録音にも対応しています。 録画時には一切トランスコードを行っていません。配信された映像や音声をそのままに記録します。 ## 用語 **一括録画ファイル** : 切断または [StopRecording](OBSOLETE_API_LEGACY_RECORDING.html#fd0de5) API の実行、または録画期限が切れた場合に一つのファイルとして出力される動画ファイル **分割録画ファイル** : `split_duration` で指定した時間ごとに区切られ分割されて出力される動画ファイル ## 録画ファイルの出力 録画ファイルの出力には 3 パターンあります。 ### 一括録画ファイルのみ出力 - `split_duration` を指定していない 上記を満たした場合、1 接続で 1 つ録画ファイルが出力されます。 ### 分割録画ファイルのみ出力 - `split_duration` が指定されている - `expire_time` が `0` に指定されている - `split_only` が `true` に指定されている 上記を満たした場合、分割された録画ファイルのみが出力されます。 ### 一括録画ファイルと分割録画ファイルの両方が出力 - `sora.conf` で `recording_dual_output` が `true` に指定されている - `split_duration` が指定されている 上記を満たした場合、 1 接続で 1 つの録画ファイルと分割された録画ファイルの両方が出力されます。 イベントウェブフックも一括録画、分割録画、両方のイベントウェブフックリクエストが送信されます。 ## 制限 ### コーデック 録画 (録音) は、映像コーデックに VP8 と VP9 と H.264 と AV1 、また音声コーデックに Opus を選択した場合のみ利用できます。 > **警告** > > - H.265 の録画には非対応です > - B フレームの録画には非対応です ### 解像度 WebRTC では配信側の CPU リソースが不足した場合や、 回線の品質が悪化した場合に解像度を動的に変更します。 そのため録画したデータの途中で解像度が低くなる可能性があります。 ### 音声や映像のクライアント側でのトラック削除 クライアント側でシグナリング接続時に音声や映像を有効にした状態で、 クライアント側で音声トラック、または映像トラックのどちらかを削除した場合でも録画は行われます。 さらに追加して戻した形であれば録画側も戻ります。 ただし、音声と映像両方のトラックを削除した場合は正常に録画が行われません。 ### マルチストリーム機能での録画 対応しています。 ### サイマルキャスト機能での録画 対応しています。 サイマルキャストを利用している際の録画は **一番優先度が低い** ストリーム、すなわちデフォルトでは最も高い画質の映像を録画します。 詳細はサイマルキャストの [映像の優先度](SIMULCAST.html#36c708) をご確認ください。 ### スポットライト機能での録画 対応しています。 サイマルキャストを利用している際の録画は **一番優先度が低い** ストリーム、すなわちデフォルトでは最も高い画質の映像を録画します。 詳細はサイマルキャストの [映像の優先度](SIMULCAST.html#36c708) をご確認ください。 ### キーフレーム要求間隔 録画機能利用時の Sora からのキーフレーム要求間隔は 20 秒に固定されています。 そのため、分割録画の最小時間は 20 秒 + `split_duration` に指定した秒数となります。 もし録画時のキーフレーム要求間隔を変更したい場合は、サポートまでご連絡ください。 ## 無変換録画 WebRTC 経由で流れてきている映像や音声を変換せず、 そのまま録画するファイルの形式に組み立て直してファイルを保存します。 そのため、CPU リソースを最小限に抑えられます。 ブラウザでの録画など、通常の録画は変換が入るため CPU に多くの負荷がかかります。 変換を行わないため、録画を終了した数秒後には録画したファイルを取得できます。 解像度は送られてきた映像の最大値を録画ファイルの解像度として使用します。 ## 録画の開始と終了について Sora の録画機能は **明示的にチャネルの録画を停止するか、 チャネルの録画開始から指定した期限が過ぎるまでは、 そのチャネルでの配信を自動で録画する** といった機能になります。 ## sora.conf の設定による録画指定制限について 録画ファイルが大きくならないように、sora.conf の指定で録画開始時のオプションを制限することができます。 設定の詳細は以下をご確認ください。 - [recording_max_expire_time](SORA_CONF.html#f3ff8d) - [recording_max_split_duration](SORA_CONF.html#927da9) - [recording_expire_time_required](SORA_CONF.html#fcfa2d) - [recording_dual_output](SORA_CONF.html#4cc9c0) ## 録画関連イベントのウェブフックについて ### recording.started イベントウェブフック 録画開始 API が実行されたタイミングで `recording.started` リクエストを送信します。 詳しくは `recording.started` をご確認ください。 ### recording.report イベントウェブフック 録画終了 API が実行されたか、 録画の期限が切れたタイミングで `recording.report` リクエストを送信します。 詳しくは `recording.report` をご確認ください。 ### archive.started ウェブフック 録画ファイルを保存しはじめたタイミングで `archive.started` リクエストを送信します。 詳しくは [archive.started](EVENT_WEBHOOK.html#462c97) をご確認ください。 ### archive.available イベントウェブフック 一括録画ファイルが出力されたタイミングで `archive.available` リクエストを送信します。 詳しくは [archive.available](EVENT_WEBHOOK.html#de9132) をご確認ください。 ### split-archive.available イベントウェブフック 録画ファイル分割出力機能を有効にした場合、 分割された録画ファイルが出力されたタイミングで `split-archive.available` リクエストを送信します。 詳しくは [split-archive.available](EVENT_WEBHOOK.html#555071) をご確認ください。 ### split-archive.end イベントウェブフック 録画ファイル分割出力機能を有効にした場合、 分割された録画が終了したタイミングで `split-archive.end` リクエストを送信します。 詳しくは [split-archive.end](EVENT_WEBHOOK.html#31be7a) をご確認ください。 ### archive.failed イベントウェブフック 録画ファイルの保存に失敗した場合、 `archive.failed` リクエストを送信します。 詳しくは [archive.failed](EVENT_WEBHOOK.html#5006f8) をご確認ください。 ## 一括録画ファイル出力のみ 一括録画ファイル出力のみの場合は `sora.conf` の [archive_dir](SORA_CONF.html#ad2156) に指定したディレクトリに `recording_id` 名のディレクトリ以下にファイルが出力されます。 `recording_id` は録画開始 API を実行したときに戻ってくる値で、 Base32 でエンコードされた UUIDv4 となります。 ディレクトリ構造: ``` ├── archive │ ├── 1CS9QJ0XPN4C76HBGBN6MGMK5M │ │ ├── archive-A4756MXP914ZB265E92JE3ZMWC.json │ │ ├── archive-A4756MXP914ZB265E92JE3ZMWC.webm │ │ ├── archive-H2NDA2YCGH7S1E9CVMFMXMA34R.json │ │ ├── archive-H2NDA2YCGH7S1E9CVMFMXMA34R.webm │ │ ├── archive-PBVZQQN3JS3MQF8XHVFXDMCEEC.json │ │ ├── archive-PBVZQQN3JS3MQF8XHVFXDMCEEC.webm │ │ └── report-1CS9QJ0XPN4C76HBGBN6MGMK5M.json │ └── CZZ8A8KZB16A1DF5PKERBHGFNR │ ├── archive-3B7AFF8ZRX6VNEYV40B35Z9S2C.json │ ├── archive-3B7AFF8ZRX6VNEYV40B35Z9S2C.webm │ ├── archive-DGSN3TC0E91RSCZT5KVPRWCDHR.json │ ├── archive-DGSN3TC0E91RSCZT5KVPRWCDHR.webm │ └── report-CZZ8A8KZB16A1DF5PKERBHGFNR.json ``` > **注意** > > `archive_dir` と `archive_tmp_dir` は違うディレクトリを指定してください ### archive- #### 一括録画ファイル 一括録画ファイルは `/archive-.webm` に WebM 形式で出力されます。 #### 一括録画メタデータファイル 一括録画メタデータファイルは `/archive-.json` に JSON 形式で出力されます。 メタデータファイルには WebM ファイルがいつ出力され、どんな形式なのか、開始時刻や終了時刻などの情報が含まれています。 - start_timestamp- この録画が開始された時刻を RFC 3339 (UTC) で表しています - stop_timestamp- この録画が終了した時刻を RFC 3339 (UTC) で表しています - start_time- この録画が開始された時刻を UNIX 時間で表しています - stop_time- この録画が終了した時刻を UNIX 時間で表しています **stats は省略しています** ```javascript { "audio": true, "audio_codec_type": "OPUS", "channel_id": "sora", "session_id": "JA8FB89ZJS1H9CV5GN3NCT5RA0", "client_id": "GK2R6PSDYX68VDQPRX4FVVFN8W", "bundle_id": "GK2R6PSDYX68VDQPRX4FVVFN8W", "connection_id": "GK2R6PSDYX68VDQPRX4FVVFN8W", "created_at": 1615524156, "file_path": "/path/to/sora/archive/WHEJ888HQ55KDCFE3TZ4VPFQHR/archive-GK2R6PSDYX68VDQPRX4FVVFN8W.webm", "filename": "WHEJ888HQ55KDCFE3TZ4VPFQHR/archive-GK2R6PSDYX68VDQPRX4FVVFN8W.webm", "metadata_file_path": "/path/to/sora/archive/WHEJ888HQ55KDCFE3TZ4VPFQHR/archive-GK2R6PSDYX68VDQPRX4FVVFN8W.json", "metadata_filename": "WHEJ888HQ55KDCFE3TZ4VPFQHR/archive-GK2R6PSDYX68VDQPRX4FVVFN8W.json", "recording_id": "WHEJ888HQ55KDCFE3TZ4VPFQHR", "size": 0, "start_time": 1615524137, "start_time_offset": 7, "start_timestamp": "2021-03-12T04:42:17.455668Z", "stats": {}, "stop_time": 1615524154, "stop_time_offset": 24, "stop_timestamp": "2021-03-12T04:42:34.094375Z", "label": "WebRTC SFU Sora", "node_name": "node1@192.0.2.10", "event_metadata": {"spam": "egg"}, "video": true, "video_bit_rate": 1000, "video_codec_type": "VP9", "video_vp9_params": { "profile_id": 0 }, "video_height": 480, "video_width": 640, "format": "mp4" } ``` ### report- 録画終了時に、それまでにそのチャネルで録画したファイル一覧が記載されているレポートファイルが JSON 形式で出力されます。 録画終了は [StopRecording](OBSOLETE_API_LEGACY_RECORDING.html#fd0de5) API を使用して指定したチャネルに対する録画を停止するか、 録画の期限が切れた場合のふたつのパターンがあります。 このファイルは主にマルチストリームや途中で切れてしまった場合などを考慮しており、 録画ファイルのグルーピングを目的としたファイルです。 ファイルは `/report-.json` に出力されます。 - トップレベルの start_timestamp- [StartRecording](OBSOLETE_API_LEGACY_RECORDING.html#c5b527) API を受け付けた時刻を RFC 3339 (UTC) で表しています - トップレベルの stop_timestamp- [StopRecording](OBSOLETE_API_LEGACY_RECORDING.html#fd0de5) API を受け付けた時刻か、 [StartRecording](OBSOLETE_API_LEGACY_RECORDING.html#c5b527) API で設定された期限の時刻を RFC 3339 (UTC) で表しています - archives 内の start_time_offset- [StartRecording](OBSOLETE_API_LEGACY_RECORDING.html#c5b527) API を叩いてから何秒経過した後にこの録画が開始したかを表しています - archives 内の stop_time_offset- [StartRecording](OBSOLETE_API_LEGACY_RECORDING.html#c5b527) API を叩いてから何秒経過した後にこの録画が終了したかを表しています ```javascript { "archives": [ { "client_id": "GK2R6PSDYX68VDQPRX4FVVFN8W", "bundle_id": "GK2R6PSDYX68VDQPRX4FVVFN8W", "connection_id": "GK2R6PSDYX68VDQPRX4FVVFN8W", "file_path": "/path/to/sora/archive/WHEJ888HQ55KDCFE3TZ4VPFQHR/archive-GK2R6PSDYX68VDQPRX4FVVFN8W.webm", "filename": "WHEJ888HQ55KDCFE3TZ4VPFQHR/archive-GK2R6PSDYX68VDQPRX4FVVFN8W.webm", "metadata_file_path": "/path/to/sora/archive/WHEJ888HQ55KDCFE3TZ4VPFQHR/archive-GK2R6PSDYX68VDQPRX4FVVFN8W.json", "metadata_filename": "WHEJ888HQ55KDCFE3TZ4VPFQHR/archive-GK2R6PSDYX68VDQPRX4FVVFN8W.json", "size": 0, "start_time_offset": 0, "start_timestamp": "2021-03-12T04:42:17.455668Z", "stop_time_offset": 17, "stop_timestamp": "2021-03-12T04:42:34.094375Z", "label": "WebRTC SFU Sora", "node_name": "node1@192.0.2.10" } ], "channel_id": "sora", "created_at": 1615524137, "expire_time": 3600, "expired_at": 1615527737, "file_path": "/path/to/sora/archive/WHEJ888HQ55KDCFE3TZ4VPFQHR/report-WHEJ888HQ55KDCFE3TZ4VPFQHR.json", "filename": "WHEJ888HQ55KDCFE3TZ4VPFQHR/report-WHEJ888HQ55KDCFE3TZ4VPFQHR.json", "metadata": {"spam": "egg"}, "recording_id": "WHEJ888HQ55KDCFE3TZ4VPFQHR", "split_only": false, "start_timestamp": "2021-03-12T04:42:17.455668Z", "stop_timestamp": "2021-03-12T04:42:34.094375Z" } ``` ## 分割録画ファイル出力のみ Sora では [StartRecording](OBSOLETE_API_LEGACY_RECORDING.html#c5b527) API 実行時に `split_duration` と `split_only: true` と `expire_time: 0` の 3 つを指定することで、 録画ファイルを指定した間隔で出力する機能を提供しています。 > **重要** > > 分割の最小単位はキーフレームから次のキーフレームまでです。例えば `split_duration` を 1 秒に設定した場合は、1 秒経過後に次のキーフレームが来たタイミングで分割出力されます。 録画が完了したファイルは `sora.conf` の [archive_dir](SORA_CONF.html#ad2156) に指定したディレクトリに `recording_id` 名のディレクトリ以下にファイルが出力されます。 `recording_id` は [StartRecording](OBSOLETE_API_LEGACY_RECORDING.html#c5b527) API を実行したときに戻ってくる値です。 ### 録画ファイル分割出力のみを行う 録画開始 API 実行時に `split_duration` と `split_only: true` と `expire_time: 0` の 3 つを指定することで、 録画ファイル分割出力 **のみ** を行うことが可能になります。 ディレクトリ構造: ``` ├── archive │ ├── 1CS9QJ0XPN4C76HBGBN6MGMK5M │ │ ├── split-archive-end-A4756MXP914ZB265E92JE3ZMWC.json │ │ ├── split-archive-A4756MXP914ZB265E92JE3ZMWC_0001.json │ │ ├── split-archive-A4756MXP914ZB265E92JE3ZMWC_0001.webm │ │ ├── split-archive-A4756MXP914ZB265E92JE3ZMWC_0002.json │ │ ├── split-archive-A4756MXP914ZB265E92JE3ZMWC_0002.webm │ │ ├── split-archive-A4756MXP914ZB265E92JE3ZMWC_0003.json │ │ ├── split-archive-A4756MXP914ZB265E92JE3ZMWC_0003.webm │ │ ├── split-archive-A4756MXP914ZB265E92JE3ZMWC_0003.json │ │ ├── split-archive-A4756MXP914ZB265E92JE3ZMWC_0003.webm │ │ └── report-1CS9QJ0XPN4C76HBGBN6MGMK5M.json │ └── CZZ8A8KZB16A1DF5PKERBHGFNR │ ├── split-archive-end-3B7AFF8ZRX6VNEYV40B35Z9S2C.json │ ├── split-archive-end-DGSN3TC0E91RSCZT5KVPRWCDHR.json │ ├── split-archive-3B7AFF8ZRX6VNEYV40B35Z9S2C_0001.json │ ├── split-archive-3B7AFF8ZRX6VNEYV40B35Z9S2C_0001.webm │ ├── split-archive-DGSN3TC0E91RSCZT5KVPRWCDHR_0001.json │ ├── split-archive-DGSN3TC0E91RSCZT5KVPRWCDHR_0001.webm │ ├── split-archive-DGSN3TC0E91RSCZT5KVPRWCDHR_0002.json │ ├── split-archive-DGSN3TC0E91RSCZT5KVPRWCDHR_0002.webm │ └── report-CZZ8A8KZB16A1DF5PKERBHGFNR.json ``` ### split-archive-_ #### 分割録画ファイル 分割録画ファイルは `/split-archive-_.webm` に WebM 形式で出力されます。 #### 分割録画メタデータファイル 分割録画メタデータファイルは `/split-archive-_.json` に JSON 形式で出力されます。 - split_index- ファイル名につくインデックスです - 0001 から始まり 9999 の後は 10000 となります **stats は省略しています** ```javascript { "audio": true, "audio_codec_type": "OPUS", "recording_id": "CZZ8A8KZB16A1DF5PKERBHGFNR", "file_path": "/path/to/sora/archive/CZZ8A8KZB16A1DF5PKERBHGFNR/split-archive-3B7AFF8ZRX6VNEYV40B35Z9S2C_001.webm", "filename": "CZZ8A8KZB16A1DF5PKERBHGFNR/split-archive-3B7AFF8ZRX6VNEYV40B35Z9S2C_001.webm", "metadata_file_path": "/path/to/sora/split-archive/CZZ8A8KZB16A1DF5PKERBHGFNR/archive-3B7AFF8ZRX6VNEYV40B35Z9S2C_001.json", "metadata_filename": "CZZ8A8KZB16A1DF5PKERBHGFNR/split-archive-3B7AFF8ZRX6VNEYV40B35Z9S2C_001.json", "channel_id": "sora", "session_id": "JA8FB89ZJS1H9CV5GN3NCT5RA0", "client_id": "3B7AFF8ZRX6VNEYV40B35Z9S2C", "bundle_id": "3B7AFF8ZRX6VNEYV40B35Z9S2C", "connection_id": "3B7AFF8ZRX6VNEYV40B35Z9S2C", "split_index": "0001", "created_at": 1604656364, "size": 823263, "start_time": 1604656354, "start_time_offset": 4, "start_timestamp": "2020-11-06T09:52:34.696758Z", "stats": {}, "stop_time": 1604656364, "stop_time_offset": 14, "stop_timestamp": "2020-11-06T09:52:44.493179Z", "label": "WebRTC SFU Sora", "node_name": "node1@192.0.2.10", "event_metadata": {"spam": "egg"}, "video": true, "video_bit_rate": 1000, "video_codec_type": "VP9", "video_vp9_params": { "profile_id": 0 }, "video_height": 480, "video_width": 640, "format": "mp4" } ``` ### split-archive-end- #### 分割録画終了メタデータファイル 分割録画終了メタデータファイルは `/split-archive-end-.json` に JSON 形式で出力されます。 **stats は省略しています** ```javascript { "audio": true, "audio_codec_type": "OPUS", "split_last_index": "0042", "recording_id": "CZZ8A8KZB16A1DF5PKERBHGFNR", "file_path": "/path/to/sora/archive/CZZ8A8KZB16A1DF5PKERBHGFNR/split-archive-end-3B7AFF8ZRX6VNEYV40B35Z9S2C.json", "filename": "CZZ8A8KZB16A1DF5PKERBHGFNR/split-archive-end-3B7AFF8ZRX6VNEYV40B35Z9S2C.json", "channel_id": "sora", "session_id": "JA8FB89ZJS1H9CV5GN3NCT5RA0", "client_id": "3B7AFF8ZRX6VNEYV40B35Z9S2C", "bundle_id": "3B7AFF8ZRX6VNEYV40B35Z9S2C", "connection_id": "3B7AFF8ZRX6VNEYV40B35Z9S2C", "start_time": 1604656354, "start_time_offset": 4, "start_timestamp": "2020-11-06T09:52:34.696758Z", "stats": {}, "stop_time": 1604656364, "stop_time_offset": 14, "stop_timestamp": "2020-11-06T09:52:44.493179Z", "label": "WebRTC SFU Sora", "node_name": "node1@192.0.2.10", "event_metadata": {"spam": "egg"}, "video": true, "video_bit_rate": 1000, "video_codec_type": "VP9", "video_vp9_params": { "profile_id": 0 }, "video_height": 480, "video_width": 640, "format": "mp4" } ``` #### 録画ファイル分割出力終了時 接続単位での録画が終了したタイミングでイベントウェブフックリクエスト `split-archive.end` がリクエスト送信されます。 詳細は [split-archive.end](EVENT_WEBHOOK.html#31be7a) をご確認ください。 ### report- 録画終了時に、それまでにそのチャネルで録画したファイル一覧が記載されているレポートファイルが JSON 形式で出力されます。 録画終了は [StopRecording](OBSOLETE_API_LEGACY_RECORDING.html#fd0de5) API を使用して指定したチャネルに対する録画を停止するか、 録画の期限が切れた場合のふたつのパターンがあります。 このファイルは主にマルチストリームや途中で切れてしまった場合などを考慮しており、 録画ファイルのグルーピングを目的としたファイルです。 ファイルは `/report-.json` に出力されます。 分割録画ファイル出力のみの場合は archives には `connection_id` や `client_id` といった接続情報と、 分割録画ファイルの最後のインデックス番号のみが含まれます。 - トップレベルの start_timestamp- [StartRecording](OBSOLETE_API_LEGACY_RECORDING.html#c5b527) API を受け付けた時刻を RFC 3339 (UTC) で表しています - トップレベルの stop_timestamp- [StopRecording](OBSOLETE_API_LEGACY_RECORDING.html#fd0de5) API を受け付けた時刻か、 [StartRecording](OBSOLETE_API_LEGACY_RECORDING.html#c5b527) API で設定された期限の時刻を RFC 3339 (UTC) で表しています - archives 内の start_time_offset- [StartRecording](OBSOLETE_API_LEGACY_RECORDING.html#c5b527) API を叩いてから何秒経過した後にこの録画が開始したかを表しています - archives 内の stop_time_offset- [StartRecording](OBSOLETE_API_LEGACY_RECORDING.html#c5b527) API を叩いてから何秒経過した後にこの録画が終了したかを表しています ```javascript { "archives": [ { "client_id": "GK2R6PSDYX68VDQPRX4FVVFN8W", "bundle_id": "GK2R6PSDYX68VDQPRX4FVVFN8W", "connection_id": "GK2R6PSDYX68VDQPRX4FVVFN8W", "split_last_index": "0042", "start_time_offset": 4, "start_timestamp": "2020-11-06T09:52:34.696758Z", "stop_time_offset": 14, "stop_timestamp": "2020-11-06T09:52:44.493179Z", "label": "WebRTC SFU Sora", "node_name": "node1@192.0.2.10" } ], "channel_id": "sora", "created_at": 1615524137, "expire_time": 3600, "expired_at": 1615527737, "file_path": "/path/to/sora/archive/WHEJ888HQ55KDCFE3TZ4VPFQHR/report-GK2R6PSDYX68VDQPRX4FVVFN8W.json", "filename": "WHEJ888HQ55KDCFE3TZ4VPFQHR/report-GK2R6PSDYX68VDQPRX4FVVFN8W.json", "recording_id": "WHEJ888HQ55KDCFE3TZ4VPFQHR", "split_duration": 3600, "split_only": false, "metadata": {"spam": "egg"}, "start_timestamp": "2020-11-06T09:52:34.696758Z", "stop_timestamp": "2020-11-06T09:52:44.493179Z" } ``` ## 一括録画ファイルと分割録画ファイル [StartRecording](OBSOLETE_API_LEGACY_RECORDING.html#c5b527) API 実行時に `split_only` を有効にしない限り、 単一ファイルと分割ファイルの二つが出力されます。 一括録画ファイルと分割録画ファイルのいいところ取りですが、その分ストレージの容量も 2 倍消費します。 出力されるファイルは単一と分割のファイルが混ざった形式になります。 ディレクトリ構造: ``` ├── archive │ ├── 1CS9QJ0XPN4C76HBGBN6MGMK5M │ │ ├── split-archive-end-A4756MXP914ZB265E92JE3ZMWC.json │ │ ├── split-archive-A4756MXP914ZB265E92JE3ZMWC_0001.json │ │ ├── split-archive-A4756MXP914ZB265E92JE3ZMWC_0001.webm │ │ ├── split-archive-A4756MXP914ZB265E92JE3ZMWC_0002.json │ │ ├── split-archive-A4756MXP914ZB265E92JE3ZMWC_0002.webm │ │ ├── split-archive-A4756MXP914ZB265E92JE3ZMWC_0003.json │ │ ├── split-archive-A4756MXP914ZB265E92JE3ZMWC_0003.webm │ │ ├── split-archive-A4756MXP914ZB265E92JE3ZMWC_0003.json │ │ ├── split-archive-A4756MXP914ZB265E92JE3ZMWC_0003.webm │ │ ├── archive-A4756MXP914ZB265E92JE3ZMWC.json │ │ ├── archive-A4756MXP914ZB265E92JE3ZMWC.webm │ │ └── report-1CS9QJ0XPN4C76HBGBN6MGMK5M.json │ └── CZZ8A8KZB16A1DF5PKERBHGFNR │ ├── split-archive-end-3B7AFF8ZRX6VNEYV40B35Z9S2C.json │ ├── split-archive-3B7AFF8ZRX6VNEYV40B35Z9S2C_0001.json │ ├── split-archive-3B7AFF8ZRX6VNEYV40B35Z9S2C_0001.webm │ ├── split-archive-end-DGSN3TC0E91RSCZT5KVPRWCDHR.json │ ├── split-archive-DGSN3TC0E91RSCZT5KVPRWCDHR_0001.json │ ├── split-archive-DGSN3TC0E91RSCZT5KVPRWCDHR_0001.webm │ ├── split-archive-DGSN3TC0E91RSCZT5KVPRWCDHR_0002.json │ ├── split-archive-DGSN3TC0E91RSCZT5KVPRWCDHR_0002.webm │ ├── archive-3B7AFF8ZRX6VNEYV40B35Z9S2C.json │ ├── archive-3B7AFF8ZRX6VNEYV40B35Z9S2C.webm │ ├── archive-DGSN3TC0E91RSCZT5KVPRWCDHR.json │ ├── archive-DGSN3TC0E91RSCZT5KVPRWCDHR.webm │ └── report-CZZ8A8KZB16A1DF5PKERBHGFNR.json ``` ### report- 出力される report ファイルは単一と分割が混ざった形式になります。 - トップレベルの start_timestamp- [StartRecording](OBSOLETE_API_LEGACY_RECORDING.html#c5b527) API を受け付けた時刻を RFC 3339 (UTC) で表しています - トップレベルの stop_timestamp- [StopRecording](OBSOLETE_API_LEGACY_RECORDING.html#fd0de5) API を受け付けた時刻か、 [StartRecording](OBSOLETE_API_LEGACY_RECORDING.html#c5b527) API で設定された期限の時刻を RFC 3339 (UTC) で表しています - archives 内の start_time_offset- [StartRecording](OBSOLETE_API_LEGACY_RECORDING.html#c5b527) API を叩いてから何秒経過した後にこの録画が開始したかを表しています - archives 内の stop_time_offset- [StartRecording](OBSOLETE_API_LEGACY_RECORDING.html#c5b527) API を叩いてから何秒経過した後にこの録画が終了したかを表しています ```javascript { "archives": [ { "client_id": "GK2R6PSDYX68VDQPRX4FVVFN8W", "bundle_id": "GK2R6PSDYX68VDQPRX4FVVFN8W", "connection_id": "GK2R6PSDYX68VDQPRX4FVVFN8W", "file_path": "/path/to/sora/archive/WHEJ888HQ55KDCFE3TZ4VPFQHR/archive-GK2R6PSDYX68VDQPRX4FVVFN8W.webm", "filename": "WHEJ888HQ55KDCFE3TZ4VPFQHR/archive-GK2R6PSDYX68VDQPRX4FVVFN8W.webm", "metadata_file_path": "/path/to/sora/archive/WHEJ888HQ55KDCFE3TZ4VPFQHR/archive-GK2R6PSDYX68VDQPRX4FVVFN8W.json", "metadata_filename": "WHEJ888HQ55KDCFE3TZ4VPFQHR/archive-GK2R6PSDYX68VDQPRX4FVVFN8W.json", "size": 0, "start_time_offset": 0, "start_timestamp": "2021-03-12T04:42:17.455668Z", "stop_time_offset": 17, "stop_timestamp": "2021-03-12T04:42:34.094375Z", "split_last_index": "0042", "label": "WebRTC SFU Sora", "node_name": "node1@192.0.2.10" } ], "channel_id": "sora", "created_at": 1615524137, "expire_time": 3600, "expired_at": 1615527737, "file_path": "/path/to/sora/archive/WHEJ888HQ55KDCFE3TZ4VPFQHR/report-WHEJ888HQ55KDCFE3TZ4VPFQHR.json", "filename": "WHEJ888HQ55KDCFE3TZ4VPFQHR/report-WHEJ888HQ55KDCFE3TZ4VPFQHR.json", "recording_id": "WHEJ888HQ55KDCFE3TZ4VPFQHR", "label": "WebRTC SFU Sora", "node_name": "node1@192.0.2.10", "split_duration": 3600, "split_only": false, "metadata": {"spam": "egg"}, "start_timestamp": "2021-03-12T04:42:17.455668Z", "stop_timestamp": "2021-03-12T04:42:34.094375Z" } ``` ## 録画ファイル出力失敗時の録画一時ファイル 何らかの理由で録画ファイル出力が失敗した場合、 `archive_tmp_dir` で指定したディレクトリに録画一時ファイルが削除されずに残ります。そのため、定期的な削除が必要です。 この録画一時ファイルは WebM 形式のためそのまま再生できます。 ## シグナリング通知 シグナリング通知で録画開始と終了を通知できます。 詳細は [録画のシグナリング通知](SIGNALING_NOTIFY.html#7ce275) をご確認ください。 ## 録画ファイル合成ツール マルチストリームを録画した場合はそれぞれの接続に対して録画ファイルが出力されます。このそれぞれ分かれた録画ファイルを合成して一つにするツールをオープンソースとして公開しています。 詳細は [WebRTC 録画合成ツール Hisui](HISUI.html) をご確認ください。 ## 試してみる Sora では録画機能を試すための開発ツールを提供しています。 [開発ツール](DEVTOOLS.html) を参照の上、開発ツールを有効にしてください。 ここでは Sora が立っているサーバーは example.com としています。 ### チャネルの録画開始 API を叩いて録画を開始してください。 console: ``` $ curl -sS \ -X POST \ http://example.com:3000/ \ -H "x-sora-target: Sora_20161101.StartRecording" \ --json '{"channel_id":"sora","expire_time":3600}' \ | jq . ``` その後 `https://example.com/sendonly.html` を開き、 connect ボタンを押して配信を開始します。 切断またはチャネルの録画終了、もしくはチャネルの録画期限が来たタイミングでクライアントの録画は終了します。 ### チャネルの録画終了 チャネルの録画を終了するには API を叩く必要があります。 console: ``` $ curl -sS \ -X POST \ http://example.com:3000/ \ -H "x-sora-target: Sora_20161101.StopRecording" \ --json '{"channel_id":"sora"}' \ | jq . ``` その後 archive/ ディレクトリに webm 形式のファイルが出力されます。 Chrome または Firefox にドラッグアンドドロップして、動作を確認してください。 ## 録画関連ファイルアップローダー > **重要** > > このツールはサポート対象外です 時雨堂では、録画関連ファイルを [Amazon S3](https://aws.amazon.com/jp/s3/) 、または S3 互換オブジェクトストレージにアップロードするツールを OSS として Apache License 2.0 で公開しています。 これは、Sora のクラウド版である [Sora Cloud](https://sora-cloud.shiguredo.jp) で利用している仕組みを 切り出したものです。 [shiguredo/sora-archive-uploader: Sora Archive Uploader](https://github.com/shiguredo/sora-archive-uploader) ## シーケンス図 ### StopRecording API ```mermaid sequenceDiagram autonumber participant C as クライアント participant S as Sora participant A as アプリケーションサーバー note over C,A: 認証成功 S->>+C: "type": "offer" C->>-S: "type": "answer" note over C,A: WebRTC 確立 A->>+S: HTTP API StartRecording S-->>-A: 200 OK S->>+A: イベントウェブフック
"type": "recording.started" A-->>-S: 200 OK note over C,A: 録画中 S->>+A: イベントウェブフック
"type": "archive.started" A-->>-S: 200 OK A->>+S: HTTP API StopRecording S-->>-A: 200 OK note over C,A: 録画終了 S->>+A: イベントウェブフック
"type": "archive.available" A-->>-S: 200 OK S->>+A: イベントウェブフック
"type": "recording.report" A-->>-S: 200 OK ``` ### 録画期限切れ ```mermaid sequenceDiagram autonumber participant C as クライアント participant S as Sora participant A as アプリケーションサーバー note over C,A: 認証成功 S->>+C: "type": "offer" C->>-S: "type": "answer" note over C,A: WebRTC 確立 A->>+S: HTTP API StartRecording S-->>-A: 200 OK S->>+A: イベントウェブフック
"type": "recording.started" A-->>-S: 200 OK note over C,A: 録画中 S->>+A: イベントウェブフック
"type": "archive.started" A-->>-S: 200 OK note over C,A: 期限切れにより録画終了 S->>+A: イベントウェブフック
"type": "archive.available" A-->>-S: 200 OK S->>+A: イベントウェブフック
"type": "recording.report" A-->>-S: 200 OK ``` ### クライアント切断 ```mermaid sequenceDiagram autonumber participant C as クライアント participant S as Sora participant A as アプリケーションサーバー note over C,A: 認証成功 S->>+C: "type": "offer" C->>-S: "type": "answer" note over C,A: WebRTC 確立 A->>+S: HTTP API StartRecording S-->>-A: 200 OK S->>+A: イベントウェブフック
"type": "recording.started" A-->>-S: 200 OK note over C,A: 録画中 S->>+A: イベントウェブフック
"type": "archive.started" A-->>-S: 200 OK C->>S: "type": "disconnect" S->>+A: イベントウェブフック
"type" :"connection.destroyed" A-->-S: 200 OK S->>C: WebSocket Close note over C,A: クライアント切断により録画終了 S->>+A: イベントウェブフック
"type": "archive.available" A-->>-S: 200 OK S->>+A: イベントウェブフック
"type": "recording.report" A-->>-S: 200 OK ``` # 統計エクスポーター機能 *バージョン 2025.1.0 で削除。* > **注意** > > この機能は 2025 年 6 月リリースの Sora にて廃止しました。 今後は [統計ウェブフック機能](STATS_WEBHOOK.html) をご利用ください。 ## 概要 Sora 経由で統計情報コレクターに向けて統計情報をエクスポートする機能です。 ## 注意 ### IPv6 非対応 現時点で、統計エクスポーターは IPv6 を利用できません。 ## HTTP/2 - 統計コレクターサーバーは HTTP/2 に対応している必要があります - h2c と h2 の両方に対応しています - `http://` から始めると h2c を利用します - `https://` から始めると h2 を利用します ## WebRTC Stats Collector Kohaku **URL**: Kohaku は統計エクスポーター対応の統計コレクターです。 ## 設定 ### stats_collector_url 統計情報を収集するコレクターの URL を指定します。 HTTP または HTTPS の URL が指定できます。 ```ini stats_collector_url = http://192.0.2.10:5890/collector ``` ### default_stats_exporter `stats_collector_url` が指定されていた場合、デフォルトでは統計情報をコレクターに送信します。 もし、統計情報の送信を接続ごとに行いたい場合、この設定を `false` にし、 統計情報を送信したい接続の認証成功時に `"stats_exporter": true` を払い出すようにしてください。 ```ini default_stats_exporter = false ``` ### stats_exporter_number 統計情報を出力するエクスポーターの数を指定できます。 基本的にはデフォルトの 5 で足りますが、同時接続数が多い場合は変更をお勧めします。 ```ini stats_exporter_number = 5 ``` ### stats_exporter_tls_fullchain_file mTLS を利用するための設定で、中間証明書を含むクライアント証明書を PEM 形式で設定して下さい。 ```ini stats_exporter_tls_fullchain_file = /path/to/fullchain.pem ``` ### stats_exporter_tls_privkey_file 統計コレクターサーバーと mTLS を利用するための設定で、クライアント証明書の秘密鍵を PEM 形式で設定して下さい。 > **重要** > > 秘密鍵にパスフレーズが設定されている場合はエラーとなります ```ini stats_exporter_tls_privkey_file = /path/to/privkey.pem ``` ### stats_exporter_tls_verify_cacert_file > **注釈** > > CA 証明書を指定しない場合、OS 組み込みの証明書を利用します。詳細は [ウェブフックリクエストなどの送信先サーバー証明書の検証に利用する OS 組み込みのルート CA 証明書について](WEBHOOK.html#e8a845) をご確認ください。 統計コレクターサーバーとの通信に HTTPS を利用した際、サーバー証明書のチェックを行う CA ファイルを PEM 形式で設定して下さい。 ```ini stats_exporter_tls_verify_cacert_file = /path/to/server_cacert.pem ``` ## エクスポーター 統計情報をコレクターに対して送ります。 ### 共通 - type- 統計情報の種類情報が入ります - node_name- Sora のノード名が入ります - クラスター機能を利用していない場合は `sora@127.0.0.1` です - version- Sora のバージョンが入ります - label- sora.conf に設定された label が入ります - timestamp- Sora が stats を送る直前の時間 RFC3339 形式の (UTC) が入ります ### HTTP ヘッダー > **注釈** > > JSON のパース時の判断などに利用してください。 > **注意** > > `x-sora-session-webhook-type` は非推奨です、 `sora-session-webhook-type` を利用してください 統計エクスポーターの HTTP ヘッダー に `sora-stats-exporter-type` と `x-sora-stats-exporter-type` というヘッダー名で統計エクスポーターのタイプが入ってきます。 `type` が `connection.user-agent` の場合は `sora-stats-exporter-type: connection.user-agent` と `x-sora-stats-exporter-type: connection.user-agent` のように値が入ってきます。 ### type: connection.user-agent クライアントから送られてくるユーザーエージェント統計情報です。 ユーザーエージェント統計情報は W3C の [Identifiers for WebRTC's Statistics API](https://www.w3.org/TR/webrtc-stats/) に準拠している必要があります。 - type- `connection.user-agent` - channel_id- チャネル ID が入ります - role - session_id- セッション ID が入ります - client_id - connection_id - simulcast - spotlight - stats ```javascript { "channel_id": "sora", "session_id": "78K3N8E5M551XEKEWR8QN77PHW", "client_id": "NCD5EF3ME900ZDJ3SE27Y6AB6R", "connection_id": "NCD5EF3ME900ZDJ3SE27Y6AB6R", "id": "N6W0DBF6A957B01BKNJJR1HC04", "label": "WebRTC SFU Sora", "spotlight": false, "simulcast": true, "stats": [ { "id": "RTCAudioSource_5", "kind": "audio", "timestamp": 1629449091306.655, "type": "media-source", "audioLevel": 0.02237006744590594, "totalAudioEnergy": 0.15581033797981153, "totalSamplesDuration": 5.089999999999936, "trackIdentifier": "922dd031-8a4f-4122-9687-ce094fa11ee2" }, ... ], "timestamp": "2021-08-20T08:44:51.308778Z", "type": "connection.user-agent", "node_name": "sora@127.0.0.1", "version": "2023.2.0" } ``` ### type: connection.sora **現時点ではまだ対応していません** Sora にため込んでいる統計情報です。 ## type の頻度指定 変化が無かったり変化の少ない stats を送る頻度を減らしています。 デフォルト 600 秒間隔にしています。 ### type: connection.user-agent 送信頻度を抑えている Stats Type。 - codec- Sora の場合、初期値から変更される項目が無いため - local-candidate- Sora の場合、初期値から変更される項目が無いため - remote-candidate- Sora の場合、初期値から変更される項目が無いため - certificate- Sora の場合、初期値から変更される項目が無いため - peer-connection- Sora の場合、初期値から変更される項目が無いため - track- DEPRECATED 項目のため - stream- DEPRECATED 項目のため ## シーケンス図 ### DataChannel シグナリング利用時 ```mermaid sequenceDiagram autonumber participant C as クライアント participant S as Sora participant kohaku as Stats Collector Kohaku participant tsdb as TimescaleDB note over C,tsdb: WebRTC 確立 C--)S: Stats over DataChannel S->>+kohaku: Stats over HTTP/2 kohaku->>+tsdb: Insert Stats tsdb-->>-kohaku: Ack kohaku-->>-S: 200 OK ``` # Sora のクライアント SDK Sora ではクライアント向け SDK をオープンソースとして Apache 2.0 ライセンスで提供しています。 ## クライアント SDK のサポートについて クライアント SDK については Sora のサポート対象外となります。 もし SDK について不明点などがある場合は、 時雨堂の Discord サーバー () の `#sora-sdk-faq` チャンネルにてご相談ください。 ## Discord にて相談する際に必要な情報 以下の情報を提供していただけると、問題の解決がスムーズになります。 - 利用している Sora のバージョン- Sora Cloud を利用している場合は、 Sora Cloud を利用していることをお伝えください - 利用しているクライアント SDK の種類とバージョン - 最新のクライアント SDK で再現するかどうか - 詳細な再現方法 - 可能であれば、再現するコードの例- GitHub Gist など ## Sora JavaScript SDK **URL**: **npm**: **Node.js**: 20 以降 **TypeScript**: 5.1 以降 TypeScript で開発されている 依存 0 のブラウザ向け JavaScript SDK です。 詳細は [Sora JavaScript SDK](JS_SDK.html) をご確認ください。 ## Sora iOS SDK **URL**: libwebrtc の iOS SDK を利用している iOS 向けの SDK です。 詳細は [Sora iOS SDK](IOS_SDK.html) をご確認ください。 ## Sora Android SDK **URL**: libwebrtc の Android SDK を利用している Android 向けの SDK です。 詳細は [Sora Android SDK](ANDROID_SDK.html) をご確認ください。 ## Sora C++ SDK **URL**: libwebrtc を組み込んだ C++ SDK です。 複数のプラットフォームに対応しています。 - Windows - macOS - Linux- Ubuntu - Raspberry Pi OS - iOS - Android 複数のハードウェアアクセラレーションに対応しています。 - NVIDIA NVCODEC - AMD AMF - Intel VPL - Raspberry Pi VideoCore - Apple VideoToolbox また OpenH264 を利用してた H.264 もサポートしています。 詳細は [Sora C++ SDK](CPP_SDK.html) をご確認ください。 ## Sora Unity SDK **URL**: Sora C++ SDK ベースの Unity SDK です。 詳細は [Sora Unity SDK](UNITY_SDK.html) をご確認ください。 ## Sora Python SDK **URL**: **PyPI**: Sora C++ SDK ベースの Python SDK です。 ## Sora Rust SDK > **警告** > > Sora Rust SDK は開発中の SDK であることに注意してください。安定版がリリースされるまでは、API が頻繁に変更される可能性があります。 **URL**: **crates.io**: libwebrtc を組み込んだ Rust SDK です。 詳細は [Sora Rust SDK](RUST_SDK.html) をご確認ください。 ## Sora Flutter SDK > **警告** > > Sora Flutter SDK は開発中の SDK であることに注意してください。安定版がリリースされるまでは、API が頻繁に変更される可能性があります。 **URL**: libwebrtc を組み込んだ Dart で開発されている SDK で、Flutter アプリケーションから Sora を利用するための SDK です。 詳細は [Sora Flutter SDK](FLUTTER_SDK.html) をご確認ください。 # Sora JavaScript (TypeScript) SDK ## 概要 **URL**: Sora JavaScript SDK は Sora を JavaScript から使用するための仕組みです。 ## サンプル **URL**: ## ドキュメント ドキュメントは にて提供しています。 ## ライセンス Sora JavaScript SDK は [Apache License, Version 2.0](https://www.apache.org/licenses/LICENSE-2.0) で公開しています。 ## サポートについて Sora JavaScript SDK に関する質問・要望・バグなどの報告は Discord の利用をお願いします。 Sora のライセンス契約の有無に関わらず、応答時間と問題の解決を保証しませんのでご了承ください。 ただし、明らかなバグに関しては優先的に対応させていただきます。 Sora JavaScript SDK に対する有償のサポートについては提供しておりません。 ## Discord **URL**: Discord にてコミュニティを運営しています。 なにか質問したい場合は Discord サーバーへ参加してください。 Sora JavaScript SDK については `#sora-sdk-faq` で `sora-javascript-sdk` タグを指定してご利用ください。 # Sora iOS (Swift) SDK ## 概要 **URL**: Sora iOS SDK は Sora を iOS から使用するための仕組みです。 ## ドキュメント ドキュメントは にて提供しています。 ## サンプル - [WebRTC SFU Sora iOS SDK クイックスタート](https://github.com/shiguredo/sora-ios-sdk-quickstart) - [WebRTC SFU Sora iOS SDK サンプル集](https://github.com/shiguredo/sora-ios-sdk-samples) ## ライセンス Sora iOS SDK は [Apache License, Version 2.0](https://www.apache.org/licenses/LICENSE-2.0) で公開しています。 ## サポートについて Sora iOS SDK に関する質問・要望・バグなどの報告は Discord の利用をお願いします。 Sora のライセンス契約の有無に関わらず、応答時間と問題の解決を保証しませんのでご了承ください。 ただし、明らかなバグに関しては優先的に対応させていただきます。 Sora iOS SDK に対する有償のサポートについては提供しておりません。 ## Discord **URL**: Discord にてコミュニティを運営しています。 なにか質問したい場合は Discord サーバーへ参加してください。 Sora iOS SDK については `#sora-sdk-faq` で `sora-ios-sdk` タグを指定してご利用ください。 ## NAT64/DNS64 対応 ### 前提 [Supporting IPv6 DNS64/NAT64 Networks](https://developer.apple.com/library/archive/documentation/NetworkingInternetWeb/Conceptual/NetworkingOverview/UnderstandingandPreparingfortheIPv6Transition/UnderstandingandPreparingfortheIPv6Transition.html) Apple IPv6 審査対応として NAT64/DNS64 への対応が必要になります。 iOS SDK は NAT64/DNS64 へ対応しています。ただ WebRTF SFU Sora 側を NAT64/DNS64 へ対応するためには設定を追加する必要があります。 ### WebRTC SFU Sora の設定 `sora.conf` の `turn` を `true` にして、 `turn_fqdn` に FQDN を設定してください。それだけで対応は完了です。 ```ini turn_fqdn = sora.example.com ``` # Sora Android (Kotlin) SDK ## 概要 **URL**: Sora Android SDK は Sora を Android から使用するための仕組みです。 ## ドキュメント ドキュメントは にて提供しています。 ## サンプル - [WebRTC SFU Sora Android SDK クイックスタート](https://github.com/shiguredo/sora-android-sdk-quickstart) - [WebRTC SFU Sora Android SDK サンプル集](https://github.com/shiguredo/sora-android-sdk-samples) ## ライセンス Sora Android SDK は [Apache License, Version 2.0](https://www.apache.org/licenses/LICENSE-2.0) で公開しています。 ## サポートについて Sora Android SDK に関する質問・要望・バグなどの報告は Discord の利用をお願いします。 Sora のライセンス契約の有無に関わらず、応答時間と問題の解決を保証しませんのでご了承ください。 ただし、明らかなバグに関しては優先的に対応させていただきます。 Sora Android SDK に対する有償のサポートについては提供しておりません。 ## Discord **URL**: Discord にてコミュニティを運営しています。 なにか質問したい場合は Discord サーバーへ参加してください。 Sora Android SDK については `#sora-sdk-faq` で `sora-android-sdk` タグを指定してご利用ください。 # Sora Unity (C++) SDK ## 概要 **URL**: Sora Unity SDK は Sora を Unity から使用するための仕組みです。 ## ドキュメント ドキュメントは にて提供しています。 ## ライセンス Sora Unity SDK は [Apache License, Version 2.0](https://www.apache.org/licenses/LICENSE-2.0) で公開しています。 ## サポートについて Sora Unity SDK に関する質問・要望・バグなどの報告は Discord の利用をお願いします。 Sora のライセンス契約の有無に関わらず、応答時間と問題の解決を保証しませんのでご了承ください。 ただし、明らかなバグに関しては優先的に対応させていただきます。 Sora Unity SDK に対する有償のサポートについては提供しておりません。 ## Discord **URL**: Discord にてコミュニティを運営しています。 なにか質問したい場合は Discord サーバーへ参加してください。 Sora Unity SDK については `#sora-sdk-faq` で `sora-unity-sdk` タグを指定してご利用ください。 # Sora C++ SDK ## 概要 **URL**: Sora C++ SDK は Sora を C++ から使用するための仕組みです。 ## 特徴 - Windows / macOS / Linux / iOS / Android といったプラットフォームに対応しています - それぞれのプラットフォーム向けのハードウェアエンコーダー / デコーダーに対応しています 詳細は [Sora C++ SDK](https://github.com/shiguredo/sora-cpp-sdk) をご確認ください。 ## サンプル **URL**: ## ライセンス Sora C++ SDK は [Apache License, Version 2.0](https://www.apache.org/licenses/LICENSE-2.0) で公開しています。 ## サポートについて Sora C++ SDK に関する質問・要望・バグなどの報告は Discord の利用をお願いします。 Sora のライセンス契約の有無に関わらず、応答時間と問題の解決を保証しませんのでご了承ください。 ただし、明らかなバグに関しては優先的に対応させていただきます。 Sora C++ SDK に対する有償のサポートについては提供しておりません。 ## Discord **URL**: Discord にてコミュニティを運営しています。 なにか質問したい場合は Discord サーバーへ参加してください。 Sora C++ SDK については `#sora-sdk-faq` で `sora-cpp-sdk` タグを指定してご利用ください。 # Sora Python (C++) SDK ## 概要 **URL**: Sora Python SDK は Sora を Python から使用するための仕組みです。 ## 特徴 - Sora C++ SDK をベースにしています - Windows / macOS / Linux といったプラットフォームに対応しています - それぞれのプラットフォーム向けのハードウェアエンコーダー / デコーダーに対応しています ## サンプル にサンプルがあります。 ## ドキュメント ドキュメントは にて提供しています。 ## ライセンス Sora Python SDK は [Apache License, Version 2.0](https://www.apache.org/licenses/LICENSE-2.0) で公開しています。 ## サポートについて Sora Python SDK に関する質問・要望・バグなどの報告は Discord の利用をお願いします。 Sora のライセンス契約の有無に関わらず、応答時間と問題の解決を保証しませんのでご了承ください。 ただし、明らかなバグに関しては優先的に対応させていただきます。 Sora Python SDK に対する有償のサポートについては提供しておりません。 ## Discord **URL**: Discord にてコミュニティを運営しています。 なにか質問したい場合は Discord サーバーへ参加してください。 Sora Python SDK については `#sora-sdk-faq` で `sora-python-sdk` タグを指定してご利用ください。 # Sora Rust SDK ## 概要 **URL**: **crates.io**: > **警告** > > Sora Rust SDK は開発中の SDK です。正式版がリリースされるまでは、 API が頻繁に変更される可能性があります。 Sora Rust SDK は Sora を Rust から使用するための仕組みです。 ## 特徴 - libwebrtc を組み込んだ Rust SDK です - Rust から Sora へ接続するアプリケーションを開発できます ## 詳細 詳細は [Sora Rust SDK](https://github.com/shiguredo/sora-rust-sdk) をご確認ください。 ## ライセンス Sora Rust SDK は [Apache License, Version 2.0](https://www.apache.org/licenses/LICENSE-2.0) で公開しています。 ## サポートについて Sora Rust SDK に関する質問・要望・バグなどの報告は Discord の利用をお願いします。 Sora のライセンス契約の有無に関わらず、応答時間と問題の解決を保証しませんのでご了承ください。 ただし、明らかなバグに関しては優先的に対応させていただきます。 Sora Rust SDK に対する有償のサポートについては提供しておりません。 ## Discord **URL**: Discord にてコミュニティを運営しています。 なにか質問したい場合は Discord サーバーへ参加してください。 Sora Rust SDK については `#sora-sdk-faq` で `sora-rust-sdk` タグを指定してご利用ください。 # Sora Flutter SDK ## 概要 **URL**: > **警告** > > Sora Flutter SDK は開発中の SDK です。正式版がリリースされるまでは、 API が頻繁に変更される可能性があります。 Sora Flutter SDK は Sora を Flutter アプリケーションから使用するための仕組みです。 ## 特徴 - libwebrtc を組み込んだ Dart で開発されている SDK です - Flutter アプリケーションから Sora へ接続できます ## 詳細 詳細は [Sora Flutter SDK](https://github.com/shiguredo/sora-flutter-sdk) をご確認ください。 ## ライセンス Sora Flutter SDK は [Apache License, Version 2.0](https://www.apache.org/licenses/LICENSE-2.0) で公開しています。 ## サポートについて Sora Flutter SDK に関する質問・要望・バグなどの報告は Discord の利用をお願いします。 Sora のライセンス契約の有無に関わらず、応答時間と問題の解決を保証しませんのでご了承ください。 ただし、明らかなバグに関しては優先的に対応させていただきます。 Sora Flutter SDK に対する有償のサポートについては提供しておりません。 ## Discord **URL**: Discord にてコミュニティを運営しています。 なにか質問したい場合は Discord サーバーへ参加してください。 Sora Flutter SDK については `#sora-sdk-faq` で `sora-flutter-sdk` タグを指定してご利用ください。 # Sora 専用ツール Sora では SOra を利用するにあたり便利なツールをオープンソースとして Apache 2.0 ライセンスで公開しています。 ## Sora 専用録画合成ツール **URL**: ## Sora 専用負荷試験ツール **URL**: ## Sora 専用 WebRTC ログ解析ツール **URL**: ## Sora 専用録画ファイルアップローダー **URL**: ## Sora 専用 Prometheus メトリクスエクスポーター **URL**: # WebRTC 負荷試験ツール Zakuro ## 概要 [shiguredo/zakuro: WebRTC Load Testing Tool Zakuro](https://github.com/shiguredo/zakuro) WebRTC は、要求するビットレートや利用するネットワーク、送信者の数、受信者の数によって負荷が変わります。 弊社では、 Sora のサーバーサイジング向けに Sora 専用の WebRTC 負荷試験ツールを公開しています。 ## ライセンス Zakuro は [Apache License, Version 2.0](https://www.apache.org/licenses/LICENSE-2.0) で公開しています。 ## サポートについて Zakuro のサポートやアドバイスは提供していません。 ## Discord **URL**: Discord にてコミュニティを運営しています。 なにか質問したい場合は Discord サーバーへ参加してください。 Zakuro のチャンネルは `#zakuro` です。 # WebRTC 録画合成ツール Hisui ## 概要 [shiguredo/hisui: Recording Composition Tool Hisui](https://github.com/shiguredo/hisui) Sora が生成する録画ファイルを合成するツールを公開しています。 ## ライセンス Hisui は [Apache License, Version 2.0](https://www.apache.org/licenses/LICENSE-2.0) で公開しています。 ## サポートについて Hisui のサポートやアドバイスは提供していません。 ## Discord **URL**: Discord にてコミュニティを運営しています。 なにか質問したい場合は Discord サーバーへ参加してください。 Hisui のチャンネルは `#hisui` です。 # WebRTC 統計解析ツール Kohaku ## 概要 [shiguredo/kohaku: WebRTC Stats Analyzer Kohaku](https://github.com/shiguredo/kohaku) WebRTC クライアントの統計情報を収集して解析するツールを公開しています。 ## ライセンス Kohaku は [Apache License, Version 2.0](https://www.apache.org/licenses/LICENSE-2.0) で公開しています。 ## サポートについて Kohaku のサポートやアドバイスは提供していません。 ## Discord **URL**: Discord にてコミュニティを運営しています。 なにか質問したい場合は Discord サーバーへ参加してください。 Kohaku のチャンネルは `#kohaku` です。 # 音声ストリーミングゲートウェイ Suzu ## 概要 [shiguredo/suzu: Audio Streaming Gateway Suzu](https://github.com/shiguredo/suzu) Sora が出力する音声ストリーミングを音声解析サービスに転送し、解析結果を Sora に転送するツールを公開しています。 ## ライセンス Suzu は [Apache License, Version 2.0](https://www.apache.org/licenses/LICENSE-2.0) で公開しています。 ## サポートについて Suzu のサポートやアドバイスは提供していません。 ## Discord Discord にてコミュニティを運営しています。 なにか質問したい場合は Discord サーバーへ参加してください。 Suzu のチャンネルは `#suzu` です。 # Sora Archive Uploader ## 概要 [shiguredo/sora-archive-uploader: Sora Archive Uploader](https://github.com/shiguredo/sora-archive-uploader) Sora Archive Uploader は Sora の出力する録画ファイルを S3 または S3 互換のオブジェクトストレージに、アップロードするツールです。 Systemd timer などで定期的に実行することで、録画ファイルを自動的にアップロードすることができます。 問題になりがちな録画ファイルのアップロードに利用する帯域を制限することができます。 ## ライセンス Sora Archive Uploader は [Apache License, Version 2.0](https://www.apache.org/licenses/LICENSE-2.0) で公開しています。 ## サポートについて Sora Archive Uploader のサポートやアドバイスは提供していません。 ## Discord **URL**: Discord にてコミュニティを運営しています。 なにか質問したい場合は Discord サーバーへ参加してください。 Sora Archive Uploader についての質問やバグ報告は Discord の `#sora-tool-faq` チャンネルにお願いします。 # Sora Exporter ## 概要 [shiguredo/sora_exporter: Prometheus exporter for WebRTC SFU Sora metrics.](https://github.com/shiguredo/sora_exporter) Sora Exporter は Sora の GetStatsReport API を Prometheus 形式に変換してくれる prometheus エージェントです。 ## ライセンス Sora Exporter は [Apache License, Version 2.0](https://www.apache.org/licenses/LICENSE-2.0) で公開しています。 ## サポートについて Sora Exporter のサポートやアドバイスは提供していません。 ## Discord **URL**: Discord にてコミュニティを運営しています。 なにか質問したい場合は Discord サーバーへ参加してください。 Sora Exporter についての質問やバグ報告は Discord の `#sora-tool-faq` チャンネルにお願いします。 # Media Processors ## 概要 [shiguredo/media-processors: Media Processors](https://github.com/shiguredo/media-processors) 仮想背景やノイズ抑制といったメディア処理をブラウザで簡単に行えるようにするためのライブラリです。 ## ライセンス Media Processors は [Apache License, Version 2.0](https://www.apache.org/licenses/LICENSE-2.0) で公開しています。 ## サポートについて Media Processors のサポートやアドバイスは提供していません。 ## Discord **URL**: Discord にてコミュニティを運営しています。 なにか質問したい場合は Discord サーバーへ参加してください。 Media Processors のチャンネルは `#media-processors` です。 # libwebrtc 音声処理 > **注意** > > この資料の正確性を保証しません。 > **重要** > > この資料についての問い合わせは Sora のサポート範囲には含まれません。 この資料は [libwebrtc M99 (4844)](https://webrtc.googlesource.com/src.git/+log/refs/branch-heads/4844) 時点の資料です。 ## libwebrtcでの音声処理全般(前提知識) ### ソースコード - 音声処理関連は [webrtc/modules/audio_processing/](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_processing) 以下にまとまっている ### 音声フレーム - 音声フレームは [AudioBuffer](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_processing/audio_buffer.h) クラスに格納されて渡ってくる - サンプリングレートは 16khz or 32kHz or 48kHz のいずれか - 1 フレームには 10ms 分のサンプルが格納されている:- 16kHz なら 160 個 - 32kHz なら 320 個 - 48kHz なら 480 個 - 基本的には、 [AudioBuffer::SplitIntoFrequencyBands()](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_processing/audio_buffer.h;l=123) を使ってフレームを周波数帯域毎のバンドに分割した上で、各バンドに対して音声処理が適用される- 何分割されるかは、サンプリングレートによって変わり、ひとつのバンド内のサンプル数は 160 になるようになっている - つまり、- 16kHz なら一分割 (分割なし) - 32kHz なら二分割 (low, high) - 48kHz なら三分割 (low, middle, high) - 処理適用後は、 [AudioBuffer::MergeFrequencyBands()](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_processing/audio_buffer.h;l=126;bpv=0;bpt=1g) ですべてのバンドが結合され、通常の音声フレームの形式に戻される ### 音声フレームの処理タイミング - 音声処理の対象となる音声フレームは [audio_processing_impl.cc](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_processing/audio_processing_impl.cc) の中で処理されることになる - 各音声フレームの処理タイミングには、音声ストリームの「入口」と「出口」の 2 つがある- 前者の場合には [AudioProcessingImpl::ProcessCaptureStreamLocked()](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_processing/audio_processing_impl.cc;l=1051;bpv=0;bpt=0) 内で処理が適用される- 大半の音声処理はここで実行される - 後者の場合には [AudioProcessingImpl::ProcessRenderStreamLocked()](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_processing/audio_processing_impl.cc;l=1483;bpv=0;bpt=0) 内で処理が適用される- ほとんどの音声処理は、こちら側では何も行わない - エコーキャンセルでは「実際に出力される音声フレームのバッファリング」といった軽い処理が実施される - なお、これはローカルストリームについての話であり、 WebRTC のようにネットワークを跨いだストリームの「入口(送信側)」と「出口(受信側)」の話とは独立している> - libwebrtc の音声処理の API としては送信側ストリームと受信側ストリームのどちらにも適用できる > - ただし、このドキュメントで扱うような処理は、一般に、送信側ストリームに適用されることが多い ### 各音声処理の適用順序 音声処理の主な適用箇所となる [AudioProcessingImpl::ProcessCaptureStreamLocked()](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_processing/audio_processing_impl.cc;l=1051;bpv=0;bpt=0) メソッド内での、各音声処理の適用順序を記載する。 なお、実際に音声データの更新まで行われる場合には `[処理]` 、(原則として)データ収集のみの場合には `[分析]` と記載としている。 また、それぞれの音声処理は、設定や構成によってスキップされることがある。 適用順序: 1. **[処理]** ハイパスフィルタ(設定次第で後ろの箇所に移動) 2. **[処理]** 前回の AGC の結果を受けての、入力音声データの音量レベル調整 3. [分析] エコーキャンセル 4. [分析] AGC マネージャ 5. **[処理]** バンド分割 6. **[処理]** ハイパスフィルタ 7. [分析] AGC 8. **[処理]** エコーキャンセル 9. [分析] ノイズ抑制 10. **[処理]** ノイズ抑制 11. **[処理]** モバイル版エコーキャンセル 12. **[処理]** AGC マネージャ 13. **[処理]** AGC 14. **[処理]** バンド統合 15. **[処理]** トランジェント抑制 ※ コメントで「AGC の前後のどちらが良いのかは要調査」との記載がある 16. **[処理]** AGC2 以下では、具体的な例として Chromium での Android および iOS の場合に適用される処理と、その順序を記載する。 ソースコードとしては [media/webrtc/helpers.cc](https://source.chromium.org/chromium/chromium/src/+/main:media/webrtc/helpers.cc) の `CreateWebRtcAudioProcessingModule()` および `ConfigAutomaticGainControl()` 関数でこれらの構成が決定されている。 なお、ハイパスフィルタやノイズ抑制、エコーキャンセル、AGC の有効・無効はユーザが利用時に指定できるが、それらはすべて有効になっているものとする。 また、実験的なフィールドトライアルの機能はすべて無効になっているものとする。 #### Android の場合の適用順序 1. **[処理]** ハイパスフィルタ 2. **[処理]** バンド分割 3. [分析] AGC 4. [分析] ノイズ抑制 5. **[処理]** ノイズ抑制 6. **[処理]** モバイル版エコーキャンセル 7. **[処理]** AGC 8. **[処理]** バンド統合 なお AGC のモードは kFixedDigital となっている(モードの意味については AGC の節を参照)。 #### iOS の場合の適用順序 1. **[処理]** ハイパスフィルタ 2. [分析] エコーキャンセル 3. **[処理]** バンド分割 4. [分析] AGC 5. **[処理]** エコーキャンセル 6. [分析] ノイズ抑制- 入力音声データ( `capture_buffer` )ではなく、 エコーキャンセル処理の結果得られた `liear_aec_buffer` を分析対象とする 7. **[処理]** ノイズ抑制 8. **[処理]** AGC 9. **[処理]** バンド統合 なお AGC のモードは kAdaptiveAnalog となっている。 ## ハイパスフィルタ 音声の低周波成分をカットする処理 ### 概要 - [HighPassFiler::Process()](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_processing/high_pass_filter.h;l=31;bpv=0;bpt=1) によって行われる - アルゴリズムは [BiQuadFilter](https://en.wikipedia.org/wiki/Digital_biquad_filter) (双2次フィルタ) の "Direct form 1" - 計算量としては「各音声フレーム内の各サンプルを走査して、数回の算術演算(加算と乗算)を適用する」という極めて軽いもの ### 補足 - 音声フレームの各チャネルは独立して処理される - [HighPassFiler::Process()](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_processing/high_pass_filter.h;l=31;bpv=0;bpt=1) に渡すフラグによって「音声フレーム全体」ないし「一番下のバンドだけ」に処理が適用されるかどうかが切り替わる- デフォルトはおそらく前者 - 後者の場合には、周波数成分の高いバンドへの処理はスキップされて、オリジナルのデータがそのまま使われる(ハイパスなのでこれでも問題はない) - フィルタの実装は [CascadedBiQuadFilter](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_processing/utility/cascaded_biquad_filter.h;bpv=0;bpt=1) クラス- "Cascaded"とあるようにフィルタを複数回適用できるようなインタフェースになっているけれど、今回の用途では、各音声フレームの各チャネルに対して、常に 1 回だけ適用される - フィルタの係数は [high_pass_filter.cc#21](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_processing/high_pass_filter.cc;bpv=0;bpt=1) で定義されている - フィルタのイメージとしては [双2次フィルタ (Biquad Filter) の周波数特性(振幅・位相)の一覧](https://www.wizard-notes.com/entry/music-analysis/biquad-filter-frequency-responses) の記事も参考になる ## ノイズ抑制 音声フレーム内の雑音を抑制するための処理 主に定常的な雑音に対して効果を発揮する ### 概要 - [NoiseSuppressor::Analyze()](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_processing/ns/noise_suppressor.h;l=39;bpv=0;bpt=0) および [NoiseSuppressor::Process()](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_processing/ns/noise_suppressor.h;l=42;bpv=0;bpt=0) によってノイズ抑制が行われる - `Analyze` と `Process` が分かれているのは、他の音声処理(e.g., エコーキャンセル)の影響を受けずに、ノイズ抑制用に必要な情報の収集を行えるようにするため #### [NoiseSuppressor::Analyze()](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_processing/ns/noise_suppressor.h;l=39;bpv=0;bpt=0) での処理: - ここでは **音声フレーム中に含まれるノイズ(スペクトル)の分析** が行われる - ノイズスペクトルの判定には [NoiseEstimator](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_processing/ns/noise_estimator.h;bpv=0;bpt=0) クラスが使用される- アルゴリズムは "quantile noise estimation"- ざっくりと言えば「ある時間範囲内の音声フレームのスペクトルを、各周波数成分単位でソートして、そのquantile (e.g, 50%タイル)以下のものをノイズと判定する」というもの - 対象とするノイズが「定常的なもの」であるという仮定があるので、突発的に発生したような雑音は苦手 - libwebrtcでの実装と完全に一致している訳ではないが ["Quantile based noise estimation for spectral subtraction and Wiener filtering"](https://ieeexplore.ieee.org/abstract/document/862122) の論文が参考になる - また、 [NoiseEstimator](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_processing/ns/noise_estimator.h;bpv=0;bpt=0) の結果のノイズスペクトルは「スペクトルの各周波数成分のスピーチ確率」によって調整される- ざっくりと言えば「ある周波数成分にスピーチ(人の声)が含まれている確率が高い場合には、前回音声フレームのノイズ推定結果を重視し、そうではない場合は今回のものを重視する」といった重み付けが行われる- [NoiseEstimator::PostUpdate()](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_processing/ns/noise_estimator.cc;l=149;bpv=0;bpt=0) - スピーチ確率の推定は [SpeechProbabilityEstimator](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_processing/ns/speech_probability_estimator.h;bpv=0;bpt=0) クラスによって行われる- その際には、まず音声フレームのスペクトルやS/N比を入力としてシグナルモデル ( [SignalModel](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_processing/ns/signal_model.h;bpv=0;bpt=0) ) を構築する - その後、そのモデルに含まれる各特徴量 (e.g., `spectral_flatness`, `lrt` (likelihood ratio test)) を使って、スペクトル内の角周波数成分のスピーチ確率が算出される - 用語としては ["Features for voice activity detection: a comparative analysis"](https://link.springer.com/article/10.1186/s13634-015-0277-z) の記事などが参考となる #### [NoiseSuppressor::Process()](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_processing/ns/noise_suppressor.h;l=42;bpv=0;bpt=0) での処理: - ここでは `Analyze` で得られたノイズスペクトルを使って **ノイズを除去するためのフィルタの構築およびその適用** が実施される - フィルタには [Wiener filter (Wikipedia)](https://en.wikipedia.org/wiki/Wiener_filter) が使用される ([WienerFilter](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_processing/ns/wiener_filter.h;bpv=0;bpt=0) クラス) - その他細々とした色々な処理が行われているけれど、それらについては後続の「補足」を参照のこと #### 計算量 - FFT(およびその逆変換)が 2 回適用されている- `O(N log N)`- `N` は 256 - ノイズ抑制の際には「現在の音声フレーム(バンド単位で160サンプル)」の前方に「前回の音声フレームの末尾部分(96サンプル)」を結合した上で処理が行われるため、 `N` の値はその合算となる - `Analyze` と `Process` のそれぞれで音声フレームはスペクトルに変換して処理されるので、その前後で FFT (とその逆変換)が走る - また、音声フレーム全体を走査するような O(N) の処理が十数回程度実施されている(回数はあくまでも感覚値) #### ノイズ抑制によって発生する(理論上の)遅延 - 6ms - [NoiseSuppressor::Process()](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_processing/ns/noise_suppressor.h;l=42;bpv=0;bpt=0) では、入力音声フレーム内の 4/10 のデータだけが出力フレームに反映されて、残りは次回の処理時まで遅らせられる- 上述の通り音声フレームの長さは 10 ms で、その内の 6/10 の出力が次回まで遅らせられるので 6 ms と遅延となる - 一部データの出力を遅らせているのは、おそらくフレームの繋ぎ目部分の音声をスムーズにするため- `Analyze` の際にも「前回の入力フレームの末尾(遅延)部分」と「今回の入力フレーム」を結合した上で分析が行われる ### 補足 #### マルチチャネルの扱い - [NoiseSuppressor::Analyze()](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_processing/ns/noise_suppressor.h;l=39;bpv=0;bpt=0) では、各チャネルが独立に処理される - [NoiseSuppressor::Process()](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_processing/ns/noise_suppressor.h;l=42;bpv=0;bpt=0) では、各チャネルのフィルタの値(ゲイン)が集約される- [NoiseSuppressor::AggregateWienerFilters()](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_processing/ns/noise_suppressor.cc;l=272;bpv=0;bpt=0) - やっていることとしては、各周波数成分について、チャネル間で一番小さなフィルタの値を採用しているだけ #### マルチバンドの扱い - [音声フレーム](LIBWEBRTC_AUDIO.html#de9618) で触れたように、入力音声フレームのサンプリングレートが 32 kHz 以上の場合は、フレームが周波数帯域(バンド)によって分割されて、バンド単位で処理されることになる - [NoiseSuppressor::Analyze()](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_processing/ns/noise_suppressor.h;l=39;bpv=0;bpt=0) では、一番低帯域のバンドのみを使って分析が行われる - [NoiseSuppressor::Process()](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_processing/ns/noise_suppressor.h;l=42;bpv=0;bpt=0) では、一番低帯域のバンドのみにノイズ抑制処理が適用される- それよりも大きなバンドについては、ノイズ抑制は行わずに、ローバンドの抑制結果に応じた、全体の音量調整のみを実施する - コード的には `upper_band_gain` というスカラ値 ( `float` )を、音声フレームに対してひとつ算出し、それをフレーム内の各サンプルに乗算している- [noise_suppressor.cc#519](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_processing/ns/noise_suppressor.cc;l=519;bpv=0;bpt=0) #### FFT用の窓関数 - ハニングとフラットのハイブリッドが使用される- [ApplyFilterBankWindow()](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_processing/ns/noise_suppressor.cc;l=72;bpv=0;bpt=0) #### 処理のスキップ - 音声フレームのローバンドが、値が `0` のサンプルしか含んでいない場合には [NoiseSuppressor::Analyze()](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_processing/ns/noise_suppressor.h;l=39;bpv=0;bpt=0) でのノイズスペクトルの分析および更新はスキップされる- このケース(無音)で各種統計値を更新してしまうと、無音ではなくなった後のしばらくは、音声データのすべてが「スピーチ(ノイズ無し)」と判定されてしまうため - 音声フレームが実際に使われることがない場合( `capture_output_used_ == false` )は、 [NoiseSuppressor::Process()](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_processing/ns/noise_suppressor.h;l=42;bpv=0;bpt=0) はフィルタの更新はするが、適用は行わない- フィルタの情報は、 [NoiseSuppressor::Analyze()](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_processing/ns/noise_suppressor.h;l=39;bpv=0;bpt=0) 呼び出しでも参照されているので、フィルタ更新までは必要 #### 各種オプション - libwebrtcには `noise_suppression.level` というオプションがあり、それによってノイズ抑制時の各処理で使用されるパラメーターが変化する - 値は `kLow` or `kModerate` or `kHigh` or `kVeryHigh` - 詳細は、以下のメソッドを参照のこと- [AudioProcessingImpl::InitializeNoiseSuppressor()](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_processing/audio_processing_impl.cc;l=1942;bpv=0;bpt=0) - [SuppressionParams::SuppressionParams()](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_processing/ns/suppression_params.cc;l=19;bpv=0;bpt=0) ## モバイル版エコーキャンセル モバイル端末向けの軽量なエコーキャンセル処理 コード中では "AECM (acoustic echo control for mobile)" と呼称されている ### 概要 - AECM では、音声データの **入力時(capture)** と **出力時(render)** のそれぞれで処理が実行される- 用語としては「入力側(の音声フレーム)は **nearend** 」、「出力側(の音声フレーム)は **farend** 」と呼ばれる - 全体の流れとしては、以下のようになる:1. [出力時] 実際に出力される音声フレームをバッファ(履歴)に保持しておく 2. [入力時] 入力音声フレーム内のエコー部分に対応する出力済み音声フレームを特定する(遅延推定) 3. [入力時] 上の遅延情報を用いて、エコー除去フィルタを適用する(ざっくりと言えば、入力音声から、対応する過去の出力音声成分を引く) - AECM 向けの API を提供しているのは [EchoControlMobileImpl](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_processing/echo_control_mobile_impl.h;bpv=0;bpt=0) クラス- 内部的には [echo_control_mobile.h](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_processing/aecm/echo_control_mobile.h;bpv=0;bpt=0) および [aecm_core.h](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_processing/aecm/aecm_core.h;bpv=0;bpt=0) に存在する `WebRtcAecm_*` 関数群によって、実際の処理が実装されている #### 音声出力時の処理 ([AudioProcessingImpl::ProcessRenderStreamLocked()](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_processing/audio_processing_impl.cc;l=1483;bpv=0;bpt=0)) 基本的には「実際に出力される音声フレームのコピーを、後続の入力時処理の際に参照できるようにバッファに保存」しているだけとなる 主な登場人物は、以下の 2 つ: - [EchoControlMobileImpl::PackRenderAudioBuffer()](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_processing/echo_control_mobile_impl.h;l=62;bpv=0;bpt=0) 関数- 出力音声フレームを [AudioProcessingImpl](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_processing/audio_processing_impl.h;bpv=0;bpt=0) クラスが管理している一時バッファに書き込む - **モノラルチャネル** かつ **サンプリングレートが 16 kHz** の場合には、単純なデータコピーとなる - **マルチチャネル** あるいは **マルチバンド (サンプリングレートが 16 kHz 以上)** の場合には、プラスアルファの処理が加わるので [補足](LIBWEBRTC_AUDIO.html#934b1d) の節を参照のこと - [EchoControlMobileImpl::ProcessRenderAudio()](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_processing/echo_control_mobile_impl.h;l=55;bpv=0;bpt=0) メソッド- [EchoControlMobileImpl](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_processing/echo_control_mobile_impl.h;bpv=0;bpt=0) が管理するリングバッファに [EchoControlMobileImpl::PackRenderAudioBuffer()](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_processing/echo_control_mobile_impl.h;l=62;bpv=0;bpt=0) の結果を書き込むだけ #### 音声入力時の処理 ([AudioProcessingImpl::ProcessCaptureStreamLocked()](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_processing/audio_processing_impl.cc;l=1051;bpv=0;bpt=0)) 関数の呼び出し階層としては、以下のようになっている: ``` - EchoControlMobileImpl::ProcessCaptureAudio() # AudioProcessingImpl::ProcessCaptureStreamLocked()から呼び出されるメソッド - WebRtcAecm_Process() - WebRtcAecm_EstBufDelay() # ここで推定した遅延情報はデバッグ用途でしか使用されていない - WebRtcAecm_ProcessFrame() - WebRtcAecm_BufferFarFrame() - WebRtcAecm_FetchFarFrame() - WebRtcAecm_ProcessBlock() # 主要な処理はこの関数内で実施される - WebRtcAecm_UpdateFarHistory() - WebRtc_AddFarSpectrumFix() - WebRtc_DelayEstimatorProcessFix() - WebRtcAecm_AlignedFarend() - WebRtcAecm_CalcEnergies() - WebRtcAecm_CalcStepSize() - WebRtcAecm_UpdateChannel() - WebRtcAecm_CalcSuppressionGain() - ComfortNoise() ``` 重要なのは [WebRtcAecm_ProcessBlock()](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_processing/aecm/aecm_core_c.cc;l=372;bpv=0;bpt=0) で、それより上の関数群は、基本的にはバッファ管理しか行っていないので、今回はあまり気にする必要はない。 [WebRtcAecm_ProcessBlock()](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_processing/aecm/aecm_core_c.cc;l=372;bpv=0;bpt=0) 関数のシグネチャは次の通り: ```c int WebRtcAecm_ProcessBlock(AecmCore* aecm, // farend の音声フレーム (64 サンプル) const int16_t* farend, // nearend の音声フレーム (64 サンプル) const int16_t* nearendNoisy, // nearendNoisy から雑音を除いたもの // 今回の用途では常に NULL になるので無視して良い const int16_t* nearendClean, // nearendNoisy に対してエコーキャンセルを適用した結果の格納先 // 今回の用途では nearendNoisy と同じポインタが使用される int16_t* output) ``` [WebRtcAecm_ProcessBlock()](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_processing/aecm/aecm_core_c.cc;l=372;bpv=0;bpt=0) 関数の処理の大まかな流れは以下の通り: 1. `farend` 引数および `nearendNoisy` 引数に FFT を適用して周波数スペクトルに変換する ( [TimeTofrequencyDomain()](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_processing/aecm/aecm_core_c.cc;l=264;bpv=0;bpt=0) ) 2. `farend` 引数の周波数スペクトルを `aecm` 引数が管理している履歴 (リングバッファ) に追記する ( [WebRtcAecm_UpdateFarHistory()](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_processing/aecm/aecm_core.cc;l=135;bpv=0;bpt=0) ) 3. 上の履歴と `nearendNoisy` 引数の周波数スペクトルを照会して、出力音声(エコー)が入力音声に含まれるまでの遅延を推定する- [WebRtc_AddFarSpectrumFix()](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_processing/utility/delay_estimator_wrapper.cc;l=203) および [WebRtc_DelayEstimatorProcessFix()](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_processing/utility/delay_estimator_wrapper.cc;l=417) - この部分の詳細は [遅延推定](LIBWEBRTC_AUDIO.html#81eb3a) を参照 4. 推定遅延に対応する出力音声フレーム(スペクトル)を取得する ( [WebRtc_AlignedFarend()](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_processing/aecm/aecm_core.cc;l=167;bpv=0;bpt=0) )- これによって、**現在の入力音声フレーム** と **そのエコー成分に対応する出力音声フレーム** が得られたので、以後の処理ではこの 2 つのフレーム(のスペクトル)が使用される 5. エコーキャンセル用のフィルタ構築の前段として `aecm` が管理しているエコー音声チャネルを更新する- チャネル更新には NLMS というアルゴリズムを使用 ( Wikipedia: [Normalizecd least squares filter (NLMS)](https://en.wikipedia.org/wiki/Least_mean_squares_filter#Normalized_least_mean_squares_filter_(NLMS)) ) - 関連する関数は [WebRtcAecm_CalcEnergies()](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_processing/aecm/aecm_core.cc;l=654;bpv=0;bpt=0) と [WebRtcAecm_CalcStepSize()](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_processing/aecm/aecm_core.cc;l=777;bpv=0;bpt=0) 、 [WebRtcAecm_UpdateChannel()](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_processing/aecm/aecm_core.cc;l=820;bpv=0;bpt=0) - この部分の詳細は [チャネル更新](LIBWEBRTC_AUDIO.html#10dc7b) を参照 6. 入力音声フレーム(スペクトル)にフィルタを適用して、エコー部分を除去する> - フィルタには [Wiener filter (Wikipedia)](https://en.wikipedia.org/wiki/Wiener_filter) を使用 > - 基本的には「入力フレームから、ひとつ上で求めたエコーチャネル成分を除去する」イメージ > - フィルタの強弱を調整するために [WebRtcAecm_CalcSuppressionGain()](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_processing/aecm/aecm_core.cc;l=1011;bpv=0;bpt=0) でゲイン値(重み)が計算される- 入力とエコーのエナジーの差分をもとに、無音、ダブルトーク、等の簡易的な状況判定を行い、それに応じてゲイン値を決定 > - NLP (non-linear processor) でフィルタの値がさらに調整される- 外れ値の処理(大き過ぎる or 小さ過ぎるフィルタの値を 1 or 0 に丸める)等がここで行われる 7. コンフォートノイズを生成( [ComfortNoise()](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_processing/aecm/aecm_core_c.cc;l=61;bpv=0;bpt=0) )> - オプショナルで、入力音声フレームにコンフォートノイズ(背景ノイズ)を生成する > - デフォルトは無効 > - ノイズキャンセルの他の箇所の処理とはほぼ独立している 8. 処理適用後の入力音声フレーム(スペクトル)に逆FFTを適用して、時間波形に戻す #### 遅延推定 出力音声が入力音声に含まれるまでの遅延の推定は [WebRtc_AddFarSpectrumFix()](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_processing/utility/delay_estimator_wrapper.cc;l=203) および [WebRtc_DelayEstimatorProcessFix()](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_processing/utility/delay_estimator_wrapper.cc;l=417) で行われている: - [WebRtc_AddFarSpectrumFix()](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_processing/utility/delay_estimator_wrapper.cc;l=203): 出力音声フレーム (farend) の形式変換と履歴への追加1. `uint16_t[64]` の形式で保持されている現在の出力音声フレーム(スペクトル)の中央部分を取り出して `uint32_t` (32 要素のビット配列)に変換する- 各周波数成分のこれまでの平均値を別途保持しており、それに比べて大きいなら 1 、小さいなら 0 となる 2. 上のビット配列を、履歴配列の先頭に挿入する- 配列の要素数は 100 で、各要素は時系列順に並んでいる - 履歴配列の位置(インデックス)が遅延値に対応する(i.e., 先頭なら遅延なしで、末尾なら 400 ms 程度) - [WebRtc_DelayEstimatorProcessFix()](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_processing/utility/delay_estimator_wrapper.cc;l=417): 遅延推定1. 現在の入力音声フレーム(スペクトル)を、上と同様の方法で `uint32_t` に変換する 2. **nearendの変換後のビット配列** と **farendの履歴の各要素** の一致度を計測する- イメージ的には `bitcount(nearend xor history[i])` といった処理で、値が小さいほど、より一致度が高いことを示す 3. 別途管理している **履歴の各位置(= 遅延)での一致度の平均** を更新する 4. 一致度の平均が最も高い位置を遅延のベスト候補とする 5. その候補を採用できる条件が揃っている場合には、その遅延値を採用し、そうではない場合には前回の遅延値を使用する- e.g., ベスト候補とワースト候補の差が小さい場合には、不安定な状況だと判断して見送る - 条件の詳細については [WebRtc_ProcessBinarySpectrum()](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_processing/utility/delay_estimator.cc;l=525) のコードを参照のこと #### チャネル更新 チャネル更新は [WebRtcAecm_UpdateChannel()](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_processing/aecm/aecm_core.cc;l=820;bpv=0;bpt=0) および、その前段の [WebRtcAecm_CalcEnergies()](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_processing/aecm/aecm_core.cc;l=654;bpv=0;bpt=0) と [WebRtcAecm_CalcStepSize()](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_processing/aecm/aecm_core.cc;l=777;bpv=0;bpt=0) によって実施される これらの関数によって `AecmCore` 構造体が管理しているエコー音声用のチャネル情報が更新される 1. まずは、出力音声フレームのVADレベル(フラグ)を推定し、もしこれが 0 (エナジーが低く無音に近い) なら後続の処理はスキップする ( [WebRtcAecm_CalcEnergies()](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_processing/aecm/aecm_core.cc;l=654;bpv=0;bpt=0) ) 2. 次に [WebRtcAecm_CalcStepSize()](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_processing/aecm/aecm_core.cc;l=777;bpv=0;bpt=0) で、 NLMS のステップサイズパラメーターである `mu` を計算する 3. 最後は [WebRtcAecm_UpdateChannel()](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_processing/aecm/aecm_core.cc;l=820;bpv=0;bpt=0) で、 NLMS を使ってエコーチャネルを更新する > - `AecmCore` は、毎フレームで更新される `channelAdapt` と、それよりは安定した `channelStored` をフィールドとして保持している- これらは出力音声フレーム(スペクトル)からエコー音声フレーム(スペクトル)を算出するための重み配列のようなもの (イメージとしては `nearend_echo[i] = farend[i] * channelXXX[i]`) > - 入出力フレーム(スペクトル) の情報を使って、 `channelAdapt` を更新 > - 十分なエナジーのフレームが一定数 (20個) 続いたら、 `channelAdapt` で `channelStored` の置換を試みる- `channelAdapt` と `channelStored` のそれぞれを用いて計算した「エコー音声フレームのエナジー」と「対応する入力音声フレームのエナジー」の差分(絶対値)を求める > - その差分の20フレーム分の合計値が `channelAdapt` を使った場合の方が小さければ、より適切なものだと判断して `channelStored` を置換する (逆の場合には `channelAdapt` が置換される) > - 後続の処理では `channelStored` の値が使用される #### バッファリングによる遅延 - 呼び出し階層の上と下で対象とする音声フレームのサンプル数は異なっている- 上の方( [EchoControlMobileImpl::ProcessCaptureAudio()](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_processing/echo_control_mobile_impl.h;l=56;bpv=0;bpt=0) )では 160 サンプル(10ms分) - 下の方( [WebRtcAecm_ProcessBlock()](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_processing/aecm/aecm_core_c.cc;l=372;bpv=0;bpt=0) )では 64 サンプル - そのため入力音声フレームは、まずリングバッファに追記され、 [WebRtcAecm_ProcessBlock()](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_processing/aecm/aecm_core_c.cc;l=372;bpv=0;bpt=0) 呼び出しの際には、そこから 64 サンプルずつ取り出されて処理されることになる - その際にキリが悪かったサンプル群は次回の入力音声処理時に持ち越されることになるので、 32 サンプル分(2ms分)の遅延が発生する #### 計算量特性 典型的には、一つの音声フレームを処理する際には、以下の関数群が1回ずつ呼び出されることになる: - [EchoControlMobileImpl::PackRenderAudioBuffer()](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_processing/echo_control_mobile_impl.h;l=62;bpv=0;bpt=0) - [EchoControlMobileImpl::ProcessRenderAudio()](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_processing/echo_control_mobile_impl.h;l=55;bpv=0;bpt=0) - [EchoControlMobileImpl::ProcessCaptureAudio()](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_processing/echo_control_mobile_impl.h;l=56;bpv=0;bpt=0) それぞれに対して、以下の処理が、チャネル数の二乗分だけ繰り返されることになる( [マルチチャネルの扱い](LIBWEBRTC_AUDIO.html#af2d71) ): - [EchoControlMobileImpl::PackRenderAudioBuffer()](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_processing/echo_control_mobile_impl.h;l=62;bpv=0;bpt=0) および [EchoControlMobileImpl::ProcessRenderAudio()](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_processing/echo_control_mobile_impl.h;l=55;bpv=0;bpt=0)- 一フレーム分のメモリコピー - [EchoControlMobileImpl::ProcessCaptureAudio()](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_processing/echo_control_mobile_impl.h;l=56;bpv=0;bpt=0)- 一フレーム分の FFT と 逆FFT - フレーム単位のメモリコピーやループを十数回~数十回 注意: 一フレームに含まれる具体的なサンプル数は、関数によって 160 あるいは 64 と変動するが、ここでは簡単のためにそれらの違いは考慮しないものとする ### 補足 #### マルチチャネルの扱い - 各チャネルは、一番下のレイヤー( [WebRtcAecm_ProcessBlock()](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_processing/aecm/aecm_core_c.cc;l=372;bpv=0;bpt=0) )では独立して処理される - 上のレイヤー( [EchoControlMobileImpl::ProcessCaptureAudio()](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_processing/echo_control_mobile_impl.h;l=56;bpv=0;bpt=0) )では、以下のような処理される- **入力音声フレームのチャネル数** の他に、 **出力音声フレームのチャネル数** の概念がある- 後者はソースコード中では `reverse_channel` と呼称されている - `EchoControlMobileImpl` クラスの初期化時には、 [WebRtcAecm_ProcessBlock()](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_processing/aecm/aecm_core_c.cc;l=372;bpv=0;bpt=0) に渡される `Aecm` 構造値インスタンスは `入力音声フレームチャネル数 * 出力音声フレームチャネル数` 個だけ生成される(おそらく典型的にはチャネル数の二乗となる) - 入力音声フレームの各チャネルの処理は、イメージとしては次のようになる( [EchoControlMobileImpl::ProcessCaptureAudio()#L173](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_processing/echo_control_mobile_impl.cc;l=173;bpv=0;bpt=0) )1. 入力音声フレームから該当チャネル部分のデータを取得する (nearend) 2. 出力音声フレームの各チャネルデータ(farend)に対して for ループを回す( [EchoControlMobileImpl::ProcessCaptureAudio()#L198](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_processing/echo_control_mobile_impl.cc;l=198;bpv=0;bpt=0) )- nearend と farend を引数として `WebRtcAecm_Process()` 経由で [WebRtcAecm_ProcessBlock()](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_processing/aecm/aecm_core_c.cc;l=372;bpv=0;bpt=0) を呼び出す - 次のイテレーションに進む前に nearend のデータは、ノイズキャンセル結果で置換される - つまりざっくりと言えば、チャネル数に対する二重ループを回して、各入力チャネルから各出力チャネルのエコー成分を順々に取り除いている感じとなる #### マルチバンドの扱い - マルチバンド自体については [音声フレーム](LIBWEBRTC_AUDIO.html#de9618) を参照 - 音声フレームがマルチバンドに分割された際には、一番下のバンドのみが処理され、残りのバンドについては 0 で埋められる(ローパス)- [EchoControlMobileImpl::ProcessCaptureAudio()#L216](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_processing/echo_control_mobile_impl.cc;l=216;bpv=0;bpt=0) #### 各種オプション - ルーティングモードの指定 ( [RoutingMode](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_processing/echo_control_mobile_impl.h;l=37;bpv=0;bpt=0) )- `kQuietEarpieceOrHeadset`, `kEarpiece`, `kLoudEarpiece`, `kSpeakerphone`, `kLoudSpeakerphone` の中から選べる - この値によって、エコーキャンセル処理時の各種パラメーターが変化する - デフォルト値は `kSpeakerphone` - NLP の ON/OFF ( [AecmCore::nlpFlag](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_processing/aecm/aecm_core.h;l=66;bpv=0;bpt=0) 、デフォルトは有効) - コンフォートノイズの ON/OFF ( [EchoControlMobileImpl::comfort_noise_enabled_](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_processing/echo_control_mobile_impl.h;l=77;bpv=0;bpt=0) 、デフォルトは無効) ## オートゲインコントロール(AGC) 出力音量レベルを適切な範囲内で一定に保つための処理 libwebrtc には「無印の AGC (ないし AGC1)」と「AGC2」が存在するが、ここでは前者を扱っている(後者については補足節を参照のこと) ### 概要 - libwebrtc で、入力音声フレームに AGC を適用する際の論理的な流れは、以下のようになっている:1. 適切な入力音量レベルを推定(e.g., 入力音声フレームでクリッピングが発生しているならレベルを下げる) 2. 上で求めた適切な音量レベルに基づいて、音声フレームの全体音量レベルを変更 3. 音声フレーム内での音量の均一化 - また、一番上の階層での構成要素としては、以下の 3 つのクラスが存在する:- [GainControlImpl](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_processing/gain_control_impl.h): 上述の三つの処理のすべてを担当できるクラス(後述のモードに応じて、一部処理を他のクラスに委譲する) - [AgcManagerDirect](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_processing/agc/agc_manager_direct.h): 「適切な音量レベルの推定」に特化した処理を担当するクラス(オプショナル) - [CaptureLevelAdjuster](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_processing/capture_levels_adjuster/capture_levels_adjuster.h): 「全体音量レベルの変更」に特化した処理を担当するクラス(オプショナル) - これらのクラスの使い分けは [GainControlImpl](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_processing/gain_control_impl.h) に指定される三つのモードによって説明できる:- モードは [AudioProcessing::GainController1::Mode](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_processing/include/audio_processing.h;l=246) 列挙型によって定義され、 `kAdaptiveAnalog` 、 `kAdaptiveDigital` 、 `kFixedDigital` のいずれかとなる - `kAdaptiveAnalog` の場合:- このモードでは「アナログ(マイク)音量が制御できる」という想定のもとでゲインコントールが行われる- "Adaptive" は「適切な音量レベル推定」と、それに応じた「全体音量レベルの変更」が行われることを示す - この場合は [GainControlImpl](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_processing/gain_control_impl.h) が「適切な音量レベルの推定」と「フレーム内での音量均一化」の両方を実施する - [CaptureLevelAdjuster](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_processing/capture_levels_adjuster/capture_levels_adjuster.h) が有効な場合には、 このクラスが「全体音量レベルの変更」(適切な音量レベルの反映)を行う- [CaptureLevelAdjuster](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_processing/capture_levels_adjuster/capture_levels_adjuster.h) は、入力マイクの音量調整の挙動をエミューレートするためのクラス - [CaptureLevelAdjuster](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_processing/capture_levels_adjuster/capture_levels_adjuster.h) が無効な場合には、入力音量レベルの調整は libwebrtc の音声処理機能の利用側の責任となる- [AudioProcessing::recommended_stream_analog_level()](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_processing/include/audio_processing.h;l=598) メソッドで、期待される音量レベルは取得できる - `kAdaptiveDigital` の場合:- このモードでは「アナログ(マイク)音量は制御できない」という想定のもとでゲインコントールが行われる - [GainControlImpl](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_processing/gain_control_impl.h) の役割は、基本的には `kAdaptiveAnalog` の場合と同様だが、「全体音量レベルの変更」まで一緒に行ってしまう点が異なる- アナログ音量調整を利用側に任せることができないので、自分で入力音声フレームに手を入れて、音量調整をしてしまう - そのため [GainControlImpl](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_processing/gain_control_impl.h) が一番多くのことを行うモードとなる - `kFixedDigital` の場合:- このモードでは [GainControlImpl](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_processing/gain_control_impl.h) は「適切な音量レベルの推定」と「全体音量レベルの変更」に関する処理を行わなくなる- 「フレーム内での音量均一化」のみを担当 - 「適切な音量レベルの推定」に関しては、 [AgcManagerDirect](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_processing/agc/agc_manager_direct.h) が代わりに担当する(有効になっている場合)- [AgcManagerDirect](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_processing/agc/agc_manager_direct.h) と [GainControlImpl](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_processing/gain_control_impl.h) を併用する場合は、常にこのモードとなる - 「全体音量レベルの変更」に関しては、 `kAdaptiveAnalog` の場合と同様( [CaptureLevelAdjuster](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_processing/capture_levels_adjuster/capture_levels_adjuster.h) が有効ならそれが使用され、無効なら利用者責任) - なお列挙的のコメントを意訳すると「組み込みデバイスなどで、入力音量レベルが予測できる(i.e., 事前に適切なゲインが判明している)場合には、全体音量レベル推定および変更処理そのものを省略できる」とのこと - 今回は簡単のために、基本的には、以下の構成を想定して説明を行うこととする:- [GainControlImpl](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_processing/gain_control_impl.h) に指定されるモードは `kFixedDigital` - [AgcManagerDirect](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_processing/agc/agc_manager_direct.h) は有効 - [CaptureLevelAdjuster](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_processing/capture_levels_adjuster/capture_levels_adjuster.h) は無効(このクラスの役割は「物理マイク音量のエミューレート」で、厳密には AGC とは独立した処理であるため) - [GainControlImpl](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_processing/gain_control_impl.h) と [AgcManagerDirect](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_processing/agc/agc_manager_direct.h) は、それぞれ Analyze と Process フェーズが存在する- 前者は、他の音声処理が適用される前に実施されて、(極力)生の入力音声フレームから、各種情報が収集される - 音声フレーム処理の入り口となる [AudioProcessingImpl::ProcessCaptureStreamLocked()](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_processing/audio_processing_impl.cc;l=1051;bpv=0;bpt=0) メソッドの中では、以下の順番で適用されている:1. [AgcManagerDirect](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_processing/agc/agc_manager_direct.h) の Analyze ( [AgcManagerDirect::AnalyzePreProcess()](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_processing/agc/agc_manager_direct.h;l=35) メソッド) 2. [GainControlImpl](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_processing/gain_control_impl.h) の Analyze ( [GainControlImpl::AnalyzeCaptureAudio()](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_processing/gain_control_impl.cc;l=149) メソッド) 3. [AgcManagerDirect](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_processing/agc/agc_manager_direct.h) の Process ( [AgcManagerDirect::Process()](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_processing/agc/agc_manager_direct.cc;l=653) メソッド) 4. [GainControlImpl](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_processing/gain_control_impl.h) の Process ( [GainControlImpl::ProcessCaptureAudio()](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_processing/gain_control_impl.cc;l=196) メソッド) - 以降のサブセクションでは、上記のメソッドそれぞれの詳細について記載する #### [AgcManagerDirect](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_processing/agc/agc_manager_direct.h) の Analyze ( [AgcManagerDirect::AnalyzePreProcess()](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_processing/agc/agc_manager_direct.h;l=35) メソッド) このメソッドが行なっていることは、主に以下の 2 つ: 1. 入力音声フレームのクリッピング判定- クリッピング判定 = 大音量領域での音声の欠損が発生するかどうか (c.f. [Audio Clipping (Wikipedia)](https://en.wikipedia.org/wiki/Clipping_(audio))) - クリッピングが発生する場合には、入力音量レベルを下げる必要がある- 上述の通り、実際に音量レベルを変更するのは、このクラスの呼び出し側の責務( [AgcManagerDirect](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_processing/agc/agc_manager_direct.h) は適切なレベルを推定するのみ) 2. 「代表チャネル」を更新する- 「代表チャネル」は、ゲインコントロールの際の基準となるチャネル - 「適切な音量レベルの推定」はチャネル毎に独立して行われるが、実際に音量調整をする際には、代表チャネルの値が使用される - 代表チャネルは [AgcManagerDirect::AnalyzePreProcess()](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_processing/agc/agc_manager_direct.h;l=35) メソッドによって選択される- 実装的には、単純に「適切な音量レベル」が一番小さなチャネルを選択しているだけ このメソッドの大半はクリッピング関連処理に費やされている。 また、オプショナルな構成要素として [ClippingPredictor](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_processing/agc/clipping_predictor.h;bpv=1;bpt=1) クラスが存在する。 これが有効となっている場合には「現在のフレームにクリッピングが存在するかどうか」の判定だけでなく、 「近い将来に発生しそうかどうか」の予測まで行われるようになる。 ただし、今回は簡単のために、このクラスの詳細は割愛し、無効となっているものと想定する。 クリッピング判定処理の流れは次の通り: 1. 入力音声フレームで、値が上端ないし下端に達しているサンプルの割合を計算( [AgcManagerDirect::ComputeClippedRatio()](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_processing/agc/agc_manager_direct.cc;l=118) )- これが規定値(デフォルトでは一割)を超えている場合には「クリッピング有り」と判定される 2. 「クリッピング有り」判定、かつ、前回の判定から一定時間(デフォルトでは 3 秒)経過している場合には、以下を実施する:> - 各チャネルに対して [MonoAgc::HandleClipping()](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_processing/agc/agc_manager_direct.cc;l=225;bpv=1;bpt=1) を呼び出す > - [MonoAgc](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_processing/agc/agc_manager_direct.h;l=156;bpv=1;bpt=1) は、各チャネルに対して独立に「適切な音量レベルの推定」処理を適用するためのクラス > - [MonoAgc::HandleClipping()](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_processing/agc/agc_manager_direct.cc;l=225;bpv=1;bpt=1) の中では(ざっくり言えば)推定適切音量レベルの定数分の減少が行われる #### [GainControlImpl](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_processing/gain_control_impl.h) の Analyze ( [GainControlImpl::AnalyzeCaptureAudio()](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_processing/gain_control_impl.cc;l=149) メソッド) このメソッドの中では主に、以下が実施される: - 入力音声フレームのエナジーなどの統計情報の取得(モードが `kFixedDigital` 以外の場合)- 取得した値は Process フェーズで利用される - 入力音声フレームの「全体音量レベルの変更」(モードが `kAdaptiveDigital` の場合) モード毎に適用される処理の概要は以下の通り: - `kAdaptiveAnalog` の場合:- 以下の処理を行う [WebRtcAgc_AddMic()](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_processing/agc/legacy/gain_control.h;l=82) 関数をチャネル毎に適用:1. 入力音量レベルが小さすぎる場合には、入力フレームの各サンプルに一律のゲイン値を適用して調整(増幅)- 一フレームで適用されるゲイン値には上限がり、複数フレームを跨いで徐々に大きくすることで、ターゲット音量に近づけていく 2. 入力フレームのバンド 0 部分を数 ms 間隔に区切って、それぞれのエナジーとエンベロープ( [Envelope (Wikipedia)](https://en.wikipedia.org/wiki/Envelope_(music)) )を計算 3. 最後に [WebRtcAgc_ProcessVad()](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_processing/agc/legacy/digital_agc.cc;l=572) 関数を使って、入力音声フレームにスピーチが含まれているかどうかの情報を取得- VAD 判定自体は簡易的なもの - ざっくりと言えば「現在のフレームのエナジー」と「長期的なエナジーの統計(平均と標準偏差)」を比較して、前者が十分に高ければ「ボイスが含まれている」と判定 - `kAdaptiveDigital` の場合:- 以下の処理を行う [WebRtcAgc_VirtualMic()](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_processing/agc/legacy/gain_control.h;l=82) 関数をチャネル毎に適用:> 1. 入力音声フレームのバンド 0 を対象として、エナジーを計算して `lowLevelSignal` かどうかを判定 > 2. 入力音量フレームの音量レベルが「適切な音量レベル」に合うように、一律のゲイン値を適用する(全体音量を上げる or 下げる)- 「全体音量レベルの変更」を行なっている箇所 > - 調整結果に応じて「現在の入力音声レベル」の値も修正する > - 「適切な音量レベル」を求めること自体は Process フェーズで行われる > 3. 最後に [WebRtcAgc_AddMic()](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_processing/agc/legacy/gain_control.h;l=82) 関数を呼び出す- つまり前処理を除けば `kAdaptiveAnalog` と同じとなる - `kFixedDigital` の場合:- 特に何も行わない #### [AgcManagerDirect](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_processing/agc/agc_manager_direct.h) の Process ( [AgcManagerDirect::Process()](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_processing/agc/agc_manager_direct.cc;l=653) メソッド) このメソッドでは、主に以下が行われる: - 「適切な全体音量レベル」の推定 - 「 後続の [GainControlImpl](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_processing/gain_control_impl.h) クラスの Process フェーズで使用されるゲイン値("compression gain")」の算出 大まかな処理の流れは次の通り: 1. 入力音声フレームのバンド 0 に対して [Agc::Process()](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_processing/agc/agc.cc;l=40) メソッドを呼び出す- 内部ではまず [VoiceActivityDetector::ProcessChunk()](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_processing/vad/voice_activity_detector.cc;l=37) を使って、細かいチャンク単位(数ms単位)でのボイス確率と RMS を求めている- RMS は "Root Mean Square" の略で、音圧に近い指標 - その後、その二つの値を [LoudnessHistogram::Update()](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_processing/agc/loudness_histogram.cc;l=90) を使って、ヒストグラムに格納している(RMS に対応するボイス確立を保持) 2. 上の結果を使って [MonoAgc::UpdateGain()](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_processing/agc/agc_manager_direct.cc;l=348) メソッドで「適切な音量レベル」を更新する- RMS のヒストグラムから、現在の loudness を求め、それをターゲットとする loudness と比較する - 現在とターゲットの loudness の差から、デジタルゲインコントールのゲイン値(対象となる調整量)を求める - デジタルゲインコントールで調整できる範囲を超えている場合には、その超過分を(物理マイク or エミューレートマイクでの)アナログ調整でカバーするために「適切な音量レベル」の値を更新する 3. 次に [MonoAgc::UpdateCompressor()](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_processing/agc/agc_manager_direct.cc;l=401) で「デジタルゲインコントロールで使用されるゲイン値」を更新する- 一つ上で求めたデジタルゲインコントロールのゲイン値をそのまま適用すると、音量が急変してしまう可能性があるので、徐々にターゲットに近づくように、ゲイン値を調整する - 調整後のゲイン値は `GainControlImpl::set_compression_gain_db()` 経由でデジタルゲインコントロールに渡される- ただし現在の実装では `WebRTC-UseLegacyDigitalGainApplier` フラグが有効になっていないと、この値は使用されない(のであまり気にしなくても良い) 4. 最後は、Analyze フェーズと同様に [AgcManagerDirect::AggregateChannelLevels()](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_processing/agc/agc_manager_direct.cc;l=702) メソッドを用いた代表チャネルが選出される #### [GainControlImpl](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_processing/gain_control_impl.h) の Process ( [GainControlImpl::ProcessCaptureAudio()](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_processing/gain_control_impl.cc;l=196) メソッド) このメソッドでは、主に以下が行われる: - 「入力音声フレーム内の音量の均一化」- 参考までに `analog_processing.h` ファイル内のコメントでは、この処理は次のように説明されている> It applies a fixed gain through most of the input level range, and compresses > (gradually reduces gain with increasing level) the input signal at higher levels. - 「適切な入力音声レベル」の推定(モードが `kFixedDigital` 以外の場合) 大まかな処理の流れは次の通り: 1. [WebRtcAgc_Analyze()](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_processing/agc/legacy/analog_agc.cc;l=935;bpv=1;bpt=1) 関数を呼び出して「適用するゲイン配列」と「適切な入力音声レベル」を計算- 内部的には [WebRtcAgc_ComputeDigitalGains()](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_processing/agc/legacy/digital_agc.cc;l=272;bpv=1;bpt=1) 関数と [WebRtcAgc_ProcessAnalog()](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_processing/agc/legacy/analog_agc.cc;l=575) 関数を使用している - [WebRtcAgc_ComputeDigitalGains()](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_processing/agc/legacy/digital_agc.cc;l=272;bpv=1;bpt=1) 関数は「適用するゲイン配列」を求める- ゲイン配列は 11 要素: 音声フレームの 1ms 毎のゲイン値(10個) + 次のフレームの冒頭部分のゲイン値(1個) - この関数は、入力音声フレームの VAD や各区間(1ms単位)のエナジーの情報を使って、それぞれの区間に適用するゲイン値を求める - [WebRtcAgc_ProcessAnalog()](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_processing/agc/legacy/analog_agc.cc;l=575) では「適切な入力音声レベル」を求めている(音声フレームの更新は、ここでは行わない)- かなり色々なヒューリスティックを用いて、期待されるアナログ音量レベルを決定しているので、詳細は実装を参照のこと- 入力音声フレームの saturation や VAD を判定したり、 etc - なお、この関数は以下のいずれかの条件に該当する場合には呼び出されない:- モードが `kFixedDigital`- [GainControlImpl](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_processing/gain_control_impl.h) が感知する範囲では「入力音声レベルの変更」が行われないため、「適切な入力音声レベル」を求めることが不要なため - モードが `kAdaptiveDigital` かつ Analyze フェーズで求めた `lowLevelSignal` フラグが真- `lowLevelSignal` の判定箇所には "digital AGC will not adapt to low-level signals" という記載があるので、それをチェックしているものと思われる 2. ゲイン配列の適用- [ApplyDigitalGain()](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_processing/gain_control_impl.cc;l=48) 関数を用いて、上で求めたゲイン配列を入力音声フレームに適用する - 基本的には、入力音声フレームの各サンプルにゲイン値を掛けているだけの単純な関数 - 1ms 区間の区切りで不自然にならないように、ゲイン値を徐々に調整していく、などの補助的な処理がいくつか入っている 3. 「適切な入力音声レベル」の更新(モードが `kAdaptiveAnalog` の場合のみ)- アナログマイク(ないしエミューレートされたマイク)による音量変更用に、チャネル毎に求めた「適切な入力音声レベル」から代表値を選択する - 行なっていることとしては、上述の [AgcManagerDirect::AggregateChannelLevels()](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_processing/agc/agc_manager_direct.cc;l=702) と同様(最小値を選択しているだけ) ### 補足 #### マルチチャネルの扱い - 基本的には各チャネルは独立して扱われる(特に分析系の処理では) - ただし、最終的に音量調整を行う際には、一番音量レベルが小さいチャネルを代表チャネルとして、それを基準として処理が適用される #### マルチバンドの扱い - 以下の処理は、入力音声フレームがマルチバンドに分割される前に適用される:- [CaptureLevelAdjuster](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_processing/capture_levels_adjuster/capture_levels_adjuster.h) による入力音声フレームの音量調整 - [AgcManagerDirect](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_processing/agc/agc_manager_direct.h) の Analyze ( [AgcManagerDirect::AnalyzePreProcess()](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_processing/agc/agc_manager_direct.h;l=35) メソッド) - 入力音声フレームの分析・情報収集の際には、バンド 0 が対象となることが多い #### バッファリングによる遅延 バッファリングを行なっていないので、それに伴う遅延も特になし #### 計算量特性 他の音声処理の多くと同様の傾向: - 入力音声フレームの走査やコピーが十数回から数十回程度行われる - 他の音声処理の多くとは異なり FFT を行なっていないのは特徴的 #### AGC2 について ここで取り上げているのは AGC1 (ないし無印の AGC )と呼ばれるもので、 libwebrtc にはそれとは別に AGC2 も存在する ( [GainController2](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_processing/gain_controller2.h) クラス)。 AGC1 と AGC2 は排他的なものではなく、両方を併用することも可能な模様。 例えば、 `audio_processing.h` ファイルに掲載されている example コードには、以下のような記載があり、両方が有効化されている: ```c AudioProcessing::Config config; // ..省略.. // AGC1 を有効化 config.gain_controller1.enabled = true; config.gain_controller1.mode = AudioProcessing::Config::GainController1::kAdaptiveAnalog; config.gain_controller1.analog_level_minimum = 0; config.gain_controller1.analog_level_maximum = 255; // AGC2 を有効化 config.gain_controller2.enabled = true; ``` また Chromium (利用側)の `media/webrtc/helpers.cc` ファイルにある [ConfigureAutomaticGainControl()](https://source.chromium.org/chromium/chromium/src/+/main:media/webrtc/helpers.cc;l=133) 関数で ゲインコントロールを設定している箇所を見ても AGC1 と AGC2 が併用されるようなコードとなっている。 ただし AGC2 については `features::kWebRtcAnalogAgcClippingControl` というフラグが有効になっている場合にのみ利用され、 AGC1 と異なり単体で使われることはない。 #### 各種オプション - 一番挙動に大きな影響を与えるのは、おそらく [AudioProcessing::GainController1::Mode](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_processing/include/audio_processing.h;l=246) の値 - それ以外にもパラメーターはたくさんあるがここでは割愛- 設定できる項目については [AudioProcessing::GainController1](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_processing/include/audio_processing.h;l=239) 構造体にまとまっている # libwebrtc リップシンク > **注意** > > この資料の正確性を保証しません。 > **重要** > > この資料についての問い合わせは Sora のサポート範囲には含まれません。 この資料は [libwebrtc M99 (4844)](https://webrtc.googlesource.com/src.git/+log/refs/branch-heads/4844) 時点の資料です。 ここでは libwebrtc でのリップシンク処理(映像および音声ストリームのタイムスタンプ同期処理)について記載しています。 ## 概要 - 同期処理は、主に以下の 3 つのパートで構成される:1. 映像・音声ストリームから同期用の情報(主にパケットのタイムスタンプ)を取得部分 2. 映像・音声ストリームを同期するために必要な遅延時間の計算部分- 片方が遅れている場合には、進んでいる方のストリームに対して遅延を課してタイミングを合わせるイメージ 3. 上で求めた同期用の遅延時間のストリームへの反映部分 - [RtpStreamsSynchronizer](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/video/rtp_streams_synchronizer2.h) がこのような同期処理のハブとなるクラス- 上述の 1 と 3 については、映像・音声ストリームと情報のやり取りが必要になるが、それは [Syncable](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/call/syncable.h) という抽象クラスを通して行われる- 映像では [VideoReceiveStream2](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/video/video_receive_stream2.h) が、音声では [AudioReceiveStream](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/audio/audio_receive_stream.h) が、 [Syncable](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/call/syncable.h) の実装クラスとなる - [RtpStreamsSynchronizer](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/video/rtp_streams_synchronizer2.h) はこれらのインスタンスをメンバ変数として保持しており、必要に応じてストリームの情報を取得したり、同期結果(必要な遅延)を伝えたりする - また [RtpStreamsSynchronizer](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/video/rtp_streams_synchronizer2.h) は [StreamSynchronization](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/video/stream_synchronization.h) というクラスのインスタンスも保持している- こちらは実際のストリームとは切り離された、同期処理用の計算部分を担っているクラス(上述の 2 を担当) - [RtpStreamsSynchronizer](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/video/rtp_streams_synchronizer2.h) は [RtpStreamsSynchronizer::UpdateDelay()](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/video/rtp_streams_synchronizer2.cc;l=80) メソッドを定期的(一秒毎)に呼び出し、その中で上の 1..3 の処理を実施している 以降では、上の三つのパートのそれぞれについて記載していく。 ## 詳細 ### 同期用の情報取得 [RtpStreamsSynchronizer](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/video/rtp_streams_synchronizer2.h) クラスは [Syncable::GetInfo()](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/call/syncable.h;l=37) メソッドを経由して、同期に必要な各種情報を取得する。 [Syncable::GetInfo()](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/call/syncable.h;l=37) メソッドは、以下の定義の [Syncable::Info](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/call/syncable.h;l=25) 構造体を返す: ```c struct Info { // 最後に RTP パケットを受信した時のシステム時刻 int64_t latest_receive_time_ms = 0; // 最後に受信した RTP パケットのタイムスタンプ uint32_t latest_received_capture_timestamp = 0; // RTCP Sender Report パケットから取得した情報 uint32_t capture_time_ntp_secs = 0; // NTP 時刻の秒部分 uint32_t capture_time_ntp_frac = 0; // NTP 時刻の秒未満部分 uint32_t capture_time_source_clock = 0; // RTP タイムスタンプ // ストリームの現在の遅延時間 // // 正確ではないが、イメージとしては「`RtpStreamsSynchronizer`が前回に求めた遅延時間(を反映した値)」が近い int current_delay_ms = 0; }; ``` 概要部分に記載の通り、映像と音声では [Syncable](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/call/syncable.h) の実装クラスは別々だが、どちらも似たような方法で RTP / RTCP パケット受信時の情報をほぼそのまま使って、この構造体に必要な情報を埋めている。 `current_delay_ms` だけは若干特殊だが、ここではこの値の求め方の詳細は割愛する。 ### 同期に必要な遅延の計算 映像ストリームと音声ストリームのタイムスタンプの同期は「片方がもう片方に対して、どの程度遅延しているか」ということを求めることで行われる。 この遅延計算を担当しているのは [RtpStreamsSynchronizer::UpdateDelay()](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/video/rtp_streams_synchronizer2.cc;l=80) メソッドで、流れは以下のようになっている: 1. 前節に記載の [Syncable::GetInfo()](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/call/syncable.h;l=37) を使って、映像と音声のそれぞれで [Syncable::Info](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/call/syncable.h;l=25) 構造体を取得する 2. [Syncable::Info](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/call/syncable.h;l=25) を使って、映像および音声用の [StreamSynchronization::Measurements](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/video/stream_synchronization.h;l=22) メンバ変数を更新する- [StreamSynchronization::Measurements](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/video/stream_synchronization.h;l=22) は「RTP タイムスタンプの NTP ドメインへの変換」を行うためのクラス - このクラスは [RtpToNtpEstimator](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/system_wrappers/include/rtp_to_ntp_estimator.h) というクラスのインスタンスを保持している- [RtpToNtpEstimator::UpdateMeasurements()](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/system_wrappers/include/rtp_to_ntp_estimator.h;l=39) は [Syncable::Info](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/call/syncable.h;l=25) の RTCP Sender Report (SR) 関連の情報を受け取り、それらを 20 個分保持している - [RtpToNtpEstimator::Estimate()](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/system_wrappers/include/rtp_to_ntp_estimator.h;l=39) では、その履歴情報を使って(線形回帰で)求めたパラメーターを用いて、 RTP タイムスタンプから NTP タイムスタンプへの変換を行う 3. 更新された映像および音声用の [StreamSynchronization::Measurements](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/video/stream_synchronization.h;l=22) を引数にして [StreamSynchronization::ComputeRelativeDelay()](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/video/stream_synchronization.h;l=39) メソッドを呼び出す- このメソッドは「音声ストリームが映像ストリームに対して、どの程度遅れているか(or 進んでいるか)」を結果として返す 4. 次に [StreamSynchronization::ComputeDelays()](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/video/stream_synchronization.h;l=31) を呼び出して「ストリームを同期するために映像と音声のそれぞれをどの程度遅延させるべきか」を計算する 5. 最後は [Syncable::SetMinimumPlayoutDelay()](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/call/syncable.h;l=40) を用いて、計算した同期用の遅延値を映像と音声ストリームのそれぞれに反映する- このメソッドの詳細については、次の節を参照 #### `ComputeRelativeDelay()` と `ComputeDelays()` の詳細 [StreamSynchronization::ComputeRelativeDelay()](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/video/stream_synchronization.h;l=39) のシグネチャは以下のようになっている: ```c bool StreamSynchronization::ComputeRelativeDelay( const Measurements& audio_measurement, // 音声用の StreamSynchronization::Measurements const Measurements& video_measurement, // 映像用の StreamSynchronization::Measurements int* relative_delay_ms) // 音声を基準にした、映像の遅延時間(音声の方が遅れている場合には負の値になる) ``` メソッド内で行われていることは単純で次の通り: - [RtpToNtpEstimator::Estimate()](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/system_wrappers/include/rtp_to_ntp_estimator.h;l=39) メソッドを使って、最後に受信した RTP パケットのタイムスタンプを NTP ドメインに変換する(映像と音声のそれぞれ) - 次の式で `relative_delay_ms` の値を計算する:- `(映像パケット受信システム時刻 - 音声パケット受信システム時刻) - (映像パケット NTP 時刻 - 音声パケット NTP 時刻)` [StreamSynchronization::ComputeDelays()](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/video/stream_synchronization.h;l=31) の方はもう少し複雑で、シグネチャは以下のようになっている: ```c bool StreamSynchronization::ComputeDelays( int relative_delay_ms, // 上で求めた`relative_delay_ms`の値(i.e., 音声に対する映像の遅延時間) int current_audio_delay_ms, // 音声の現在の遅延時間 (`Info.current_delay_ms`) int* total_audio_delay_target_ms, // 音声用の同期用遅延時間(初期値は 0) int* total_video_delay_target_ms) // 映像用の同期用遅延時間(初期値は映像の現在の遅延時間=`Info.current_delay_ms`) ``` この関数は、大まかには以下のようなことを行なっている: 1. `映像の現在の遅延 - 音声の現在の遅延 + relative_delay_ms` という式で映像と音声の遅延のズレを算出- この結果は、過去四回分が保持されており、以降ではその平均値が使用される 2. 上の結果が 30 ms 未満なら、許容範囲ということで、ここで処理は終了- 次節に記載の同期用遅延の反映処理もスキップされる 3. 急激な遅延調整を防ぐために、上で求めた「ズレの平均値」の値を調整する- 二で割った後に、±80 ms の範囲に収まるようにmin/max を取る - 結果は `diff_ms` という変数に格納する 4. `diff_ms` が正の場合:- 映像の方が遅れている(遅延時間が長い)ので **映像の遅延を減らす** か **音声の遅延を増やす** 必要がある - 別途設定された「基準となるターゲット遅延時間」よりも映像の遅延時間が長い場合には、映像の遅延時間を `diff_ms` 分だけ減らす- かつ、音声の遅延時間を「基準となるターゲット遅延時間」にリセットする - 注釈:> - 「基準となるターゲット遅延時間」は [StreamSynchronization::SetTargetBufferingDelay()](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/video/stream_synchronization.h;l=45) メソッドによって設定される > - ただし通常はデフォルト値である 0 が使用されるように見える - 「基準となるターゲット遅延時間」よりも映像の遅延時間が短い場合には、音声の遅延時間を `diff_ms` 分だけ増やす- かつ、映像の遅延時間を「基準となるターゲット遅延時間」にリセットする 5. `diff_ms` が負の場合:- 音声の方が遅れている(遅延時間が長い)ので **音声の遅延を減らす** か **映像の遅延を増やす** 必要がある - 映像と音声が逆転している以外はひとつ前のステップで行なっていることと同じなので、詳細は割愛する 6. ここまでで計算した映像の遅延時間が「基準となるターゲット遅延時間」を超えている場合には、その値を結果に採用する- そうではない場合には、前回の映像遅延時間をそのまま採用する - なお、遅延時間は 10 秒を超えないように min を取る - この値が `total_video_delay_target_ms` に格納されて呼び出し元に伝えられる 7. 映像で前回の遅延時間が採用されなかった場合には、音声の方の遅延時間を更新する- 一度のメソッド呼び出しで更新されるの映像か音声のどちらか一つの遅延時間のみ - それ以外は映像の場合の処理と同様 - この値が `total_audio_delay_target_ms` に格納されて呼び出し元に伝えられる ### 同期用遅延の反映 前節で計算された「映像と音声を同期させるために必要なそれぞれの遅延時間」は [Syncable::SetMinimumPlayoutDelay()](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/call/syncable.h;l=40) メソッドを通して、 それぞれのストリームに伝達され処理されることになる。 以降では、映像と音声のそれぞれについて、サブセクションに分けて概要を記載していく。 なお、メソッド名に含まれる "PlayoutDelay" という用語については、以下のドキュメントも参考になる: #### 映像の場合 - 映像の [Syncable](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/call/syncable.h) 実装は [VideoReceiveStream2](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/video/video_receive_stream2.h) クラスで行われているので [VideoReceiveStream2::SetMinimumPlayoutDelay()](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/video/video_receive_stream2.h;l=180) メソッドがエントリポイントとなる- このメソッドの内部では(細々とした調整処理を経て) [VCMTiming::set_min_playout_delay()](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/video_coding/timing.h;l=50) にターゲット遅延値が渡される - 映像の遅延関連処理はこの [VCMTiming](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/video_coding/timing.h) クラスに集約されている- 同期用の遅延以外にも jitter, render, composition, etc の遅延がこのクラスで管理されている - 上述の [VCMTiming](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/video_coding/timing.h) インスタンスへの参照は、 [VideoReceiveStream2](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/video/video_receive_stream2.h) 以外にも複数箇所で共有されている- その内の一つが [FrameBufferProxy](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/video/frame_buffer_proxy.h) であり、同期遅延の反映処理は、このクラスで行われている - [FrameBufferProxy](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/video/frame_buffer_proxy.h) は設定によっていくつか別のクラスに処理を委譲することになる- 例えば [FrameBuffer2Proxy](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/video/frame_buffer_proxy.cc;l=37) が使われる場合には、 [VCMTiming](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/video_coding/timing.h) への参照は、さらに [FrameBuffer](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/video_coding/frame_buffer2.h) クラスに渡されて、処理されることになる - 以降では、この [FrameBuffer](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/video_coding/frame_buffer2.h) での挙動を見ていく - [VCMTiming](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/video_coding/timing.h) に保持された同期用の遅延時間は、以下のメソッドの中で参照されている:- [VCMTiming::TargetVideoDelay()](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/video_coding/timing.h;l=92):「同期用遅延時間」と「jitter, decode, render 遅延の合計時間」を比較し、大きい方を返すメソッド - [VCMTiming::RenderTime()](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/video_coding/timing.h;l=77): 「フレームのタイムスタンプ」を入力として受け取り、それを描画すべきタイムスタンプを返すメソッド- その際に「現在の遅延時間」を加味するが、その現在値が同期用の遅延時間の範囲内に収まるように min/max を取っている - [VCMTiming::MaxWaitingTime()](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/video_coding/timing.h;l=86): 「デコーダに次のフレームを渡すまでの待機時間」を計算するメソッド- 同期用の遅延時間が 0 の場合(かつ、その他の条件が整った場合)には、特別な計算が実施される - この中の最初の二つのメソッドは [FrameBuffer::GetNextFrame()](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/video_coding/frame_buffer2.h;l=124) メソッド、最後の一つは [FrameBuffer::FindNextFrame()](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/video_coding/frame_buffer2.h;l=123) の中で使用されている - [FrameBuffer::FindNextFrame()](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/video_coding/frame_buffer2.h;l=123) は「次にデコードするフレーム」と「デコードまでの待機時間」を決定するためのメソッド- この中で [VCMTiming::RenderTime()](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/video_coding/timing.h;l=77) を使ってフレームの描画時刻が決定される(まだ未定だった場合) - その次に [VCMTiming::MaxWaitingTime()](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/video_coding/timing.h;l=86) を呼び出して、そのフレームをデコーダに渡すまでの待機時間が決定される- もしその待機時間が負数(正確には -5ms 未満)だった場合には、そのフレームはドロップされる - [FrameBuffer::GetNextFrame()](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/video_coding/frame_buffer2.h;l=124) は上で準備したフレームを、デコード時間になったら、実際に取得するメソッド- 対象フレームの描画時刻は [FrameHasBadRenderTiming()](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/video_coding/frame_helpers.cc;l=19) 関数を使ってチェックされる- このメソッドに [VCMTiming::TargetVideoDelay()](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/video_coding/timing.h;l=92) の値も渡される - ざっくり言えば、タイムスタンプの値が負数だったり、遅延時間が 10 秒を超えている場合に "Bad" と判定される - その場合には [VCMTiming::reset()](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/video_coding/timing.h;l=40) を呼び出して状態をリセットした上で、再度 [VCMTiming::RenderTime()](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/video_coding/timing.h;l=77) を使って描画時刻が計算される #### 音声の場合 - 音声の [Syncable](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/call/syncable.h) 実装は [AudioReceiveStream](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/audio/audio_receive_stream.h) クラスで行われているので [AudioReceiveStream::SetMinimumPlayoutDelay()](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/audio/audio_receive_stream.h;l=120) メソッドがエントリポイントとなる- その後、以下のメソッド群の呼び出し通じて値が(ほぼそのまま)伝播する:1. [ChannelReceiveInterface::SetMinimumPlayoutDelay()](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/audio/channel_receive.h;l=121) 2. [AcmReceiver::SetMinimumDelay()](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_coding/acm2/acm_receiver.h;l=97) 3. [NetEq::SetMinimumDelay()](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/api/neteq/neteq.h;l=236) 4. [NetEqController::SetMinimumDelay()](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/api/neteq/neteq_controller.h;l=138) 5. [DelayManager::SetMinimumDelay()](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_coding/neteq/delay_manager.h;l=77) - [DelayManager::SetMinimumDelay()](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_coding/neteq/delay_manager.h;l=77) に渡された遅延時間は [DelayManager::Update()](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_coding/neteq/delay_manager.h;l=62) メソッドの中で参照される- これは「RTP パケットのタイムスタンプ」を入力に受け取り、内部の統計情報等を更新した上で、パケットの遅延時間を返すメソッド - このメソッド呼び出し時には、他のクラスから参照される「ターゲット遅延時間」の値も更新される- このターゲット遅延時間の値は [DelayManager::TargetDelayMs()](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_coding/neteq/delay_manager.h;l=70) 経由で取得できる - [DelayManager::TargetDelayMs()](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_coding/neteq/delay_manager.h;l=70) の返り値と [DelayManager::SetMinimumDelay()](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_coding/neteq/delay_manager.h;l=77) に渡された値は、必ずしも一致する訳ではない- ただし、大枠を理解する上では「おおむね同じもの」と考えてしまってもそこまで問題はない - [DelayManager::TargetDelayMs()](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_coding/neteq/delay_manager.h;l=70) は [DecisionLogic](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_coding/neteq/decision_logic.h) クラスの色々な箇所で呼び出されている- その中でも [DecisionLogic::GetDecision()](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_coding/neteq/decision_logic.h;l=61) がおそらく一番重要 - [DecisionLogic::GetDecision()](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_coding/neteq/decision_logic.h;l=61) は最後に受け取ったパケットやジッタバッファの情報を使って、次に行うべき操作を指示する [NetEq::Operation](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/api/neteq/neteq.h;l=143) 列挙型を返す - 操作決定の際には [DelayManager::TargetDelayMs()](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_coding/neteq/delay_manager.h;l=70) の値も考慮し、それに応じて `Operation::kAccelerate` (再生時間を早める) や `Operation::kExpand` (再生時間を遅らせる)を指示してペース調整が行われる - なお [NetEq](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/api/neteq/neteq.h) クラスについては以下のリンクも参考になる: # libwebrtc ペーサー > **注意** > > この資料の正確性を保証しません。 > **重要** > > この資料についての問い合わせは Sora のサポート範囲には含まれません。 この資料は [libwebrtc M104 (5112)](https://webrtc.googlesource.com/src.git/+log/refs/branch-heads/5112) 時点の資料です。 このドキュメントでは libwebrtc でのペーサーの処理について記載しています。 ペーサーは「RTP パケットの送信ペースを調整し、指定されたビットレート要求を満たすようにする」役目を担っているコンポーネントです。 なおペーサー関連の話の大枠については、libwebrtc のリポジトリで提供されている [Paced Sending](https://webrtc.googlesource.com/src/+/06aea31d10f860ae4236e3422252557762d39188/modules/pacing/g3doc/index.md) というドキュメントによくまとまっているので、 理解を深めるためには、そちらに先に目を通しておくことをお勧めします。 > **注釈** > > 今回取り上げているクラスは、2022 年 7 月現在でも継続的に修正が行われています。 > そのため、今後の libwebrtc のバージョン更新に伴い、処理内容が変わる可能性は十分にあり得ます。 ## 概要 - ペーサー関連のコードは [webrtc/src/modules/pacing/](https://webrtc.googlesource.com/src/+/06aea31d10f860ae4236e3422252557762d39188/modules/pacing/) ディレクトリ以下にまとまっている - その中でペース調整ロジックを提供している中心的なクラスは [PacingController](https://webrtc.googlesource.com/src/+/06aea31d10f860ae4236e3422252557762d39188/modules/pacing/pacing_controller.h):- 新規に送信される RTP パケットは [PacingController::EnqueuePacket()](https://webrtc.googlesource.com/src/+/06aea31d10f860ae4236e3422252557762d39188/modules/pacing/pacing_controller.h#133) に渡され、一度キューイングされる - その後、 [PacingController::ProcessPackets()](https://webrtc.googlesource.com/src/+/06aea31d10f860ae4236e3422252557762d39188/modules/pacing/pacing_controller.h#197) 呼び出しタイミングで、指定されたターゲットビットレート要求を満たすペースで実際のパケット送信が行われる - ターゲットビットレートは [PacingController::SetPacingRates()](https://webrtc.googlesource.com/src/+/06aea31d10f860ae4236e3422252557762d39188/modules/pacing/pacing_controller.h#165) によって、このクラスの外から指定される - [PacingController](https://webrtc.googlesource.com/src/+/06aea31d10f860ae4236e3422252557762d39188/modules/pacing/pacing_controller.h) のペース制御アルゴリズムは [リーキーバケット](https://ja.wikipedia.org/wiki/%E3%83%AA%E3%83%BC%E3%82%AD%E3%83%BC%E3%83%90%E3%82%B1%E3%83%83%E3%83%88) に基づいている- リーキーバケットとは「穴の空いたバケツ」のこと - このアルゴリズムでは、水の流量(= パケットの送信ペース)は、バケツ内の水の容量(= キュー内のパケットの合計サイズ)には左右されず、その穴の大きさ(= 指定ビットレート)によって制御されることになる - [PacingController](https://webrtc.googlesource.com/src/+/06aea31d10f860ae4236e3422252557762d39188/modules/pacing/pacing_controller.h) は「送信済みパケットサイズ」および「経過時間」、「ターゲットビットレート」をもとに「バジェット(現在の送信可能サイズ)」を計算し、その範囲内でパケットの送信を行う - デフォルトでは、音声パケットはペース調整の対象外となっており、常に即座に送信される - RTP パケットには、その種類に応じた優先度が設定されている:- バジェットに余裕ができた際には、優先度が高いパケットから先にキューから取り出されて送信される- 優先度が同じパケットを含む複数のストリームがある場合にはラウンドロビン - パケットの種類に応じた優先度は以下の通り:1. 音声パケット 2. 再送パケット 3. 映像ないし FEC パケット 4. パディングパケット(キープアライブや後述のプローブ用途で使用される) - この優先順位(と音声の特別扱い)に照らし合わせて、ペーサーの役割を端的に表現するなら「映像の送信によって、音声の送信が阻害されないようにすること」とも言える - [PacingController](https://webrtc.googlesource.com/src/+/06aea31d10f860ae4236e3422252557762d39188/modules/pacing/pacing_controller.h) と関係がある主要なクラスとしては以下のものがある:- [PacingController](https://webrtc.googlesource.com/src/+/06aea31d10f860ae4236e3422252557762d39188/modules/pacing/pacing_controller.h) が利用するクラス:- [BitrateProber](https://webrtc.googlesource.com/src/+/06aea31d10f860ae4236e3422252557762d39188/modules/pacing/bitrate_prober.h):- 帯域推定などを補佐するためのクラス - 送信パケットが少な過ぎると帯域推定の信頼度が下がるので、プローブ用のパディングパケットを、ペース調整の範囲内で挿入する役目を持つ - [RoundRobinPacketQueue](https://webrtc.googlesource.com/src/+/06aea31d10f860ae4236e3422252557762d39188/modules/pacing/round_robin_packet_queue.h):- 送信パケットを一時的に格納するためのキュー - このドキュメントの範囲内では、単なる優先順位付きキュー、とみなしてしまって問題ない - [PacingController::PacketQueue](https://webrtc.googlesource.com/src/+/06aea31d10f860ae4236e3422252557762d39188/modules/pacing/pacing_controller.h#60) インタフェースの実装クラス - [PacketRouter](https://webrtc.googlesource.com/src/+/06aea31d10f860ae4236e3422252557762d39188/modules/pacing/packet_router.h):- [PacingController](https://webrtc.googlesource.com/src/+/06aea31d10f860ae4236e3422252557762d39188/modules/pacing/pacing_controller.h) が実際にパケット送信を行う際のインタフェースを規定する [PacingController::PacketSender](https://webrtc.googlesource.com/src/+/06aea31d10f860ae4236e3422252557762d39188/modules/pacing/pacing_controller.h#45) の実装クラス - このインタフェースは、パケット送信に加えて、FEC パケットやパディングパケットの生成メソッドも定義している - [PacingController](https://webrtc.googlesource.com/src/+/06aea31d10f860ae4236e3422252557762d39188/modules/pacing/pacing_controller.h) を利用するクラス:- [TaskQueuePacedSender](https://webrtc.googlesource.com/src/+/06aea31d10f860ae4236e3422252557762d39188/modules/pacing/task_queue_paced_sender.h):> - [PacingController](https://webrtc.googlesource.com/src/+/06aea31d10f860ae4236e3422252557762d39188/modules/pacing/pacing_controller.h) の API ラップして `pacing` モジュール外から呼び出すためのインタフェースを提供する > - [PacingController::ProcessPackets()](https://webrtc.googlesource.com/src/+/06aea31d10f860ae4236e3422252557762d39188/modules/pacing/pacing_controller.h#197) の呼び出しタイミングを決定するのもこのクラス - [RtpTransportControllerSend](https://webrtc.googlesource.com/src/+/06aea31d10f860ae4236e3422252557762d39188/call/rtp_transport_controller_send.h):> - 帯域推定や輻輳制御を行うクラスが検知したネットワーク状態の変更を [PacingController](https://webrtc.googlesource.com/src/+/06aea31d10f860ae4236e3422252557762d39188/modules/pacing/pacing_controller.h) に伝えるためのハブとなるクラス > - [PacingController::SetPacingRates()](https://webrtc.googlesource.com/src/+/06aea31d10f860ae4236e3422252557762d39188/modules/pacing/pacing_controller.h#165) などを( [TaskQueuePacedSender](https://webrtc.googlesource.com/src/+/06aea31d10f860ae4236e3422252557762d39188/modules/pacing/task_queue_paced_sender.h) を経由して) 呼び出す - [PacingController](https://webrtc.googlesource.com/src/+/06aea31d10f860ae4236e3422252557762d39188/modules/pacing/pacing_controller.h) がやらないこと:- ネットワークの状態(帯域や輻輳)の推定- 送信ペース調整の際には、これらの状態を考慮はするが、推定自体は外部に任せている- [PacingController](https://webrtc.googlesource.com/src/+/06aea31d10f860ae4236e3422252557762d39188/modules/pacing/pacing_controller.h) はあくまでも、指定されたペースは正しいものとして、それを遵守するのが役割 - この辺りは帯域推定や輻輳制御を専門に行うクラスの責務であり、本ドキュメントの対象外となる - 送信キューが詰まった場合のパケットドロップ- 指定されたターゲット送信ビットレートが、実際に送信されるパケット群に対して小さ過ぎる場合(帯域推定が誤っている場合など)には、キューの消化ペースが追いつかなくなる - そのような場合でも [PacingController](https://webrtc.googlesource.com/src/+/06aea31d10f860ae4236e3422252557762d39188/modules/pacing/pacing_controller.h) はパケットドロップは行わず、(時間は掛かっても)すべてのパケットの送信を試みる - ただし、キューが詰まっている場合には、指定されたターゲット送信ビットレートを超過したペースでのパケット送信が許容されるようになる 以降では [PacingController](https://webrtc.googlesource.com/src/+/06aea31d10f860ae4236e3422252557762d39188/modules/pacing/pacing_controller.h) および関連するクラスの実装やアルゴリズムの詳細を取り上げていく。 なお、フィールドトライアルやオプションによって挙動が変わる機能については、簡単のためにデフォルトの構成に準拠して記述を行なっている (末尾の「構成オプション」節も参照)。 ## 詳細 ### [PacingController](https://webrtc.googlesource.com/src/+/06aea31d10f860ae4236e3422252557762d39188/modules/pacing/pacing_controller.h) クラスの詳細 ペース調整ロジックの中心を担う [PacingController](https://webrtc.googlesource.com/src/+/06aea31d10f860ae4236e3422252557762d39188/modules/pacing/pacing_controller.h) の主要なメソッドについて説明していく。 #### [PacingController::SetPacingRates()](https://webrtc.googlesource.com/src/+/06aea31d10f860ae4236e3422252557762d39188/modules/pacing/pacing_controller.h#165) [PacingController](https://webrtc.googlesource.com/src/+/06aea31d10f860ae4236e3422252557762d39188/modules/pacing/pacing_controller.h) に「パケットの送信ペース(ターゲットビットレート)」を第一引数で指示するためのメソッド。 また第二引数で「パディングパケットの送信レート」を指定することもでき、これが 0 より大きい場合には、 送信ペースに余裕がある場合は、パディングパケットが常に送信されることになる。 [PacingController](https://webrtc.googlesource.com/src/+/06aea31d10f860ae4236e3422252557762d39188/modules/pacing/pacing_controller.h) の各処理では、ここで指示された送信ペースが厳守されることになる。 ペース調整は、イメージとしては `経過時間 * 送信ペース - これまでの送信量 = バジェット` として、そのバジェットに収まる分だけのパケット送信を許可する形となっている。 この式を見て分かる通り、基本的には「時間経過分だけバジェットが増えて、パケット送信分だけ減る(かつ、プラスの場合にだけ送信できる)」という単純なもの。 なお、実際のコードでは「バジェット(= 余裕分)」ではなく「 `dept` (= 不足分)」として実装されているが、符号の向きが異なるだけで、意味するところはどちらもほぼ同じ。 ただし、いくつか例外もある: - (デフォルトでは)音声パケットは、送信ペース管理の対象外(常にすぐ送信可能、また、送信分もバジェットから引かれない) - キューが詰まっている場合には、要素が延々と増えていくことを防止するために、送信ペースを(指示されたものよりも)増加させる- 詳細は [PacingController::MaybeUpdateMediaRateDueToLongQueue()](https://webrtc.googlesource.com/src/+/06aea31d10f860ae4236e3422252557762d39188/modules/pacing/pacing_controller.h#246) を参照 - [PacingController::SetSendBurstInterval()](https://webrtc.googlesource.com/src/+/06aea31d10f860ae4236e3422252557762d39188/modules/pacing/pacing_controller.h#161) によってバースト送信が許可されている場合には、一時的に送信ペースを超過することがある- ただし、これによって消費されるバジェットの合計が増える訳ではない なお、本メソッドの呼び出し側に関しては「 [PacingController](https://webrtc.googlesource.com/src/+/06aea31d10f860ae4236e3422252557762d39188/modules/pacing/pacing_controller.h) の利用側クラスや呼び出しタイミング」節を参照。 #### [PacingController::EnqueuePacket()](https://webrtc.googlesource.com/src/+/06aea31d10f860ae4236e3422252557762d39188/modules/pacing/pacing_controller.h#133) 送信対象の RTP パケット( [RtpPacketToSend](https://webrtc.googlesource.com/src/+/06aea31d10f860ae4236e3422252557762d39188/modules/rtp_rtcp/source/rtp_packet_to_send.h) )を受け取り、それをキューに追加するメソッド。 キューイングされたパケットは [PacingController::ProcessPackets()](https://webrtc.googlesource.com/src/+/06aea31d10f860ae4236e3422252557762d39188/modules/pacing/pacing_controller.h#197) の呼び出し時に、 (ペース調整を満たしたタイミングで)実際に送信される。 メソッドの処理の流れは以下の通り: 1. BitRateProber::OnIncomingPacket() を呼び出して、プローバに送信対象パケットのサイズを教える- プローブ関連処理の詳細は「 [BitrateProber](https://webrtc.googlesource.com/src/+/06aea31d10f860ae4236e3422252557762d39188/modules/pacing/bitrate_prober.h) クラスの詳細」の節を参照 2. キューが空だった場合には、現在時刻を基点にして、バジェットを再計算する:- 処理としては `UpdateBudgetWithElapsedTime(UpdateTimeAndGetElapsed(現在時刻));` が呼ばれるイメージ:- `UpdateTimeAndGetElapsed()` で、最終処理時刻を現在時刻に設定(返り値が前回の処理時刻からの経過時間) - `UpdateBudgetWithElapsedTime()` で、経過時間を元に送信バジェットを更新する - この二つのメソッドの組み合わせは [PacingController](https://webrtc.googlesource.com/src/+/06aea31d10f860ae4236e3422252557762d39188/modules/pacing/pacing_controller.h) 内の色々なところで登場する頻出パターン - それぞれのメソッドの詳細については、後続のサブセクションを参照 3. キュー( [PacingController::PacketQueue](https://webrtc.googlesource.com/src/+/06aea31d10f860ae4236e3422252557762d39188/modules/pacing/pacing_controller.h#60) の実装クラス)に RTP パケットを追加 4. キューの要素が増えたので [PacingController::MaybeUpdateMediaRateDueToLongQueue()](https://webrtc.googlesource.com/src/+/06aea31d10f860ae4236e3422252557762d39188/modules/pacing/pacing_controller.h#246) を呼び出して、必要なら送信ペースを増加する(キュー詰まり解消用) なおユーザが直接生成した RTP パケットだけではなく、 [PacingController::ProcessPackets()](https://webrtc.googlesource.com/src/+/06aea31d10f860ae4236e3422252557762d39188/modules/pacing/pacing_controller.h#197) 呼び出し時に生成される 以下のパケットも、一度キューを経由して送信され、ペース調整の対象となる: - FEC 用のパケット - プローブ用のパディングパケット #### [PacingController::ProcessPackets()](https://webrtc.googlesource.com/src/+/06aea31d10f860ae4236e3422252557762d39188/modules/pacing/pacing_controller.h#197) キューに格納されているパケット群を [PacingController::SetPacingRates()](https://webrtc.googlesource.com/src/+/06aea31d10f860ae4236e3422252557762d39188/modules/pacing/pacing_controller.h#165) で指定されたペース制約を満たす範囲で送信するメソッド。 その他に、キープアライブやプローブ用のパディングパケットの送信を行なったりもする。 処理の流れ: 1. [PacingController::ShouldSendKeepalive()](https://webrtc.googlesource.com/src/+/06aea31d10f860ae4236e3422252557762d39188/modules/pacing/pacing_controller.h#203) を呼び出して、キープアライブ用のパディングパケットの送信が必要かどうかを判定する- [PacingController::ShouldSendKeepalive()](https://webrtc.googlesource.com/src/+/06aea31d10f860ae4236e3422252557762d39188/modules/pacing/pacing_controller.h#203) は大まかには「500ms 以上パケットが送信されていない場合」に、キープアライブが必要と判定する - 必要と判定されたら、ペイロードサイズが 1 のパディングパケットが送信される(この場合は [PacingController::EnqueuePacket()](https://webrtc.googlesource.com/src/+/06aea31d10f860ae4236e3422252557762d39188/modules/pacing/pacing_controller.h#133) は経由しない) 2. [PacingController::Pause()](https://webrtc.googlesource.com/src/+/06aea31d10f860ae4236e3422252557762d39188/modules/pacing/pacing_controller.h#140) 呼び出しによって、送信処理が一時停止中になっている場合には、ここで終了 3. [PacingController::NextSendTime()](https://webrtc.googlesource.com/src/+/06aea31d10f860ae4236e3422252557762d39188/modules/pacing/pacing_controller.h#193) で、パケットの次回送信時刻を取得する- もし現在時刻が送信時刻に到達していない場合(i.e., 送信バジェット枯渇中)には、ここで終了 4. `UpdateTimeAndGetElapsed(次回送信時刻)` を呼び出して、「前回の処理実施時刻」から「次回送信時刻」までの経過時間を取得する- NOTE: バジェットに余裕がある場合には、次回送信時刻は、現在時刻よりも前になることがある - 経過時刻が 0 秒以上なら [PacingController::UpdateBudgetWithElapsedTime()](https://webrtc.googlesource.com/src/+/06aea31d10f860ae4236e3422252557762d39188/modules/pacing/pacing_controller.h#219) を呼び出して、バジェットを更新する(経過時間分だけ送れる量が増える) 5. プローブ中の場合には [BitrateProber::RecommendedMinProbeSize()](https://webrtc.googlesource.com/src/+/06aea31d10f860ae4236e3422252557762d39188/modules/pacing/bitrate_prober.h#70) を呼び出して「プローブに必要な送信データサイズ」を取得する 6. 以降で、キュー内のパケットの送信ループ処理に入る- 各イテレーションの冒頭では [PacingController::GetPendingPacket()](https://webrtc.googlesource.com/src/+/06aea31d10f860ae4236e3422252557762d39188/modules/pacing/pacing_controller.h#213) によって、次に送信するパケットがキューから取り出される - ただし、送信バジェットが枯渇している場合などは、キューに要素が存在しても `null` が返されることがある(詳細は後述) - 「次に送信するパケットがあるかどうか」で処理が分岐する 7. **[送信パケットがない場合]** 必要に応じて、プローブ用のパディングパケットをキューに追加する1. [PacingController::PaddingToAdd()](https://webrtc.googlesource.com/src/+/06aea31d10f860ae4236e3422252557762d39188/modules/pacing/pacing_controller.h#245) でパディングパケットのサイズを計算する- パディングパケットの送信が不要な場合には 0 が返され、ここで送信ループを抜ける 2. [PacingController::PacketSender::GeneratePadding()](https://webrtc.googlesource.com/src/+/06aea31d10f860ae4236e3422252557762d39188/modules/pacing/pacing_controller.h#86) で上記のサイズのパディングパケットを生成する 3. [PacingController::EnqueuePacket()](https://webrtc.googlesource.com/src/+/06aea31d10f860ae4236e3422252557762d39188/modules/pacing/pacing_controller.h#133) を呼び出して、パディングパケットをキューに追加する 4. 送信ループの次のイテレーションに進む 8. **[送信パケットがある場合]** RTP パケットを実際に送信する1. [PacingController::PacketSender::SendPacket()](https://webrtc.googlesource.com/src/+/06aea31d10f860ae4236e3422252557762d39188/modules/pacing/pacing_controller.h#48) を呼び出して、パケットを送信する 2. FEC パケットがある場合には [PacingController::PacketSender::FetchFec()](https://webrtc.googlesource.com/src/+/06aea31d10f860ae4236e3422252557762d39188/modules/pacing/pacing_controller.h#51) で取得して、キューに追加する 3. [PacingController::OnPacketSent()](https://webrtc.googlesource.com/src/+/06aea31d10f860ae4236e3422252557762d39188/modules/pacing/pacing_controller.h#217) メソッドを呼び出して、(主に)以下を行う- 最終送信時刻の更新 - [PacingController::UpdateBudgetWithSentData()](https://webrtc.googlesource.com/src/+/06aea31d10f860ae4236e3422252557762d39188/modules/pacing/pacing_controller.h#207) を呼び出してバジェットを更新(送信分だけバジェットを減らす) 4. ループ内で送信したパケットのサイズ合計を更新する 5. プローブ中の場合には、その合計サイズが「プローブに必要な送信データサイズ」を超過しているかどうかをチェックする- 超過している場合には、ここでループを抜ける - プローブ中の場合は、一度に送信するデータサイズが、少な過ぎても多過ぎても良くない 6. [PacingController::NextSendTime()](https://webrtc.googlesource.com/src/+/06aea31d10f860ae4236e3422252557762d39188/modules/pacing/pacing_controller.h#193) を呼び出して、パケットの次回送信時刻を取得する- 次回送信時刻が「現在時刻を超えている(バジェットが枯渇した)」かつ「プローブ中ではない」場合には、ここでループを抜ける 7. `UpdateBudgetWithElapsedTime(UpdateTimeAndGetElapsed(次回送信時刻))` を呼び出して、次のイテレーションに備えてバジェットを更新する 9. 送信ループを抜けた後は、プローブ中なら BitRateProber::ProbeSent() を呼び出して、今回送信したデータサイズ合計を [BitrateProber](https://webrtc.googlesource.com/src/+/06aea31d10f860ae4236e3422252557762d39188/modules/pacing/bitrate_prober.h) に伝える 10. 最後に [PacingController::MaybeUpdateMediaRateDueToLongQueue()](https://webrtc.googlesource.com/src/+/06aea31d10f860ae4236e3422252557762d39188/modules/pacing/pacing_controller.h#246) を呼び出して、以降の送信ペースの調整を行う #### [PacingController::NextSendTime()](https://webrtc.googlesource.com/src/+/06aea31d10f860ae4236e3422252557762d39188/modules/pacing/pacing_controller.h#193) パケットの次の送信時刻を決定するためのメソッド。 バジェットが枯渇している場合には、それが回復する予定時刻を返す。 反対にバジェットに余裕がある場合には、現在より前の時刻が返されることがある。 決定の際の流れは以下の通り: 1. [PacingController::Pause()](https://webrtc.googlesource.com/src/+/06aea31d10f860ae4236e3422252557762d39188/modules/pacing/pacing_controller.h#140) が呼ばれており、一時停止中なら「次のキープアライブ時刻」を返す- 「次のキープアライブ時刻」は `最後の送信時刻 + 500ms` 2. プローブ中の場合には [BitrateProber::NextProbeTime()](https://webrtc.googlesource.com/src/+/06aea31d10f860ae4236e3422252557762d39188/modules/pacing/bitrate_prober.h#63) に次回時刻の決定を委譲する 3. 送信キューの先頭が音声パケットの場合には、そのパケットをキューに追加した時刻(つまり過去)を返す- 音声パケットは、デフォルトではペース調整の対象外なので、即座に送信される - 音声パケットがペース調整の対象に含まれる構成の場合には、この部分の処理はスキップされる 4. 「輻輳発生中」ないし「まだ [PacingController::EnqueuePacket()](https://webrtc.googlesource.com/src/+/06aea31d10f860ae4236e3422252557762d39188/modules/pacing/pacing_controller.h#133) が一度も呼び出されていない」場合には「次のキープアライブ時刻」を返す- 「輻輳発生中」かどうかは [PacingController::SetCongested()](https://webrtc.googlesource.com/src/+/06aea31d10f860ae4236e3422252557762d39188/modules/pacing/pacing_controller.h#178) によって、外部から [PacingController](https://webrtc.googlesource.com/src/+/06aea31d10f860ae4236e3422252557762d39188/modules/pacing/pacing_controller.h) に伝えられる - 輻輳時には、音声パケットやキープアライブ用パディングパケットを除いて、パケット送信は抑制される 5. キューに要素がある場合には、1. `負債 / 送信ペース` で負債が解消するまで(= 次にパケットが送信可能になるまで)に掛かる時間を求める> - 「負債」は、バジェットを超過して送信したパケットの合計サイズ(超過しておらずバジェットに余裕がある場合には負数になる) 2. その時間分を「最後の送信時刻」に加算し、それを次回の送信時刻とする 6. キューが空の場合には、- 「 [PacingController::SetPacingRates()](https://webrtc.googlesource.com/src/+/06aea31d10f860ae4236e3422252557762d39188/modules/pacing/pacing_controller.h#165) でパディングパケットの送信レートが指定されている」場合は、そのレートに合わせて次回の送信時刻を決定する - それ以外の場合には、「次のキープアライブ時刻」を次回送信時刻とする #### [PacingController::PaddingToAdd()](https://webrtc.googlesource.com/src/+/06aea31d10f860ae4236e3422252557762d39188/modules/pacing/pacing_controller.h#245) プローブやその他の目的で使用するパディングパケットのサイズを決定するメソッド。 決定方法: - 送信キューが空ではないなら、パディングサイズは 0 (パディングではなく実際のパケットを送るべきなので) - 輻輳中ならパディングサイズは 0 (ネットワークに負荷をかけたくない) - [PacingController::EnqueuePacket()](https://webrtc.googlesource.com/src/+/06aea31d10f860ae4236e3422252557762d39188/modules/pacing/pacing_controller.h#133) が一度も呼び出されていないなら、パディングサイズは 0 (パディングパケットを生成しても、適切なタイムスタンプを振ることができない) - プローブ中の場合には `プローブに必要なバイト数 - これまでに送信したバイト数` をパディングサイズとする - [PacingController::SetPacingRates()](https://webrtc.googlesource.com/src/+/06aea31d10f860ae4236e3422252557762d39188/modules/pacing/pacing_controller.h#165) で「パディングパケットの送信レート」が指定されている場合には `レート * 5ms` を返す -ただし、パディング用のバジェットに余裕がある場合のみ #### [PacingController::MaybeUpdateMediaRateDueToLongQueue()](https://webrtc.googlesource.com/src/+/06aea31d10f860ae4236e3422252557762d39188/modules/pacing/pacing_controller.h#246) 送信キューへの操作(要素追加や削除)があった場合に呼び出されるメソッド。 [SetPacingRates()](https://webrtc.googlesource.com/src/+/06aea31d10f860ae4236e3422252557762d39188/modules/pacing/pacing_controller.h#165) で指定された送信ペース(ターゲットビットレート)に対して、 [EnqueuePacket()](https://webrtc.googlesource.com/src/+/06aea31d10f860ae4236e3422252557762d39188/modules/pacing/pacing_controller.h#133) で追加されるペースが多過ぎると、キューが詰まって延々と要素数が増えてしまう。 それに対処するために、送信ペースの調整(増加)を行うのがこのメソッドの役割。 処理の流れ: 1. 最初に送信ペースを [PacingController::SetPacingRates()](https://webrtc.googlesource.com/src/+/06aea31d10f860ae4236e3422252557762d39188/modules/pacing/pacing_controller.h#165) で指定された値にリセットする 2. キューにあるパケットの「サイズ合計」を求める- もし 0 ならここで終了(指定された送信ペースをそのまま使う) 3. キュー内の各要素の平均滞在時間(エンキューされてから、実際に送信されるまでの平均時間)を求める 4. 「キューが空になるまでの期待時間」を `2 秒 - 平均滞在時間` で求める(0 以下になる場合には 1ms にする)- 「2 秒」の部分は [PacingController::SetQueueTimeLimit()](https://webrtc.googlesource.com/src/+/06aea31d10f860ae4236e3422252557762d39188/modules/pacing/pacing_controller.h#220) で変更できる - 「キューが空になるまでの期待時間」は、「キュー内の最後のパケットの遅延を 2 秒以下にするために使える残り時間」とも言える 5. `サイズ合計 / キューが空になるまでの期待時間` で、その期待時間を達成するために必要な送信ペースを求める- 求めた送信ペースが [PacingController::SetPacingRates()](https://webrtc.googlesource.com/src/+/06aea31d10f860ae4236e3422252557762d39188/modules/pacing/pacing_controller.h#165) よりも大きい場合には、(指定のペースではなく)そちらを採用する #### [PacingController::UpdateTimeAndGetElapsed()](LIBWEBRTC_PACER.html#ff3435) 基本的には「現在時刻」を引数にとって、それと「最終処理時刻」との差分(経過時間)を計算して返すメソッド。 処理の流れ: 1. 「最終処理時刻」よりも前の時刻が「現在時刻」として指定された場合には、このメソッドは 0 秒を経過時間として返す- 「現在時刻」には [PacingController::NextSendTime()](https://webrtc.googlesource.com/src/+/06aea31d10f860ae4236e3422252557762d39188/modules/pacing/pacing_controller.h#193) が返した時刻が渡ってくることがあるため、過去の時刻になることもある 2. `現在時刻 - 最終処理時刻` で経過時間を求める 3. もし経過時刻が 2 秒を超えている場合には、2 秒に丸める 4. 「最終処理時刻」を「現在時刻」の値で更新して、経過時間を呼び出し元に返す #### [PacingController::UpdateBudgetWithElapsedTime()](https://webrtc.googlesource.com/src/+/06aea31d10f860ae4236e3422252557762d39188/modules/pacing/pacing_controller.h#219) および [PacingController::UpdateBudgetWithSentData()](https://webrtc.googlesource.com/src/+/06aea31d10f860ae4236e3422252557762d39188/modules/pacing/pacing_controller.h#207) バジェットの増減を行うための単純なメソッド群: - [PacingController::UpdateBudgetWithElapsedTime()](https://webrtc.googlesource.com/src/+/06aea31d10f860ae4236e3422252557762d39188/modules/pacing/pacing_controller.h#219) は経過時間を引数に取り `経過時間 * 送信ペース` の分だけバジェットを増やす - [PacingController::UpdateBudgetWithSentData()](https://webrtc.googlesource.com/src/+/06aea31d10f860ae4236e3422252557762d39188/modules/pacing/pacing_controller.h#207) は送信したパケットサイズを引数に取り、その分だけバジェットを減らす ### [BitrateProber](https://webrtc.googlesource.com/src/+/06aea31d10f860ae4236e3422252557762d39188/modules/pacing/bitrate_prober.h) クラスの詳細 - [BitrateProber](https://webrtc.googlesource.com/src/+/06aea31d10f860ae4236e3422252557762d39188/modules/pacing/bitrate_prober.h) は「送信帯域の推定(プローブ)用に追加で送信するパディングパケット」のサイズや送信タイミングを決定するためのクラス - プローブ処理は [BitrateProber::CreateProbeCluster()](https://webrtc.googlesource.com/src/+/06aea31d10f860ae4236e3422252557762d39188/modules/pacing/bitrate_prober.h#58) 呼び出しにより開始され、プローブに必要な期間やパケット送信回数を超えたら終了する- この一回のプローブ処理のまとまりは「クラスター」と呼ばれる - クラスターは [BitrateProber::CreateProbeCluster()](https://webrtc.googlesource.com/src/+/06aea31d10f860ae4236e3422252557762d39188/modules/pacing/bitrate_prober.h#58) 呼び出し毎に新しく生成され、FIFO キューの末尾に追加される - 一度に処理されるのはキューの先頭のクラスターのみ - [BitrateProber](https://webrtc.googlesource.com/src/+/06aea31d10f860ae4236e3422252557762d39188/modules/pacing/bitrate_prober.h) には [ProbingState](https://webrtc.googlesource.com/src/+/06aea31d10f860ae4236e3422252557762d39188/modules/pacing/bitrate_prober.h#78) で表現される以下のような状態遷移がある:- [ProbingState::kDisabled](https://webrtc.googlesource.com/src/+/06aea31d10f860ae4236e3422252557762d39188/modules/pacing/bitrate_prober.h#80):- プローブ処理が無効な構成の場合には、常にこの状態となる - [ProbingState::kInactive](https://webrtc.googlesource.com/src/+/06aea31d10f860ae4236e3422252557762d39188/modules/pacing/bitrate_prober.h#82):- この状態になるのは、- [BitrateProber](https://webrtc.googlesource.com/src/+/06aea31d10f860ae4236e3422252557762d39188/modules/pacing/bitrate_prober.h) のインスタンス生成直後、ないし、 - [BitrateProber::CreateProbeCluster()](https://webrtc.googlesource.com/src/+/06aea31d10f860ae4236e3422252557762d39188/modules/pacing/bitrate_prober.h#58) によってクラスターが生成されたが、まだプローブ処理が開始されていない場合 - 基本的には、新しいパケットが [PacingController](https://webrtc.googlesource.com/src/+/06aea31d10f860ae4236e3422252557762d39188/modules/pacing/pacing_controller.h) のキューに積まれた段階で [ProbingState::kActive](https://webrtc.googlesource.com/src/+/06aea31d10f860ae4236e3422252557762d39188/modules/pacing/bitrate_prober.h#85) に遷移する - [ProbingState::kActive](https://webrtc.googlesource.com/src/+/06aea31d10f860ae4236e3422252557762d39188/modules/pacing/bitrate_prober.h#85):- プローブ処理の実施中を示す状態( [PacingController](https://webrtc.googlesource.com/src/+/06aea31d10f860ae4236e3422252557762d39188/modules/pacing/pacing_controller.h) と協調して、適宜パディングパケットが送信される) - すべてのクラスターでのプローブ処理が完了した時点で [ProbingState::kSuspended](https://webrtc.googlesource.com/src/+/06aea31d10f860ae4236e3422252557762d39188/modules/pacing/bitrate_prober.h#88) に遷移する - [ProbingState::kSuspended](https://webrtc.googlesource.com/src/+/06aea31d10f860ae4236e3422252557762d39188/modules/pacing/bitrate_prober.h#88):- すべてのクラスターでのプローブ処理が完了して待機中の状態 - 次の [BitrateProber::CreateProbeCluster()](https://webrtc.googlesource.com/src/+/06aea31d10f860ae4236e3422252557762d39188/modules/pacing/bitrate_prober.h#58) 呼び出しによって [ProbingState::kInactive](https://webrtc.googlesource.com/src/+/06aea31d10f860ae4236e3422252557762d39188/modules/pacing/bitrate_prober.h#82) に遷移する - プローブ処理は常時実行されるものではなく、通信相手との接続直後やネットワーク状況の変更に応じて実施される 以降では [BitrateProber](https://webrtc.googlesource.com/src/+/06aea31d10f860ae4236e3422252557762d39188/modules/pacing/bitrate_prober.h) の主要メソッドについて説明していく。 #### [BitrateProber::CreateProbeCluster()](https://webrtc.googlesource.com/src/+/06aea31d10f860ae4236e3422252557762d39188/modules/pacing/bitrate_prober.h#58) 新しいクラスターを生成するためのメソッド。 処理の流れは以下の通り: - 古いクラスターがキューに残っている場合には削除- 作成から五秒以上経過しているクラスターは、古いと判定される - 引数で指定された以下の情報をもとに、新しいクラスターを生成する:- ターゲット送信ビットレート - プローブ用のパケット送信回数 - プローブ用に送信するパケットサイズの合計- この値は `ターゲット送信ビットレート * プローブ期間(デフォルトでは 15ms)` によって算出される - 生成したクラスターをキューの末尾に追加 - [BitrateProber](https://webrtc.googlesource.com/src/+/06aea31d10f860ae4236e3422252557762d39188/modules/pacing/bitrate_prober.h) の状態を `kInactive` にする- 次の [BitrateProber::OnIncomingPacket()](https://webrtc.googlesource.com/src/+/06aea31d10f860ae4236e3422252557762d39188/modules/pacing/bitrate_prober.h#55) 呼び出しによってプローブが開始される - 既に `kActive` の場合には何もしない) #### [BitrateProber::OnIncomingPacket()](https://webrtc.googlesource.com/src/+/06aea31d10f860ae4236e3422252557762d39188/modules/pacing/bitrate_prober.h#55) - [PacingController::EnqueuePacket()](https://webrtc.googlesource.com/src/+/06aea31d10f860ae4236e3422252557762d39188/modules/pacing/pacing_controller.h#133) の中で、追加対象パケットのサイズを引数として、呼び出されるメソッド - 「現在が `kInactive` 」かつ「クラスターキューが空ではない」かつ「パケットサイズが十分に大きい場合」に `kActive` 状態に遷移する- 「パケットサイズが十分に大きい場合」== 「パケットサイズが `min(200, RecommendedMinProbeSize())` 以上」 #### [BitrateProber::RecommendedMinProbeSize()](https://webrtc.googlesource.com/src/+/06aea31d10f860ae4236e3422252557762d39188/modules/pacing/bitrate_prober.h#70) - 一度に送信するプローブ用のデータサイズの推奨(最低)値を返すメソッド- 送信量がこれより少ないとプローブの結果の信頼度が下がるので、不足分は( [PacingController](https://webrtc.googlesource.com/src/+/06aea31d10f860ae4236e3422252557762d39188/modules/pacing/pacing_controller.h) によって)パディングパケットで補填される - 計算式: `2 * ターゲット送信ビットレート * 1ms` #### [BitrateProber::NextProbeTime()](https://webrtc.googlesource.com/src/+/06aea31d10f860ae4236e3422252557762d39188/modules/pacing/bitrate_prober.h#63) - プローブ用のパケット送信を次に行うべき時刻を返すメソッド - 状態が `kActive` ではない場合には `Timestamp::PlusInfinity()` が返される - `kActive` (かつクラスターキューが空ではない)場合には [BitrateProber::CalculateNextProbeTime()](https://webrtc.googlesource.com/src/+/06aea31d10f860ae4236e3422252557762d39188/modules/pacing/bitrate_prober.h#103) によって事前に計算されていた、次回プローブ時刻、を返す private なメソッドである [BitrateProber::CalculateNextProbeTime()](https://webrtc.googlesource.com/src/+/06aea31d10f860ae4236e3422252557762d39188/modules/pacing/bitrate_prober.h#103) は [BitrateProber::ProbeSent()](https://webrtc.googlesource.com/src/+/06aea31d10f860ae4236e3422252557762d39188/modules/pacing/bitrate_prober.h#75) の中で呼び出され、 以下のようにして次回プローブ時刻を決定する: - 計算式: `クラスターでの送信開始時刻 + (クラスターで送信済みのサイズ合計 / ターゲットビットレート)`- 「送信開始時刻」はクラスターの生成時刻とは異なり、初めて実際にパケットが送信された時刻 - クラスター生成時に指定されたターゲットビットレート通りの送信ペースになるように設定された単純な式 - ターゲットビットレートに対して「送信量が多い場合には未来の時刻」になり、逆に「送信量が少ない場合には過去の時刻」になる #### [BitrateProber::ProbeSent()](https://webrtc.googlesource.com/src/+/06aea31d10f860ae4236e3422252557762d39188/modules/pacing/bitrate_prober.h#75) [PacingController::ProcessPackets()](https://webrtc.googlesource.com/src/+/06aea31d10f860ae4236e3422252557762d39188/modules/pacing/pacing_controller.h#197) の中で「実際に送信された合計パケットサイズ」を引数に取り呼び出されるメソッド。 処理の流れは以下の通り(キュー内の先頭のクラスターに対して適用される): - このクラスターでのパケット送信が初の場合には「送信開始時刻」を現在時刻に設定する - 「送信済みバイト数合計」に、今回の送信分を加算する - 「プローブ(用のデータ送信)回数」をインクリメントする - [BitrateProber::CalculateNextProbeTime()](https://webrtc.googlesource.com/src/+/06aea31d10f860ae4236e3422252557762d39188/modules/pacing/bitrate_prober.h#103) を呼び出して、次のプローブ時刻を決定する - 以下の両方の条件を満たす場合には、プローブ処理を終えたものと判断し、クラスターをキューから除去する:- 「送信済みバイト数合計」が [BitrateProber::CreateProbeCluster()](https://webrtc.googlesource.com/src/+/06aea31d10f860ae4236e3422252557762d39188/modules/pacing/bitrate_prober.h#58) で指定された規定値を超過した - 「プローブ回数」が [BitrateProber::CreateProbeCluster()](https://webrtc.googlesource.com/src/+/06aea31d10f860ae4236e3422252557762d39188/modules/pacing/bitrate_prober.h#58) で指定された規定値を超過した - クラスターキューが空になった場合には、 [BitrateProber](https://webrtc.googlesource.com/src/+/06aea31d10f860ae4236e3422252557762d39188/modules/pacing/bitrate_prober.h) の状態を `kSuspended` に遷移する #### [BitrateProber::CurrentCluster()](https://webrtc.googlesource.com/src/+/06aea31d10f860ae4236e3422252557762d39188/modules/pacing/bitrate_prober.h#66) 現在のプローブ処理を行なっているクラスターを返すメソッド。 基本的にはキューの先頭要素を返すだけだが、細々とした条件や処理がある。 - [BitrateProber](https://webrtc.googlesource.com/src/+/06aea31d10f860ae4236e3422252557762d39188/modules/pacing/bitrate_prober.h) の状態が `kActive` ではない場合には `null` を返す(クラスター生成直後は `kInactive` である可能性がある) - 「次のプローブ時刻(cf. [BitrateProber::CalculateNextProbeTime()](https://webrtc.googlesource.com/src/+/06aea31d10f860ae4236e3422252557762d39188/modules/pacing/bitrate_prober.h#103) )」が現在時刻に対して 10ms よりも前の場合には「そのクラスターには深刻な遅延が発生している」と判断する:- そのクラスターはキューから除去して、次のクラスターを返す - キューが空の場合には、状態を `kSuspended` に遷移した上で `null` を返す ### [PacingController](https://webrtc.googlesource.com/src/+/06aea31d10f860ae4236e3422252557762d39188/modules/pacing/pacing_controller.h) の利用側クラスや呼び出しタイミング - [PacingController](https://webrtc.googlesource.com/src/+/06aea31d10f860ae4236e3422252557762d39188/modules/pacing/pacing_controller.h) の各メソッドは直接外部から触られる訳ではなく [TaskQueuePacedSender](https://webrtc.googlesource.com/src/+/06aea31d10f860ae4236e3422252557762d39188/modules/pacing/task_queue_paced_sender.h) が(ほぼ)同名のメソッドをラップして提供している- `EnqueuePackets()`, `SetPacingRates()`, `SetCongested()`, `Pause()`, `Resume()`, `CreateProbeClusters()`, etc - ただし [PacingController::ProcessPackets()](https://webrtc.googlesource.com/src/+/06aea31d10f860ae4236e3422252557762d39188/modules/pacing/pacing_controller.h#197) に対応する [TaskQueuePacedSender::MaybeProcessPackets()](https://webrtc.googlesource.com/src/+/06aea31d10f860ae4236e3422252557762d39188/modules/pacing/task_queue_paced_sender.h#128) は外部に公開されていない- [TaskQueuePacedSender::MaybeProcessPackets()](https://webrtc.googlesource.com/src/+/06aea31d10f860ae4236e3422252557762d39188/modules/pacing/task_queue_paced_sender.h#128) は上述の各ラッパー関数の最後で呼び出される形となっている - このメソッドは [PacingController::NextSendTime()](https://webrtc.googlesource.com/src/+/06aea31d10f860ae4236e3422252557762d39188/modules/pacing/pacing_controller.h#193) の結果などを考慮し、適宜 [PacingController::ProcessPackets()](https://webrtc.googlesource.com/src/+/06aea31d10f860ae4236e3422252557762d39188/modules/pacing/pacing_controller.h#197) を呼び出す役目を担っている - [TaskQueuePacedSender](https://webrtc.googlesource.com/src/+/06aea31d10f860ae4236e3422252557762d39188/modules/pacing/task_queue_paced_sender.h) が(ラップして)公開しているメソッド群を呼び出すのは、- `EnqueuePackets()` は、映像/音声を処理しているモジュールによって使用される - `SetPacingRates()`, `SetCongested()`, `createProbeClusters()`, `Pause()`, `Resume()` といったネットワークの帯域や状態に関連するメソッドは [RtpTransportControllerSend](https://webrtc.googlesource.com/src/+/06aea31d10f860ae4236e3422252557762d39188/call/rtp_transport_controller_send.h) クラスから呼び出される: - さらにこれらのメソッドは [RtpTransportControllerSend](https://webrtc.googlesource.com/src/+/06aea31d10f860ae4236e3422252557762d39188/call/rtp_transport_controller_send.h) クラスから呼び出される:- [RtpTransportControllerSend::PostUpdates()](https://webrtc.googlesource.com/src/+/06aea31d10f860ae4236e3422252557762d39188/call/rtp_transport_controller_send.h#154)- [NetworkControlInterface](https://webrtc.googlesource.com/src/+/06aea31d10f860ae4236e3422252557762d39188/api/transport/network_control.h#59) の実装クラスの各メソッド呼び出し後に、その結果( [NetworkControlUpdate](https://webrtc.googlesource.com/src/+/06aea31d10f860ae4236e3422252557762d39188/api/transport/network_types.h#232) 構造体)を引数として呼び出されるメソッド - [NetworkControlUpdate](https://webrtc.googlesource.com/src/+/06aea31d10f860ae4236e3422252557762d39188/api/transport/network_types.h#232) 構造体には [PacerConfig](https://webrtc.googlesource.com/src/+/06aea31d10f860ae4236e3422252557762d39188/api/transport/network_types.h#201) や [PacerClusterConfig](https://webrtc.googlesource.com/src/+/06aea31d10f860ae4236e3422252557762d39188/api/transport/network_types.h#212), [TargetTransferRate](https://webrtc.googlesource.com/src/+/06aea31d10f860ae4236e3422252557762d39188/api/transport/network_types.h#220) といったペーサーに関係するフィールドが含まれている- これらのフィールドに変更があった場合には [TaskQueuePacedSender](https://webrtc.googlesource.com/src/+/06aea31d10f860ae4236e3422252557762d39188/modules/pacing/task_queue_paced_sender.h) の `SetCongested()`, `SetPacingRates()`, `createProbeClusters()` などのメソッドが呼び出される - これによって [NetworkControlInterface](https://webrtc.googlesource.com/src/+/06aea31d10f860ae4236e3422252557762d39188/api/transport/network_control.h#59) を実装している輻輳制御や帯域推定を行なっているクラスが得たフィードバックが [PacingController](https://webrtc.googlesource.com/src/+/06aea31d10f860ae4236e3422252557762d39188/modules/pacing/pacing_controller.h) に伝わることになる - [RtpTransportControllerSend::OnNetworkAvailability()](https://webrtc.googlesource.com/src/+/06aea31d10f860ae4236e3422252557762d39188/call/rtp_transport_controller_send.h#100):- ネットワークの利用可能性が変わった時に呼び出されるコールバックメソッド - [TaskQueuePacedSender](https://webrtc.googlesource.com/src/+/06aea31d10f860ae4236e3422252557762d39188/modules/pacing/task_queue_paced_sender.h) の `Pause()` および `Resume()` が必要に応じて呼び出される(ネットワークが利用不可になったなら前者、利用可能になったなら後者) ### ペーサーによって発生し得る遅延 おそらく以下のようなケースが考えられる: - [PacingController::SetPacingRates()](https://webrtc.googlesource.com/src/+/06aea31d10f860ae4236e3422252557762d39188/modules/pacing/pacing_controller.h#165) で指定されたターゲットビットレートが小さ過ぎる場合:- [PacingController](https://webrtc.googlesource.com/src/+/06aea31d10f860ae4236e3422252557762d39188/modules/pacing/pacing_controller.h) は一度キューに入ったパケットを破棄しない - そのため [PacingController::EnqueuePacket()](https://webrtc.googlesource.com/src/+/06aea31d10f860ae4236e3422252557762d39188/modules/pacing/pacing_controller.h#133) で追加されるパケットのサイズ(ペース)が、そもそもそのターゲットビットレート内で送信できる量を超えている場合には、キューが詰まり、遅延も増加していく - ただし、キュー内に存在するパケットの待機時間の平均値が 2 秒を超えそうな場合には、一時的に送信ビットレートを上げて、キューに無限に要素が増えないようにしようとする - 2 秒はデフォルト値で [PacingController::SetQueueTimeLimit()](https://webrtc.googlesource.com/src/+/06aea31d10f860ae4236e3422252557762d39188/modules/pacing/pacing_controller.h#220) を使うことで変更が可能 - 映像パケットのサイズの振れ幅が大きい場合:- [PacingController](https://webrtc.googlesource.com/src/+/06aea31d10f860ae4236e3422252557762d39188/modules/pacing/pacing_controller.h) が採用しているリーキーバケットアルゴリズムでは、一度に送信できるサイズに上限がある - そのため「極端にサイズが大きい映像の I フレームを定期的に送信」といった場合には、全体としては余裕があって、その I フレームパケットの送信がペース調整されて一度に行えず、遅延が発生する可能性がある - これが問題となる場合には [PacingController::SetSendBurstInterval()](https://webrtc.googlesource.com/src/+/06aea31d10f860ae4236e3422252557762d39188/modules/pacing/pacing_controller.h#161) といったメソッドで、ある程度のバースト送信を許容するようにできるので、これで緩和できる可能性がある ### 構成オプション フィールドトライアルやメソッド呼び出しなどによって挙動を以下のように変更することが可能(注意: 網羅的ではない): - プローブ処理の無効化 - 音声パケットをペース調整処理に含める(e.g. バジェットが不足している場合には即座に送信しない、バジェット計算の際に送信済み音声パケットサイズを考慮する) - 送信済みサイズの決定の際に、RTP / TCP / IP のヘッダー部分を考慮するかどうか(デフォルトでは RTP のペイロードサイズのみが使われる) - ある程度のバースト送信を許容する ( [PacingController::SetSendBurstInterval()](https://webrtc.googlesource.com/src/+/06aea31d10f860ae4236e3422252557762d39188/modules/pacing/pacing_controller.h#161) )- 利用できる送信帯域の総容量が増える訳ではないが、一時的に大きなパケット(e.g., 映像の I フレーム)が来た場合に、それを一気に送信できるようになる - 送信キューの実装として [RoundRobinPacketQueue](https://webrtc.googlesource.com/src/+/06aea31d10f860ae4236e3422252557762d39188/modules/pacing/round_robin_packet_queue.h) の代わりに [PrioritizedPacketQueue](https://webrtc.googlesource.com/src/+/06aea31d10f860ae4236e3422252557762d39188/modules/pacing/prioritized_packet_queue.h) を使用する # libwebrtc ミキサーのストリーム数上限 > **注意** > > この資料の正確性を保証しません。 > **重要** > > この資料についての問い合わせは Sora のサポート範囲には含まれません。 この資料は [libwebrtc M105 (5195)](https://webrtc.googlesource.com/src.git/+log/refs/branch-heads/5195) 時点の資料です。 このドキュメントでは libwebrtc での音声ミキサーの処理ストリームの上限について記載しています。 音声ミキサーは、複数の入力音声ストリームがある場合に、それらをまとめて一本のストリームとして出力する機能です。 ## 処理対象となる入力ストリーム数の上限値 ミキサーの処理対象となる入力ストリーム数の上限は [kDefaultNumberOfMixedAudioSources](https://webrtc.googlesource.com/src.git/+/42be4ae879ed6870dfc5ca554d11062b536da717/modules/audio_mixer/audio_mixer_impl.h#38) 定数によって定義されており、 値は 3 となっています。 この上限は [AudioMixerImpl::Create()](https://webrtc.googlesource.com/src.git/+/42be4ae879ed6870dfc5ca554d11062b536da717/modules/audio_mixer/audio_mixer_impl.h#40) メソッドの引数に別の値を指定することで変更できます。 ## 処理対象入力ストリームの選択方法 ミキサーの処理対象となる入力ストリームの選択は [AudioMixerImpl::GetAudioFromSources()](https://webrtc.googlesource.com/src.git/+/42be4ae879ed6870dfc5ca554d11062b536da717/modules/audio_mixer/audio_mixer_impl.cc#198) メソッドで行われます。 選択手順の概要は以下の通りです: 1. すべての入力音声ストリームを集める 2. それらを [ShouldMixBefore()](https://webrtc.googlesource.com/src.git/+/42be4ae879ed6870dfc5ca554d11062b536da717/modules/audio_mixer/audio_mixer_impl.cc#74) 関数を使ってソートする- この関数は音声ストリーム同士の音量を比較し、音の大きい方が前に配置されるようにする 3. ソート結果の先頭から上限値に達するまでストリームを選択する- ただし、ミュート状態のストリームは常に対象外となる ## 処理対象入力ストリームが入れ替わった場合の挙動 処理対象となる入力ストリーム一覧は、各ストリームの音量やミュート状態の変化、 あるいはストリーム自体の増減によって変化します。 その際に、処理対象に新しく追加されたストリームの最初の音声フレームは、ゲイン(各サンプルに乗算される重み) を調整することで、徐々に音が大きくなっていくように処理されています。 具体的には libwebrtc での音声フレームは 10ms 区切りとなっていますが、 そのフレーム内の先頭サンプルでは 0.0 (無音)から初めて、末尾サンプルでは 1.0 となるように、 段階的にゲインを増やすという処理が適用されます。 これらの処理は [RampAndUpdateGain()](https://webrtc.googlesource.com/src.git/+/42be4ae879ed6870dfc5ca554d11062b536da717/modules/audio_mixer/audio_mixer_impl.cc#89) メソッドや [Ramp()](https://webrtc.googlesource.com/src.git/+/42be4ae879ed6870dfc5ca554d11062b536da717/modules/audio_mixer/audio_frame_manipulator.cc#35) 関数によって実装されています。 なお [RampAndUpdateGain()](https://webrtc.googlesource.com/src.git/+/42be4ae879ed6870dfc5ca554d11062b536da717/modules/audio_mixer/audio_mixer_impl.cc#89) メソッド自体は、ストリームが対象から外れた場合(この場合はゲインが 1.0 から 0.0 に減少していく)も考慮された実装となっています。 ただし、このメソッドの呼び出しもとの実装的に、初回追加時にのみゲイン調整が行われます (一度対象から外れた後に再度追加された場合もゲイン処理の適用外となります)。 # マルチストリーム ## 概要 Sora は音声と映像の扱いにマルチストリームを採用しています。 マルチストリームとは一つのコネクションの中で複数の映像や音声を動的に追加したり削除したりする仕組みです。 この機能を利用することで、複数のコネクションを管理せずに複数の映像や音声、データのやりとりが利用できます。 ## 制限 - 配信側は音声 1 トラック、映像 1 トラック固定です - 動的に配信側のトラックを追加したりするマルチトラックには対応していません ## マルチストリームにおける映像ビットレート自動シェアリング機能 > **警告** > > この機能は非推奨です。 ビットレート自動シェアリング機能を Sora 2025 年 12 月リリースの Sora からデフォルトで無効にしました。 この機能は [スポットライト機能](SPOTLIGHT.html) がまだない時代に、参加者が増えた場合でも視聴側の負担を減らす機能でした。 しかし、現在はスポットライト機能を利用することで、参加者が増えた場合でも視聴側の負荷を減らせることや、シェアリング機能の結果、指定したビットレートとは異なる配信が行われて混乱を招くことが多いことから、デフォルトで無効にすることにしました。 今後は、同一チャネルで複数人により双方向配信を行う場合は、スポットライト機能の利用を強くおすすめします。 もし継続してマルチストリームにおける映像ビットレート自動シェアリング機能を利用したい場合は、 `sora.conf` の [multistream_auto_sharing_video_bit_rate](SORA_CONF.html#93f542) を `true` に設定してください。 # Microsoft Edge の WebRTC について ## 概要 2026 年 6 月 時点で Microsoft Edge 143 を使用して確認しています。 [Download New Microsoft Edge Browser | Microsoft](https://www.microsoft.com/en-us/edge) ## 現状 Chrome とほぼ同様の仕様で、特に問題なく動作します。 Edge 121 から AV1 もサポートされています。 ## 注意 Chrome 136 から H.265 に対応しましたが、Edge では H.265 に対応していません。 # Apple Safari の WebRTC について ## 概要 2026 年 6 月 時点で Safari 28.2 を使用して確認しています。 > **重要** > > Safari の利用者がいる場合は [Safari タイムスタンプバグに対するワークアラウンド](WORKAROUND.html#e73b7a) をご確認ください。 ## 注意点 - 音声が含まれているまたは音声のみの配信の場合 iOS の Safari では自動再生されません- これは iOS の Safari の仕様のため、今のところ回避の方法はありません - macOS の Safari の場合も設定を有効にしないと同様です - Certificate Management API に非対応です- ECDSA P256 使えません - ontrack を利用してください - 映像コーデック VP9 は対応していますが、古い iPhone では動作しなかったりします - getUserMedia を利用するには HTTPS が必須です- 開発モードで HTTPS 必須を無効にできます ## iOS の Chrome や Firefox について iOS の Chrome や Firefox は WKWebView を利用しています。 WKWebView は iOS 14.3 にて getUserMedia に対応しました。 ## iOS Safari で画面共有について iOS Safari には画面共有用の getDisplayMedia API が実装されていません。 そのため、画面共有を利用するにはネイティブアプリケーションを利用する必要があります。 2026 年 6 月 時点ですべてのモバイルブラウザが getDisplayMedia API には対応していません。 [MediaDevices.getDisplayMedia() - Web APIs | MDN](https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getDisplayMedia#browser_compatibility) ## 録画機能音ズレ問題 Safari や Safari Technology Preview では録画機能利用時に `replaceTrack` などを利用して `MediaStreamTrack` を削除し、 一定時間経過後に新しく追加した際、音声パケットに関連するタイムスタンプと NTP タイムスタンプが正しく出力されない問題あります。 この問題により Safari や Safari Technology Preview では録音/録画したファイルにて音ズレが発生してしまいます。 この問題はブラウザ側のバグであり、現在のところ回避策はありません。 ## WebRTC Encoded Transform API が利用できる Safari では [WebRTC Encoded Transform](https://www.w3.org/TR/webrtc-encoded-transform/) API が利用できます。 ## H.265 (HEVC) Safari 18.0 から HEVC (H.265) がデフォルトで有効になりました。 [Safari 18.0 Release Notes | Apple Developer Documentation](https://developer.apple.com/documentation/safari-release-notes/safari-18-release-notes#Media) ## VP9 Profile 2 ドキュメントに記載はありませんが、Safari 18.0 より VP9 Profile 2 がデフォルトで有効になりました。 ## 実験的機能 > **注意** > > [Safari](https://www.apple.com/jp/safari/) や [Safari Technology Preview (Safari TP)](https://developer.apple.com/safari/technology-preview/) では実験的機能の挙動が異なります ### WebRTC AV1 - [Safari Technology Preview (Safari TP)](https://developer.apple.com/safari/technology-preview/) 最新版では WebRTC AV1 が利用できます - [Safari](https://www.apple.com/jp/safari/) 最新版では開発メニューで有効にすることで WebRTC AV1 が利用できます。 # NGINX > **注意** > > NGINX の設定に関する質問については Sora のサポート範囲外となります。 **この設定はある程度の NGINX や証明書の知識が必要になります** ## 概要 Sora のシグナリングを暗号化する場合に何かしらのサーバーを立てる必要があります。 ここでは NGINX での設定例を紹介しています。 ## 設定例 nginx.conf の http ディレクティブに include を使用した場合の設定例です。 `ssl_*` 関連の設定は済んでいる前提とします。 ### NGINX 経由でオンラインの開発ツールを利用する場合 ```nginx server { listen 443 ssl default_server; server_name sora.example.com; # Sora のシグナリング に Proxy します location = /signaling { proxy_pass http://127.0.0.1:5000; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; } # Sora の HTTP API に Proxy します # 本番環境では認証などの機能を利用してください location /api { proxy_pass http://127.0.0.1:3000/; } # Sora の開発ツールにリバース Proxy します # 本番環境では不要です location / { index index.html; proxy_http_version 1.1; proxy_pass https://sora-devtools.shiguredo.app; proxy_set_header Host sora-devtools.shiguredo.app; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_ssl_server_name on; proxy_ssl_name sora-devtools.shiguredo.app; proxy_ssl_protocols TLSv1.2 TLSv1.3; } } ``` ### NGINX 経由でオフラインの発者ツールを利用する場合 ```nginx server { listen 443 ssl default_server; server_name sora.example.com; # Sora のシグナリング に Proxy します location = /signaling { proxy_pass http://127.0.0.1:5000; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; } # Sora の HTTP API に Proxy します # 本番環境では認証などの機能を利用してください location /api { proxy_pass http://127.0.0.1:3000/; } # Sora の開発ツールにリバース Proxy します # 本番環境では不要です location / { root /path/to/sora-devtools-; index index.html; try_files $uri $uri/ /index.html; } } ``` ## TURN を含んだ設定 TURN 関連は [本番稼働に向けて](PRODUCTION.html) にある資料を確認してください。 [TURN-TLS、TURN-TCP、シグナリングで 443 番ポートを使用する](PRODUCTION.html#14258d) ## ウェブフックを NGINX 経由で送信する ウェブフックをリバースプロキシする設定は [本番稼働に向けて](PRODUCTION.html) にある資料を確認してください。 [ウェブフックを NGINX 経由で送信する](PRODUCTION.html#775c13) ## デフォルトで有効になっている設定を無効化する NGINX パッケージのインストール時には、/etc/nginx/sites-enabled/default の設定がデフォルトで有効化されていることがあります。 この設定を明示的に無効にしない場合は、意図しない仮想ホストが有効となり、想定外のリクエストを処理してしまう可能性があります。 そのため、特に目的がなければ、/etc/nginx/sites-enabled/default ファイルを削除して無効化し、 必要な設定のみを明示的に有効化した状態にすることをおすすめします。 # オープンソースライセンス **WebRTC SFU Sora で利用しているオープンソースのライセンス一覧** ## Apache License 2.0 **URL**: - [erlang/otp](https://github.com/erlang/otp) - [openssl/openssl](https://github.com/openssl/openssl) - [uwiger/gproc](https://github.com/uwiger/gproc) - [rabbitmq/ra](https://github.com/rabbitmq/ra) - [rabbitmq/gen-batch-server](https://github.com/rabbitmq/gen-batch-server) - [rabbitmq/aten](https://github.com/rabbitmq/aten) - [rabbitmq/seshat](https://github.com/rabbitmq/seshat) - [shiguredo/jsone](https://github.com/shiguredo/jsone) - [shiguredo/jesse](https://github.com/shiguredo/jesse) - [shiguredo/swidden](https://github.com/shiguredo/swidden) - [shiguredo/kvconf](https://github.com/shiguredo/kvconf) - [shiguredo/base32_clockwork](https://github.com/shiguredo/base32_clockwork) ## ISC License **URL**: - [ninenines/cowboy](https://github.com/ninenines/cowboy) - [ninenines/cowlib](https://github.com/ninenines/cowlib) - [ninenines/ranch](https://github.com/ninenines/ranch) - [ninenines/gun](https://github.com/ninenines/gun) # 古いリリースノート **UPDATE** : 後方互換性がある変更 **ADD** : 後方互換性がある追加 **CHANGE** : 後方互換性のない変更 **FIX** : バグ修正 > **重要** > > 変更、廃止された一部機能のリンクは無効になっています。 ## 2025.2.1 **バグフィックスアップデート** **リリース**: 2026 年 04 月 13 日 ### 変更履歴 - [FIX] [OBS Studio 32.1.0](https://github.com/obsproject/obs-studio/releases/tag/32.1.0) における WHIP の仕様変更に伴い、Sora 2025.2.0 以前のバージョンで配信ができない問題を修正しました- 詳細については obs_whip_notice をご確認ください ## 2025.2.0 **メジャーアップデート** **リリース**: 2025 年 12 月 17 日 > **重要** > > Sora 2025.1.x から 2025.2.x への移行については 2025.1.x から 2025.2.x への移行 をご確認ください。 ### ハイライト - 環境変数 `SORA_*` で `sora.conf` の設定を上書きできる機能を追加しました - 実験的機能として、クライアントから Sora の一部の HTTP API を DataChannel 経由で呼び出すことができる [RPC 機能](RPC.html) を追加しました - 実験的機能として、視聴側の環境に合わせてサイマルキャストのストリームを自動で切り替える機能を追加しました - 実験的機能として、ノード単位での最大同時接続数制限機能を追加しました - 実験的機能として、認証ウェブフックで録画を開始する機能を追加しました ### 正式版 今回のリリースで以下の機能が実験的機能から正式版になりました。 - [シグナリング通知メタデータ拡張機能](SIGNALING_NOTIFY_METADATA_EXT.html) - [シグナリング通知 ICE コネクションステート](ICE_CONNECTION_STATE.html#149f7e) - [マルチ転送フィルター機能](MULTI_FORWARDING_FILTER.html) - [MP4 形式録画機能](RECORDING.html#65b0fb) - [プレイアウト遅延機能](PLAYOUT_DELAY.html) ### 破壊的変更 - マルチストリームにおける映像ビットレート自動シェアリング機能のデフォルト設定を **無効** に変更しました- もしビットレート自動シェアリング機能を有効にしたい場合は `sora.conf` の [multistream_auto_sharing_video_bit_rate](SORA_CONF.html#93f542) を `true` に設定してください - 録画機能(セッション単位)のデフォルト出力フォーマットを MP4 に変更しました- `sora.conf` の `default_recording_format` のデフォルト値を `webm` から `mp4` に変更しました - `sora.conf` に [テスト API](TEST_API.html) を利用するかどうかを指定する [test_api](SORA_CONF.html#a2f020) を追加して、デフォルト無効にしました- 利用する場合は [test_api](SORA_CONF.html#a2f020) を `true` に設定してください ### 廃止機能 - レガシー録画関連 API を廃止しました- [StartRecording](OBSOLETE_API_LEGACY_RECORDING.html#c5b527) API を廃止しました - [StopRecording](OBSOLETE_API_LEGACY_RECORDING.html#fd0de5) API を廃止しました - [GetStartedRecording](OBSOLETE_API_LEGACY_RECORDING.html#8095d0) API を廃止しました - [ListStartedRecording](OBSOLETE_API_LEGACY_RECORDING.html#838360) API を廃止しました - [ListArchiving](OBSOLETE_API_LEGACY_RECORDING.html#d4ba61) API を廃止しました - RTP ストリーム停止/再開 関連 API を廃止しました- [PauseRtpStream](OBSOLETE_API_RTP_STREAM_PAUSE_RESUME.html#de7a52) API を廃止しました - [ResumeRtpStream](OBSOLETE_API_RTP_STREAM_PAUSE_RESUME.html#43002a) API を廃止しました - [ListPauseRtpStreams](OBSOLETE_API_RTP_STREAM_PAUSE_RESUME.html#c4de52) API を廃止しました - 再送要求の頻度を利用した不安定レベルの通知機能を廃止しました- `sora.conf` の `legacy_signaling_notify_network_status` を廃止しました - `sora.conf` の `turn` を廃止し、 [TURN 機能](TURN.html) を無効化することができなくなりました - `sora.conf` の `whip_turn` を廃止し、 [WHIP 機能](WHIP.html) の TURN のサポートを無効化することができなくなりました - `sora.conf` の `whep_turn` を廃止し、 [WHEP 機能](WHEP.html) の TURN のサポートを無効化することができなくなりました - `sora.conf` の `ice_connection_state_disconnected_timeout` を廃止しました- 今後は [default_ice_connection_state_disconnected_timeout](SORA_CONF.html#420a1e) をご利用ください - `sora.conf` の `ice_connection_state_failed_timeout` を廃止しました- 今後は [default_ice_connection_state_failed_timeout](SORA_CONF.html#d6f965) をご利用ください - `sora.conf` の `av1` を廃止し、 AV1 のサポートを無効化することができなくなりました - `sora.conf` の `h265` を廃止し、 H.265 のサポートを無効化することができなくなりました - `sora.conf` の `devtools` を廃止し、組み込みの開発ツールが利用できなくなりました- 開発ツールを利用する場合は NGINX のリバースプロキシやホスティングを利用してください - 詳細は [開発ツール](DEVTOOLS.html) をご覧ください - `sora.conf` の `signaling_forwarding_filter` を廃止しました ### 変更履歴 - [CHANGE] [multistream_auto_sharing_video_bit_rate](SORA_CONF.html#93f542) をデフォルト無効にしました- もしビットレート自動シェアリング機能を有効にしたい場合は [multistream_auto_sharing_video_bit_rate](SORA_CONF.html#93f542) を `true` に設定してください - [CHANGE] `sora.conf` に [テスト API](TEST_API.html) を利用するかどうかを指定する [test_api](SORA_CONF.html#a2f020) を追加し、デフォルトはテスト API を無効にしました- テスト API を利用する場合は [test_api](SORA_CONF.html#a2f020) を `true` に設定してください - [CHANGE] レガシー録画機能を廃止しました- レガシー録画機能廃止に伴い `sora.conf` の `legacy_recording` を廃止しました - [CHANGE] コネクションログの `e2ee` を廃止しました- E2EE 機能は 2024.2.0 で廃止されており、ログに出力しても意味がないため廃止しました - 認証ウェブフックの `e2ee` 項目は削除しておりません - [CHANGE] コネクションログの `simulcast_encodings` の出力条件を変更しました- サイマルキャストが有効でかつスポットライトが無効で、ロールが `sendonly` または `sendrecv` の場合に出力されるようになりました - [CHANGE] コネクションログの `spotlight_encodings` の出力条件を変更しました- サイマルキャストが無効でかつスポットライトが有効で、ロールが `sendonly` または `sendrecv` の場合に出力されるようになりました - [CHANGE] シグナリングメッセージの `"type": "re-answer"` の受信待ち受け時間を 30 秒に制限しました - [ADD] スポットライトシグナリング通知を送るかどうかを `sora.conf` の `signaling_notify_spotlight` で指定できるようになりました- デフォルトは `true` です - `false` に設定するとスポットライトシグナリング通知 `spotlight.{focused, unfocused}` が送信されなくなります - [ADD] コネクションログの項目を追加しました- `id`: コネクションログのユニーク ID - `version`: Sora のバージョン - `label`: Sora のラベル - `node_name`: Sora のノード名 - [FIX] [セッション単位での最大同時接続数制限機能](SESSION_MAX_CONNECTIONS.html) と [セッション単位でのクライアント ID 重複時の既存接続の追い出し機能](SESSION_DUPLICATE_CLIENT_ID.html) を同時に有効にした場合に、最大同時接続数に達している状態で追い出しが発生した際、追い出しは成功するが最大同時接続数制限により接続が失敗する問題を修正しました - [FIX] 音声の SDP に `a=rtcp-fb` の `transport-cc` が付与されていない問題を修正しました - [FIX] サイマルキャストで特定の `rid` ストリームが復帰した際に、最初のキーフレームの SRTP 復号をスキップしてしまう問題を修正しました - [FIX] スポットライト機能利用時に `spotlight_number` を超える数のフォーカスが同時に当たり、かつ、次のアンフォーカスイベント発生まで、同時フォーカスが維持され続ける問題を修正しました - [FIX] スポットライト機能利用時に [sora_conf-default_spotlight_focus_min_interval](SPOTLIGHT.html#9ba866) の値より [sora_conf-default_spotlight_auto_unfocus_interval](SPOTLIGHT.html#fcf07a) の値が短い場合に [sora_conf-default_spotlight_auto_unfocus_interval](SPOTLIGHT.html#fcf07a) が優先される問題を修正しました - [FIX] サイマルキャスト機能利用時に、認証成功時の払い出しで `simulcast_rid` を指定しても無視されてしまう問題を修正しました #### `role` が `recvonly` の場合の `codec_type` や `bit_rate` などの指定を無視する変更 マルチストリーム機能のみの提供になっても、 Sora 2025.1.0 で廃止したレガシーストリームとの互換性を維持するために、 `role` が `recvonly` の場合でもシグナリングや認証成功時の払い出しで、 `codec_type` や `bit_rate` などの指定ができていました。 Sora 2025.2.0 からは、下記のように `codec_type` や `bit_rate` などを指定したとしても無視する仕様に変更しました。 - [CHANGE] `role` が `recvonly` の場合、シグナリングや認証成功時に以下の指定が無視されるようになりました- `audio` の `codec_type` 、 `bit_rate` 、 `opus_params` - `video` の `codec_type` 、 `bit_rate` 、 `simulcast` 、 `vp9_params` 、 `av1_params` 、 `h264_params` 、 `h265_params` - [CHANGE] `role` が `recvonly` の場合、connection ログに以下の情報が出力されなくなりました- `audio` の `codec_type` 、 `bit_rate` 、 `opus_params` - `video` の `codec_type` 、 `bit_rate` 、 `simulcast` 、 `vp9_params` 、 `av1_params` 、 `h264_params` 、 `h265_params` #### 環境変数による sora.conf の設定上書き機能 環境変数にて `SORA_<設定項目名>` を指定することで `sora.conf` の設定を上書きできる機能を追加しました。 例えば `SORA_DEFAULT_VIDEO_BIT_RATE=500` という環境変数を指定することで `sora.conf` の `default_video_bit_rate` の設定を上書きできます。もし設定が `default_video_bit_rate = 300` であっても、Sora は起動時に環境変数の値を優先して `500` として動作します。 - [ADD] 環境変数にて `SORA_<設定項目名>` を指定することで `sora.conf` の設定を上書きできるようになりました 詳細は [環境変数による設定上書き機能](SORA_CONF.html#e551e8) をご確認ください。 #### RPC 機能 **これは実験的機能です** クライアントから、Sora の一部の HTTP API をデータチャネル経由で呼び出すことができる RPC 機能を追加しました。 この機能を利用するにはデータチャネルシグナリングを有効にする必要があります。 - [ADD] `sora.conf` に RPC 機能を指定する [data_channel_rpc](SORA_CONF.html#26f332) を追加しました- デフォルトは `true` です - [ADD] 認証成功時の払い出しに、利用できる RPC メソッドの一覧を指定する `rpc_methods` を追加しました- `"rpc_methods": ["2025.2.0/RequestSimulcastRid"]` のように指定します - 未指定または空リスト `[]` の場合は RPC 機能を利用できません - [ADD] シグナリングメッセージ `"type": "offer"` に認証成功時に払い出した `rpc_methods` が含まれるようになりました - [ADD] `connection.jsonl` に `rpc_methods` が含まれるようになりました - [ADD] メタデータ拡張機能の [PutSignalingNotifyMetadata](API_SIGNALING_NOTIFY_METADATA_EXT.html#a20c95) API を RPC 機能で利用できるようになりました- メソッド名は [2025.2.0/PutSignalingNotifyMetadata](RPC.html#0907eb) です - `channel_id` と `connection_id` は省略することができます - [ADD] メタデータ拡張機能の [PutSignalingNotifyMetadataItem](API_SIGNALING_NOTIFY_METADATA_EXT.html#387c9c) API を RPC 機能で利用できるようになりました- メソッド名は [2025.2.0/PutSignalingNotifyMetadataItem](RPC.html#bd02ac) です - `channel_id` と `connection_id` は省略することができます - [ADD] サイマルキャスト機能の [RequestSimulcastRid](API_SIMULCAST.html#7d26ab) API を RPC 機能で利用できるようになりました- メソッド名は [2025.2.0/RequestSimulcastRid](RPC.html#07fda8) です - `channel_id` と `receiver_connection_id` は省略することができます - [ADD] スポットライト機能の [RequestSpotlightRid](API_SPOTLIGHT.html#5c2650) API を RPC 機能で利用できるようになりました- メソッド名は [2025.2.0/RequestSpotlightRid](RPC.html#3e09d6) です - `channel_id` と `recv_connection_id` は省略することができます - [ADD] スポットライト機能の [ResetSpotlightRid](API_SPOTLIGHT.html#680344) API を RPC 機能で利用できるようになりました- メソッド名は [2025.2.0/ResetSpotlightRid](RPC.html#ac4795) です - `channel_id` と `recv_connection_id` は省略することができます 詳細は [RPC 機能](RPC.html) をご確認ください。 #### セッション単位でのクライアント ID 重複時の既存接続の追い出し機能 **これは実験的機能です** - [ADD] クライアント ID 重複時の既存接続の追い出し機能が有効になっているセッションにおいて、追い出される対象の既存のコネクションが存在する場合に、そのクライアントの `ice_connection_state` を認証ウェブフックに含めるようになりました- シグナリング接続時に、その接続と重複した `client_id` が指定されている追い出し対象のコネクションがすでに存在する場合にのみ `ice_connection_state` が含まれます #### サイマルキャスト新機能追加に関する設定項目名と API 名の変更 Sora 2025.2.0 から `rid` に `none` を設定できるようになりました。これに伴い `sora.conf` の設定や、接続時、認証成功時の払い出し項目、API の名前をよりわかりやすくしたものを追加しました。 Sora 2025.2.0 より前の古い設定項目名や API 名も引き続き利用できますが、2027 年 12 月リリース予定の Sora にて廃止予定です。新しい設定項目名や API 名をご利用ください。 古い設定項目や API では `rid` に `none` を指定することはできません。 [ResetRtpStream](DEPRECATED_API_SIMULCAST.html#afba6e) API については活用場所が難しく、 [RequestSimulcastRid](API_SIMULCAST.html#7d26ab) で代替できることから 2026 年 12 月にて廃止することにしました。 - [CHANGE] [ResetRtpStream](DEPRECATED_API_SIMULCAST.html#afba6e) API を非推奨にしました- 今後は [RequestSimulcastRid](API_SIMULCAST.html#7d26ab) API をご利用ください - [ADD] `rid` の切り替えをリクエストする [RequestSimulcastRid](API_SIMULCAST.html#7d26ab) API を追加しました- `rid` は `r0` 、 `r1` 、 `r2` に加えて `none` が指定できるようになりました - [RequestRtpStream](DEPRECATED_API_SIMULCAST.html#6fe0b3) API は 2027 年 12 月リリース予定の Sora にて廃止予定です - `send_connection_id` を `sender_connection_id` へ変更しています - `recv_connection_id` を `receiver_connection_id` へ変更しています - [ADD] サイマルキャスト視聴側がどの rid を視聴するかのデフォルトを指定する `sora.conf` の [default_simulcast_request_rid](SORA_CONF.html#9891c8) を追加しました- デフォルトは `r0` です - `simulcast` が `true` の場合にのみ有効です - `sora.conf` の [default_simulcast_rid](SORA_CONF.html#d95788) は 2027 年 12 月リリース予定の Sora にて廃止予定です - [ADD] シグナリング接続時に視聴するストリームの rid を指定する `simulcast_request_rid` を追加しました- `simulcast_request_rid` には `none` 、 `r0` 、 `r1` 、 `r2`、 を指定できます - `simulcast_request_rid` は `role` が `sendrecv` または `recvonly` の場合にのみ有効です - `simulcast` が `true` の場合にのみ有効です - シグナリング接続時の `simulcast_rid` は 2027 年 12 月リリース予定の Sora にて廃止予定です - [ADD] 認証成功時の払い出しにて視聴するストリームの rid を指定する `simulcast_request_rid` を追加しました- `simulcast_request_rid` には `none` 、 `r0` 、 `r1` 、 `r2` を指定できます - `simulcast_request_rid` は `role` が `sendrecv` または `recvonly` の場合にのみ有効です - `simulcast` が `true` の場合にのみ有効です - 認証成功時の `simulcast_rid` は 2027 年 12 月リリース予定の Sora にて廃止予定です - [ADD] 認証成功時の払い出しにて RPC 機能経由で `2025.2.0/RequestSimulcastRid` で利用できる `rid` を指定する `simulcast_rpc_rids` を追加しました- デフォルトは未指定で、どれも指定できません - `simulcast` が `true` の場合にのみ有効です - `"simulcast_rpc_rids": ["none", "r0", "r1"]` のように指定します #### サイマルキャスト機能利用時の視聴環境に合わせたストリーム自動切り替え機能 **これは実験的機能です** 実験的機能として、サイマルキャスト機能に Sora 側で視聴環境に合わせてストリームを自動で切り替える仕組みを追加しました。 例えば、 `rid` が `r2` のストリームが高ビットレート、 `r1` のストリームが低ビットレートの場合、視聴環境が悪化した場合に Sora が自動で `r2` から `r1` に切り替えます。 > **重要** > > `simulcast_auto_rids` が指定された場合、 Sora 2025.2.0 ではまだ **視聴環境が悪化した場合に、ビットレートが低い映像に自動的に下げる機能** のみになります。 **視聴環境が改善した場合にビットレートが高い映像に自動的に上げる機能** は 2026 年リリース予定の Sora にて対応予定です。 - [ADD] `sora.conf` にサイマルキャスト機能利用時に、視聴環境に合わせて Sora が自動で配信する `rid` ストリームを切り替える [default_simulcast_auto_rids](SORA_CONF.html#97a674) を追加しました- デフォルトは未指定で、自動では切り替わりません - [default_simulcast_auto_rids](SORA_CONF.html#97a674) はサイマルキャストが有効な場合のみ利用できます - `default_simulcast_auto_rids = r0, r1` のように複数指定することができます - 指定した `rid` の中で視聴環境に合わせて Sora が自動で切り替えます - [ADD] 認証成功時の払い出しに、サイマルキャスト利用時に、視聴側の環境に合わせて配信する `rid` ストリームを Sora が自動で切り替える [simulcast_auto_rids の払い出し](AUTH_WEBHOOK_RETURN.html#3b4f6a) を追加しました- デフォルトは [default_simulcast_auto_rids](SORA_CONF.html#97a674) の値です - [simulcast_auto_rids の払い出し](AUTH_WEBHOOK_RETURN.html#3b4f6a) を払い出す場合は同時に `simulcast` を `true` で払い出す必要があります - `rids` には `["r0", "r1"]` のように複数指定できます - 指定した `rid` の中で視聴環境に合わせて Sora が自動で切り替えます - 空リスト `[]` で指定した場合は自動で切り替わらなくなります - [ADD] サイマルキャスト機能利用時に視聴側の環境に合わせて Sora が自動で配信する `rid` ストリームを切り替えるように変更できる [ChangeSimulcastAuto](EXPERIMENTAL_API_SIMULCAST.html#81b01b) API を追加しました- デフォルトは [default_simulcast_auto_rids](SORA_CONF.html#97a674) の値です - [ChangeSimulcastAuto](EXPERIMENTAL_API_SIMULCAST.html#81b01b) API はサイマルキャストが有効な場合のみ利用できます - `rids` には `["r0", "r1"]` のように複数指定できます - 指定した `rid` の中で視聴環境に合わせて Sora が自動で切り替えます - 空リスト `[]` を指定した場合、自動切り替えは無効になります - [ADD] `sora.conf` にサイマルキャスト機能利用時に `simulcast_auto_rids` を指定した際、自動で切り替わる最小の間隔を秒数で指定します [simulcast_auto_min_switch_interval](SORA_CONF.html#cbfb69) を追加しました- デフォルトは `5 s` です - 範囲は `1..300 s` です - [ADD] 統計情報にサイマルキャスト機能利用時に視聴環境に自動で切り替わる `simulcast_auto` を追加しました- `target_sender_count`- サイマルキャスト rid 切り替えの対象となった送信ストリーム数 - `total_switched`- サイマルキャスト rid が自動で切り替わった回数 - `total_up_trend`- 帯域推定が上昇傾向だった際に切り替えをスキップした回数 - `total_history_not_ready` - 履歴サイズが十分でないために切り替えをスキップした回数の累計値 #### サイマルキャスト機能利用時の rid 切り替わり時のシグナリング通知機能 **これは実験的機能です** 今まで視聴側で simulcast の `rid` が切り替わったことを知る手段がありませんでした。 今回、サイマルキャストの `rid` が切り替わった際にシグナリング通知が送信される機能を追加しました。 - [ADD] サイマルキャスト機能で rid が切り替わった際に送信するシグナリング通知 `simulcast.switched` を追加しました - [ADD] `sora.conf` にサイマルキャストの rid が切り替わった際にシグナリング通知を送信するかどうかを指定する [signaling_notify_simulcast_switched](SORA_CONF.html#022113) を追加しました- デフォルトは `true` です ```javascript { "type": "notify", "timestamp": "string", "event_type": "simulcast.switched", "sender_connection_id": "string", "priority": "higher | lower", "trigger": "api | rpc | sender | receiver", // simulcast_rpc_rids を指定した場合に含まれます // 未指定の場合は "rpc_rids": [] になります "rpc_rids": ["none", "r0", "r1", "r2"], // simulcast_auto_rids を指定した場合に含まれます // 未指定の場合は "auto_rids": [] になります "auto_rids": ["none", "r0", "r1", "r2"], "request_rid": "none | r0 | r1 | r2", "current_rid": "none | r0 | r1 | r2", "previous_rid": "none | r0 | r1 | r2", } ``` #### 認証ウェブフック経由での録画開始機能 **これは実験的機能です** 録画はセッションウェブフック [session.created](SESSION_WEBHOOK.html#1d1984) のタイミングで開始するか [StartRecording](API_RECORDING.html#c5b527) API を呼び出すことで開始できますが、ウェブフックを利用して途中から録画を開始する事ができませんでした。 今回、実験的機能として認証ウェブフックの戻り値で録画を開始できる仕組みを追加しました。 - [ADD] `sora.conf` に認証ウェブフック成功時の払い出しで録画を開始できるかどうかを指定する [auth_webhook_recording](SORA_CONF.html#24d27d) を追加しました。 - [ADD] 認証ウェブフックの戻り値に `recording` を追加しました- `recording` に `true` を指定すると録画が既に開始されていない場合は録画を開始します - `recording` に `false` を指定した場合は無視します - [ADD] 認証ウェブフックの戻りに `recording` に `true` を指定した際に利用できる録画用の項目を追加しました- `recording_expire_time` - `recording_split_only` - `recording_split_duration` - `recording_metadata` - `recording_format` - これらの設定の詳細については [認証ウェブフック](RECORDING.html#cd90e9) をご確認ください。 #### ノード単位での最大同時接続数制限機能 **これは実験的機能です** Sora は今までノード単位の同時接続数はライセンスでのみ制限をしていましたが、 低スペックのインスタンスを一時的に利用する際、ノード単位での最大同時接続数を制限したいという要望がありました。 今回 `sora.conf` にてノード単位での接続数を制限する仕組みを追加しました。 この機能を利用することで、例えば、ライセンスでは 300 同時接続まで許可されているが、ノード単位で 100 同時接続までに制限するといった運用が可能になります。 - [ADD] `sora.conf` にノード単位での最大同時接続数を制限する `max_connections` を追加しました- デフォルトは未指定で無制限です - 0 から 10000 までの値を指定できます - この値をチェックする前にライセンスによる最大同時接続数をチェックするため、ライセンスによる最大同時接続数を超えた接続はできません #### セッション単位での最大同時接続数を無視する機能 **これは実験的機能です** セッション作成時の `max_connections` にてセッション単位の最大同時接続数を制限できますが、 特定のクライアントは、このセッション単位の最大同時接続数の制限を無視して接続を許可したい場合があります。 今回、認証成功時の払い出しでセッション単位の最大同時接続数を無視して接続を許可する仕組みを追加しました。 - [ADD] 認証成功時の払い出しにて `ignore_max_connections` を指定できるようになりました- セッション単位の最大同時接続数制限が指定されている場合に有効になります - `ignore_max_connections` に `true` を指定するとセッション単位での最大同時接続数制限を無視して接続を許可します - [ADD] コネクションログ `connection.jsonl` に `ignore_max_connections` を追加しました- コネクションログの `ignore_max_connections` が `true` の場合、セッション単位の最大同時接続数制限を無視して接続が許可されたことを示します ## 2025.1.0 **メジャーアップデート** **リリース**: 2025 年 6 月 25 日 ### ハイライト - クラスターリレー機能のツリー化によりノードの負荷を分散できるようになりました - クラスターリレー機能が正式版になりました- クラスターアフィニティ機能やテンポラリーノード機能も正式版になりました - セッション単位で最大同時接続数を制限できる機能が正式版になりました - セッション単位でのクライアント ID 重複時の既存接続の追い出し機能を追加しました - 帯域推定機能を追加しました - メディア配信ワーカー自動スケール機能を追加しました ### 正式版 今回のリリースで以下の機能が実験的機能から正式版になりました。 - [リレー機能](CLUSTER.html#4b3bf1) - [アフィニティ機能](CLUSTER.html#6f4bfb) - [テンポラリーノード機能](CLUSTER.html#3cb6c8) - セッション単位での最大同時接続数制限機能の [max_connections](SESSION_WEBHOOK.html#498be9) 払い出し - [ListSessions](API_SESSION.html#748f19) API - [GetSession](API_SESSION.html#427a59) API - [RTC 統計情報 API](API_RTC_STATS.html) - [統計ウェブフック](STATS_WEBHOOK.html) ### 破壊的変更 - WHIP の TURN 機能をデフォルトで有効にしました- 2024 年 7 月リリースの OBS 30.2 より以前の OBS が接続できなくなります - 2025 年 12 月リリース予定の Sora にて WHIP の TURN 機能の設定 `whip_turn` を廃止し、TURN 機能を無効にできなくなります - WHEP の TURN 機能をデフォルトで有効にしました- WHEP の TURN 機能を無効にする設定は非推奨になりました - 2025 年 12 月リリース予定の Sora にて WHEP の TURN 機能の設定 `whep_turn` を廃止し、TURN 機能を無効にできなくなります ### 廃止情報 - レガシーストリームを廃止しました- `multistream` 項目をウェブフック、ログ、API から削除しました - `multistream` を `false` にして接続した場合バリデーションエラーになります - ユーザーエージェント統計機能を廃止しました- 今後は RTC 統計機能をご利用ください - 統計エクスポーター機能を廃止しました - モード機能のウェブフック `session.vanished` を廃止しました - メディア配信ワーカー数を指定する `media_publish_worker_number` を廃止しました- ワーカーは自動でスケールするようになりました - 自動スケールの閾値は `sora.conf` の [media_publish_worker_autoscale_threshold](SORA_CONF.html#664e74) を利用してください - デフォルトは 50 で、50 接続単位でワーカーを増減させます ### 非推奨情報 - 組み込み TURN 機能を無効にする `turn` を `false` に設定することを非推奨にしました- 2025 年 12 月リリース予定の Sora にて組み込み TURN 機能を無効にする設定 `turn` を廃止し、組み込み TURN 機能を無効にできなくなります - セッション単位での最大同時接続数制限機能の `trial_max_connections` を非推奨にしました- 今後は [max_connections](SESSION_WEBHOOK.html#498be9) をご利用ください - 2025 年 12 月リリース予定の Sora にて廃止します - `sora.conf` の `ice_connection_state_disconnected_timeout` を非推奨にしました- [default_ice_connection_state_disconnected_timeout](SORA_CONF.html#420a1e) をご利用ください - 2025 年 12 月リリース予定の Sora にて廃止します - `sora.conf` の `ice_connection_state_failed_timeout` を非推奨にしました- [default_ice_connection_state_failed_timeout](SORA_CONF.html#d6f965) をご利用ください - 2025 年 12 月リリース予定の Sora にて廃止します - AV1 を無効にする必要がないと判断したため、 `sora.conf` の `av1` を `false` にする設定を非推奨としました> - 2025 年 12 月リリース予定の Sora にてこの設定は廃止し、AV1 の利用を無効化することはできなくなります - H.265 を無効にする必要がないと判断したため、 `sora.conf` の `h265` を `false` にする設定を非推奨としました> - 2025 年 12 月リリース予定の Sora にてこの設定は廃止し、H.265 の利用を無効化することはできなくなります - WHIP の TURN 機能を無効にする `whip_turn` を `false` に設定することを非推奨にしました- 2025 年 12 月リリース予定の Sora にて WHIP の TURN 機能の設定 `whip_turn` を廃止し、TURN 機能を無効にできなくなります - WHEP の TURN 機能を無効にする `whep_turn` を `false` に設定することを非推奨にしました- 2025 年 12 月リリース予定の Sora にて WHEP の TURN 機能の設定 `whep_turn` を廃止し、TURN 機能を無効にできなくなります - WHIP の RFC 9725 化に伴い `/whip-resource/:channel_id/:secret/` を非推奨にしました- NGINX の設定を `resource` から `session` に変更してください - 2025 年 12 月リリース予定の Sora にて廃止します - WHEP も WHIP に合わせて `/whep-resource/:channel_id/:secret/` を非推奨にしました- NGINX の設定を `resource` から `session` に変更してください - 2025 年 12 月リリース予定の Sora にて廃止します ### 変更履歴 - [CHANGE] スポットライト機能利用時に、フォーカスなしの音声転送の上限レートを指定する `sora.conf` の [sora_conf-default_spotlight_unfocus_audio_rate_limit](SPOTLIGHT.html#27c5ad) のデフォルト値を 2 から 5 に引き上げました- この変更により多人数で同時に発話があった際の音声がより快適になります - [CHANGE] スポットライト機能利用時に、フォーカスなしの音声転送の上限レートを指定する `sora.conf` の [sora_conf-default_spotlight_unfocus_audio_rate_limit](SPOTLIGHT.html#27c5ad) の上限を 20 に引き上げました - [CHANGE] RTP ヘッダー拡張 `abs-send-time` の利用を廃止しました- libwebrtc 側でもここ数年利用されていません - [Deprecate and remove the abs-send-time extension [398065914] - WebRTC](https://issues.webrtc.org/issues/398065914) - [FIX] セッション終了と [DisconnectChannel](API_SIGNALING.html#a87366) API の実行が重なった場合、 `SIGNALING-API-INTERNAL-ERROR` エラーが出力されていたのを修正しました - [FIX] セッション終了と [DisconnectClient](API_SIGNALING.html#e91c0b) API の実行が重なった場合、 `SIGNALING-API-INTERNAL-ERROR` エラーが出力されていたのを修正しました - [FIX] セッション終了と [DisconnectConnection](API_SIGNALING.html#2ec3a0) API の実行が重なった場合、 `SIGNALING-API-INTERNAL-ERROR` エラーが出力されていたのを修正しました - [FIX] 同じチャネル ID のセッション破棄と作成が連絡した場合、録画情報がセッションをまたいで使い回される問題を修正しました - [FIX] パケロスが多い状況で DataChannel が正常に動作せず、メッセージを送信しなくなる問題を修正しました - [FIX] パケロスが多い状況で OBS WHIP を利用して高いビットレートの配信を録画しようとしたときに、録画が正常に行われない問題を修正しました - [FIX] OBS WHIP 利用時に H.265 の録画開始後、すぐに終了すると録画が正常に行われない問題を修正しました - [FIX] SIGTERM で Sora を終了した際に、意図しないログが出力されてしまう問題を修正しました - [FIX] H.264 録画時に H.264 NAL Unit の SEI をスキップするように修正しました - [FIX] クラスター機能利用時にスポットライトのアンフォーカスの音声転送の上限レートが正しく設定されない問題を修正しました - [FIX] クラスターリレー機能利用時にスポットライトのアンフォーカス音声のペース制限の対象となるパケット判定が正しく行われない問題を修正しました #### パッケージ - [UPDATE] RHEL 9 x86_64 版のパッケージを 9.6 へ更新しました - [ADD] RHEL 10 x86_64 版のパッケージを追加しました #### sora.conf - [CHANGE] セッションウェブフック `session.vanished` 廃止に伴い `sora.conf` の `ignore_session_vanished_webhook` を廃止しました - [CHANGE] `sora.conf` の設定コメントをドキュメントの URL のみに変更しました - [CHANGE] `sora.conf` のコメントの値をデフォルト値に変更しました - [CHANGE] `sora.conf` のコメントのデフォルト値が存在しない場合、 `key =` のみの表記に変更しました - [CHANGE] `sora.conf` の設定の並び順をアルファベット順に変更しました - [ADD] `sora.conf` にコネクションライフタイムのデフォルト値を指定する [default_connection_lifetime](SORA_CONF.html#7ec6a4) を追加しました- デフォルトは未指定です - 最小は 0 ms で最大は 720 h です #### レガシーストリーム廃止 - [CHANGE] レガシーストリーム機能を廃止しました- `multistream` 項目をウェブフック、ログ、API から削除しました - `multistream` を `false` にして接続した場合バリデーションエラーになります - [CHANGE] レガシーストリーム機能廃止に伴い `sora.conf` の `legacy_stream` を廃止しました - [CHANGE] レガシーストリーム機能廃止に伴い [StartForwardingRtp](EXPERIMENTAL_API_RTP_FORWARDING.html#c734b8) API の `connection_id` を必須にしました - [CHANGE] レガシーストリーム機能廃止に伴い [StopForwardingRtp](EXPERIMENTAL_API_RTP_FORWARDING.html#729828) API の `connection_id` を必須にしました #### 統計エクスポーター廃止 今後は [統計ウェブフック](STATS_WEBHOOK.html) をご利用ください。 - [CHANGE] 統計エクスポーター機能を廃止しました- `sora.conf` の `default_stats_exporter` を廃止しました - `sora.conf` の `default_stats_collector_url` を廃止しました - `sora.conf` の `default_stats_exporter_number` を廃止しました - `sora.conf` の `default_stats_exporter_tls_fullchain_file` を廃止しました - `sora.conf` の `default_stats_exporter_tls_privatekey_file` を廃止しました - `sora.conf` の `default_stats_exporter_tls_verify_cacert_file` を廃止しました #### ユーザーエージェント統計機能廃止 ユーザーエージェント統計機能を廃止しました。 今後は RTC 統計機能をご利用ください。 - [CHANGE] `sora.conf` の `user_agent_stats` を廃止しました- 今後は [default_rtc_stats](SORA_CONF.html#558c2b) をご利用ください - [CHANGE] 認証成功払い出しから `user_agent_stats` を廃止しました- 今後は [rtc_stats の払い出し](AUTH_WEBHOOK_RETURN.html#9e5912) を払い出すようにしてください - [CHANGE] [ListUserAgentStats](OBSOLETE_API_USER_AGENT_STATS.html#f9a4fe) API を廃止しました- 今後は [ListRtcStats](API_RTC_STATS.html#956f4b) API をご利用ください - [CHANGE] [ListChannelUserAgentStats](OBSOLETE_API_USER_AGENT_STATS.html#df496a) API を廃止しました- 今後は [ListChannelRtcStats](API_RTC_STATS.html#6704c0) API をご利用ください - [CHANGE] [GetUserAgentStats](OBSOLETE_API_USER_AGENT_STATS.html#a078ba) API を廃止しました- 今後は [GetRtcStats](API_RTC_STATS.html#4e8cb0) API をご利用ください #### レガシーシグナリングエラー廃止 - [CHANGE] `sora.conf` のレガシーシグナリングを指定する `legacy_signaling_error` を廃止しました- `log/connection_created_wait_timeout` にログが出力されなくなりました - `log/signaling_error.jsonl` にシグナリングエラーログが出力されるようになりました - `connection.failed` ウェブフックは **認証成功時** かつ **connection.created** が送信されていない場合のみ送信されるようになりました - `sora.jsonl` に認証失敗ログが出力されなくなりました - `sora.jsonl` にシグナリング失敗ログが出力されなくなりました #### データチャネル - [ADD] API やログで取得できるデータチャネル関連の統計情報を追加しました- `total_enqueued_sent_chunk`- SCTP 送信用キュー (sent_queue) に追加されたチャンク数 - `total_dequeued_sent_chunk`- SCTP 送信用キュー (sent_queue) から取り出されたチャンク数 - `total_enqueued_outbound_chunk`- SCTP 送信待ちキュー (outbound_queue) に追加されたチャンク数 - `total_dequeued_outbound_chunk`- SCTP 送信待ちキュー (outbound_queue) から取り出されたチャンク数 - `total_increased_flight_size`- SCTP フライトサイズの増加量の合計値 (バイト単位) - `total_decreased_flight_size`- SCTP フライトサイズの減少量の合計値 (バイト単位) - `total_expired_t3_timer`- SCTP T3 タイマーの満了回数 #### ウェブフック - [CHANGE] イベントウェブフック利用時のワーカー数を指定する [event_webhook_worker_number](SORA_CONF.html#58523d) のデフォルトを 5 から 100 に変更しました - [ADD] イベントウェブフック利用時にウェブフックがどのワーカーを利用するかを判断する [event_webhook_worker_key](SORA_CONF.html#d73d7a) を追加しました- デフォルトは `channel_id` です - `channel_id` の場合はチャネル ID 単位でイベントウェブフックは同一のウェブフックワーカーを利用します- 例えば `channel_id` が `sora` に接続している全てのクライアントは同一ウェブフックを利用します - `connection_id` の場合はコネクション ID 単位でイベントウェブフックは同一のウェブフックワーカーを利用します- `connection_id` は接続ごとにユニークなため、同じチャネルに接続しているコネクションでも、それぞれに割り当てられたウェブフックワーカーを利用します - [ADD] セッションウェブフック [session.destroyed](SESSION_WEBHOOK.html#ccb165) を送信しないようにする [ignore_session_destroyed_webhook](SORA_CONF.html#1ad557) を追加しました- デフォルトは `false` です - この設定を `true` にすると [session.destroyed](SESSION_WEBHOOK.html#ccb165) を送信しなくなります - [ADD] セッションウェブフック [recording.report](SESSION_WEBHOOK.html#920a02) を送信しないようにする [ignore_recording_report_webhook](SORA_CONF.html#1faedc) を追加しました- デフォルトは `false` です - この設定を `true` にすると [recording.report](SESSION_WEBHOOK.html#920a02) を送信しなくなります - [ADD] イベントウェブフック [archive.available](EVENT_WEBHOOK.html#de9132) を送信しないようにする [ignore_archive_available_webhook](SORA_CONF.html#5de946) を追加しました- デフォルトは `false` です - この設定を `true` にすると [archive.available](EVENT_WEBHOOK.html#de9132) を送信しなくなります - [ADD] イベントウェブフック [split-archive.end](EVENT_WEBHOOK.html#31be7a) を送信しないようにする [ignore_split_archive_end_webhook](SORA_CONF.html#c7a923) を追加しました- デフォルトは `false` です - この設定を `true` にすると [split-archive.end](EVENT_WEBHOOK.html#31be7a) を送信しなくなります - [ADD] イベントウェブフック [archive.failed](EVENT_WEBHOOK.html#5006f8) を送信しないようにする [ignore_archive_failed_webhook](SORA_CONF.html#c355b0) を追加しました- デフォルトは `false` です - この設定を `true` にすると [archive.failed](EVENT_WEBHOOK.html#5006f8) を送信しなくなります #### ログ - [ADD] API ログ `api.jsonl` に `id` を追加しました- `id` は Base32 化した UUIDv4 です - [ADD] `event_webhook.jsonl` に `connection.updated` を出力しなくする [event_webhook_connection_updated_log](SORA_CONF.html#435f7c) を `sora.conf` に追加しました- デフォルトは `true` です - この設定を `false` にすると `event_webhook.jsonl` に `connection.updated` を出力しなくなります - [ADD] `session_webhook.jsonl` に `session.updated` を出力しなくする [session_webhook_session_updated_log](SORA_CONF.html#0fba6b) を `sora.conf` に追加しました- デフォルトは `true` です - この設定を `false` にすると `session_webhook.jsonl` に `session.updated` を出力しなくなります #### 映像コーデックパラメーター追加 - [ADD] AV1 コーデックパラメーターに `level_idx` を指定できるようにしました- デフォルトは `5` です - 範囲は `0` から `31` の整数が指定できます - [ADD] AV1 コーデックパラメーターに `tier` を指定できるようにしました- デフォルトは `0` です - 範囲は `0` か `1` の整数が指定できます - [ADD] H.265 コーデックパラメーターに `profile_id` を指定できるようにしました- デフォルトは `1` です - 範囲は `0` から `31` の整数が指定できます - [ADD] H.265 コーデックパラメーターに `tier_flag` を指定できるようにしました- デフォルトは `0` です - 範囲は `0` か `1` の整数が指定できます - [ADD] H.265 コーデックパラメーターに `tx_mode` を指定できるようにしました- デフォルトは `SRST` です - `SRST` か `MRST` か `MRMT` が指定できます #### グループ機能 **これは実験的機能です** セッションをグルーピングする `group_id` をセッションウェブフック [session.created](SESSION_WEBHOOK.html#1d1984) の払い出しで指定できるようになりました。 - [ADD] セッションウェブフック [session.created](SESSION_WEBHOOK.html#1d1984) の払い出しで `group_id` を指定できるようになりました- `group_id` は 1 バイト以上 255 バイト以下の文字列です - `group_id` は未指定の場合は `session_id` が入ります - [ADD] [ListSessions](API_SESSION.html#748f19) API に `group_id` を指定できるようになりました- `group_id` を指定した場合は指定した `group_id` のセッションのみを返します - `group_id` はオプションです - `group_id` を指定しない場合は全てのセッションを返します - [ADD] `session_id` 項目を含むウェブフックのリクエストに `group_id` を含めるようにしました - [ADD] `session_id` 項目を含む API の戻り値に `group_id` も含めるようにしました - [ADD] `session_id` 項目を含むログに `group_id` を含めるようにしました - [ADD] `session_id` 項目を含む録画メタデータに `group_id` を含めるようにしました > **注釈** > > クライアントへの送るシグナリングメッセージには `group_id` は含まれません。 > **注意** > > [session.created](SESSION_WEBHOOK.html#1d1984) で `group_id` を指定して、ウェブフックの戻り値を受け取るまでは `group_id` は `session_id` の値になります。 #### セッション単位での最大同時接続数制限機能 セッション単位での最大同時接続数制限機能を正式版としてリリースしました。 - [ADD] [session.created](SESSION_WEBHOOK.html#1d1984) でセッション単位での最大同時接続数を制限する `max_connections` を払い出せるようになりました- 正式版リリースに伴い `trial_max_connections` は 2025 年 12 月リリース予定の Sora にて廃止します- `trial_max_connections` は廃止後には無視します - `trial_max_connections` と `max_connections` を同時に指定した場合は `max_connections` が優先されます #### クラスターリレー機能でツリー構造の採用 今までのクラスターリレー機能は他のノードへの転送はクライアントが配信しているノードが担当していました。 この場合多くのノードにリレーが発生するとそのノードの負荷が高くなってしまいます。 そこで、リレーを [Plumtree](https://asc.di.fct.unl.pt/~jleitao/pdf/srds07-leitao.pdf) という分散アルゴリズムを利用したツリー構造を採用する事で、冗長なリレーを削減し、ノードの負荷分散を実現しました。 #### セッション単位でのクライアント ID 重複時の既存接続の追い出し機能 **これは実験的機能です** 今までのクライアント ID の重複を許可するのに加えて、 既存の同一クライアント ID の接続を破棄することをセッション単位で指定できるようになりました。 この仕組みはセッションウェブフック [session.created](SESSION_WEBHOOK.html#1d1984) の払い出しで、 `duplicate_client_id` に `evict` を指定することで有効になります。 - [ADD] `sora.conf` にクライアント ID が重複するコネクションが認証に成功した際の挙動を指定する [default_duplicate_client_id](SORA_CONF.html#c8b57b) を追加しました- デフォルトは `allow` です - `allow` は未指定と同じで、今まで通り重複を許容します - `evict` は既存の接続を破棄し、新規接続を受け入れます - [ADD] セッションウェブフック [session.created](SESSION_WEBHOOK.html#1d1984) の払い出しにセッション単位での重複するクライアント ID を持つコネクションが認証成功した際の挙動を指定する `duplicate_client_id` を払い出せるようになりました- `duplicate_client_id` には `allow` または `evict` を指定できます - 未指定は `sora.conf` の [default_duplicate_client_id](SORA_CONF.html#c8b57b) の値を利用します - `allow` は今まで通り重複を許容します - `evict` は既存の接続を破棄し、新規接続を受け入れます - [ADD] クライアント ID の重複によるコネクションを破棄した際 [connection.destroyed](EVENT_WEBHOOK.html#6c02d0) の `data.reason` に `"duplicate_client_id"` を含めるようにしました- この値はセッションウェブフック [session.created](SESSION_WEBHOOK.html#1d1984) の払い出しで `duplicate_client_id` に `evict` を指定して既存接続を破棄した場合に `data.reason` に含まれます #### 統計機能 - [ADD] 実験的機能として [GetStatsReport](EXPERIMENTAL_API_STATS.html#bbbfca) に Sora 内部で発生した遅延の累積値 (マイクロ秒単位) `total_sent_srtp_sfu_delay_us` を追加しました - [ADD] 実験的機能として [GetStatsConnection](API_STATS.html#e79b61) に Sora 内部で発生した遅延の累積値 (マイクロ秒単位) `total_sent_rtp_sfu_delay_us` を追加しました - [ADD] 実験的機能として [GetStatsClient](API_STATS.html#ef69ae) に Sora 内部で発生した遅延の累積値 (マイクロ秒単位) `total_sent_rtp_sfu_delay_us` を追加しました - [ADD] 実験的機能として [GetStatsAllConnections](API_STATS.html#ef695a) に Sora 内部で発生した遅延の累積値 (マイクロ秒単位) `total_sent_rtp_sfu_delay_us` を追加しました #### 帯域推定機能 帯域推定機能を追加しました、様々な情報を利用し帯域推定を行います。 以下を参考にしています。 - [RFC 8888 - RTP Control Protocol (RTCP) Feedback for Congestion Control](https://datatracker.ietf.org/doc/html/rfc8888) - [RFC 8869 - Evaluation Test Cases for Interactive Real-Time Media over Wireless Networks](https://datatracker.ietf.org/doc/html/rfc8869) - [RFC 8868 - Evaluating Congestion Control for Interactive Real-Time Media](https://datatracker.ietf.org/doc/html/rfc8868) - [RFC 8867 - Test Cases for Evaluating Congestion Control for Interactive Real-Time Media](https://datatracker.ietf.org/doc/html/rfc8867) - [RFC 8836 - Congestion Control Requirements for Interactive Real-Time Media](https://datatracker.ietf.org/doc/html/rfc8836) - [RTP Extensions for Transport-wide Congestion Control](https://datatracker.ietf.org/doc/html/draft-holmer-rmcat-transport-wide-cc-extensions-01) - [A Google Congestion Control Algorithm for Real-Time Communication](https://datatracker.ietf.org/doc/html/draft-ietf-rmcat-gcc-02) - [BBR: Congestion-Based Congestion Control - ACM Queue](https://queue.acm.org/detail.cfm?id=3022184) #### シグナリング通知 network.status に帯域推定結果を追加 **これは実験的機能です** 実験的機能としてシグナリング通知の [ネットワークのシグナリング通知](SIGNALING_NOTIFY.html#58a82d) に帯域推定結果を通知する機能を追加しました。 これは受信者の帯域推定結果を通知するもので、送信者の帯域推定結果は通知しません。 そのため `role` が `sendrecv` または `recvonly` の場合に有効になります。 - [ADD] sora.conf に `legacy_signaling_notify_network_status` を追加しました- デフォルトは `false` です - この設定を `true` にするとシグナリング通知 network.status のフォーマットを 2024.2.x までと同様にします - この設定は 2025 年 12 月リリースの Sora にて廃止します - [ADD] sora.conf にシグナリング通知 `network.status` の通知間隔を設定する [signaling_notify_network_status_interval](SORA_CONF.html#e0f78e) を追加しました- デフォルトは `10 s` です - 最小は `20 ms` で、最大は `10 min` です - [ADD] シグナリング通知 [ネットワークのシグナリング通知](SIGNALING_NOTIFY.html#58a82d) に `estimated_bandwidth` を追加しました- sora.conf の `legacy_signaling_notify_network_status` が `false` の場合に有効になります - この通知は role が `sendrecv` または `recvonly` の場合に通知します - 帯域推定の値が含まれます - [ADD] シグナリング通知 [ネットワークのシグナリング通知](SIGNALING_NOTIFY.html#58a82d) に `previous_estimated_bandwidth` を追加しました- sora.conf の `legacy_signaling_notify_network_status` が `false` の場合に有効になります - この通知は role が `sendrecv` または `recvonly` の場合に通知します - 前回通知時の帯域推定の値が含まれます - 初回の通知時は 0 が入ります - [ADD] シグナリング通知 [ネットワークのシグナリング通知](SIGNALING_NOTIFY.html#58a82d) に `unix_timestamp_ms` を追加しました- sora.conf の `legacy_signaling_notify_network_status` が `false` の場合に有効になります - この通知は role が `sendrecv` または `recvonly` の場合に通知します - Unix タイムのミリ秒が含まれます - [ADD] シグナリング通知 [ネットワークのシグナリング通知](SIGNALING_NOTIFY.html#58a82d) に `total_sent_rtp_byte_size` を追加しました- sora.conf の `legacy_signaling_notify_network_status` が `false` の場合に有効になります - この通知は role が `sendrecv` または `recvonly` の場合に通知します - 通知時の RTP (音声と映像) 送信合計バイトサイズが含まれます - [ADD] シグナリング通知 [ネットワークのシグナリング通知](SIGNALING_NOTIFY.html#58a82d) に `previous_unix_timestamp_ms` を追加しました- sora.conf の `legacy_signaling_notify_network_status` が `false` の場合に有効になります - この通知は role が `sendrecv` または `recvonly` の場合に通知します - 前回通知時の Unix タイムのミリ秒が含まれます - 初回の通知時は 0 が入ります - [ADD] シグナリング通知 [ネットワークのシグナリング通知](SIGNALING_NOTIFY.html#58a82d) に `previous_total_sent_rtp_byte_size` を追加しました- sora.conf の `legacy_signaling_notify_network_status` が `false` の場合に有効になります - この通知は role が `sendrecv` または `recvonly` の場合に通知します - 前回通知時の RTP (音声と映像) 送信合計バイトサイズが含まれます - 初回の通知時は 0 が入ります #### ICE コネクションステート機能 - [ADD] 認証成功時の払い出しに ICE コネクションステートの `disconnected` 状態へ遷移するタイムアウトを指定する [ice_connection_state_disconnected_timeout_ms の払い出し](AUTH_WEBHOOK_RETURN.html#38a86f) を追加しました - [ADD] 認証成功時の払い出しに ICE コネクションステートの `failed` 状態へ遷移するタイムアウトを指定する [ice_connection_state_failed_timeout_ms の払い出し](AUTH_WEBHOOK_RETURN.html#1f5eb9) を追加しました - [ADD] `sora.conf` に ICE コネクションステート機能の `disconnected` 状態へ遷移するタイムアウトを指定する [default_ice_connection_state_disconnected_timeout](SORA_CONF.html#420a1e) を追加しました- [default_ice_connection_state_disconnected_timeout](SORA_CONF.html#420a1e) と `ice_connection_state_disconnected_timeout` の値が設定している場合は `ice_connection_state_disconnected_timeout` の値を優先します - `sora.conf` の `ice_connection_state_disconnected_timeout` は 2025 年 12 月リリース予定の Sora にて廃止します - [ADD] `sora.conf` に ICE コネクションステート機能の `failed` 状態へ遷移するタイムアウトを指定する [default_ice_connection_state_failed_timeout](SORA_CONF.html#d6f965) を追加しました- [default_ice_connection_state_failed_timeout](SORA_CONF.html#d6f965) と `ice_connection_state_failed_timeout` の両方を設定している場合は `ice_connection_state_failed_timeout` の値を優先します - `sora.conf` の `ice_connection_state_failed_timeout` は 2025 年 12 月リリース予定の Sora にて廃止します #### メディア配信ワーカー自動スケール機能 メディア配信ワーカー機能のワーカーを自動で増減する仕組みを追加しました。 - [CHANGE] `sora.conf` の配信ワーカー数を指定する `media_publish_worker_number` を廃止しました - [ADD] `sora.conf` に配信ワーカー数を自動で増減させる閾値を指定する [media_publish_worker_autoscale_threshold](SORA_CONF.html#664e74) を追加しました- デフォルトは 50 です - [ADD] メディア配信ワーカーに関する統計情報を追加しました- `media_publish_worker.peak_count`- その接続でこれまでに同時に起動した配信ワーカー数の最大値 - `media_publish_worker.total_started`- その接続でこれまでに起動した配信ワーカーの総数 - `media_publish_worker.total_stopped`- その接続でこれまでに停止した配信ワーカーの総数 - `media_publish_worker.total_unknown_subscriber`- 配信ワーカーとの対応が存在しないサブスクライバー (受信側接続) の数 #### WHIP/WHEP 機能 WHIP が [RFC 9725](https://www.rfc-editor.org/rfc/rfc9725.html) として公開されたため、RFC への準拠を進めています。 - [CHANGE] `sora.conf` の `whip_turn` と `whep_turn` をデフォルト `true` に変更しました - [CHANGE] WHIP/WHEP 利用時に `offer` の SDP に `a=sendrecv` を指定できるように変更しました - [CHANGE] WHIP/WHEP 利用時にセッション URL に `PATCH` メソッドでアクセスした場合 `501` ではなく `422` を返すように変更しました - [CHANGE] WHIP/WHEP 利用時にエンドポイントとセッション URL に `GET` や `HEAD` メソッドでアクセスした場合、 `405` ではなく `200` を返すように変更しました - [CHANGE] RFC でリソース URL がセッション URL と名前が変わったことにより Location ヘッダーでは `/whip-session/:channel_id/:secret/` を払い出すように変更しました- 2025 年 12 月リリース予定の Sora にて `/whip-resource/:channel_id/:secret/` は廃止します - [ADD] クラスター利用時に別のノードへのリダイレクトが発生した際に HTTP ステータスコード 307 を返すようにしました- OBS が HTTP ステータスコード 307 に対応していなかったため、Sora 2024.2.x まではノード間通信で認証処理を行うようにしていました - [ADD] WHIP/WHEP 利用時にエンドポイントとセッション URL に `OPTIONS` メソッドでアクセスした場合 `Accept-Post` ヘッダーで `application/sdp` を返すようにしました #### TURN-UDP 利用時の認証エラー時のレートリミット TURN-UDP 時に認証エラーが発生した場合にレートリミットを設けて、 サイレントディスカードする仕組みを追加しました。デフォルトで特に困ることはありません。 - [ADD] GetStatsConnection API に TURN-UDP 利用時の認証エラー時のレートリミットを超えた回数 `total_turn_udp_allocate_request_401_rate_limit_exceeded` を追加しました- この値は TURN-UDP 利用時の認証エラー時のレートリミットを超えた回数を累積した値です - [ADD] `sora.conf` に TURN-UDP 利用時の認証エラー時のレートリミットウィンドウを指定する [turn_udp_allocate_request_401_rate_limit_window](SORA_CONF.html#56ea52) を追加しました- デフォルトは `60 s` です - 最小は `1 s` で、最大は `60 s` です - [ADD] `sora.conf` に TURN-UDP 利用時の認証エラー時のレートリミット回数を指定する [turn_udp_allocate_request_401_rate_limit_count](SORA_CONF.html#5deefa) を追加しました- デフォルトは `60` です - 最小は `0` で、最大は `300` です ## 2024.2.3 **バグフィックスアップデート** **リリース**: 2025 年 5 月 19 日 ### 変更履歴 - [ADD] 録画機能利用時に Safari 18.4 から Safari 18.5 で H.264/H.265 を利用している場合に発生するタイムスタンプの不具合に対するワークアラウンド機能を追加しました- デフォルトでは未指定です - 指定する場合は `sora.conf` に `workaround_20250515 = 18.4,18.4.1,18.5` のように、ワークアラウンドに対応させる Safari のバージョンを `,` で区切って指定してください - iOS 版 Chrome でもワークアラウンドが有効になります - 詳細は [Safari タイムスタンプバグに対するワークアラウンド](WORKAROUND.html#e73b7a) をご確認ください。 - [FIX] 録画機能で Chrome 136 で特定のハードウェアエンコーダーと組み合わせた際、 H.265 の録画が正常に行えない問題を修正しました ## 2024.2.2 **バグフィックスアップデート** **リリース**: 2025 年 4 月 9 日 ### 変更履歴 - [FIX] 依存している OpenSSL を 3.4.1 にアップデートしました - [FIX] ウェブフック機能、音声ストリーミング機能、統計エクスポーター機能で HTTPS を利用する際、証明書の鍵の使用法と拡張された鍵の使用法の互換性チェックが間違っていたため、サポートされていないサーバー証明書と判断して接続に失敗する場合がある問題を修正しました- これは Sora が利用している PKI ライブラリのバグにより発生していた問題で、ライブラリをアップデートすることで解消しました ## 2024.2.1 **バグフィックスアップデート** **リリース**: 2025 年 1 月 8 日 ### 変更履歴 - [FIX] AV1 コーデック利用時、主にハードウェアエンコーダーなど、 `libwebrtc` が採用している `libaom` 以外のエンコーダーを利用するとキーフレーム判定が失敗する場合がある問題を修正しました - [FIX] クラスター構成で Sora 2024.1.x からのローリングアップデート中、録画が開始できない場合がある問題を修正しました - [FIX] クラスター構成で Sora 2024.1.x からのローリングアップデート中、録画を開始すると `recording.report` ウェブフックが送信されない場合がある問題を修正しました ## 2024.2.0 **メジャーアップデート** **リリース**: 2024 年 12 月 18 日 ### ハイライト - 録画アーカイブファイルの MP4 形式による出力に対応しました - 録画アーカイブファイルの H.265 コーデックによる出力に対応しました - リアルタイムメッセージング機能で、メッセージのヘッダーに送信元の connection_id を付与する機能を追加しました - 実験的機能として、転送フィルター機能で複数のフィルターを設定できる「マルチ転送フィルター機能」を追加しました - 実験的機能として、 [session.created](SESSION_WEBHOOK.html#1d1984) の払い出しに、セッションの同時接続数を制限する `trial_max_connections` を追加しました - 指定したコネクションにキーフレームを要求する [RequestKeyFrame](API_CONNECTION.html#716b40) API を追加しました ### 正式版 今回のリリースで以下の機能が実験的機能から正式版になりました。 - [クラスター機能](CLUSTER.html) - [センシティブデータ](SENSITIVE_DATA.html) - [OBS (WHIP) 対応](WHIP.html) - `メディア配信ワーカー機能` - [セッションライフタイム機能](SESSION_WEBHOOK.html#36a751) - [コネクションライフタイム機能](AUTH_WEBHOOK_RETURN.html#8b77ca) - [TerminateSession](API_SESSION.html#ba022b) API ### 破壊的変更 - 既存のセッションの同時接続数が `0` の際に、このセッションと異なる `multistream` または `spotlight` 設定の新規接続が来た場合、エラーになるように変更しました - クライアントに通知されるエラーメッセージを改善しました - 転送フィルターの認証成功時の払い出しエラーが発生した場合、接続が失敗するようになりました - 転送フィルターのセッション生成時の払い出しエラーが発生した場合、セッションが破棄されるようになりました- [session_created_response_validate_warning_as_error](SORA_CONF.html#9df65e) が `false` の場合でもエラーとなりセッションを破棄します - 統計情報に含まれる `total_received_intra_frame` を `total_received_key_frame` に変更しました ### 廃止情報 - [JoinCluster](OBSOLETE_API.html#17f3f5) API を廃止しました- 今後は同じ機能を持つ [RegisterClusterNode](API_CLUSTER.html#09ed96) API をご利用ください - E2EE 機能を廃止しました- 将来的に Message Layer Security (MLS) を利用した E2EE 機能を提供予定です - ウェブフックに含まれる `e2ee` 項目は予約項目として常に `false` が含まれます - `sora.conf` から `e2ee` 項目を廃止しました - `sora.conf` の移行用の設定 `legacy_auth_webhook_log` 設定を廃止しました - `sora.conf` の移行用の設定 `legacy_event_webhook_connection_destroyed_reason` 設定を廃止しました ### 非推奨情報 - 転送フィルターを認証成功時やセッション生成時の払い出しで指定できる `forwarding_filter` を非推奨にしました- `forwarding_filter` は 2025 年 12 月リリース予定の Sora で廃止します - 代わりに複数の転送フィルターを指定できる `forwarding_filters` をご利用ください - シグナリング接続時に転送フィルターを指定できる `signaling_forwarding_filter` を非推奨にしました- `signaling_forwarding_filter` は 2025 年 12 月リリース予定の Sora で廃止します - 代わりに複数の転送フィルターを指定できる [signaling_forwarding_filters](SORA_CONF.html#bf0e30) をご利用ください - `mode_session_vanished` を非推奨にしました- `mode_session_vanished` は 2025 年 6 月リリース予定の Sora にて廃止します - 代わりに [GetStatsReport](EXPERIMENTAL_API_STATS.html#bbbfca) API の `total_ongoing_connections` をご利用ください。 - 値の監視については [Sora Exporter](SORA_EXPORTER.html) の利用をお勧めします - [RTP ストリーム停止/再開 API](OBSOLETE_API_RTP_STREAM_PAUSE_RESUME.html) を非推奨にしました- [RTP ストリーム停止/再開 API](OBSOLETE_API_RTP_STREAM_PAUSE_RESUME.html) は 2025 年 12 月リリース予定の Sora にて廃止します - 代わりに [転送フィルター](FORWARDING_FILTER.html) をご利用ください ### 変更履歴 - [CHANGE] 統計情報に含まれる `total_received_intra_frame` を `total_received_key_frame` に変更しました- [RequestKeyFrame](API_CONNECTION.html#716b40) API に合わせた変更になります - [CHANGE] `spotlight.focused` と `spotlight.unfocused` イベントウェブフックの送信を行わない場合はログを書き込まないよう変更しました - [CHANGE] ウェブフックを送信を行わない (ignore) の設定した場合でも以下のウェブフックはログを出力するように変更しました- `recording.started` セッションウェブフック - `session.updated` セッションウェブフック - `session.vanished` セッションウェブフック - `connection.failed` イベントウェブフック- `legacy_signaling_error` が `true` かつ `ignore_connection_failed_webhook` が `true` の場合、ログを出力しません - `archive.started` イベントウェブフック - `recording.started` イベントウェブフック - [CHANGE] `E2EE` 機能を廃止しました- `sora.conf` の `e2ee` を廃止しました - ウェブフックに含まれる `e2ee` は常に `false` が含まれます - [ADD] [copy_websocket_signaling_header_names](SORA_CONF.html#db39f3) で指定した WebSocket シグナリングの HTTP ヘッダーを `rtc_stats.jsonl` と `connection.jsonl` に `copy_headers` 項目で出力するようにしました - [ADD] 特定環境向けに TURN 利用時に 5-TUPLE を無視する設定を追加しました- **この機能を利用する場合は事前にサポートまでご連絡ください** - `sora.conf` の [ignore_turn_five_tuple](SORA_CONF.html#14e2aa) を `true` に設定することで、送られてくるパケットの 5-TUPLE を無視するようになります - [ADD] `"type": "offer"` メッセージに `audio` と `video` 関連項目を追加しました- `audio` は必ず含まれます - `audio_codec_type` はオプションで、 `audio` が `true` かつ `role` が `sendrecv` または `sendonly` の場合に含まれます - `audio_bit_rate` はオプションで、 `audio` が `true` かつ `role` が `sendrecv` または `sendonly` で `audio_bit_rate` が指定された場合に含まれます - `video` は必ず含まれます - `video_codec_type` はオプションで、 `video` が `true` かつ `role` が `sendrecv` または `sendonly` の場合に含まれます - `video_bit_rate` はオプションで、 `video` が `true` かつ `role` が `sendrecv` または `sendonly` の場合に含まれます - [ADD] サイマルキャスト機能の設定項目に `scaleResolutionDownTo` を追加しました- `{"maxHeight": 1080, "maxWidth": 1920}` のように解像度を指定することができるようになります - この機能は Chrome/Edge 131 以降で利用できます - [ADD] `connection.jsonl` に `simulcast_encodings` と `simulcast_codecs` 項目を追加しました- `simulcast` のみ `true` の場合は `simulcast_encodings` を出力します - `simulcast` と `simulcast_multicodec` が `true` の場合は `simulcast_codecs` も出力します - [FIX] Safari や Chrome Canary で H.265 の配信ができない問題を修正しました - [FIX] コネクションの切断が発生しない録画失敗のログレベルを `error` から `warning` に修正しました - [FIX] 録画ファイル書き込みに失敗するとクラッシュログが出力されることがある問題を修正しました - [FIX] サイマルキャスト機能利用時に `simulcast_encodings` に `active` を未指定だと接続が失敗する問題を修正しました - [FIX] H.264 の RTP ペイロードヘッダーが不正な場合、サイレントディスカードするように修正しました #### sora.conf - [CHANGE] `sora.conf` の `legacy_recording` のデフォルトを `true` から `false` に変更しました - [CHANGE] `sora.conf` の移行用の設定 `legacy_auth_webhook_log` 設定を廃止しました - [CHANGE] `sora.conf` の移行用の設定 `legacy_event_webhook_connection_destroyed_reason` 設定を廃止しました - [CHANGE] `sora.conf` の [default_h264_param_profile_level_id](SORA_CONF.html#1581db) のデフォルト値を `42e01f` から `42e02a` へ変更しました- Chrome / Edge がデフォルト値を変更した事への追従です - [UPDATE] `sora.conf` の [connection_created_wait_timeout](SORA_CONF.html#0509af) の最小値を `1 s` から `0 s` へ変更しました- 挙動確認などで意図的にエラーを発生させられるように変更しました - [FIX] ウェブフック送信時にボディを待つ時間に [webhook_response_timeout](SORA_CONF.html#e81d13) が反映されていない問題を修正しました - [FIX] ウェブフック送信時に TCP コネクションの確立を待つ時間に [webhook_connect_timeout](SORA_CONF.html#7a0122) が反映されていない問題を修正しました #### API - [UPDATE] [ListConnections](API_SIGNALING.html#d3da2a) API の戻り値に `node_name` を追加しました - [UPDATE] [ListChannelConnections](API_SIGNALING.html#d388f3) API の戻り値に `node_name` を追加しました - [UPDATE] [GetStatsAllConnections](API_STATS.html#ef695a) API の戻り値に `session_id` を追加しました - [UPDATE] [GetStatsConnection](API_STATS.html#e79b61) API の戻り値に `session_id` を追加しました - [UPDATE] [GetStatsClient](API_STATS.html#ef69ae) API の戻り値に `session_id` を追加しました - [ADD] 指定したクライアントにキーフレームを要求する [RequestKeyFrame](API_CONNECTION.html#716b40) API を追加しました- レガシーストリームでは利用できません - [FIX] [GetStatsReport](EXPERIMENTAL_API_STATS.html#bbbfca) API のウェブフック統計情報はウェブフックを送信したときのみカウントされるように修正しました - [FIX] [GetStatsReport](EXPERIMENTAL_API_STATS.html#bbbfca) API のウェブフック統計情報が正しくカウントされない問題を修正しました- `total_ignored_session_webhook` が実際よりも少なくカウントされていた問題を修正しました - [audio-streaming.started](SESSION_WEBHOOK.html#e7b17a) と [audio-streaming.stopped](SESSION_WEBHOOK.html#13e583) のウェブフック統計情報が `total_ignored_XXX_webhook` と `total_successful_XXX_webhook` の両方がカウントされていた問題を修正しました #### セッション単位での同時接続数制限機能 **これは実験的機能です** 認証ウェブフックでの接続制限はウェブフックが並列で送信されるため、厳密な同時接続制限ができませんでした。 この機能ではセッション単位での同時接続数を制限することで、厳密に同時接続制限ができるようになります。 この機能を利用することで認証に成功した場合でも、セッションに接続できない場合があります。 その場合は、クライアントには `SERVICE-UNAVAILABLE` が通知されます。 この機能は実験的機能のトライアル中です。 将来的にロール単位やクライアント ID 単位での接続制限機能などを加えていく予定です。 正式版と明確に区別するため `trial_` を prefix として付与しています。 - [ADD] [session.created](SESSION_WEBHOOK.html#1d1984) の払い出しにセッションの同時接続数を制限する `trial_max_connections` を追加しました- デフォルトは未指定で制限がない状態です - 指定できる範囲は 0..10000 です - `trial_max_connections` が `0` の場合は誰も接続することができなくなります - セッションが同時接続数制限に達した場合はクライアントに `SERVICE-UNAVAILABLE` を通知します #### 統計情報の追加 - [ADD] [GetStatsReport](EXPERIMENTAL_API_STATS.html#bbbfca) API に SRTP パケットの統計情報を追加しました- `total_received_srtp`- 受信した SRTP パケットの合計数 - `total_received_srtp_byte_size`- 受信した SRTP パケットの合計バイト数 - `total_sent_srtp`- 送信した SRTP パケットの合計数 - `total_sent_srtp_byte_size`- 送信した SRTP パケットの合計バイト数 - `total_decrypted_srtp`- 復号した SRTP パケットの合計数 - `total_decrypted_srtp_byte_size`- 復号した SRTP パケットの合計バイト数 - [ADD] [GetStatsReport](EXPERIMENTAL_API_STATS.html#bbbfca) API に DataChannel で利用している SCTP パケットの統計情報を追加しました- `total_received_sctp`- DataChannel で受信した SCTP パケットの合計数 - `total_received_sctp_byte_size`- DataChannel で受信した SCTP パケットの合計バイト数 - `total_sent_sctp`- DataChannel で送信した SCTP パケットの合計数 - `total_sent_sctp_byte_size`- DataChannel で送信した SCTP パケットの合計バイト数 - [ADD] [GetStatsReport](EXPERIMENTAL_API_STATS.html#bbbfca) API に無視されたウェブフックの統計情報を追加しました- `total_ignored_session_webhook`- 無視されたセッションウェブフックの合計数 - `total_ignored_event_webhook`- 無視されたイベントウェブフックの合計数 - `total_ignored_stats_webhook`- 無視された統計ウェブフックの合計数 #### Sora 側からのシグナリング切断時のクライアントへの通知改善 - [CHANGE] WebSocket シグナリング利用時にメッセージサイズが大きすぎる場合の `code` を `4490` から `1009` に変更しました- メッセージサイズの最大は 5 MiB です - WebSocket の仕様に合わせました - [CHANGE] WebSocket シグナリング利用時に Sora 側からのクライアントへの通知を改善しました- 正常切断- `code` は `1000` です - `reason` には切断理由が含まれます- `TYPE-DISCONNECT` - `DISCONNECTED-API` - `LIFETIME-EXPIRED` - `SESSION-DESTROYED` - 異常切断- 異常が発生して Sora 側から切断した場合は `code` に `4490` が含まれます - `reason` には切断理由が含まれます - [ADD] `sora.conf` に [data_channel_signaling_close_message](SORA_CONF.html#058a1e) を追加しました- デフォルトは `false` です - `true` の場合は Sora からコネクションを切断する際、 DataChannel シグナリングが有効かつ、`ignore_disconnect_websocket` が `true` な場合 `signaling` ラベルに `"type": "close"` メッセージを送信します - `false` の場合は今まで通り、 DataChannel を閉じます - `"type": "close"` メッセージには `code` と `reason` が含まれます - 正常切断- 切断 API や期限切れで Sora 側から切断した場合は `code` に `1000` が含まれます - `reason` には切断理由が含まれます- `LIFETIME-EXPIRED` - `SESSION-DESTROYED` - `DISCONNECTED-API` - 異常切断- 異常が発生して Sora 側から切断した場合は `code` に `4490` が含まれます - `reason` には切断理由が含まれます - [ADD] `sora.conf` に [signaling_normal_close_reason](SORA_CONF.html#4486a4) を追加しました- デフォルトは `true` です - `false` を指定した場合、正常切断時の `reason` が空文字になります - `false` を指定した場合でも異常切断時は `reason` は含まれます #### シグナリングエラーの改善 - [ADD] `sora.conf` にレガシーシグナリングエラーを有効にする設定を追加しました `legacy_signaling_error` を追加しました- デフォルトは `false` です - **この設定は移行用で 2025 年 6 月に廃止します** - この設定は 2024.1.x までの Sora との後方互換性を維持するための機能です - `false` の場合は `log/connection_created_wait_timeout` にログが出力されなくなりました - `false` の場合は `log/signaling_error.jsonl` にシグナリングエラーログが出力されるようになりました - `false` の場合は `connection.failed` ウェブフックは **認証成功時** かつ **connection.created** が送信されていない場合のみ送信されるようになりました - `false` の場合は `sora.jsonl` に認証失敗ログが出力されなくなりました - `false` の場合は `sora.jsonl` にシグナリング失敗ログが出力されなくなりました - `true` の場合は今まで通り `ignore_connection_failed_webhook` が `true` の場合、 `event_webhook.jsonl` にシグナリングログが出力されません - [CHANGE] クライアントに通知するエラーメッセージを変更しました- クライアントへ通知するエラーがあまりにもサーバーよりのメッセージが多く、混乱を招くため整理しました - Sora の内部的なエラーは `INTERNAL-ERROR` を通知するよう変更しました- 以下のメッセージはクライアントへは通知されなくなりました - `SIGNALING-INTERNAL-ERROR` - `AUTH-WEBHOOK-RESPONSE-EMPTY-BODY` - `AUTH-WEBHOOK-RESPONSE-UNEXPECTED-STATUS-CODE` - `INVALID-AUTHZ-MEDIA` - `WHEP-INCOMPATIBLE-UPSTREAM-TRACK` - `DUPLICATED-CONNECTION-ID-ERROR` - `INVALID-SPOTLIGHT-NUMBER` - `DUPLICATED-CHANNEL-ID` - `UNMATCH-CODEC-TYPE-ERROR` - Sora が一時的に利用できない場合は `SERVICE-UNAVAILABLE` を通知するように変更しました- 以下のメッセージはクライアントへは通知されなくなりました - `EXCEED-MAX-CONNECTIONS` - `BLOCK-NEW-CONNECTION` - `BLOCK-NEW-SESSION` - `INVALID-MODE` - Sora でタイムアウトが発生した場合は `TIMEOUT` を通知するように変更しました- 以下のメッセージはクライアントへは通知されなくなりました - `CONNECTION-CREATED-WAIT-TIMEOUT-ERROR` - `CONNECT-WAIT-TIMEOUT-ERROR` - `ANSWER-TIMEOUT-ERROR` - `PONG-TIMEOUT-ERROR` - シグナリングメッセージが不正な場合は `INVALID-MESSAGE` を通知するように変更しました- 以下のメッセージはクライアントへは通知されなくなりました - `INVALID-JSON` - `INVALID-SIGNALING-TYPE` - `INVALID-SIGNALING-PARAMS` - `MISSING-TYPE` - `BAD-FINGERPRINT` - `TOO-LARGE-JSON` - `TOO-MANY-CANDIDATE` - `INVALID-VIDEO-FORMAT` - `FAILURE-SDP-PARSE` - `MISSING-ICE-SDP` - `INVALID-VIDEO-FORMAT` - `INVALID-AUDIO-FORMAT` - `FAILURE-JSON-DECODE` - `UNEXPECTED-SIGNALING-TYPE` - `UNKNOWN-AUDIO-CODEC-TYPE` - `INVALID-AUDIO-BIT-RATE` - `UNKNOWN-VIDEO-CODEC-TYPE` - `INVALID-VIDEO-BIT-RATE` #### 録画機能 - [CHANGE] 録画ファイル処理の開始に失敗した場合のログレベルを `ERROR` から `WARNING` に変更しました - [ADD] イベントウェブフック `archive.*` と `split-archive.*` に項目を追加しました- `split_only`- 指定していない場合、値は `false` になります - `format`- `mp4` または `webm` が含まれます - `expire_time`- 指定していない場合は項目が含まれません - `expired_at`- 指定していない場合は項目が含まれません - `split_duration`- 指定していない場合は項目が含まれません - [FIX] AV1 サイマルキャスト使用時に録画が正常に行われない問題を修正しました #### MP4 録画機能 **これは実験的機能です** MP4 形式での録画ファイル出力に対応しました。 - [ADD] MP4 形式での録画に対応しました- **MP4 録画機能はレガシー録画機能では利用できません** - OBS が提唱する Hybrid MP4 形式に対応しています - [ADD] `sora.conf` に [default_recording_format](SORA_CONF.html#f9fa7d) を追加しました- デフォルトは `webm` です - `webm` と `mp4` が指定できます - MP4 録画機能はレガシー録画機能では利用できません - [ADD] [StartRecording](API_RECORDING.html#c5b527) API に `format` (オプション) を追加しました- `format` には `webm` と `mp4` が指定できます - `format` が未指定の場合は [default_recording_format](SORA_CONF.html#f9fa7d) の値が利用されます - 映像コーデックが H.265 の場合 `format` に `mp4` を指定しない場合、録画が行われません - [ADD] [session.created](SESSION_WEBHOOK.html#1d1984) の払い出しに `recording_format` を追加しました- `recording_format` には `webm` と `mp4` が指定できます - `recording_format` が未指定の場合は [default_recording_format](SORA_CONF.html#f9fa7d) の値が利用されます - 映像コーデックが H.265 の場合 `format` に `mp4` を指定しない場合、録画が行われません - [ADD] [session.updated](SESSION_WEBHOOK.html#2a5b1b) の `recording` に `format` を追加しました- `"format": "webm"` または `"format": "mp4"` が含まれるようになりました - [ADD] セッションウェブフック `recording.*` に `data.format` を追加しました- `"format": "webm"` または `"format": "mp4"` が含まれるようになりました - [ADD] イベントウェブフック `archive.*` と `split-archive.*` に `data.format` を追加しました- `"format": "webm"` または `"format": "mp4"` が含まれるようになりました - [ADD] `sora.conf` に録画機能(セッション単位) 利用時に MP4 形式を利用した場合、クライアントへ送るキーフレーム要求 (PLI) の間隔を指定できる [default_recording_mp4_pli_interval](SORA_CONF.html#874e5b) を追加しました- デフォルトは `20 s` です - 最小は `1 s` で、最大は `240 s` です - WebM 形式ではキーフレームの間隔が最大でも 31 秒までという制約がありましたが、 MP4 形式ではこの制約がなくなりました #### H.265 録画機能 **これは実験的機能です** H.265 コーデックでの録画機能に対応しました。 - [ADD] H.265 録画機能に対応しました- H.265 は `format` に `mp4` が設定されている場合のみ録画ができます - WebM 形式を設定した場合 H.265 の録画は行われません - H.265 録画機能はレガシー録画では利用できません #### ICE コネクションステート変更のシグナリング通知 **これは実験的機能です** ICE コネクションステートが変更した際、 同一チャネルに接続している自分を含むクライアント全員へ通知する仕組みを追加しました。 この機能を利用することで、 自分の ICE コネクションステートの変更を **同じセッションに参加している自分を含むクライアント全員** へシグナリング通知が送信されます。 また、接続時に **既にチャネルに参加しているクライアント全員の ICE コネクションステート** を取得できるようになります。 他のシグナリング通知機能とは異なり、この設定は有効にした場合、 自分を含むチャネル参加者全員へ通知を行いますので注意してください。 用途としては 4 人で双方向のビデオ通話をしている際、 特定のクライアントが不安定だという事を知ったり、 1:50 の片方配信の際に配信者の通信状態を視聴者側が知ったりすることができるようになります。 通知されるタイミングは 4 種類あります。 1. connected から checking になった時 2. checking から connected になった時 3. checking から disconnected になった時 4. disconnected から checking になった時 - [ADD] `sora_conf` に [signaling_notify_ice_connection_state](SORA_CONF.html#e65192) を追加しました- デフォルトは `false` です - `true` に設定すると ICE コネクションステートが変更された際に、同一チャネルに接続しているクライアントへシグナリング通知 `ice-connection-state.changes` を送信します - `true` にするとチャネル参加時のシグナリング通知 `connection.created` の既存参加者の `data` に `ice_connection_state` が含まれるようになります - [ADD] 認証成功時の払い出しに `signaling_notify_ice_connection_state` を追加しました- デフォルトは [signaling_notify_ice_connection_state](SORA_CONF.html#e65192) の値が採用されます - `false` を払い出すことで自身の ICE コネクションステートの状態を他のチャネルに参加しているクライアントへシグナリング通知が送信されなくなります - [ADD] ICE コネクションステートを強制的に変更し維持する [LockIceConnectionState](TEST_API.html#8b5622) テスト API を追加しました #### 転送フィルター機能 - [CHANGE] 認証成功時の転送フィルターの払い出しがエラーになった場合、接続が失敗するように変更しました- `INTERNAL-ERROR` エラーとなります - [CHANGE] セッション生成時の転送フィルターの払い出しがエラーになった場合、セッションを破棄するように変更しました- `INTERNAL-ERROR` エラーとなります - [session_created_response_validate_warning_as_error](SORA_CONF.html#9df65e) が `false` の場合でもエラーとなりセッションを破棄します #### マルチ転送フィルター機能 **これは実験的機能です** マルチ転送フィルター機能は 1 チャネルや 1 コネクションに対して 1 つしか指定できなかった転送フィルターを 名前と優先度を設定し、複数の転送フィルターを指定できるようにする機能です。 - [ADD] 認証成功時の払い出しに複数の転送フィルターを設定できる `forwarding_filters` を追加しました- 既存の `forwarding_filter` は 2025 年 12 月リリース予定の Sora にて廃止します - [ADD] セッション生成時の払い出しに複数の転送フィルターを設定できる `forwarding_filters` を追加しました- `forwarding_filter` は 2025 年 12 月リリース予定の Sora にて廃止します - [ADD] `sora.conf` にシグナリング時に複数の転送フィルターを設定できる `forwarding_filters` を設定できるようになる [signaling_forwarding_filters](SORA_CONF.html#bf0e30) を追加しました- `signaling_forwarding_filter` は 2025 年 12 月リリースの Sora にて廃止します - [ADD] 転送フィルター設定時に `name` と `priority` を指定できるようになりました - [ADD] 転送フィルター API [ListForwardingFilters](API_FORWARDING_FILTER.html#a1dd75) にチャネルの転送フィルターをリストで表示する `channel_forwarding_filters` を追加しました- 既存の `channel_forwarding_filter` は 2025 年 12 月リリース予定の Sora にて廃止します - [ADD] 転送フィルター API [CreateChannelForwardingFilter](API_FORWARDING_FILTER.html#fe98d1) と [CreateConnectionForwardingFilter](API_FORWARDING_FILTER.html#d80a51) に `name` と `priority` を追加しました - [ADD] 転送フィルター API [UpdateChannelForwardingFilter](API_FORWARDING_FILTER.html#36fc45) と [UpdateConnectionForwardingFilter](API_FORWARDING_FILTER.html#23ed63) に `name` と `priority` を追加しました - [ADD] 転送フィルター API [DeleteChannelForwardingFilter](API_FORWARDING_FILTER.html#9410fd) と [DeleteConnectionForwardingFilter](API_FORWARDING_FILTER.html#0d65da) に `name` を追加しました 詳細は [マルチ転送フィルター機能](MULTI_FORWARDING_FILTER.html) をご確認ください。 #### OBS WHIP - [FIX] OBS WHIP で H.264 で一部のエンコーダーを利用した際、録画ファイルの映像が正常に記録されない問題を修正しました - [FIX] OBS WHIP で AV1 で録画できない問題を修正しました #### メッセージングヘッダー機能 リアルタイムメッセージング機能において、 メッセージに Sora 側でヘッダーを追加する機能です。 `sender_connection_id` を追加できます。 - [ADD] `data_channels` にメッセージングにヘッダーを追加する `header` 項目を新しく追加しました- **ヘッダーを付与するかどうかはメッセージを受信する側が指定します**- `{"label": "#spam", "direction": "recvonly", "header": [{"type": "sender_connection_id"}]` - この設定を行ったクライアントは `#spam` ラベルのメッセージは常に先頭 26 バイトに `sender_connection_id` が含まれるようになります - ヘッダーは Sora 側で付与します - `header` はオプションです - `header` には `[{"type": "sender_connection_id"}]` のように指定します - `type` は `sender_connection_id` のみ指定できます- `sender_connection_id` はメッセージングの送信元の connection_id です - 先頭 26 バイトが `sender_connection_id` になります - 将来的に指定できる `type` を増やして行く予定です - `"type": "offer"` 時の `data_channels` に `header` が含まれる場合、 `length` 項目を追加します- `length` は `sender_connection_id` の長さです - `length` の単位はバイトです - `sender_connection_id` の場合 `length` は 26 固定です #### 音声ストリーミングヘッダー機能 音声ストリーミング機能において、HTTP/2 経由で送信する音声パケットに Sora 側でヘッダーを追加する機能です。 - [ADD] 音声ストリーミング機能利用時に `sora.conf` に [audio_streaming_header](SORA_CONF.html#3edcef) を追加しました- デフォルトは `false` です - `true` に設定すると音声パケットに Sora がヘッダーを追加します - ヘッダーのフォーマットは `[Timestamp:64 bit, SequenceNumber:64 bit, Length:32 bit]` です - `timestamp` は音声パケット送信時の UTC 時間マイクロ秒の整数です- RTP のタイムスタンプとは異なります - `seq_num` は音声パケットのシーケンス番号で、 1 から始まります- RTP のシーケンス番号とは異なります - `length` はヘッダーを除いた音声パケットの長さです ```mermaid --- title: "音声ストリーミングヘッダーフォーマット" --- packet-beta 0-63: "Timestamp" 64-127: "SeqNum" 128-159: "Length" ``` #### プレイアウト遅延機能 **実験的機能です** プレイアウト遅延機能の仕様を変更しました。 今までは配信側に影響する設定でしたが、今回のリリースから視聴側に影響する設定に変更しました。 この変更により視聴側ごとにプレイアウト遅延を指定できるようになりました。 - [ADD] sendrecv と recvonly のロールに影響するよう設定を変更しました- sendonly には影響しません - [CHANGE] `sora.conf` の [default_playout_delay_min_delay](SORA_CONF.html#194218) は視聴側のプレイアウト遅延の最小値のデフォルトを指定するように変更しました- デフォルトは未指定です - [CHANGE] `sora.conf` の [default_playout_delay_max_delay](SORA_CONF.html#c1b0ab) は視聴側のプレイアウト遅延の最大値のデフォルトを指定するように変更しました- デフォルトは未指定です - [CHANGE] 認証成功時の払い出し `playout_delay_min_delay` は視聴側の最小値を指定するように変更しました- `playout_delay_max_delay` も一緒に指定する必要があります - [CHANGE] 認証成功時の払い出し `playout_delay_max_delay` は視聴側の最大値を指定するように変更しました- `playout_delay_min_delay` も一緒に指定する必要があります 詳細は [プレイアウト遅延機能](PLAYOUT_DELAY.html) をご確認ください。 #### テスト API - [UPDATE] テスト API がクラスターで利用できるようになりました - [UPDATE] テスト向け API の録画失敗を意図的に起こす [FailArchive](TEST_API.html#80c0b0) API をクラスターに対応しました - [UPDATE] テスト向け API のシグナリング通知を送信する [SendSignalingNotify](TEST_API.html#c9b5c5) API をクラスターに対応しました ## 2024.1.3 **バグフィックスアップデート** **リリース**: 2024 年 8 月 9 日 ### 変更履歴 - [FIX] 証明書の署名アルゴリズムに SHA1 が利用されている場合でも、許容するように変更しました - [FIX] クラスター機能利用時に、アフィニティが有効な場合でもまれにリレーが発生する場合がある問題を修正しました - [FIX] 転送フィルター機能利用時に、シグナリング通知の送信がまれに失敗する場合がある問題を修正しました - [FIX] イベントウェブフックやシグナリング通知の `connection.created` のチャネル接続数の値が、まれに実際の値よりも小さくなる場合がある問題を修正しました - [FIX] 録画機能利用時に、RTP のシーケンス番号が等しいが RTP ヘッダー拡張 `abs-capture-time` の値が異なるパケットが短期間に複数送られて来た場合に録画が失敗してしまう問題を修正しました - [FIX] 録画機能利用時に、一部の端末で RTP ヘッダー拡張 `abs-capture-time` に意図しない値が含まれると録画が失敗してしまう事があるため、[rtp_hdrext_abs_capture_time](SORA_CONF.html#6cf562) のデフォルトを `false` に変更しました- 詳細については [Chrome/Edge の不具合による録画機能利用時の音ズレ問題について](KNOWN_ISSUES.html#e85482) をご確認ください ## 2024.1.1 **バグフィックスアップデート** **リリース**: 2024 年 7 月 1 日 ### 変更履歴 - [FIX] 録画機能利用時、パケットのタイムスタンプに異常がある場合に発生する問題を修正しました ## 2024.1.0 **メジャーアップデート** **リリース**: 2024 年 6 月 26 日 ### ハイライト - クラスターリレー機能を追加しました- いずれのノードからでも同一のチャネルに接続できるようになりました - クラスターアフィニティ機能を追加しました- リレー機能利用時に、特定のノードに同一セッションの接続を集約する仕組みを追加しました - この機能によりノード間通信を極力発生させないようにすることができます - ライセンスの同時接続数の合計を維持する機能を追加しました- ノードに障害が発生したとしても、クラスター全体の同時接続数を維持できるようになりました - テンポラリーノード機能を追加しました- クラスターの維持に影響しないノードを手軽に削除できるようになりました - OBS WHEP に対応しました- OBS の WHEP ソース機能を利用し Sora から映像を取得できるようになりました - 2026 年 6 月 現在、OBS 安定版では WHEP に対応していません - OBS WHIP/WHEP の TURN に対応しました- 2026 年 6 月 現在、OBS 安定版では TURN に対応していません - OBS WHIP/WHEP の H.265 (HEVC) に対応しました- 2026 年 6 月 現在、OBS 安定版では H.265 に対応していません - セッションとコネクションが破棄される時間を指定できるライフタイム機能を追加しました- セッションやコネクションで指定した時間が経過すると自動的に破棄されるようになりました - 複数のコーデックで、複数の画質が同時に配信できるサイマルキャストマルチコーデック機能を追加しました- 2026 年 6 月 現在、ブラウザでは利用できません - 音声トラックを削除した後に、再度音声トラックを追加した際に正常に録音されない問題に対応しました- Chrome/Edge の不具合により、今まで音声がずれて録画されてしまっていた問題を解決しました - Safari でも同様の不具合を確認していますが、本対応では解決できていません ### 正式版 今回のリリースで以下の機能は実験的機能から正式版になりました。 - [モード機能](MODE.html) - [転送フィルター機能](FORWARDING_FILTER.html) - [音声ストリーミング機能](AUDIO_STREAMING.html) - [録画ブロック機能の払い出し](AUTH_WEBHOOK_RETURN.html#0c4e64) - SDP 再利用機能- [recycle_media_section](SORA_CONF.html#d3e2b5) ### 廃止情報 - CentOS 7 向けパッケージの提供を終了しました - モード機能のイニシャルモードを廃止しました - 認証成功時に払い出す `h264_profile_level_id` を廃止しました- 代わりに `"video_h264_params": {"profile_level_id": ""}` を使用してください - `sora.conf` から `default_h264_profile_level_id` を廃止しました- 代わりに [default_h264_param_profile_level_id](SORA_CONF.html#1581db) を使用してください - 実験的機能として提供していた `sora.conf` の `rtp_publish_worker_number` を廃止しました- 代わりに `media_publish_worker_number` を使用してください - 実験的機能として提供していた Lyra を廃止しました- Opus 1.5 で Lyra 同様の低ビットレートが利用可能になったこと、Lyra が 2 年間更新がないことが廃止の理由です - `sora.conf` の `contact_node_name_list` を廃止しました- 今後は [RegisterClusterNode](API_CLUSTER.html#09ed96) API を利用してください - `sora.conf` の `cluster_auto_connect` を廃止しました- クラスター機能の自動での再接続は常に有効になります ### 非推奨情報 - Ubuntu 20.04 の提供を Sora 2024.1.x 系をもって終了します- Ubuntu 20.04 は 2025 年 4 月にサポートが終了します - `multistream: false` で利用するレガシーストリームを非推奨にしました- `multistream: false` は 2025 年 6 月リリース予定の Sora で廃止します - マルチストリームを利用してください - `JoinCluster` API を非推奨にしました- `JoinCluster` API は 2024 年 12 月リリース予定の Sora で廃止します - [RegisterClusterNode](API_CLUSTER.html#09ed96) API を利用してください - [ListClusterNodes](API_CLUSTER.html#a70901) API の `include_all_known_nodes` 指定を非推奨にしました- `include_all_known_nodes` は 2024 年 12 月リリース予定の Sora で廃止します - 廃止後は `include_all_known_nodes` が常に `true` として動作するようになります - 統計エクスポーター機能を非推奨にしました- 統計エクスポーター機能は 2025 年 6 月リリース予定の Sora で廃止します - [統計ウェブフック](STATS_WEBHOOK.html) を利用してください - ユーザエージェント統計を非推奨にしました- ユーザエージェント統計は 2025 年 6 月リリース予定の Sora で廃止します - RTC 統計情報を利用してください - ユーザエージェント統計 API を非推奨にしました- ユーザエージェント統計 API は 2025 年 6 月リリース予定の Sora で廃止します - [RTC 統計情報](API_RTC_STATS.html) API を利用してください ### 破壊的変更 - クラッシュを意図的に発生させるテスト用 `Sora_20221221.GenerateCrashLog` API を [Sora_20380119.GenerateCrashLog](TEST_API.html#26eea6) に変更しました - イベントウェブフック [connection.destroyed](EVENT_WEBHOOK.html#6c02d0) の `reason` に含まれる値を変更しました- 2023.2.x までは `disconnect_api_reason` と同じ、または `disconnect_api_reason` が無ければ `null` が含まれていました - 2024.1.x からは `normal` / `disconnected_api` / `session_destroyed` / `lifetime_expired` が含まれるようになります - 2023.2.x までの設定を維持する移行用の設定 `legacy_event_webhook_connection_destroyed_reason` を追加しています- この移行用の設定 `legacy_event_webhook_connection_destroyed_reason` は 2024 年 12 月リリース予定の Sora にて廃止します - 統計 API の RTP ヘッダー拡張の項目名のプレフィックスを `rtp_hdr_ext` から `rtp_hdrext` へ変更しました - [TerminateSession](API_SESSION.html#ba022b) API を非同期に変更しました- セッション破棄の確認は [session.destroyed](SESSION_WEBHOOK.html#ccb165) ウェブフックを利用してください - ライセンスチェックのタイミングを変更しました- 今までは WebSocket 接続時にライセンスチェックを行っていましたが、 `"type": "connect"` 時にチェックを行うように変更しました- `WHIP` と `WHEP` については変更はありません - 詳細についてはサポートまでお問い合わせください ### 変更履歴 - [CHANGE] シグナリング ["type": "disconnect"](WEBSOCKET_SIGNALING.html#306b81) 時に指定できる `reason` の最大値を 128 バイトに制限しました - [CHANGE] [TerminateSession](API_SESSION.html#ba022b) API を非同期に変更しました- セッション破棄の確認は [session.destroyed](SESSION_WEBHOOK.html#ccb165) ウェブフックを利用してください - [CHANGE] 統計 API の RTP ヘッダー拡張の項目名のプレフィックスを `rtp_hdr_ext` から `rtp_hdrext` へ変更しました - [CHANGE] モード機能のイニシャルモードを廃止しました - [CHANGE] 最大帯域幅指定で利用する SDP を `b=TIAS` と `b=AS` から `b=TIAS` のみに変更しました - [CHANGE] 帯域推定で利用する `REMB` で送信するビットレートを `b=TIAS` のみに変更したのに合わせて音声ビットレートを含めないようにしました - [CHANGE] 音声コーデック Lyra への対応を廃止しました - [CHANGE] SDP の `msid` の `appdata` を UUIDv4 を BASE32 でエンコードした値から、 `connection_id` に メディアの種類を追加した値に変更しました- [RFC 8830 WebRTC MediaStream Identification in the Session Description Protocol](https://www.rfc-editor.org/rfc/rfc8830.html) - この変更により MediaStreamTrack の id から `connection_id` を取得できるようになりました - この変更により WebRTC 統計情報の `inbound-rtp` の `trackIdentifier` から `connection_id` を取得できるようになりました - **Firefox では利用できません** - [UPDATE] [開発ツール](DEVTOOLS.html) を最新版に更新しました - [ADD] Ubuntu 24.04 x86_64 と arm64 版のパッケージ提供を開始しました - [ADD] `connection.jsonl` にコネクションを破棄した理由 `destroyed_reason` を追加しました- `destroyed_reason` には `normal` / `disconnected_api` / `session_destroyed` / `lifetime_expired` が含まれます - [ADD] `sora.conf` に VP9 利用時に RTP ヘッダー拡張 `dependency_descriptor` を払い出す [rtp_hdrext_dependency_descriptor_vp9](SORA_CONF.html#ead2c0) を追加しました- デフォルトは `false` です - この設定を `true` した場合 **Firefox で VP9 が利用できなくなります** - [ADD] [ListConnections](API_SIGNALING.html#d3da2a) API と [ListChannelConnections](API_SIGNALING.html#d388f3) API の戻り値に `recording_block` 項目を追加しました - [FIX] メッセージングオンリー機能利用時に `multistream: true` の指定を不要にしました #### テスト機能 - [CHANGE] クラッシュを意図的に発生させるテスト用 `Sora_20221221.GenerateCrashLog` API のバージョンを変更し [Sora_20380119.GenerateCrashLog](TEST_API.html#26eea6) API に変更しました- 今後、テスト API はバージョンが全て `20380119` に固定されます - [ADD] シグナリング通知を送信するテスト用 [SendSignalingNotify](TEST_API.html#c9b5c5) API を追加しました #### スポットライト機能 - [ADD] スポットライト機能利用時に、セッションウェブフック [session.updated](SESSION_WEBHOOK.html#2a5b1b) と [session.destroyed](SESSION_WEBHOOK.html#ccb165) に `spotlight_number` 項目が含まれるようにしました - [ADD] セッションウェブフック [session.created](SESSION_WEBHOOK.html#1d1984) 時に `spotlight_number` を払い出せるようにしました- `spotlight_number` には `1` から `8` までの値を指定できます - セッションウェブフックで `spotlight_number` を払い出した場合、シグナリング接続時や認証成功時の払い出しの `spotlight_number` と異なる場合はエラーとなります。 - シグナリング時と認証成功時の `spotlight_number` 指定は非推奨になりました - [FIX] スポットライト機能利用時に同一セッションで `spotlight_number` が同時接続数 `0` の場合にシグナリング接続時、または認証成功時払い出しで変更できてしまう問題を修正しました - セッション破棄までは [ChangeSpotlightNumber](API_SPOTLIGHT.html#17e930) API 以外ではスポットライト数を変更できないように修正しました - [FIX] スポットライト機能利用時に `multistream: true` の指定を不要にしました #### レガシーストリームを非推奨化 今まで `multistream: false` で利用していた、レガシーストリーム(非マルチストリーム)を非推奨にしました。 レガシーストリームは 2025 年 6 月リリースの Sora 2025.1.0 にて廃止します。 - [CHANGE] `sora.conf` にレガシーストリームを有効にする `legacy_stream` を追加しました- デフォルトは `false` です - レガシーストリームを利用する場合は `true` に設定してください #### ウェブフック機能 - [ADD] `sora.conf` に認証ウェブフック失敗時に `auth_webhook.jsonl` にのみログを出力する `legacy_auth_webhook_log` を追加しました- 2023.2.x までの挙動を維持する設定です - この設定は 2024 年 12 月リリース予定の Sora にて廃止します - デフォルトは `false` です - この設定を `false` にした場合、認証ウェブフックが失敗した際には `auth_webhook_error.jsonl` にログを出力します- `auth_webhook.jsonl` にはログを出力しません - この設定を `true` にした場合、認証ウェブフックが失敗した際には 2023.2.x までと同様に `auth_webhook.jsonl` にログを出力します- `auth_webhook_error.jsonl` にはログを出力しません - [ADD] `sora.conf` にウェブフックの接続確立タイムアウト時間を指定する [webhook_connect_timeout](SORA_CONF.html#7a0122) を追加しました- 今までは固定の `600 s` としていましたが、設定を追加するにあたりデフォルトを `30 s` と変更しました - 範囲は `1 s` から `600 s` です - [ADD] 認証ウェブフックリクエストに `Accept` ヘッダーを追加しました- `Accept` ヘッダーに `application/json` が含まれます - [ADD] セッションウェブフックリクエストに `Accept` ヘッダーを追加しました- `Accept` ヘッダーに `application/json` が含まれます - [FIX] 認証ウェブフックでステータスコード 2XX で空ボディを受け取った際の不具合を修正しました - [FIX] 認証ウェブフックにシグナリング接続時の転送フィルターが含まれていない問題を修正しました #### セッションウェブフック機能 - [ADD] セッションウェブフック [session.created](SESSION_WEBHOOK.html#1d1984) の戻り値が正常では無い場合、エラーとしてセッションを破棄して、セッションウェブフック [session.destroyed](SESSION_WEBHOOK.html#ccb165) を送信する設定の [session_created_response_validate_warning_as_error](SORA_CONF.html#9df65e) を `sora.conf` に追加しました- デフォルトは `false` です - `false` の場合はバリデーションに失敗した場合、デフォルト値が採用されそのまま処理は継続します - `true` の場合はバリデーションに失敗した場合、エラーとしてセッションを破棄します- セッションウェブフック [session.destroyed](SESSION_WEBHOOK.html#ccb165) の `reason` には `validate_error` が含まれます - [ADD] セッションウェブフック [session.created](SESSION_WEBHOOK.html#1d1984) のウェブフック処理中に問題が発生した際に [session.destroyed](SESSION_WEBHOOK.html#ccb165) の `reason` に `webhook_error` が含まれるようになりました - [ADD] セッションウェブフックがエラーになった理由を、 `session_webhook_error.jsonl` ログに `reason` として出力するようにしました - [FIX] セッションウェブフックの戻り値の JSON が不正な場合に、センシティブデータの処理をしていた問題を修正しました - [FIX] セッションウェブフックの戻り値が JSON オブジェクトではない場合に処理が失敗していた問題を修正しました #### 録画アーカイブイベントウェブフック機能 - [ADD] 録画アーカイブ失敗時のウェブフック [archive.failed](EVENT_WEBHOOK.html#5006f8) に `split` と `split_only` と `split_index` を含むようにしました - [FIX] 分割録画にもかかわらず、録画アーカイブ失敗時のウェブフック [archive.failed](EVENT_WEBHOOK.html#5006f8) に分割録画ファイルが含まれない問題を修正しました- 一括と分割録画の両方が有効な場合、 `filename` と `file_path` と `split_filename` と `split_file_path` が含まれるようになります - 分割録画が有効な場合、 `split_filename` と `split_file_path` が含まれるようになります - 分割録画のみの場合、 `filename` と `file_path` は含まれなくなります - [ADD] テスト向け API として録画失敗を意図的に起こす [FailArchive](TEST_API.html#80c0b0) API を追加しました- 録画が実行されている指定した `client_id` の録画を失敗させます - イベントウェブフックの録画失敗ウェブフック [archive.failed](EVENT_WEBHOOK.html#5006f8) を意図的に発生させることができます #### イベントウェブフック connection.destroyed の reason の破壊的変更 - [CHANGE] イベントウェブフック `connection.destroyed` に含まれる reason の変更を行いました- 今までは `disconnect_api_reason` と同様、コネクション切断系 API で指定した `reason` 値、または未指定の場合は `null` が含まれていましたが、今回の変更で `normal` / `disconnected_api` / `session_destroyed` / `lifetime_expired` のいずれかが含まれるようになりました - `normal` は通常のコネクション破棄 - `disconnected_api` はコネクション切断系 API でコネクション破棄 - `session_destroyed` はセッションライフタイムによりセッションの期限が切れた、または [TerminateSession](API_SESSION.html#ba022b) API によってセッション強制破棄されたことでのコネクション破棄 - `lifetime_expired` はコネクションライフタイムによりコネクションの期限が切れたことによるコネクション破棄 - [ADD] `sora.conf` にイベントウェブフック `connection.destroyed` に含まれる `reason` の値を、 `disconnect_api_reason` に含まれる値と同じにする移行用の設定 `legacy_event_webhook_connection_destroyed_reason` を追加しました- デフォルトは `false` です - 設定を `true` にした場合、 `disconnect_api_reason` の項目が無い場合は `null` が含まれます- また、コネクションライフタイム機能で切断したか際の判断ができなくなります - この設定は 2024 年 12 月リリース予定の Sora にて廃止します #### 録画機能音ズレ問題の改善 この問題の改善はレガシー録画、セッション録画の両方で行っています。 Chrome / Edge 側のバグにより、録画機能利用時に `replaceTrack` などを利用して `MediaStreamTrack` を削除し、 一定時間経過後に新しく `MediaStreamTrack` を追加した際に、音声パケットに関連するタイムスタンプと NTP タイムスタンプが正しく出力されない問題あります。 この問題により Chrome / Edge では録音/録画したファイルにて音ズレが発生してしまう場合がありました。 今回、新しく利用できるようになった RTP ヘッダー拡張 `abs-capture-timestamp` を利用する事で、 音声タイムスタンプを実際の値に推測する機能を導入することでこの問題に対応しました。 この問題は Safari / Safari Technology Preview では RTP ヘッダー拡張 `abs-capture-timestamp` が音声パケットに含まれてこないため、 改善することができません。 - [CHANGE] [rtp_hdrext_abs_capture_time](SORA_CONF.html#6cf562) のデフォルトを `true` に変更しました - [FIX] RTP ヘッダー拡張録画機能の音声タイムスタンプの推測機能を利用し、Chromium ベースのブラウザで録音/録画を行った際、音ズレが発生する問題を修正しました- `abs-capture-time` が利用できない場合は今まで通り音ズレが発生する場合があります #### OBS WHIP対応 **これは実験的機能です** - [CHANGE] ウェブフックの `sora_client` に含まれる `type` を `OBS-Studio` から `OBS-Studio-WHIP` に変更しました```javascript "sora_client": { "raw": "Mozilla/5.0 (OBS-Studio/30.1.0; Mac OS X; ja-JP)", "type": "OBS-Studio-WHIP", "version": "30.1.0", "environment": "environment":"Mozilla/5.0 (OBS-Studio/30.1.0; Mac OS X; ja-JP)" }, ``` - [ADD] `sora.conf` に OBS WHIP で TURN を利用する `whip_turn` を追加しました- この設定は OBS が正式に TURN へ対応したタイミングで廃止します - [ADD] OBS WHIP/WHEP で将来的に必須になる `rtcp-mux-only` に対応しました - [ADD] OBS WHIP で H.265 (HEVC) に対応しました- OBS 30.1 ではまだ WHIP での H.265 はサポートされていません #### OBS WHEP 対応 **これは実験的機能です** OBS での WebRTC/WHEP に対応しました。WebRTC で送られてくる音声と映像を WHEP ソースとして利用する事ができます。 - [ADD] OBS WHEP に対応しました- Opus と H.264 の組み合わせのみ利用できます - WHEP での接続は複数の配信が発生したタイミングで切断されます - WHEP での接続は複数の配信が存在するチャネルには接続できません - OBS 30.1 ではまだ WHEP に対応していません - [ADD] `sora.conf` に OBS (WHEP) を有効にする [whep](SORA_CONF.html#5a91bb) を追加しました- デフォルトは `false` です - [ADD] `sora.conf` に OBS WHEP の Bearer トークンを認証ウェブフックの `metadata` に対応させるキーを指定する [whep_bearer_token_metadata_key](SORA_CONF.html#f857c6) を追加しました- OBS WHEP からの接続についても Bearer トークンを利用した認証機能が利用できます - デフォルトは未指定です - [ADD] WHEP 向けエンドポイント URL `https://example.com/whep/` を追加しました - [ADD] WHEP 向けリソース URL `https://example.com/whep-resource//` を追加しました- PATCH と DELETE メソッドに対応しています - [ADD] WHEP を利用した際、認証ウェブフックに `whep: true` を追加しました- WHEP を利用していない接続の場合はこの項目は含まれません - [ADD] OBS WHEP で User-Agent として送られてくる情報を sora_client としてウェブフックで送信するようにしました- `"raw": "Mozilla/5.0 (OBS-Studio/31.0.0; Mac OS X; ja-JP)"` - `"type": "OBS-Studio-WHEP"` - `"environment": "environment":"Mozilla/5.0 (OBS-Studio/31.0.0; Mac OS X; ja-JP)"` - `"version": "31.0.0"` - [ADD] `sora.conf` に OBS WHEP で TURN を利用する `whep_turn` を追加しました- この設定は OBS が正式に TURN へ対応したタイミングで廃止します 詳細は [OBS (WHEP) 対応機能](WHEP.html) をご確認ください。 #### クラスター機能 **これは実験的機能です** - [UPDATE] [ListClusterNodes](API_CLUSTER.html#a70901) API にライセンス情報を追加しました- `license_type` - `license_serial_code` - `license_max_connections` - [UPDATE] [ListClusterNodes](API_CLUSTER.html#a70901) API にエラー情報を追加しました- ノードに接続ができなかった場合、そのノード情報に `error` を含めるようにしました - [CHANGE] 最大ノード数ライセンスと通常ライセンスが同一クラスターで混在できなくなりました - [CHANGE] `sora.conf` の `contact_node_name_list` を廃止しました- 今後は [RegisterClusterNode](API_CLUSTER.html#09ed96) API を利用してください - [CHANGE] `sora.conf` の `cluster_auto_reconnect` を廃止しました- クラスター機能の自動での再接続は常に有効になります - [CHANGE] `JoinCluster` API の名前だけを変更した [RegisterClusterNode](API_CLUSTER.html#09ed96) API を追加しました- [RegisterClusterNode](API_CLUSTER.html#09ed96) API は `JoinCluster` API とまったく同じ動作をします - `JoinCluster` API は 2024 年 12 月にリリース予定の Sora で廃止します - [ADD] クラスター利用時に以下の API でクラスター全体の結果を返せる仕組みを追加しました- API に `local` を追加し `false` を指定した場合はクラスター全体の結果を返します - `local` のデフォルトは `true` です - [ListConnections](API_SIGNALING.html#d3da2a) API - [ListChannels](EXPERIMENTAL_API_SIGNALING.html#b27c42) API - [GetStatsAllConnections](API_STATS.html#ef695a) API - [ListRtcStats](API_RTC_STATS.html#956f4b) API - [ListUserAgentStats](OBSOLETE_API_USER_AGENT_STATS.html#f9a4fe) API - クラスターのローリングアップデート中に `local=false` は利用できません - [FIX] [InitCluster](API_CLUSTER.html#621990) API で指定するノードが全て同一バージョンでは無い場合、エラーを返すように修正しました #### クラスターテンポラリーノード機能 **これは実験的機能です** クラスターの維持に影響しない一時的なノードを追加できるようになりました。 テンポラリーノードを利用する事でスケールアウト/スケールインが容易になります。 - [ADD] `sora.conf` にテンポラリーノードとして利用する [cluster_temporary_node](SORA_CONF.html#30cb14) を追加しました- デフォルトは `false` です - この設定は [cluster](SORA_CONF.html#b2cd99) が `true` の時のみ有効です - この機能は [最大ノード数ライセンス](LICENSE.html#aee259) のみ有効です- [最大ノード数ライセンス](LICENSE.html#aee259) を利用していない場合は [cluster_temporary_node](SORA_CONF.html#30cb14) が `true` の場合、起動できません - テンポラリーノードはクラスター構成を維持するためのノードとしては認識されません - テンポラリーノードに障害が発生してもライセンスで決められた最大同時接続数の合計を維持する機能による接続数の維持は行われません - テンポラリーノードはクラスターへの登録には [RegisterClusterNode](API_CLUSTER.html#09ed96) API を利用してください - テンポラリーノードは停止時にクラスターから消去されます - テンポラリーノードを再起動した場合、クラスターには自動で参加しません。再度 [RegisterClusterNode](API_CLUSTER.html#09ed96) API を利用して登録してください - テンポラリーノードだけでクラスターを構築する事はできません - テンポラリーノードは [PurgeClusterNode](API_CLUSTER.html#13b35a) API でノードを消去することはできません - テンポラリーノードは [InitCluster](API_CLUSTER.html#621990) API で初期化することはできません - テンポラリーノードはクラスターの全てのノードが `2024.1.0` 以降である必要があります - [UPDATE] [ListClusterNodes](API_CLUSTER.html#a70901) API に `temporary_node: ` 項目を追加しました 詳細は [テンポラリーノード機能](CLUSTER.html#3cb6c8) をご確認ください。 #### ライセンスで決められた最大同時接続数の合計を維持する機能 **これは実験的機能です** クラスターのノードが離脱した際に、合計接続数を残りのノードで維持する機能を追加しました。 - [ADD] クラスターでライセンスの同時接続数の合計を維持する機能を追加しました- この機能は `cluster` が `true` の場合にのみ有効です - この機能は [最大ノード数ライセンス](LICENSE.html#aee259) のみ有効です - 同時接続数が 100 の 3 ノードのクラスターで動作させた場合に、1 ノードが離脱した際、残りの 2 ノードが最大同時接続数が 150 に一時的に引き上げられ、合計での接続数を維持しますその後、障害が発生していたノードが復旧した歳には、最大同時接続数は 100 に戻ります100 を超えている接続は切断されたりはしません 詳細は [ライセンスで決められた最大同時接続数の合計を維持する機能](CLUSTER.html#7bc873) をご確認ください。 #### クラスターリレー機能 **これは実験的機能です** クラスター利用時に、複数のノードから同一チャネルに参加できる仕組みを追加しました。 - [ADD] `sora.conf` にクラスター利用時に複数ノードから同一チャネルに接続できる機能を実現する `cluster_relay` の設定を追加しました- この機能は `cluster` が `true` の場合にのみ利用できます - デフォルトで `true` が設定されています - クラスターリレー機能は [最大ノード数ライセンス](LICENSE.html#aee259) のみで利用できます- [最大ノード数ライセンス](LICENSE.html#aee259) を利用していない場合は `cluster_relay` が `true` になっていても、リレー機能は利用できません - クラスターリレー機能は `"multistream": false` では利用できません - リレー機能はクラスターの全てのノードが `2024.1.0` 以降である必要があります - 詳細は [リレー機能](CLUSTER.html#4b3bf1) をご確認ください - [ADD] [GetStatsReport](EXPERIMENTAL_API_STATS.html#bbbfca) API にクラスターリレー機能の統計情報を追加しました- **この統計データは厳密なデータではないため、参考程度にご利用ください** - ノードが削除された場合でも再起動するまでは統計情報は残り続けます - `cluster_relay`- `[{"node_name": "sora-01@192.0.2.100", "total_sent_byte_size": 5000, "total_received_byte_size": 5000, ...]` - `node_name`- 対象ノード名 - `total_sent_byte_size`- 対象ノードへリレー機能で送信したバイト数の合計 - `total_received_byte_size`- 対象ノードからリレー機能で受信したバイト数の合計 - `total_sent`- 対象ノードからリレー機能で送信したパケット数の合計 - `total_received`- 対象ノードからリレー機能で受信したパケット数の合計 - [CHANGE] リレー機能利用時には認証が 2 回発生する場合があります- 詳細は [クラスターリレー機能利用時に認証が 2 回行われる場合がある](AUTH_WEBHOOK.html#a1fc2c) をご確認ください - [CHANGE] リレー機能利用時には [spotlight が既存セッションと異なる場合の挙動](SESSION_WEBHOOK.html#b67a91) の挙動が変わり、接続数が `0` の場合に `multistream` と `spotlight` の指定が既存セッションと異なる場合でもセッションが破棄されなくなります- この挙動は 2024 年 12 月リリースの Sora にてリレー機能を利用しない場合でも反映される予定です 詳細は [リレー機能](CLUSTER.html#4b3bf1) をご確認ください。 #### クラスターリレー機能利用時のアフィニティ機能 **これは実験的機能です** クラスターリレー機能利用時に一定の同時接続数まで特定のノードに同一セッションの接続を集約する機能を追加しました。 - [ADD] `sora.conf` にリレー機能を利用する際に、アフィニティ機能(同一セッションへの接続を同一ノードに寄せる) かどうかを指定する [default_cluster_affinity](SORA_CONF.html#95466d) の設定を追加しました- デフォルトで `true` が設定されています - この機能は `sora.conf` の [cluster](SORA_CONF.html#b2cd99) が `true` の場合にのみ利用できます - この機能は `sora.conf` の [cluster_relay](SORA_CONF.html#0ef660) が `true` の場合にのみ利用できます- [最大ノード数ライセンス](LICENSE.html#aee259) を利用していない場合は `sora.conf` の [cluster_relay](SORA_CONF.html#0ef660) が `true` になっていても、リレー機能やアフィニティ機能は利用できません - `true` の場合は一定数の接続までは特定のノードに接続を集約します- 同時接続数がライセンス最大値の場合はリダイレクトが発生します - `false` を指定すると、可能な限りリダイレクトをせずにそのノードでリレーが行われます- 同時接続数がライセンス最大値の場合はリダイレクトが発生します - [ADD] `sora.conf` にアフィニティを行う 1 ノード、1 セッションあたりの最大同時接続数を指定する [cluster_affinity_threshold](SORA_CONF.html#2abc6a) を追加しました- デフォルトは 10 です - 1 ノード、1 セッションあたりの同時接続数が `cluster_affinity_threshold` 未満のノードがあれば、同じノードに新規接続が割り振られます - [ADD] 認証成功時の払い出しで [cluster_affinity の払い出し](AUTH_WEBHOOK_RETURN.html#f156a1) を払い出すことでコネクション単位でのアフィニティ機能を利用するかどうかを指定できる機能を追加しました- 払い出しをしない場合は `sora.conf` の [default_cluster_affinity](SORA_CONF.html#95466d) の値が利用されます #### 音声ストリーミング 音声ストリーミング機能のエラー処理を充実させました。 - [ADD] [audio_streaming_url](SORA_CONF.html#6b5dd6) に接続ができない場合、再接続を試みる機能を追加しました - [ADD] [audio_streaming_url](SORA_CONF.html#6b5dd6) への接続を諦める機能を追加しました- 接続を諦めた場合、再接続を試みるには一度クライアントを切断する必要があります - [ADD] [audio_streaming_url](SORA_CONF.html#6b5dd6) に接続ができない場合、再接続を試みる回数を指定する [audio_streaming_max_retries](SORA_CONF.html#9fd67a) を追加しました- **最大リトライ回数まで再接続を試みても接続ができない場合は接続を諦めます** - デフォルトは `0` です - `0` にした場合は常に再接続を試みます - `0..10` の間で指定できます - [ADD] [audio_streaming_url](SORA_CONF.html#6b5dd6) に接続ができない場合、再接続を試みる間隔を指定する [audio_streaming_retry_interval](SORA_CONF.html#15f73d) を追加しました- デフォルトは `5 s` です - `0` にした場合は音声パケットが送られてきたタイミングで再接続を試みます - `0..60 s` の間で指定できます - [ADD] [audio_streaming_url](SORA_CONF.html#6b5dd6) からステータスコード 5xx が返ってきた場合、再接続を試みる機能を追加しました- **最大リトライ回数まで再接続を試みても接続ができない場合は接続を諦めます** - 再接続の回数は [audio_streaming_max_retries](SORA_CONF.html#9fd67a) を利用します - 再接続の間隔は [audio_streaming_retry_interval](SORA_CONF.html#15f73d) を利用します - [ADD] [audio_streaming_url](SORA_CONF.html#6b5dd6) への接続を諦めた際、イベントウェブフック `audio-streaming.failed` を送信する機能を追加しました- 諦めるのはコネクション単位のため、イベントウェブフックを送信します - このウェブフックは [ignore_audio_streaming_webhook](SORA_CONF.html#8f086b) の影響は受けません - [ADD] イベントウェブフック `audio-streaming.failed` を送信しない設定 [ignore_audio_streaming_failed_webhook](SORA_CONF.html#80d7fb) を追加しました- デフォルトは `true` です - `true` にした場合は `audio-streaming.failed` イベントウェブフックを送信しません - [ADD] [audio_streaming_url](SORA_CONF.html#6b5dd6) から `"type": "error"` が含まれる JSON が送られてきた際、音声ストリーミングサーバーへの接続を諦める機能を追加しました - [ADD] [audio_streaming_url](SORA_CONF.html#6b5dd6) への接続を諦めた際、セッションに参加している全てのコネクションにシグナリング通知 `audio-streaming.failed` を送信する機能を追加しました- デフォルトは `false` です - [signaling_notify_audio_streaming_failed](SORA_CONF.html#d13e38) を `true` にすることで有効になります - [FIX] 音声ストリーミング [audio-streaming.started](SESSION_WEBHOOK.html#e7b17a) のウェブフック処理中にエラーになった場合、セッションが破棄されてしまう問題を修正しました #### 統計ウェブフック機能 **実験的機能です** [統計エクスポーター](OBSOLETE_STATS_EXPORTER.html) に変わる、 [統計ウェブフック機能](STATS_WEBHOOK.html) を追加しました。 - [ADD] `sora.conf` に統計ウェブフックの送信先を指定する [stats_webhook_url](SORA_CONF.html#1f750f) を追加しました - [ADD] `sora.conf` に統計ウェブフックログを出力するかどうかを指定する [stats_webhook_log](SORA_CONF.html#2fa540) を追加しました- デフォルト `false` です - デフォルトではログを出力しません。ログを出力したい場合は `true` に設定してください - [ADD] `sora.conf` に統計ウェブフック [type: connection.rtc](STATS_WEBHOOK.html#645901) を無視するかどうかを指定する [ignore_connection_rtc_webhook](SORA_CONF.html#83bc00) を追加しました- デフォルト `false` です - [ADD] `sora.conf` に [stats_webhook_worker_number](SORA_CONF.html#00e194) を追加しました - [ADD] 統計ウェブフックにクライアントの RTC 統計情報を送信する [type: connection.rtc](STATS_WEBHOOK.html#645901) を追加しました- これは統計エクスポーターの `"type": "connection.user-agent"` と同じデータをウェブフックとしてリクエストを送信します - 統計エクスポーターでは HTTP/2 を利用して送信していましたが、統計ウェブフックは HTTP/1.1 で送信します - [ADD] [GetStatsReport](EXPERIMENTAL_API_STATS.html#bbbfca) API に統計ウェブフックの成功数の項目 `total_successful_stats_webhook` を追加しました - [ADD] [GetStatsReport](EXPERIMENTAL_API_STATS.html#bbbfca) API に統計ウェブフックの失敗数の項目 `total_failed_stats_webhook` を追加しました 詳細は [統計ウェブフック機能](STATS_WEBHOOK.html) をご確認ください。 #### RTC 統計 (ユーザエージェント機能) 統計ウェブフック機能追加に伴い、ユーザーエージェント統計から RTC 統計へ名前を変更します。 ユーザエージェント機能は 2025 年 6 月リリース予定の Sora で廃止します。 - [ADD] `sora.conf` に RTC 統計機能をデフォルトを指定する [default_rtc_stats](SORA_CONF.html#558c2b) を追加しました- デフォルトは `true` です - `true` の場合、 Sora はクライアントへ RTC 統計の送信を要求します - [ADD] 認証成功時の払い出しに [rtc_stats の払い出し](AUTH_WEBHOOK_RETURN.html#9e5912) を追加しました- 未指定の場合は [default_rtc_stats](SORA_CONF.html#558c2b) の値が利用されます - [ADD] [ListRtcStats](API_RTC_STATS.html#956f4b) API を追加しました - [ADD] [ListChannelRtcStats](API_RTC_STATS.html#6704c0) API を追加しました - [ADD] [GetRtcStats](API_RTC_STATS.html#4e8cb0) API を追加しました - [ADD] 実験的機能として `sora.conf` に [rtc_stats_log](SORA_CONF.html#2fc848) を追加しました- デフォルトで `false` です - `rtc_stats` 項目個別に `rtc_stats.jsonl` にログを出力します - [FIX] ユーザーエージェント統計情報の認証成功時払い出し指定が無視されていた問題を修正しました - [FIX] ユーザーエージェント統計情報の [GetUserAgentStats](OBSOLETE_API_USER_AGENT_STATS.html#a078ba) の戻り値の `stats` を `user_agent_stats` に修正しました #### セッションライフタイム機能 **実験的機能です** セッションに対してライフタイム (破棄されるまでの時間) を設定する機能を追加しました。 - [ADD] セッションのライフタイムをセッションウェブフック [session.created](SESSION_WEBHOOK.html#1d1984) の戻り値で [session_lifetime](SESSION_WEBHOOK.html#36a751) を指定できるようになりました- **秒** で指定してください - 最大 2,592,000 秒 (30 日) まで指定できます - セッション生成後に変更することはできません - `session_lifetime` が未指定の場合は **無制限** です - `session.destroyed` の `reason` に `lifetime_expired` が入ります - `connection.destroyed` の `reason` に `session_destroyed` が入ります - セッションのライフタイムが終了すると、セッションが破棄され切断します - セッションのライフタイムが終了すると、セッションウェブフック `session.destroyed` が送信されます #### コネクションライフタイム機能 **実験的機能です** コネクションに対してライフタイム (破棄されるまでの時間) を設定する機能を追加しました。 - [ADD] コネクションのライフタイムを認証ウェブフックの払い出しで [connection_lifetime の払い出し](AUTH_WEBHOOK_RETURN.html#8b77ca) を指定できるようになりました- **秒** で指定してください - 最大 2,592,000 秒 (30 日) まで指定できます - コネクション生成後に変更することはできません - `connection_lifetime` が未指定の場合は **無制限** です - `connection.destroyed` の `reason` に `lifetime_expired` が入ります - コネクションのライフタイムが終了すると、コネクションが破棄され切断します - コネクションのライフタイムが終了すると、コネクションウェブフック `connection.destroyed` が送信されます - コネクションのライフタイムよりセッションのライフタイムが優先されます #### サイマルキャストマルチコーデック機能 **実験的機能です** 一つのサイマルキャストで複数のコーデックを利用する事ができる、サイマルキャストマルチコーデックを追加しました。 - [ADD] 複数の映像コーデックを同時に配信するサイマルキャストマルチコーデック機能に対応しました- サイマルキャストマルチコーデックの配信に対応した SDK のみで利用できます- 2026 年 6 月 時点で以下の SDK が実験的に対応しています - Sora C SDK - Sora C++ SDK - ブラウザを利用した場合、サイマルキャストマルチコーデック機能を利用して配信することはできません、視聴側は利用できます - [ADD] `sora.conf` にてサイマルキャストコーデック機能を有効にするするかどうかを指定する [simulcast_multicodec](SORA_CONF.html#a8cf0f) を追加しました- デフォルトは `false` です - [simulcast_multicodec](SORA_CONF.html#a8cf0f) を `true` に設定するとサイマルキャストマルチコーデック機能が利用可能になります - [ADD] シグナリング接続時に `"simulcast_multicodec"` 項目を追加しました- `"simulcast_multicodec": true` を指定する際には `"simulcast": true` を指定する必要があります - [ADD] 認証ウェブフックに `"simulcast_multicodec"` 項目を追加しました- `simulcast` が `true` かつ `simulcast_multicodec` が `true` の時のみ含まれます - [ADD] 認証成功時の払い出しで `simulcast_multicodec` を払い出した場合、サイマルキャストマルチコーデックを利用できるようになりました- `sora.conf` にて [simulcast_multicodec](SORA_CONF.html#a8cf0f) が `true` に指定されている必要があります - `"simulcast": true` が指定されている必要があります - [ADD] 認証成功時の払い出しで `simulcast_codecs` を指定できるようになりました - [ADD] `sora.conf` にてサイマルキャストのデフォルトコーデックを設定する [simulcast_codecs_file](SORA_CONF.html#cc4473) を指定できるようになりました - [ADD] イベントウェブフック `connection.{created, updated, destroyed}` に simulcast_multicodec 項目を追加しました- `simulcast` が `true` かつ `simulcast_multicodec` が `true` の時のみ含まれます - [ADD] コネクションログに `simulcast_multicodec` 項目を追加しました- 項目は必ず含まれます - [ADD] `"type": "offer"` 時に `simulcast_multicodec` 項目を追加しました- 項目は必ず含まれます 詳細は [サイマルキャストマルチコーデック](SIMULCAST_MULTICODEC.html) をご確認ください。 #### H.264/H.265 B-frame 対応 **実験的機能です** 実験的機能として H.264 と H.265 の [B-frame 向けの RTP ヘッダー拡張](https://datatracker.ietf.org/doc/html/draft-deping-avtcore-video-bframe) に対応しました。 B-frame 向けの RTP ヘッダー拡張に対応している場合、 H.264/H.265 で B-frame を利用した配信/視聴が行えるようになります。 B フレームの録画には対応していません。 - [ADD] H.264 と H.264 で B-frame を利用する RTP ヘッダー拡張に対応しました - [ADD] `sora.conf` に H.264 で B-frame を利用するかどうかを指定する [h264_b_frame](SORA_CONF.html#f546aa) を追加しました- デフォルトは `false` です - [ADD] `sora.conf` に H.265 で B-frame を利用するかどうかを指定する [h265_b_frame](SORA_CONF.html#a9a8f8) を追加しました- デフォルトは `false` です - [ADD] シグナリング `type: connect` 時に H.264 で B-frame を利用するかどうかを指定する `h264_params: {"b_frame": true}` を追加しました- デフォルトは `false` です - `sora.conf` にて [h264_b_frame](SORA_CONF.html#f546aa) が `true` に指定されている必要があります - `sora.conf` にて [signaling_h264_params](SORA_CONF.html#b32e49) が `true` に指定されている必要があります - [ADD] シグナリング `type: connect` 時に H.265 で B-frame を利用するかどうかを指定する `h265_params: {"b_frame": true}` を追加しました- デフォルトは `false` です - `sora.conf` にて [h265_b_frame](SORA_CONF.html#a9a8f8) が `true` に指定されている必要があります - `sora.conf` にて [signaling_h265_params](SORA_CONF.html#8ed4e9) が `true` に指定されている必要があります - [ADD] ウェブフックの `video_h264_params` に `b_frame` を追加しました- `sora.conf` の [h264_b_frame](SORA_CONF.html#f546aa) が `true` に指定されていない場合は `b_frame` は含まれません - [ADD] ウェブフックの `video_h265_params` に `b_frame` を追加しました- `sora.conf` の [h264_b_frame](SORA_CONF.html#f546aa) が `true` に指定されていない場合は `b_frame` は含まれません - [ADD] 認証成功時の払い出しで `video_h264_params` に `b_frame` を追加しました- デフォルトは `false` です - 接続時や払い出し時に未指定の場合はデフォルトの `false` が利用されます - [ADD] 認証成功時の払い出しで `video_h265_params` に `b_frame` を追加しました- デフォルトは `false` です - 接続時や払い出し時に未指定の場合はデフォルトの `false` が利用されます #### プレイアウト遅延機能 **実験的機能です** プレイアウト遅延機能を追加しました。 プレイアウト遅延機能を利用することでフレームをどれくらい速くレンダリングする必要があるかを配信ごとに指定できます。 - [CHANGE] `sora.conf` の RTP ヘッダー拡張 playout-delay を利用するかどうかを指定する [rtp_hdrext_playout_delay](SORA_CONF.html#d34a4b) のデフォルトを `true` に変更しました - [ADD] `sora.conf` にプレイアウト遅延の最小値のデフォルトを指定する [default_playout_delay_min_delay](SORA_CONF.html#194218) を追加しました - [ADD] `sora.conf` にプレイアウト遅延の最大値のデフォルトを指定する [default_playout_delay_max_delay](SORA_CONF.html#c1b0ab) を追加しました - [ADD] 認証成功時の払い出しでプレイアウト遅延の最小値を指定する `playout_delay_min_delay` を追加しました- `playout_delay_max_delay` も一緒に指定する必要があります - [ADD] 認証成功時の払い出しでプレイアウト遅延の最大値を指定する `playout_delay_max_delay` を追加しました- `playout_delay_min_delay` も一緒に指定する必要があります 詳細は [プレイアウト遅延機能](PLAYOUT_DELAY.html) をご確認ください。 #### メディア配信ワーカー **実験的機能です** 配信ワーカー機能をメディア配信ワーカー機能に変更しました。 - [UPDATE] スポットライト機能をメディア配信ワーカーで利用できるようになりました - [CHANGE] `sora.conf` の `rtp_publish_worker_number` を `media_publish_worker_number` に変更しました #### WebSocket シグナリング時の HTTP ヘッダーを認証ウェブフックにコピーする機能 **実験的機能です** - [ADD] `sora.conf` に WebSocket シグナリング接続時の HTTP ヘッダーを認証ウェブフックのヘッダーにコピーする [copy_websocket_signaling_header_names](SORA_CONF.html#db39f3) を追加しました- デフォルトは未指定です - 大文字小文字は区別されません - `copy_websocket_signaling_header_names = X-Forwarded-For, X-Real-IP, Tracestate` のように指定してください - [ADD] 認証ウェブフックログ `auth_webhook.jsonl` に `copy_headers` 項目を追加しました- 認証ウェブフックにコピーされたヘッダーを出力します ## 2023.2.7 **バグフィックスアップデート** **リリース**: 2024-04-24 - [FIX] レガシー録画機能または録画機能(セッション単位)利用時の録画停止処理中に、新規コネクションが参加した際に、そのコネクションが切断されるまで、録画停止処理が完了しない問題を修正しました - [FIX] レガシー録画機能にて録画停止処理中に録画の開始および [StopRecording](OBSOLETE_API_LEGACY_RECORDING.html#fd0de5) API 実行した際 `RECORDING-INTERNAL-ERROR` が返されていたのを `STOPPING-RECORDING` を返すように修正しました - [FIX] クラスター有効時に、ごく稀にノード起動に失敗することがある問題を修正しました ## 2023.2.5 **ホットフィックスアップデート** **リリース**: 2024-03-08 - [FIX] 録画機能で録画中、出力済の分割録画ファイルのファイルディスクリプタを掴み続ける問題を修正しました ## 2023.2.4 **ホットフィックスアップデート** > **重要** > > このリリースはクラスターをご利用いただいているお客様にのみ提供しております。 **リリース**: 2024-02-27 - [FIX] クラスター利用時にでリーダーノードがダウンした場合に、他のノードのセッションも終了してしまう問題を修正しました ## 2023.2.3 **バグフィックスアップデート** **リリース**: 2024-02-07 - [FIX] `"multistream": false` を指定して接続した場合に、配信/視聴ができない問題を修正しました - [FIX] セッションウェブフックが一部の HTTP サーバーで正常に処理できず、エラーになる問題を修正しました - [FIX] データチャネルの終了時にクライアント側で警告が出力される問題を修正しました ## 2023.2.2 **バグフィックスアップデート** **リリース**: 2024-01-04 ### 変更履歴 - [FIX] `sora.conf` の [event_webhook_url](SORA_CONF.html#e1a4d2) が未指定の状態で録画を開始した場合、セッションが破棄されない問題を修正しました - [FIX] ウェブフックで mTLS 利用時に、特定の条件下でクライアント証明書を送らなくなる問題を修正しました- ウェブフックで HTTPS を利用する場合は TLS 1.2 のみを利用するように変更しました - [FIX] ウェブフックで mTLS 利用時に、 CA 証明書が指定されていない場合に OS 組み込みの証明書を利用できない問題を修正しました - [FIX] 統計エクスポーターで mTLS 利用時に、 CA 証明書が指定されていない場合に OS 組み込みの証明書を利用できない問題を修正しました - [FIX] 音声ストリーミングで mTLS 利用時に、 CA 証明書が指定されていない場合に OS 組み込みの証明書を利用できない問題を修正しました - [FIX] API ログの書き込みに失敗した場合でも、 API の処理を中断しないように修正しました - [FIX] [PurgeClusterNode](API_CLUSTER.html#13b35a) API の API ログ操作名が `LeaveCluster` となっていたのを `PurgeClusterNode` に修正しました - [FIX] クラスターに参加済のノードが、別クラスターに対する [JoinCluster](OBSOLETE_API.html#17f3f5) API を受け入れてしまう問題を修正しました - [FIX] 録画機能で大幅にパケットの到着が遅れている場合、分割録画に失敗することがある問題を修正しました ## 2023.2.0 **メジャーアップデート** **リリース**: 2023-12-20 ### ハイライト - セッション単位で録画する新しい録画機能を追加しました- 今までの録画機能は [レガシー録画機能](OBSOLETE_LEGACY_RECORDING.html) と名前を変更しました - レガシー録画機能と新しい録画機能は別チャネルであれば同時に利用することができます - レガシー録画機能は 2025 年 12 月リリース予定の Sora にて廃止します - 詳細は [録画機能 (セッション単位)](RECORDING.html) をご確認ください - 接続単位で録画をブロックできる機能を追加しました- 今まではチャネルに参加している全ての接続が録画されていましたが、新しい録画機能では接続単位で録画をブロックできるようになりました - 新しい録画機能でのみ利用できます - より大規模な配信を可能にする配信ワーカー機能を追加しました- 今まで音声や映像をクライアントに配信するワーカーは 1 つでしたが、配信するワーカーを複数にすることで、より多くのユーザーに配信することができるようになりました - データチャネルの負荷を下げるために SCTP パケットのチェックサム計算を省略する機能を追加しました- 利用するにはクライアント側もチェックサム計算を省略する機能に対応している必要があります - ウェブフックで IPv6 アドレスが利用できるようになりました - ウェブフックなどでルート CA 証明書に OS 組み込みのものを利用するようにしました ### 正式版 - [セッションウェブフック](SESSION_WEBHOOK.html) が正式版になりました - [DataChannel 経由のシグナリング](DATA_CHANNEL_SIGNALING.html) が正式版になりました - [リアルタイムメッセージング機能](MESSAGING.html) が正式版になりました ### 廃止情報 - `sora.conf` の `legacy_log_format` を廃止しました- 詳細は [sora.conf の legacy_log_format の廃止](OBSOLETE.html#daeabd) をご確認ください - `sora.conf` の `legacy_log_extension` を廃止しました- 詳細は [sora.conf の legacy_log_extension の廃止](OBSOLETE.html#c35c81) をご確認ください - `sora.conf` の `legacy_webhook_audio_video_json_structure` を廃止しました- 詳細は [sora.conf の legacy_webhook_audio_video_json_structure の廃止](OBSOLETE.html#a7613b) をご確認ください ### 破壊的変更 - `sora.conf` の [signaling_notify_metadata](SORA_CONF.html#2d9340) を `false` にした場合でもシグナリング通知の `data` が含まれるようになりました - `sora.conf` の以下の設定を全て `false` にした場合、シグナリング通知の `data` が含まれなくなりました- [signaling_notify_metadata](SORA_CONF.html#2d9340) - [signaling_notify_client_id](SORA_CONF.html#fc78ca) - [signaling_notify_bundle_id](SORA_CONF.html#f2a58f) - [signaling_notify_connection_id](SORA_CONF.html#7882d6) - [signaling_notify_connection_created_timestamp](SORA_CONF.html#7fe7b3) - 実験的機能のクラスター機能利用時のセッションウェブフック [session.destroyed](SESSION_WEBHOOK.html#ccb165) に `connections` が含まれなくなりました - 実験的機能のクラスター機能のログを `cluster.jsonl` に出力するよう変更しました - 実験的機能のセッションウェブフック [audio-streaming.started](SESSION_WEBHOOK.html#e7b17a) に `max_connections` と `total_connections` が含まれなくなりました - 実験的機能のセッションウェブフック [audio-streaming.started](SESSION_WEBHOOK.html#e7b17a) に `max_connections` と `total_connections` が含まれなくなりました ### 変更履歴 - [CHANGE] ウェブフックなどで利用するルート CA 証明書に OS 組み込みのものを利用するように変更しました- Ubuntu の場合は `apt install ca-certificates` でインストールされる証明書を利用します - RHEL の場合は `dnf install ca-certificates` でインストールされる証明書を利用します - 詳細は [ウェブフックリクエストなどの送信先サーバー証明書の検証に利用する OS 組み込みのルート CA 証明書について](WEBHOOK.html#e8a845) をご確認ください - [UPDATE] DataChannel を利用したメッセージングのみで接続する場合に `role` が `sendrecv` 以外でも接続ができるようになりました - [ADD] シグナリング `"type": "offer"` に `channel_id` と `session_id` を追加しました - [ADD] `connection.jsonl` の `ice_connection_state` に ICE コネクションステート `checking` と `disconnected` だった時間を追加しました - [ADD] Sora が利用している Erlang VM の設定を追加できる環境変数 `SORA_ADDITIONAL_ERL_ARGS` を追加しました - [ADD] 認証成功時の払い出しに検証用の RTP パケットロスシミュレーターの設定値、 `rtp_packet_loss_simulator_incoming` と `rtp_packet_loss_simulator_outgoing` が指定できるようになりました - [ADD] `sora.jsonl` と `internal.jsonl` に UUIDv4 を Base32 でエンコードしたユニークな ID を含めるようにしました- `"id": "base32(uuidv4)"` - [FIX] データチャネルで利用する SCTP のストリーム ID 採番を RFC 8832 に準拠させました - [FIX] 録画機能で H.264 利用時に送られてくる分割ペイロードが壊れている場合は処理をスキップするように修正しました #### OBS WHIP **これは実験的機能です** - [ADD] OBS WHIP で User-Agent として送られてくる情報を sora_client としてウェブフックで送信するようにしました```javascript "sora_client": { "raw": "Mozilla/5.0 (OBS-Studio/30.0.0; Mac OS X; ja-JP)", "type": "OBS-Studio", "version": "30.0.0", "environment": "environment":"Mozilla/5.0 (OBS-Studio/30.0.0; Mac OS X; ja-JP)" }, ``` - [ADD] OBS WHIP で AV1 が動作するようにしました- OBS WHIP で AV1 を配信する仕組みは 2026 年 6 月 現在、 OBS には組み込まれていません - [FIX] WHIP 利用時に認証ウェブフックの項目に `ignore_disconnect_websocket` が含まれない問題を修正しました- 常に `false` が含まれます #### 転送フィルター機能 **これは実験的機能です** 転送フィルターに `version` や `metadata` が指定できるようになりました。 `version` を指定することで、転送フィルターの更新 API が並列で実行されても期待した値に変更することができるようになりました。 - [ADD] 転送フィルターに `version` を設定できるようになりました - [ADD] 転送フィルターに `metadata` を設定できるようになりました - [ADD] 転送フィルター API [CreateChannelForwardingFilter](API_FORWARDING_FILTER.html#fe98d1) と [CreateConnectionForwardingFilter](API_FORWARDING_FILTER.html#d80a51) に `version` を指定できるようになりました - [ADD] 転送フィルター API [CreateChannelForwardingFilter](API_FORWARDING_FILTER.html#fe98d1) と [UpdateChannelForwardingFilter](API_FORWARDING_FILTER.html#36fc45) に `metadata` を指定できるようになりました - [ADD] 転送フィルター API [CreateConnectionForwardingFilter](API_FORWARDING_FILTER.html#d80a51) と [UpdateConnectionForwardingFilter](API_FORWARDING_FILTER.html#23ed63) に `metadata` を指定できるようになりました - [ADD] 転送フィルター API [UpdateChannelForwardingFilter](API_FORWARDING_FILTER.html#36fc45) と [UpdateConnectionForwardingFilter](API_FORWARDING_FILTER.html#23ed63) API に指定した `expected_version` が既存の `version` と一致していない場合は更新エラーになるようになりました- `expected_version` が既存のバージョンと一致した場合のみ `desired_version` で指定した値で `version` の値を更新します - [ADD] セッションウェブフックの戻り値に `version` と `metadata` を指定できるようになりました - [ADD] 認証成功の払い出し時に `version` と `metadata` を指定できるようになりました - [ADD] シグナリング時に `version` と `metadata` を指定できるようになりました #### セッション API - [ADD] 指定したセッションを取得する [GetSession](API_SESSION.html#427a59) API を追加しました- `channel_id` を指定してセッションを取得します - [ADD] セッション一覧を取得する [ListSessions](API_SESSION.html#748f19) API を追加しました- 全てのセッション一覧を取得します #### 録画機能 - [ADD] `sora.conf` に一括録画ファイルと分割録画ファイルの両方を出力する機能を有効にするかどうかを指定する [recording_dual_output](SORA_CONF.html#4cc9c0) を追加しました- デフォルトは `true` です - `false` に指定した場合は `一括録画ファイルと分割録画ファイルの両方が出力` のパターンを指定できなくなります - [ADD] `sora.conf` に録画期限の最大値を指定する [recording_max_expire_time](SORA_CONF.html#f3ff8d) を追加しました- デフォルトは `86400 s` です - 設定できる最大値は `86400 s` です - レガシー録画機能では一括録画と一括&分割録画で `expire_time` が指定できます - 新しい録画機能(セッション単位)では一括録画、分割録画、一括&分割録画で `expire_time` が指定できます - [ADD] `sora.conf` に分割録画時の分割時間の最大値を指定する [recording_max_split_duration](SORA_CONF.html#927da9) を追加しました- デフォルトは `86400 s` です - 設定できる最大値は `86400 s` です - [ADD] `sora.conf` に一括録画を含む場合に録画期限の設定を要求する [recording_expire_time_required](SORA_CONF.html#fcfa2d) を追加しました- **この設定は一括録画時に録画ファイルが大きくなりすぎるのを防ぐための設定です** - デフォルトは `false` です - この設定を `true` にした場合、一括録画を含む場合に `expire_time` が必須になります - この設定を `true` にした場合、レガシー録画機能では `expire_time` に `0` 以外の値を指定する必要があります - この設定を `true` にした場合、新しい録画機能(セッション単位)では `expire_time` の値を指定する必要があります - この設定を `true` にした場合でも分割録画のみの場合は `expire_time` は必須になりません #### 新しい録画機能 (セッション単位) 今までの録画機能は [レガシー録画機能](OBSOLETE_LEGACY_RECORDING.html) と名前を変更しました。 レガシー録画機能と新しい録画機能は別チャネルであれば同時に利用することができます。 - [ADD] `sora.conf` にレガシー録画を有効にするかどうか指定する `legacy_recording` を追加しました- デフォルトは `true` です - `false` にした場合、レガシー録画機能が利用できなくなります - この設定は移行用の設定で、 2025 年 12 月リリース予定の Sora にて廃止します。 - [ADD] セッションウェブフック `session.created` 時に `"recording": true` を指定することで録画を開始します - [ADD] セッションウェブフック `session.created` 時に `"recording_expire_time"` を指定することができるようになりました- セッション破棄時に録画は自動で終了します - セッション破棄前に期限が来た場合はそこで録画は終了します - [ADD] セッションウェブフック `session.created` 時に `"recording_split_duration"` を指定することができるようになりました - [ADD] セッションウェブフック `session.created` 時に `"recording_split_only"` を指定することができるようになりました - [ADD] セッションウェブフック `session.created` 時に `"recording_metadata"` を指定することができるようになりました - [ADD] セッションウェブフック `recording.started` を追加しました - [ADD] セッションウェブフック `recording.report` を追加しました - [ADD] 新しい録画用の [StartRecording](API_RECORDING.html#c5b527) API を追加しました- セッション破棄時に自動で録画は終了します - `expire_time` がオプションになっています - `expire_time` デフォルトは未定義です - [ADD] 新しい録画用の [StopRecording](API_RECORDING.html#fd0de5) API を追加しました 詳細については [録画機能 (セッション単位)](RECORDING.html) をご確認ください。 移行については レガシー録画機能から新しい録画機能 (セッション単位) への移行 をご確認ください。 #### 新しい録画機能 (セッション単位) における接続単位の録画ブロック機能 **これは実験的機能です** **この機能は新しい録画機能 (セッション単位) でのみ利用できます。レガシー録画機能では利用できません** - [ADD] 認証成功時に `"recording_block": true` を払い出すことで、その接続の録画をブロックし、録画ファイルの出力を拒否できるようになりました- これは録画が有効になっていない場合に払い出しても問題ありません - この値を途中で変更することはできません - [ADD] イベントウェブフック `connection.{created, updated, destroyed}` の `data` に `"recording_block"` の項目を追加しました- 認証成功時に `"recording_block": true` を払い出していれば `true` に、それ以外は `false` になります #### シグナリング通知メタデータ `sora.conf` で `signaling_notify_metadata` を `false` にした際の挙動を変更しました。 - [CHANGE] `sora.conf` の `signaling_notify_metadata` を `false` にした際でも `data` 項目が含まれるようになりました- `data` の `metadata` と `authn_metadata` と `authz_metadata` は含まれません - [CHANGE] `sora.conf` で以下の設定を全て `false` にした場合、シグナリング通知の `data` が含まれなくなりました- [signaling_notify_metadata](SORA_CONF.html#2d9340) - [signaling_notify_client_id](SORA_CONF.html#fc78ca) - [signaling_notify_bundle_id](SORA_CONF.html#f2a58f) - [signaling_notify_connection_id](SORA_CONF.html#7882d6) - [signaling_notify_connection_created_timestamp](SORA_CONF.html#7fe7b3) - [FIX] `sora.conf` で `signaling_notify_metadata` を `false` にした際にも、シグナリング通知の `data` 項目の `authn_metadata` と `authz_metadata` が含まれてしまう問題を修正しました #### 外部への HTTP リクエストに HTTP ヘッダーを追加 ウェブフックや統計エクスポーター、音声ストリーミングを利用した際の外部への HTTP リクエストに、 `x-sora-` prefix とは別に `sora-` prefix の HTTP ヘッダーを追加しました。 これは [RFC 6648](https://datatracker.ietf.org/doc/html/rfc6648) による `x-` prefix の非推奨化に準拠するためです。 今後 `x-sora-` prefix は非推奨になります。 現時点で具体的な時期は決まっていませんが、将来的に 1 年以上の移行期間を設けて廃止する予定です。 - [ADD] セッションウェブフックに `sora-session-webhook-type` ヘッダーを追加しました- すでにある `x-sora-session-webhook-type` ヘッダーは将来的に廃止予定です - [ADD] イベントウェブフックに `sora-event-webhook-type` ヘッダーを追加しました- すでにある `x-sora-event-webhook-type` ヘッダーは将来的に廃止予定です - [ADD] 統計エクスポーターに `sora-stats-exporter-type` ヘッダーを追加しました- すでにある `x-sora-stats-exporter-type` ヘッダーは将来的に廃止予定です - [ADD] セッションウェブフックに `sora-session-id` ヘッダーを追加しました - [ADD] イベントウェブフックに `sora-connection-id` ヘッダーを追加しました - [ADD] イベントウェブフックに `sora-session-id` ヘッダーを追加しました #### ウェブフック - [CHANGE] セッションウェブフック `audio-streaming.started` に `max_connections` と `total_connections` が含まれなくなりました - [CHANGE] セッションウェブフック `audio-streaming.stopped` に `max_connections` と `total_connections` が含まれなくなりました - [CHANGE] クラスター機能利用時のセッションウェブフック `session.destroyed` に `connections` が含まれなくなりました - [ADD] `sora.conf` にウェブフックで IPv6 利用する [webhook_ipv6](SORA_CONF.html#6c895b) を追加しました- デフォルトは `false` です - この設定を有効にしない限りウェブフックで IPv6 は利用できません - [ADD] `sora.conf` にイベントウェブフック `connection.updated` の送信間隔を変更する [connection_updated_webhook_interval](SORA_CONF.html#e67c3b) を追加しました- デフォルトは `1 min` です - 最小は `1 min` です - 最大は `10 min` です - 時間単位は `min` のみが指定できます - [ADD] `sora.conf` に 録画イベントウェブフック `split-archive.available` を送信しないようにする [ignore_split_archive_available_webhook](SORA_CONF.html#a62b1e) を追加しました- デフォルトは `false` です - [ADD] 接続イベントウェブフック `connection.{created, updated, destroyed}` に ICE コネクションステートが `checking` と `disconnected` だった時間の項目を追加しました- `data.ice_connection_state.total_checking_duration_ms` に `checking` だった合計時間(ミリ秒)が入ります - `data.ice_connection_state.total_disconnected_duration_ms` に `disconnected` だった合計時間(ミリ秒)が入ります - [ADD] 認証ウェブフックに `spotlight_focus_rid` と `spotlight_unfocus_rid` を追加しました- `spotlight` が `true` の時だけ追加されます - [ADD] 接続イベントウェブフック `connection.{created, updated, destroyed}` に ICE コネクションステートの `checking` と `disconnected` の時間を通知する項目を追加しました- `ice_connection_state` 項目を追加しました - `ice_connection_state` に `total_checking_duration_ms` に `checking` だった合計時間(ミリ秒)が入ります - `ice_connection_state` に `total_disconnected_duration_ms` に `disconnected` だった合計時間(ミリ秒)が入ります ```javascript "data": { "ice_connection_state": { "total_checking_duration_ms": 0, "total-disconnected_duration_ms": 0 } } ``` - [ADD] セッションウェブフック [session.updated](SESSION_WEBHOOK.html#2a5b1b) を追加しました- クラスターが有効時には `connections` は含まれません - 録画機能 (セッション単位) 有効時に `recording` 項目が含まれます - [ADD] セッションウェブフック `session.destroyed` に `reason` が含まれるようになりました- `reason` には以下が含まれます- `normal`- 正常終了 - `terminated_api`- [TerminateSession](API_SESSION.html#ba022b) API を利用した終了 - `abort`- 異常終了 - [ADD] `sora.conf` にセッションウェブフック [session.updated](SESSION_WEBHOOK.html#2a5b1b) を送信しないようにする [ignore_session_updated_webhook](SORA_CONF.html#0901a0) を追加しました- デフォルトは `false` です - [ADD] `sora.conf` にセッションウェブフック [session.updated](SESSION_WEBHOOK.html#2a5b1b) の送信間隔を変更する [session_updated_webhook_interval](SORA_CONF.html#4612dc) を追加しました- デフォルトは `1 min` です - 最小は `1 min` です - 最大は `10 min` です - 時間単位は `min` のみが指定できます - [FIX] 認証ウェブフックで `simulcast_rid` は `spotlight` が `true` の場合は追加しないようにしました- `simulcast` が `true` かつ `spotlight` が `false` の時だけ追加されます #### データチャネル - [ADD] データチャネルの SCTP のパケットのチェックサム計算を省略する仕組みを追加しました- データチャネルは DTLS レイヤーでデータ保護が行われているため、 SCTP のチェックサムは追加の整合性を得ることができないため省略することができます - クライアント側もチェックサム計算を省略する機能に対応している必要があります - データチャネル利用時の CPU リソースがクライアント、SFU ともに節約されます - [ADD] SCTP のチェックサムを省略した回数の統計情報を追加しました- `total_received_sctp_zero_checksum` - `total_sent_sctp_zero_checksum` #### クラスター機能 **これは実験的機能です** `Sora 2023.1.x` で構築されているクラスターは `Sora 2023.2.x` へローリングアップデートで移行できます。 > **警告** > > 2023.2.x から 2023.1.x へのローリングアップデートは行えません。クラスターを再構築する必要があります。 - [CHANGE] クラスター関連のログは `cluster.jsonl` に出力するよう変更しました - [ADD] 最新のバージョンと 1 世代前のバージョンの Sora ノードが混在する状態でのクラスター運用ができるようになりました- 全てのクラスターに参加するノードが同じバージョンになるまでは 1 世代前のバージョンと混在できる仕組みを追加しました - `Sora 2023.2.x` と `2023.1.x` で、特定のノードのアップデートが難しい場合でも、先に他のノードをアップデートすることができるようになります - クラスターに 1 世代前のバージョンのノードが混在している場合、新しい接続は全て古いバージョンのクラスターの仕組みを利用します - 全てのノードが新しいバージョンのクラスターになったタイミングで、新しいバージョンのクラスターの仕組みを利用しはじめます 詳細については [クラスター機能](CLUSTER.html) をご確認ください。 > **注釈** > > [InitCluster](API_CLUSTER.html#621990) API でクラスターを初期化する際には、新旧バージョンは混在させないでください。また `Sora 2023.2.x` で構成されたクラスターに [JoinCluster](OBSOLETE_API.html#17f3f5) API で `Sora 2023.1.x` のノードを参加させることはできません。 #### メディア配信ワーカー機能 **これは実験的機能です** メディア配信ワーカー機能は音声や映像を配信するワーカーを複数用意することで、 1 チャネルで高ビットレートの映像をより多くのクライアントに配信することができるようになります。 - [ADD] `sora.conf` に音声や映像の 1 配信に利用するメディア配信ワーカー数を指定する `sora_conf-media_publish_worker_number` を追加しました- デフォルトのメディア配信ワーカー数は 1 です - 同時に 100 クライアント以上へ配信する場合はまず 10 を設定することを推奨します - ワーカー数が 10 であれば 1 チャネル 1000 クライアント以上の配信ができるようになります - 最小は 1 で、最大は 500 です ワーカー数の設定を 10 以上で検討している場合はまずサポートにご相談ください。 詳細については `メディア配信ワーカー機能` をご確認ください。 #### シグナリング通知メタデータ拡張機能 **これは実験的機能です** - [ADD] 認証成功時に、シグナリング通知メタデータ拡張の初期値を払い出す `signaling_notify_metadata_ext` を追加しました。- sora.conf にて [signaling_notify_metadata_ext](SORA_CONF.html#e94720) を有効にしている必要があります - デフォルトは `{}` です #### 統計エクスポーター **これは実験的機能です** - [ADD] `sora.conf` に統計エクスポーターをデフォルトで有効にするかどうかの `default_stats_exporter` を追加しました- デフォルトは `true` です - [ADD] 認証成功時の払い出しで接続単位で統計エクスポーターを有効にするかどうかを指定する `stats_exporter` を追加しました- `false` を設定した場合は `stats_collector_url` が指定されていたとしても統計情報がエクスポートされません #### H.265 **これは実験的機能です** 2026 年 6 月 現在、WebRTC H.265 のプロファイルに対応している WebRTC ライブラリはありません。 現在 [仕様策定中](https://datatracker.ietf.org/doc/html/draft-ietf-avtcore-hevc-webrtc) です。 - [ADD] H.265 サイマルキャストに対応しました - [ADD] `sora.conf` に H.265 のデフォルトレベル ID を指定する [default_h265_param_level_id](SORA_CONF.html#d15808) を追加しました- デフォルトは `93` (3.1) です - [ADD] 認証払い出し時に H.265 のデフォルトレベル ID を指定する `video_h265_params` を追加しました- `"video_h265_params": {"level_id": 93}` のように指定できます - level_id の値は 0 から 255 の間である必要があります - [ADD] シグナリング時に H.265 のデフォルトレベル ID を指定する `h265_params` を追加しました- `"video": {"codec_type": "H265", "h265_params": {"level_id": 93}}` のように指定できます - level_id の値は 0 から 255 の間である必要があります - [ADD] `sora.conf` に、シグナリング時に H.265 のパラメータ指定を許可するかどうか設定する [signaling_h265_params](SORA_CONF.html#8ed4e9) を追加しました- デフォルトは `false` です ## 2023.1.3 **バグフィックスアップデート** **リリース**: 2023-10-17 ### 変更履歴 - [FIX] 録画機能利用時、分割録画に失敗かつ分割録画ファイルが一つ以上生成されている場合に、終了処理に失敗する問題を修正しました- 終了中の失敗のため、録画処理自体には影響はありません - [FIX] サイマルキャスト機能の `simulcast_encodings` と `spotlight_encodings` の `scalabilityMode` のデフォルト値を `L1T1` に修正しました- AV1 サイマルキャスト利用時に `L1T1` 以外の `scalabilityMode` を利用すると録画ができない問題があります - [FIX] データチャネルを利用したメッセージング機能利用時に、パケロスが発生すると一定期間パケットを破棄してしまうことがある問題を修正しました- この問題は `ordered` が `true` で `max_retransmits` や `max_packet_life_time` が設定されている場合に発生します - [FIX] クラスター機能利用時に、ノードの起動・停止と新規チャネルへの接続が重なると接続に失敗することがある問題を修正しました - [FIX] `sora.conf` の `default_simulcast_rid` の設定値が設定に反映されない問題を修正しました - [FIX] 依存している OpenSSL を 3.1.3 にアップデートしました ## 2023.1.2 **バグフィックスアップデート** **リリース**: 2023-08-10 ### 変更履歴 - [FIX] Safari 側の問題により Safari 14 系および Safari 15 系の一部で Sora に接続できない問題を修正しました- Safari 15.6 以降では問題が修正されていることを確認しています ## 2023.1.1 **バグフィックスアップデート** **リリース**: 2023-07-14 ### 変更履歴 - [ADD] connection ログに `ice_connection_state` という ICE コネクション機能の統計情報を追加しました- サポートにて問題をより素早く解決しやすくするための追加です - [ADD] connection ログに `network_status` に不安定レベルごとの統計情報を追加しました- サポートにて問題をより素早く解決しやすくするための追加です - [ADD] [GetStatsConnection](API_STATS.html#e79b61) API に `ice_connection_state` の統計情報を追加しました - [ADD] [GetStatsConnection](API_STATS.html#e79b61) API に `network_status` にレベルごとの統計情報を追加しました - [FIX] CentOS 7 x86_64 利用時にセグメンテーション違反で Sora が落ちてしまう問題を修正しました - [FIX] DTLS 再ネゴシエーションの挙動を修正しました - [FIX] スポットライト機能利用時に OBS での WHIP が利用できない問題を修正しました- 新しく WHIP エンドポイント URL 指定時に `spotlight=true` を指定することで利用できるようにしました - ただし、音声がそのままでは配信されないため [FocusSpotlightFixed](API_SPOTLIGHT.html#beaf88) API を利用して音声を配信する必要があります - [FIX] ICE コネクションステート機能で `disconnected` 時のクライアント状態確認の挙動を修正しました - [FIX] [PutSignalingNotifyMetadata](API_SIGNALING_NOTIFY_METADATA_EXT.html#a20c95) API の結果の誤字を修正しました - [FIX] [JoinCluster](OBSOLETE_API.html#17f3f5) API のエラー応答の誤字を修正しました ## 2023.1.0 **メジャーアップデート** **リリース**: 2023-06-28 ### サポート期間変更 - Sora 2023.1.0 より、サポート提供期間をメジャーアップデートがリリースされた日から **12 ヶ月後の月末最終日まで** に変更しました - 2023年 6 月リリースの Sora 2023.1.0 およびその後リリースされる可能性のある Sora 2023.1.x は、2024 年 6 月 30 日までサポート対象となります 詳細は [サポートライフサイクル](SUPPORT_LIFECYCLE.html) をご確認ください。 ### ハイライト - OBS で WebRTC を利用した配信を実現する WHIP に対応しました- 詳細は [OBS (WHIP) 機能](WHIP.html) をご確認ください - VP9 / AV1 でのサイマルキャストに対応しました- 詳細は [VP9 と AV1 でのサイマルキャスト](SIMULCAST.html#860410) をご確認ください - メディアストリームを柔軟に制御するための [転送フィルター機能](FORWARDING_FILTER.html) を追加しました - 音声ストリーミング機能に自動開始/停止機能を追加しました- 詳細は [自動開始/停止機能](AUDIO_STREAMING.html#1492a6) をご確認ください - IPv6 のみの環境での動作に対応しました- 詳細は [ipv6_only](SORA_CONF.html#5e9e68) をご確認ください ### 互換なしの変更情報 - 移行用の設定である `sora_conf-legacy_webhook_audio_video_json_structure` の設定のデフォルトを `false` に変更しました- 詳細は [sora.conf の legacy_webhook_audio_video_json_structure の廃止](OBSOLETE.html#a7613b) をご確認ください - 移行用の設定である `legacy_log_format` の設定のデフォルトを `false` に変更しました- 詳細は [sora.conf の legacy_log_format の廃止](OBSOLETE.html#daeabd) をご確認ください - 移行用の設定である `legacy_log_extension` の設定のデフォルトを `false` に変更しました- 詳細は [sora.conf の legacy_log_extension の廃止](OBSOLETE.html#c35c81) をご確認ください ### 廃止情報 - Ubuntu 18.04 向けパッケージのサポートを終了しました- 詳細は [Ubuntu 18.04 サポートの終了](OBSOLETE.html#afde12) をご確認ください - `sora.conf` の `split_archive_legacy_prefix` を廃止しました- 詳細は [sora.conf の split_archive_legacy_prefix の廃止](OBSOLETE.html#050276) をご確認ください - `sora.conf` の `default_multistream` を廃止しました- 詳細は [sora.conf の default_multistream の廃止](OBSOLETE.html#615559) をご確認ください - `sora.conf` の `dcsctp_heartbeat_interval` を廃止しました- 詳細は [DataChannel で利用している SCTP 関連の実験的な設定の廃止](OBSOLETE.html#0af146) をご確認ください - `sora.conf` の `dcsctp_slow_start_tcp_style` を廃止しました- 詳細は [DataChannel で利用している SCTP 関連の実験的な設定の廃止](OBSOLETE.html#0af146) をご確認ください ### 変更履歴 - [CHANGE] データチャネル関連の設定である `dcsctp_heartbeat_interval` を廃止しました - [CHANGE] データチャネル関連の設定である `dcsctp_slow_start_tcp_style` を廃止しました - [CHANGE] サイマルキャスト利用時に `"active": false` を指定したストリームは、 `~r0` といった SDP が生成されます- r1 と r2 が false の場合は `a=simulcast:recv r0;~r1;~r2` のような SDP が生成されます - これは [RFC 8853: Using Simulcast in SDP and RTP Sessions](https://www.rfc-editor.org/rfc/rfc8853.html) に準拠しています - [CHANGE] `sora.conf` のウェブフックの audio と video 項目のレガシーな入れ子構造を利用する `sora_conf-legacy_webhook_audio_video_json_structure` のデフォルト値を `false` に変更しました- これは移行用設定です - [CHANGE] `sora.conf` のログフォーマットのレガシー形式を維持する `legacy_log_format` のデフォルト値を `false` に変更しました- これは移行用設定です - [CHANGE] `sora.conf` の JSONL 形式で出力しているログのレガシー拡張子を `.log` に維持する `legacy_log_extension` のデフォルト値を `false` に変更しました- これは移行用設定です - [UPDATE] RHEL 9.2 に対応しました - [UPDATE] RHEL 8.8 に対応しました - [ADD] 録画イベントウェブフック `recording.started` に `data.start_timestamp` を追加しました - [ADD] 録画イベントウェブフック `recording.started` に `data.split_duration` を追加しました - [ADD] `sora.conf` に IPv6 アドレスのみを利用する [ipv6_only](SORA_CONF.html#5e9e68) の設定を追加しました - [ADD] クラスター機能が有効な際、セッションウェブフックに `external_signaling_url` 項目を追加しました- `sora.conf` の [external_signaling_url](SORA_CONF.html#d6bf68) に指定されている値がそのまま入ります - [ADD] モードが `block_new_connection` の場合は、接続に失敗する仕組みを追加しました - [ADD] イベントウェブフックにログの書き込みが成功したかどうかを示す `log_written` フラグを追加しました- イベントウェブフックログの書き込みが成功した場合は `"log_written": true` が含まれます - イベントウェブフックログの書き込みが失敗した場合は `"log_written": false` が含まれます - イベントウェブフックログには常に `log_written` が含まれます - [ADD] 録画機能で録画ファイル生成に失敗したファイル情報を `recording.report` ウェブフックやファイルに `failed_archives` という項目で追加しました - [ADD] 録画機能の `recording.report` イベントウェブフックに `"file_written"` フラグを追加しました- `report-*.json` ファイルの書き込みに成功した場合 `"file_written": true` が含まれます - `report-*.json` ファイルの書き込みに失敗した場合 `"file_written": false` が含まれます - `report-*.json` ファイルには常に `file_written` が含まれます - [ADD] 認証ウェブフックに `id` を追加しました - [FIX] IPv6 のみの環境で Firefox が正常に動作しない問題を修正しました - [FIX] Sora 終了中に HTTP API が呼ばれるとクラッシュログが出力される問題を修正しました - [FIX] 認証ウェブフックで `simulcast` が `false` の場合でも `simulcast_rid` が含まれていた問題を修正しました- `simulcast` が `false` の場合は `simulcast_rid` は含まれなくなります - [FIX] 録画機能で H.264 でまれに録画が失敗してしまう問題を修正しました - [FIX] スポットライト機能でフォーカスが当たっていない場合でも、無音の音声パケットが配信されてしまう問題を修正しました #### パッケージファイル名の変更 OS 名とバージョンの間に `-` を入れるようにし、x86_64 もアーキテクチャを追加しました。 展開後のディレクトリにアーキテクチャは含まれません。 - [CHANGE] `sora-2023.1.0-ubuntu22.04-arm64v8.tar.gz` から `sora-2023.1.0-ubuntu-22.04-arm64v8.tar.gz` に変更しました- `ubuntu22.04` を `ubuntu-22.04` に変更しました - [CHANGE] `sora-2023.1.0-ubuntu20.04-arm64v8.tar.gz` から `sora-2023.1.0-ubuntu-20.04-arm64v8.tar.gz` に変更しました- `ubuntu20.04` を `ubuntu-20.04` に変更しました - [CHANGE] `sora-2023.1.0-ubuntu22.04.tar.gz` から `sora-2023.1.0-ubuntu-22.04-x86_64.tar.gz` に変更しました- `ubuntu22.04` を `ubuntu-22.04` に変更しました - ファイル名に `-x86_64` を追加しました - [CHANGE] `sora-2023.1.0-ubuntu20.04.tar.gz` から `sora-2023.1.0-ubuntu-20.04-x86_64.tar.gz` に変更しました- `ubuntu20.04` を `ubuntu-20.04` に変更しました - ファイル名に `-x86_64` を追加しました - [CHANGE] `sora-2023.1.0-ubuntu20.04.tar.gz` から `sora-2023.1.0-ubuntu-20.04-x86_64.tar.gz` に変更しました- `ubuntu20.04` を `ubuntu-20.04` に変更しました - ファイル名に `-x86_64` を追加しました - [CHANGE] `sora-2023.1.0-rhel9.2.tar.gz` から `sora-2023.1.0-rhel-9.2-x86_64.tar.gz` に変更しました- `rhel9.2` を `rhel-9.2` に変更しました - ファイル名に `-x86_64` を追加しました - [CHANGE] `sora-2023.1.0-rhel8.8.tar.gz` から `sora-2023.1.0-rhel-8.8-x86_64.tar.gz` に変更しました- `rhel8.8` を `rhel-8.8` に変更しました - ファイル名に `-x86_64` を追加しました - [CHANGE] `sora-2023.1.0-centos7.9.tar.gz` から `sora-2023.1.0-centos-7.9-x86_64.tar.gz` に変更しました- `centos7.9` を `centos-7.9` に変更しました - ファイル名に `-x86_64` を追加しました #### セッション破棄 API - [ADD] 指定したセッションを終了させる [TerminateSession](API_SESSION.html#ba022b) API を追加しました- `channel_id` の指定は必須で、 `session_id` がオプションで指定できます #### ヘルスチェック - [ADD] `http://:5000/.ok` で Sora のヘルスチェックができるようになりました- 単体利用時には問題が無ければ常に 200 OK を返します - クラスター利用時には `block_new_connection` モード時には `503 Service Unavailable` を返します 詳細は [ヘルスチェック機能](OK.html) をご確認ください。 #### シグナリング通知 - [ADD] シグナリング通知の `"event_type": "connection.created"` に `timestamp` を追加しました- data にも `"data": [{"timestamp": "2023-06-28T10:00:00.999999", ...}, .. ]` のように `timestamp` が含まれるようになります - [ADD] シグナリング通知の `"event_type": "connection.created"` に `timestamp` を含める設定 [signaling_notify_connection_created_timestamp](SORA_CONF.html#7fe7b3) を `sora.conf` に追加しました- デフォルトは `true` です #### 映像コーデックパラメーター指定機能 - [ADD] ウェブフックに映像コーデックパラメーター `"video_vp9_params": {"profile_id": 0}` を追加しました- この設定を利用する場合 `legacy_webhook_audio_video_json_structure` が `false` である必要があります - [ADD] ウェブフックに映像コーデックパラメーター `"video_av1_params": {"profile": 0}` を追加しました- この設定を利用する場合 `sora_conf-legacy_webhook_audio_video_json_structure` が `false` である必要があります - [ADD] ウェブフックに映像コーデックパラメーター `"video_h264_params": {"profile_level_id": ""}` を追加しました- この設定を利用する場合 `sora_conf-legacy_webhook_audio_video_json_structure` が `false` である必要があります - [ADD] シグナリング接続時に H.264 のプロファイルレベル ID を `"video": {"codec_type": "H264", "h264_params": {"profile_level_id": "42e01f"}` のように指定できるようになりました- この指定を利用する場合は [signaling_h264_params](SORA_CONF.html#b32e49) が `true` である必要があります - `h264_params` を指定する場合は、 `codec_type` は `H264` である必要があります - [ADD] シグナリング接続時に VP9 のプロファイル ID を `"video": {"codec_type": "VP9", "vp9_params": {"profile_id": 0}}` のように指定できるようになりました- この指定を利用する場合は [signaling_vp9_params](SORA_CONF.html#3261ea) が `true` である必要があります - `vp9_params` を指定する場合は、 `codec_type` は `VP9` である必要があります - profile_id には 0 から 3 までの値を指定できます - [ADD] シグナリング接続時に AV1 のプロファイルを `"video": {"codec_type": "AV1", "av1_params": {"profile": 0}}` のように指定できるようになりました- この指定を利用する場合は [signaling_av1_params](SORA_CONF.html#91f3b8) が `true` である必要があります - `av1_params` を指定する場合は、 `codec_type` は `AV1` である必要があります - profile には 0 から 2 までの値を指定できます - [ADD] 認証成功時払い出しに VP9 のプロファイル ID を指定できる `"video_vp9_params": {"profile_id": 0}` を追加しました- この設定を利用する場合 `sora_conf-legacy_webhook_audio_video_json_structure` が `false` である必要があります - profile_id には 0 から 3 までの値を指定できます - [ADD] 認証成功時払い出しに AV1 のプロファイルを指定できる `"video_av1_params": {"profile": 0}` を追加しました- この設定を利用する場合 `sora_conf-legacy_webhook_audio_video_json_structure` が `false` である必要があります - profile には 0 から 2 までの値を指定できます - [ADD] 認証成功時払い出しに H.264 のプロファイルを指定できる `"video_h264_params": {"profile_level_id": "42e01f"}` を追加しました- この設定を利用する場合 `sora_conf-legacy_webhook_audio_video_json_structure` が `false` である必要があります - `h264_profile_level_id` は 2024 年 6 月リリース予定の Sora にて廃止します - [ADD] `sora.conf` に VP9 のプロファイル ID のデフォルト値を指定する [default_vp9_param_profile_id](SORA_CONF.html#ab0de9) を追加しました- デフォルトは 0 が設定されています - 0 から 3 までの値を指定できます - [ADD] `sora.conf` に AV1 のプロファイルのデフォルト値を指定する [default_av1_param_profile](SORA_CONF.html#319e30) を追加しました- デフォルトは 0 が設定されています - 0 から 2 までの値を指定できます - [ADD] `sora.conf` に H.264 のプロファイルレベル ID のデフォルト値を指定する [default_h264_param_profile_level_id](SORA_CONF.html#1581db) を追加しました- 既存の default_h264_profile_level_id は 2024 年 6 月リリース予定の Sora にて廃止します #### OBS (WHIP) 対応 OBS が対応予定の WebRTC (WHIP) で配信ができるようになりました。 - [ADD] `sora.conf` に OBS (WHIP) を有効にする [whip](SORA_CONF.html#615414) を追加しました- デフォルトは `false` です - [ADD] `sora.conf` に OBS (WHIP) の Bearer トークンを認証ウェブフックの `metadata` に対応させるキーを指定する [whip_bearer_token_metadata_key](SORA_CONF.html#699f57) を追加しました- OBS (WHIP) からの接続についても Bearer トークンを利用した認証機能が利用できます - デフォルトは未指定です - [ADD] WHIP 向けエンドポイント URL `https://example.com/whip/` を追加しました- クエリー文字列で `client_id` と `bundle_id` を指定できるようになりました - [ADD] WHIP 向けリソース URL `https://example.com/whip-resource//` を追加しました- PATCH と DELETE メソッドに対応しています - [ADD] WHIP を利用した際、認証ウェブフックに `whip: true` を追加しました- WHIP を利用していない接続の場合はこの項目は含まれません 詳細は [OBS (WHIP) 対応機能](WHIP.html) をご確認ください。 #### VP9 / AV1 サイマルキャスト対応 - [UPDATE] VP9 と AV1 でのサイマルキャスト機能に対応しました- Chrome 113 以降でスポットライト機能にて VP9 と AV1 が利用できるようになりました - Edge 113 以降でスポットライト機能にて VP9 が利用できるようになりました - [UPDATE] 認証成功時の払い出し `simulcast_encodings` と `spotlight_encodings` で `scalabilityMode` を指定できるようになりました- デフォルトでは `scalabilityMode` に `L1T3` が設定されています - [UPDATE] [simulcast_encodings_file](SORA_CONF.html#dead73) と [spotlight_encodings_file](SORA_CONF.html#6115fb) で `scalabilityMode` を指定できるようになりました 詳細は [scalabilityMode](SIMULCAST.html#918c4d) をご確認ください。 #### Lyra 録音機能 - [ADD] 録画機能に Lyra コーデックを利用した際に WebM ファイルで録音する仕組みを追加しました 詳細は recording-lyra をご確認ください。 #### 転送フィルター機能 今まで [PauseRtpStream](OBSOLETE_API_RTP_STREAM_PAUSE_RESUME.html#de7a52) / [ResumeRtpStream](OBSOLETE_API_RTP_STREAM_PAUSE_RESUME.html#43002a) API で実現していたメディアストリームの停止/再開をより細かく、柔軟に設定をできるようにした、 転送フィルター機能を追加しました。 - [ADD] セッション生成時 `forwarding_filter` を指定することでチャネル単位の転送フィルターを追加できるようになりました - [ADD] シグナリング接続時に `forwarding_filter` を指定することで接続単位の転送フィルターを追加できるようになりました - [ADD] 認証成功時に `forwarding_filter` を指定することで接続単位の転送フィルターを追加できるようになりました - [ADD] チャネル単位でチャネルとコネクションの転送フィルターを確認できる [ListForwardingFilters](API_FORWARDING_FILTER.html#a1dd75) API を追加しました - [ADD] チャネル単位の転送フィルターを作成する [CreateChannelForwardingFilter](API_FORWARDING_FILTER.html#fe98d1) API を追加しました - [ADD] チャネル単位の転送フィルターを更新する [UpdateChannelForwardingFilter](API_FORWARDING_FILTER.html#36fc45) API を追加しました - [ADD] チャネル単位の転送フィルターを削除する [DeleteChannelForwardingFilter](API_FORWARDING_FILTER.html#9410fd) API を追加しました - [ADD] コネクション単位の転送フィルターを作成する [CreateConnectionForwardingFilter](API_FORWARDING_FILTER.html#d80a51) API を追加しました - [ADD] コネクション単位の転送フィルターを更新する [UpdateConnectionForwardingFilter](API_FORWARDING_FILTER.html#23ed63) API を追加しました - [ADD] コネクション単位の転送フィルターを削除する [DeleteConnectionForwardingFilter](API_FORWARDING_FILTER.html#0d65da) API を追加しました - [ADD] 転送フィルターで転送がブロックされたタイミングでシグナリング通知する機能を追加しました - [ADD] 転送フィルターで転送がブロックが解除されたタイミングでシグナリング通知する機能を追加しました - [ADD] `sora.conf` に転送フィルターをシグナリング経由で指定できるかどうかを設定する `signaling_forwarding_filter` を追加しました- デフォルト は `false` です - [ADD] `sora.conf` に転送フィルターのブロックの状態が変わったタイミングでシグナリング通知を飛ばすかどうかを設定する [signaling_notify_forwarding_filter](SORA_CONF.html#338e96) を追加しました- デフォルト は `true` です 詳細は [転送フィルター機能](FORWARDING_FILTER.html) をご確認ください。 #### SDP 再利用機能 今までマルチストリーム利用した際に、クライアント切断してもその SDP が残ってしまう問題がありました。 今回のリリースで、SDP を再利用する仕組みにより SDP が残る問題を解決しました。 - [CHANGE] `recycle_media_section` が `true` の際に、SDP を再利用する仕組みを追加しました - [ADD] `sora.conf` に SDP の再利用を行う [recycle_media_section](SORA_CONF.html#d3e2b5) 設定を追加しました- デフォルトは `true` です #### 音声ストリーミング機能 - [ADD] 音声ストリーミングの結果通知の状態を確認する [ListAudioStreamingResultPushState](API_AUDIO_STREAMING.html#70450f) API を追加しました - [ADD] 音声ストリーミング機能にサブスクライブが 0 になると音声ストリーミングを停止し、サブスクライブが 1 以上になると音声ストリーミングを開始する機能を追加しました- この機能はセッション生成時に指定できます - この機能が有効になっている場合は音声ストリーミング開始/終了 API は利用できません - [ADD] セッションウェブフックの払い出しに音声ストリーミングの自動開始と停止を有効にする `audio_streaming_auto` を追加しました- この設定を利用する場合は必ず `audio_streaming` を `true` で払い出す必要があります - [ADD] `sora.conf` に音声ストリーミングのウェブフックを送信するかどうかを設定する [ignore_audio_streaming_webhook](SORA_CONF.html#8f086b) を追加しました- デフォルトは `true` で、送信しません - [ADD] 音声ストリーミング機能の開始のウェブフック `audio-streaming.started` を追加しました- `sora.conf` にて [ignore_audio_streaming_webhook](SORA_CONF.html#8f086b) を `false` にすることで送信します - [ADD] 音声ストリーミング機能の終了のウェブフック `audio-streaming.stopped` を追加しました- `sora.conf` にて [ignore_audio_streaming_webhook](SORA_CONF.html#8f086b) を `false` にすることで送信します #### WebSocket 経由シグナリングでの ping / pong / stats のインターバルやタイムアウトの設定 WebSocket 経由でのシグナリングにおいて、 `"type": "ping"` や `"type": "pong"` のインターバルやタイムアウトを設定できるようになりました。 また `"type": "ping"` 送信時の `"stats": true` にする間隔を指定できるようになりました。 - [CHANGE] `"type": "ping"` 時におくる `"stats": true` の間隔を 5 秒から 30 秒に変更しました - [ADD] `sora.conf` に ping を送信する間隔を指定する [websocket_signaling_ping_interval](SORA_CONF.html#27aae2) 設定を追加しました- デフォルトは `5 s` です - 最小は `5 s` です - 最大は `300 s` です - [ADD] `sora.conf` に pong のタイムアウト時間を指定する [websocket_signaling_pong_timeout](SORA_CONF.html#140464) 設定を追加しました- デフォルトは `60 s` です - 最小は `60 s` です - 最大は `600 s` です - [ADD] `sora.conf` に ping 送信時に `"stats": true` にする間隔を指定する [websocket_stats_timer_interval](SORA_CONF.html#67a631) 設定を追加しました- デフォルトは `30 s` です - 最小は `30 s` です - 最大は `600 s` です #### クラスター機能利用時のディスク障害時の対応を追加 - [CHANGE] クラスター利用時に `block_new_connection` モードへ遷移した場合には新規接続のリダイレクトを行わないように変更しました - [ADD] クラスター利用時にディスク障害が発生した際に、 `block_new_connection` モードへ遷移する機能を追加しました ## 2022.2.3 **リリース**: 2023-02-08 ### 変更履歴 - [FIX] 依存している OpenSSL を 3.0.8 にアップデートしました - [FIX] 2023 年 4 月 4 日リリース予定の Chrome 112 でシグナリング時に接続が必ず失敗してしまう問題を修正しました - [FIX] ディスク障害が発生してログの書き込みに失敗した際に、障害が復旧した後でもログが書き込めなくなることがある問題を修正しました ## 2022.1.4 **リリース**: 2023-02-08 ### 変更履歴 - [FIX] 2023 年 4 月 4 日リリース予定の Chrome 112 でシグナリング時に接続が必ず失敗してしまう問題を修正しました ## 2022.2.2 **リリース**: 2023-01-05 ### 変更履歴 - [FIX] 音声ストリーミング機能で `sora.conf` の [default_audio_streaming_result_push](SORA_CONF.html#0b4a07) が `true` の際、プッシュ通知が行われない問題を修正しました - [FIX] 音声ストリーミング機能でロールが `recvonly` の場合にプッシュ通知が受信できない問題を修正しました - [FIX] 音声ストリーミング機能で API を利用して音声ストリーミングを開始した際、通知が正常に行われない問題を修正しました ## 2022.2.1 **リリース**: 2022-12-21 ### 変更履歴 - [FIX] 開発ツールが Safari / Mobile Safari / Firefox で動作しない問題を修正しました ## 2022.2.0 **リリース**: 2022-12-21 ### ハイライト - sora ログと internal ログを JSONL 形式で出力するようになりました - Google が公開した超低ビットレートコーデック Lyra に対応しました - 音声パケットを HTTP/2 経由で出力する音声ストリーミング機能を追加しました - 録画開始ととアーカイブ開始のウェブフックを追加しました - ウェブフックが mTLS と CA 証明書の指定に対応しました ### 互換なしの変更情報 - 実験的機能であるセッションウェブフックのログ出力を req/res 形式に変更しました - 実験的機能であるセンシティブデータ向け設定 `redact_archive_metadata_sensitive_data` と `redact_api_sensitive_data` を廃止しました- 録画メタデータファイルと API はセンシティブなデータがあっても編集を行わないようにしました - クラスター機能の仕組みを変更したため互換性がなくなりました、クラスターの再構築をお願いします ### 変更履歴 - [FIX] DTLS 処理終了時に起きていた問題を修正しました - [FIX] 録画ウェブフックの `expired_at` が秒単位の UNIX Time ではなくマイクロ秒になっていたのを修正しました - [FIX] 録画ウェブフックの `split-archive.available` と `split-archive-*.json` に offset が含まれていなかったのを修正しました - [FIX] ULPFEC が有効でな状態でパケロス発生時に録画に失敗することがある問題を修正しました - [FIX] 録画機能のウェブフックやファイルに含まれる統計値の名前 total_audio_discarded が間違っていたのを修正しました #### JSONL 形式でのログ出力 - [ADD] `sora.conf` にログフォーマットのレガシー形式を維持する `legacy_log_format` を追加しました- デフォルトは `true` です - これは移行用設定です - [ADD] `sora.conf` に JSONL 形式で出力しているログのレガシー拡張子を `.log` に維持する `legacy_log_extension` を追加しました- デフォルトは `true` です - これは移行用設定です - [ADD] `sora.conf` の `legacy_log_format` を `false` にすることで以下のログは JSONL 形式で出力されます- sora ログ - internal ログ - signaling ログ - api ログ - auth_webhook ログ - session_webhook ログ - session_webhook_error ログ - event_webhook ログ - event_webhook_error ログ - connection ログ - [ADD] `sora.conf` の `legacy_log_extension` を `false` にすることでJSONL 形式で出力されているログファイルの拡張子が `.log` から `.jsonl` に変更されます- `sora.log` が `sora.jsonl` に変更されます - `internal.log` が `internal.jsonl` に変更されます - `signaling.log` が `signaling.jsonl` に変更されます - `api.log` が `api.jsonl` に変更されます - `auth_webhook.log` が `auth_webhook.jsonl` に変更されます - `session_webhook.log` が `session_webhook.jsonl` に変更されます - `session_webhook_error.log` が `session_webhook_error.jsonl` に変更されます - `event_webhook.log` が `event_webhook.jsonl` に変更されます - `event_webhook_error.log` が `event_webhook_error.jsonl` に変更されます - `connection.log` が `connection.jsonl` に変更されます - [CHANGE] サポート用ログファイルである `connection_created_wait_timeout_error/_.json`の拡張子を `.json` から `.jsonl` に変更しました #### クラスター機能 - [CHANGE] クラスターの仕組みを変更したため、2022.1 系までのクラスターの仕組みとは互換性がありません- クラスターの初期化が必要になります - [ADD] クラスター初期化に利用する [InitCluster](API_CLUSTER.html#621990) API を追加しました - [CHANGE] クラスター機能の [ListClusterNodes](API_CLUSTER.html#a70901) API の `member_since` を廃止しました - [CHANGE] クラスター機能の [ListClusterChannels](API_CLUSTER.html#0a4459) API の戻り値を変更しました- `owners` を追加し、その下にリストで `node_name` `epoch` `epoch_latest` `connected` を持つようにしました - `node_in_charge` を `node_name` に変更しました - `node_in_charge_epoch` を `epoch` に変更しました - `node_in_charge_epoch_stale` を `epoch_latest` に変更しました - `node_in_charge_connected` を `connected` に変更しました #### Lyra コーデックへの対応 **これは実験的機能です** - [ADD] `sora.conf` に Google が公開した音声圧縮用超低ビットレートコーデック[Lyra](https://github.com/google/lyra) を有効にする設定 `lyra` を追加しました- デフォルトは `false` です - `lyra = true` のように設定してください - [ADD] シグナリング接続時の音声コーデックタイプに Lyra を指定できるようになりました- 指定する際は大文字の `LYRA` で指定する必要があります - Lyra を利用する際は lyra_params を指定する必要があります- `lyra_params` には lyra のバージョンを指定する `version` とビットレートを指定する `bit_rate` が指定できます - `{"audio": "codec_type": "LYRA", "lyra_params": {"version": "1.3.0", "bit_rate": 9200}}` - [ADD] 認証成功時に `{"audio": true, "audio_codec_type": "LYRA", "audio_lyra_params": {"version": "1.3.0", "bitrate": 9200}` のように指定できるようになりました- この指定を利用する場合は `sora_conf-legacy_webhook_audio_video_json_structure` を `false` にする必要があります #### 音声ストリーミング機能 **これは実験的機能です** - [ADD] `sora.conf` に音声ストリーミングのリクエスト先の URL を指定する [audio_streaming_url](SORA_CONF.html#6b5dd6) を追加しました - [ADD] `sora.conf` に音声ストリーミングで利用するデフォルトのランゲージコードを指定する [default_audio_streaming_language_code](SORA_CONF.html#856531) を追加しました - [ADD] `sora.conf` に音声ストリーミングでデフォルトで結果をプッシュ通知で行うかどうかを指定する [default_audio_streaming_result_push](SORA_CONF.html#0b4a07) を追加しました - [ADD] `sora.conf` に音声ストリーミングで mTLS を利用する秘密鍵を指定する [audio_streaming_tls_privkey_file](SORA_CONF.html#5f8e61) を追加しました - [ADD] `sora.conf` に音声ストリーミングで mTLS を利用する証明書を指定する [audio_streaming_tls_fullchain_file](SORA_CONF.html#e5459b) を追加しました - [ADD] `sora.conf` に音声ストリーミングで利用する CA ルート証明書を指定する [audio_streaming_tls_verify_cacert_file](SORA_CONF.html#feef99) を追加しました - [ADD] 音声ストリーミングを開始する [StartAudioStreaming](API_AUDIO_STREAMING.html#0f1087) API を追加しました - [ADD] 音声ストリーミングを終了する [StopAudioStreaming](API_AUDIO_STREAMING.html#bad1bb) API を追加しました - [ADD] 音声ストリーミングの解析結果を購読する [SubscribeAudioStreamingResultPush](API_AUDIO_STREAMING.html#d26262) API を追加しました - [ADD] 音声ストリーミングの解析結果を購読解除する [UnsubscribeAudioStreamingResultPush](API_AUDIO_STREAMING.html#b63656) API を追加しました 詳細は [音声ストリーミング機能](AUDIO_STREAMING.html) をご確認ください。 #### 音声冗長化機能 - [CHANGE] `sora.conf` の `audio_red` のデフォルト値を `false` に変更しました #### センシティブデータ - [ADD] `sora.conf` にセンシティブなデータが含まれる可能性がある項目を `"REDACTED"` という文字列への書き換えをスキップする [skip_redact_sensitive_data](SORA_CONF.html#00d209) を追加しました- デフォルトでは `false` です - [CHANGE] `sora.conf` の `redact_archive_metadata_sensitive_data` を廃止しました- 録画メタデータファイルの `event_metadata` はセンシティブなデータの書き換え対象外としました - [CHANGE] `sora.conf` の `redact_api_sensitive_data` を廃止しました- API の `event_metadata` はセンシティブなデータの書き換え対象外としました 詳細は [センシティブデータ](SENSITIVE_DATA.html) をご確認ください。 #### ウェブフックの audio と video 項目の JSON 構造のフラット化 - [ADD] `sora.conf` にウェブフックの audio と video 項目のレガシーな JSON 構造する `sora_conf-legacy_webhook_audio_video_json_structure` を追加しました- デフォルトでは `true` です - これは移行用設定です 詳細は `ウェブフックの audio と video 項目の JSON 構造のフラット化` をご確認ください #### セッションウェブフックログを req/res 形式に変更 - [CHANGE] `session_webhook.jsonl` の出力形式を req/res 形式に変更しました - [CHANGE] `session_webhook_error.jsonl` の出力形式を req 形式に変更しました #### 録画とアーカイブ開始ウェブフックを追加 - [ADD] 録画開始ウェブフック `recording.started` を追加しました - [ADD] アーカイブ開始ウェブフック [archive.started](EVENT_WEBHOOK.html#462c97) を追加しました - [ADD] `sora.conf` に [ignore_recording_started_webhook](SORA_CONF.html#d9e570) を追加しました- デフォルトでは `false` です - [ADD] `sora.conf` に [ignore_archive_started_webhook](SORA_CONF.html#3fddc0) を追加しました- デフォルトでは `false` です #### ウェブフック mTLS / CA 証明書指定対応 - [ADD] `sora.conf` にウェブフックのリクエスト先との通信で mTLS を利用する際の証明書を指定する [webhook_tls_fullchain_file](SORA_CONF.html#93f2b9) を追加しました - [ADD] `sora.conf` にウェブフックのリクエスト先との通信で mTLS を理世する際の秘密鍵を指定する [webhook_tls_privkey_file](SORA_CONF.html#7065d6) を追加しました - [ADD] `sora.conf` にウェブフックのリクエスト先の証明書をベリファイするルート CA を指定する [webhook_tls_verify_cacert_file](SORA_CONF.html#7036dc) を追加しました #### ウェブフック統計情報 - [ADD] ウェブフック関連の統計情報を GetStatsReport API に追加しました- `total_auth_webhook_allowed`- 認証ウェブフックで許可された数 - `total_auth_webhook_denied`- 認証ウェブフックで拒否された数 - `total_successful_auth_webhook`- 認証ウェブフックが成功した数 - `total_failed_auth_webhook`- 認証ウェブフックが失敗した数 - `total_successful_session_webhook`- セッションウェブフックが成功した数 - `total_failed_session_webhook`- セッションウェブフックが失敗した数 - `total_successful_event_webhook`- イベントウェブフックが成功した数 - `total_failed_event_webhook`- イベントウェブフックが失敗した数 #### クラッシュログ出力 API **これは実験的機能です** - [ADD] 意図的に crash.log を出力させる `20221221.GenerateCrashLog` API を追加しました- **この API はログ出力の動作確認にのみ利用してください** - この API はかならずステータスコード 500 を返します ## 2022.1.3 **リリース**: 2022-11-02 ### 変更履歴 - [FIX] 依存している OpenSSL を 3.0.7 にアップデートしました - [FIX] データチャネルの性能ボトルネックを修正しました - [FIX] データチャネル利用時に高負荷になった状態が継続する問題を修正しました - [FIX] データチャネル利用時に意図しないメッセージを受信した際の問題を修正しました - [FIX] データチャネル利用時に意図しないエラーが発生する問題を修正しました - [FIX] データチャネル利用時に `compress` が `true` になっている Label のメッセージが壊れている場合の問題を修正しました ## 2022.1.1 **リリース**: 2022-07-12 ### 変更履歴 - [FIX] 依存している OpenSSL を 3.0.5 にアップデートしました - [FIX] 録画機能の `{"type": "split-archive-end"}` ウェブフックには解像度を含めないように修正しました - [FIX] 録画機能の `split-archive-end-.json` ファイルには解像度を含めないように修正しました - [FIX] `sora.log` にでるべきログの一部が `internal.log` に出力されていた問題を修正しました - [FIX] クラスターのノードが異常な状態になったタイミングで `emergency` ログを出力して終了するように修正しました - [FIX] sora.conf の `default_multistream` が true の時に、 `"type": "connect"` メッセージの `role` に `sendrecv` を指定し、かつ `multistream` を `指定しない` 場合に、エラーとなり接続できない問題を修正しました ## 2022.1.0 **リリース**: 2022-06-29 ### ハイライト - Ubuntu 22.04 に対応しました - RHEL 9 に対応しました - サイマルキャスト機能が正式版になりました - スポットライト機能が正式版になりました - スポットライト機能がサイマルキャスト無効でも利用できるようになりました - サイマルキャスト機能やスポットライト機能利用時に、視聴されていないストリームは復号処理を行わない仕組みを追加しました - 録画機能で、録画ファイル分割出力機能を有効にした場合にも recording.report ウェブフック通知とレポートファイルが作成されるようになりました - クラスター利用時に、同一ライセンスを利用できる「最大ノード数ライセンス」の提供を開始しました - クラスター機能で録画状態を共有する機能を追加しました - クラスター機能でクラスター参加を自動で行う仕組みを追加しました - クラスター機能でネットワーク障害発生時に自動で復旧を試みる仕組みを追加しました - 特定の接続からのストリームを受信しないようにできる `bundle_id` を追加しました - センシティブなデータが含まれる可能性がある `session_metadata` や `event_metadata` の値を `"REDACTED"` という文字列に書き換える仕組みを追加しました ### 廃止情報 - `sora.conf` の `demo` を廃止しました - `sora.conf` の `remote_stats` を廃止しました - `sora.conf` の `unuse_metadata_list` を廃止しました - `sora.conf` の `use_re_offer` を廃止しました - `GetAllRemoteStats` API を廃止しました - `GetChannelRemoteStats` API を廃止しました - `GetConnectionRemoteStats` API を廃止しました - `StopRecording` API の `redirect` を廃止しました ### 互換なしの変更情報 - マルチストリームをデフォルトで有効にしました- `sora.conf` の `default_multistream` を `false` にすることでマルチストリームがデフォルトではなくなります - この設定は 2023 年 6 月リリースの Sora にて廃止します - 詳細は [sora.conf の default_multistream の廃止](OBSOLETE.html#615559) をご確認ください - `type: archive.end` を `type: split-archive.end` に変更しました- `sora.conf` の `split_archive_legacy_prefix` を `true` にすることで `type: archive.end` がそのまま利用できます - この設定は 2023 年 6 月リリースの Sora にて廃止します - 詳細は [sora.conf の split_archive_legacy_prefix の廃止](OBSOLETE.html#050276) をご確認ください - `type: archive.split` を `type: split-archive.available` に変更しました- `sora.conf` の `split_archive_legacy_prefix` を `true` にすることで `type: archive.split` がそのまま利用できます - この設定は 2023 年 6 月リリースの Sora にて廃止します - 詳細は [sora.conf の split_archive_legacy_prefix の廃止](OBSOLETE.html#050276) をご確認ください - `archive-_.webm` を `split-archive-_.webm` に変更しました- `sora.conf` の `split_archive_legacy_prefix` を `true` にすることで `archive-_.webm` がそのまま利用できます - この設定は 2023 年 6 月リリースの Sora にて廃止します - 詳細は [sora.conf の split_archive_legacy_prefix の廃止](OBSOLETE.html#050276) をご確認ください - `archive-_.json` を `split-archive-_.json` に変更しました- `sora.conf` の `split_archive_legacy_prefix` を `true` にすることで `archive-_.json` がそのまま利用できます - この設定は 2023 年 6 月リリースの Sora にて廃止します - 詳細は [sora.conf の split_archive_legacy_prefix の廃止](OBSOLETE.html#050276) をご確認ください - セッションウェブフックでセッションの接続数が 0 のタイミングで `multistream` と `spotlight` がセッションと異なる新規接続が来た場合は既存のセッションを破棄し `session.destroyed` ウェブフックリクエストを送信した後に、新規でセッションを作成し `session.created` を送信するように変更しました - セッションウェブフックでセッションの接続数が 0 ではないタイミングで `multistream` と `spotlight` がセッションと異なる新規接続が来た場合は `INVALID-SIGNALING-PARAMS` エラーを返し切断するように変更しました - セッションウェブフック `session.created` と `session.destroyed` の `created_time` と `destroyed_time` を UNIX 時間に変更しました - `sora.log` と `internal.log` の時刻を RFC3339 準拠に変更しました - `cluster` 関連設定名を変更しました- `cluster_node_name` を `node_name` へ変更しました - `cluster_api_url` を `external_api_url` へ変更しました - `cluster_signaling_url` を `external_signaling_url` へ変更しました - `sora_version` を `version` に変更しました - `cluster` 関連 API の引数や戻り値を変更しました - クラスター機能を有効にしたときのモードを `initial` へ変更しました - クラスターに参加したときに自動でモードが `initial` から `normal` へ切り替わるよう変更しました ### 変更履歴 - [CHANGE] セッションウェブフック `session.created` の `created_time` を UNIX 時間に変更しました - [CHANGE] セッションウェブフック `session.destroyed` の `created_time` を UNIX 時間に変更しました - [CHANGE] セッションウェブフック `session.destroyed` の `destroyed_time` を UNIX 時間に変更しました - [UPDATE] 組み込みの開発ツールを `2022.1.0` にアップデートしました - [ADD] RHEL 9 x86_64 に対応しました - [ADD] Ubuntu 22.04 x86_64 に対応しました - [ADD] イベントウェブフック `connection.created` に RFC3339 形式で出力する `created_timestamp` を追加しました - [ADD] イベントウェブフック `connection.updated` に RFC3339 形式で出力する `created_timestamp` を追加しました - [ADD] イベントウェブフック `connection.destroyed` に RFC3339 形式で出力する `created_timestamp` を追加しました - [ADD] イベントウェブフック `connection.destroyed` に RFC3339 形式で出力する `destroyed_timestamp` を追加しました - [ADD] イベントウェブフック `connection.destroyed` に UNIX 時間で出力する `destroyed_time` を追加しました - [ADD] [GetStatsReport](EXPERIMENTAL_API_STATS.html#bbbfca) API に Sora のバージョンを取得できる `version` を追加しました - [ADD] 認証成功時の H.265 の払い出しを追加しました - [ADD] 認証ウェブフックに `simulcast_rid` を追加しました - [ADD] Sora 内部で利用するファイルを書き出す `data` ディレクトリを追加しました - [ADD] `sora.conf` に Sora 内部で利用するファイルを書き出す `data` ディレクトリを指定する `data_dir` を追加しました - [FIX] Opus の RED の仕様変更ともない動作しなくなっていた問題を修正しました - [FIX] 0 番ポートでパケットが送られてきた場合の問題を修正しました - [FIX] DTLS で異常なパケットが送られてきた場合でも可能な限り丁寧に終了処理を行うように修正しました - [FIX] 異常な STUN パケットが送られてきた場合の問題を修正しました - [FIX] 録画した WebM ファイルの `Cluster Timecode` が負の値になると発生する問題を修正しました #### マルチストリームをデフォルトで有効化 マルチストリームをデフォルトで有効にしました。 いままでマルチストリームを利用する場合は、シグナリング接続時に `"multistream": true` を指定して有効にする必要がありました。これをデフォルトで有効に変更しました。 今後は、マルチストリームを利用しない場合は明示的に `"multistream": false` を指定する必要があります。 - [CHANGE] マルチストリームをデフォルトで有効に変更しました - [ADD] `sora.conf` にマルチストリームのデフォルト値を指定する `default_multistream` を追加しました- デフォルトでは `true` が設定されています - この設定は 2023 年 6 月リリース予定の Sora にて廃止します - 詳細は [sora.conf の default_multistream の廃止](OBSOLETE.html#615559) をご確認ください 例外的にスポットライト機能を利用するときは `"multistream": true` を明示する必要があります。 #### bundle_id の追加 複数のコネクションを同じ端末から接続する際、それぞれのコネクションで同一の `bundle_id` を指定すると、 同一の `bundle_id` を指定した接続からの音声や映像、メッセージングを受信しなくなります。 画面共有の映像を受信したくない場合などにお使いください。 - [ADD] `sora.conf` に `"type": "connect"` 時に `bundle_id` を指定できるかどうかを設定する [signaling_bundle_id](SORA_CONF.html#279311) を追加しました- デフォルトでは `false` が設定されています - [ADD] `sora.conf` に [signaling_notify_bundle_id](SORA_CONF.html#f2a58f) を追加しました- デフォルトでは `true` が設定されています - [ADD] `"type": "connect"` で `bundle_id` が指定できるようになりました- 詳細は [bundle_id の指定](WEBSOCKET_SIGNALING.html#196326) をご確認ください - [ADD] 認証成功時の払い出しで `bundle_id` を指定できるようになりました- 詳細は [bundle_id の払い出し](AUTH_WEBHOOK_RETURN.html#d2b87b) をご確認ください #### sora.log と internal.log の出力 - [CHANGE] タイムスタンプの出力を RFC3339 準拠に変更しました- Sora 2021.2.7 まで- `2022-03-07 02:54:26.847 UTC [info] [-/-/-] <0.1218.0> SORA | node_name=sora@192.0.2.1, version=2021.2.7` - Sora 2022.1.0 から- `2022-03-07T02:54:26.847130Z [info] [-/-/-] <0.1218.0> SORA | node_name=sora@192.0.2.1, version=2022.1.0` #### 録画機能 - [CHANGE] 分割録画ファイルとメタデータファイルの出力名を `archive-_.(json|webm)` から `split-archive-_.(json|webm)` に変更しました- `sora.conf` の `split_archive_legacy_prefix` を `true` にすることで `archive-_.(json|webm)` を維持できます - [CHANGE] 録画分割時のウェブフックのタイプ `"type": "archive.split"` を `"type": "split-archive.available"` に変更しました - [CHANGE] 録画分割時のウェブフックのタイプ `"type": "split.end"` を `"type": "split-archive.end"` に変更しました - [CHANGE] 録画一時ファイルディレクトリ `archive_tmp_dir` に保存される録画一時ファイルは、録画が失敗した場合には削除されなくなりました - [ADD] `report-.json` に `node_name` と `label` 項目を追加しました - [ADD] `sora.conf` に分割録画ファイル名を `archive-_.(json|webm)` にする `split_archive_legacy_prefix` を追加しました- デフォルトは `false` です - この設定は 2023 年 6 月リリース予定の Sora にて廃止します - 詳細は [sora.conf の split_archive_legacy_prefix の廃止](OBSOLETE.html#050276) をご確認ください - [ADD] 録画の状態をクラスターで共有する仕組みを追加しました - [ADD] `split_only` に `true` を指定した場合に、 `archive.end` ウェブフックと対になる `split-archive-end-.json` ファイルを作成するようになりました - [ADD] `split_only` に `true` を指定した場合でも `recording.report` ウェブフックリクエストを飛ばすようになりました - [ADD] `split_only` に `true` を指定した場合でも `report-.json` ファイルを作成するようになりました - [ADD] 録画メタデータファイルとレポートファイルに `label` と `node_name` を追加するようにしました - [UPDATE] 録画で生成された WebM ファイルが Windows の `Windows標準アプリケーションの"映画&テレビ"` で正常に再生できない問題へ対応しました- Sora 側の問題ではなく `Windows標準アプリケーションの"映画&テレビ"` が WebM の仕様を守っていないことによる問題です #### サイマルキャストやスポットライト機能利用時の負荷削減 - [ADD] サイマルキャストやスポットライト利用時に誰も視聴していない音声や映像ストリームの復号を行わない処理を追加しました - [ADD] 統計 API の rtp 項目に `tocal_decrypt_skipped_audio_srtp` を追加しました - [ADD] 統計 API の rtp 項目に `tocal_decrypt_skipped_video_srtp` を追加しました - [ADD] 統計 API の simulcast.rtp.(r0|r1|r2) 項目に `total_decrypt_skipped_srtp` を追加しました #### サイマルキャスト無効でのスポットライト機能利用 - [ADD] スポットライト機能が `"simulcast": false` でも利用できるようになりました #### クラスター機能 - [CHANGE] クラスター有効時に起動した際のモードを `initial` モードに変更しました - [CHANGE] クラスターに参加したタイミングで自動で `initial` モードから `normal` モードに切り替わるように変更しました - [CHANGE] `sora.conf` の `cluster_node_name` を `node_name` に変更しました - [CHANGE] `sora.conf` の `cluster_signaling_url` を `external_signaling_url` に変更しました - [CHANGE] `sora.conf` の `cluster_api_url` を `external_api_url` に変更しました - [CHANGE] クラスター有効時に sora.log / internal.log にクラスターノード名を出力するように変更しました - [CHANGE] [JoinCluster](OBSOLETE_API.html#17f3f5) API の `cluster_node_name` を `contact_node_name` に変更しました - [CHANGE] [ListClusterNodes](API_CLUSTER.html#a70901) API の `cluster_node_name` を `node_name` に変更しました - [ADD] クラスターから特定のノードの情報を完全消去する [PurgeClusterNode](API_CLUSTER.html#13b35a) API を追加しました - [ADD] `sora.conf` に Sora 起動時に自動でクラスター参加を試みる `contact_node_name_list` を追加しました- 詳細は `contact_node_name_list` をご確認ください - [ADD] `sora.conf` にネットワーク障害等発生時に自動で再接続を試みる `cluster_auto_reconnect` を追加しました- デフォルトは有効です - [ADD] ネットワーク障害等発生時に自動で復旧を試みる仕組みを追加しました #### 最大ノード数対応ライセンス クラスター利用時に、複数のノードに同一のライセンスが利用できる最大ノードライセンスの提供を開始しました。 詳細は [最大ノード数ライセンス](LICENSE.html#aee259) をご確認ください。 - [CHANGE] 最大ノード数ライセンスに対応していないライセンスを複数のノードに適用し、クラスターを構築しようとすると `DUPLICATE-LICENSE` が出力されるように変更されました- 無制限ライセンスをご利用のお客様でクラスターを利用されている場合はサポートまでご連絡ください - [ADD] クラスター利用時に同一のライセンスを利用できる最大ノード数ライセンスに対応しました- **新規でライセンスを発行し直す必要がありますのでサポートまでご連絡ください** - 新しくライセンスに `max_nodes` という項目を追加し、この最大ノード数までは複数の Sora で同一のライセンスを利用できるようになります #### 統計機能 - [ADD] 統計 API の rtp 項目に `total_received_srtp_invalid` を追加しました - [ADD] 統計 API の turn 項目に `total_received_unknown_packet` を追加しました - [ADD] 統計 API の turn 項目に `total_received_stun_unknown` を追加しました - [ADD] 統計 API の turn 項目に `total_received_stun_invalid` を追加しました - [ADD] 統計 API の turn 項目に `total_received_turn_invalid_stun` を追加しました - [ADD] データチャネルの破棄やリトライの回数をラベルごとに取得できるようになりました- データチャネルの破棄メッセージ数 `total_data_channel_abandon_message` を追加しました - データチャネルの再送メッセージ数 `total_data_channel_retransmit_message` を追加しました - データチャネルの `DATA_CHANNEL_OPEN` メッセージ数 `total_data_channel_ack_message` を追加しました - データチャネルの `DATA_CHANNEL_ACK` メッセージ数 `total_data_channel_open_message` を追加しました - [UPDATE] `total_sent_data_channel_message` から `DATA_CHANNEL_OPEN` メッセージを除外しました - [UPDATE] `total_received_data_channel_message` から `DATA_CHANNEL_ACK` メッセージを除外しました #### センシティブデータ編集済出力機能 詳細は [センシティブデータ](SENSITIVE_DATA.html) をご確認ください。 - [CHANGE] `auth_webhook.log` に含まれる `event_metadata` の中身を編集済みを表す `"REDACTED"` という文字列に書き換える変更を行いました - [CHANGE] `session_webhook.log` に含まれる `session_metadata` と `event_metadata` の中身を編集済みを表す `"REDACTED"` という文字列にに書き換える変更を行いました - [CHANGE] `event_webhook.log` に含まれる `event_metadata` の中身を、編集済みを表す `"REDACTED"` という文字列に書き換える変更を行いました- `event_webhook_error.log` の `event_metadata` は書き換えを行いません - [ADD] `sora.conf` にAPI 戻り値に含まれるセンシティブな可能性があるデータを、編集済みを表す `"REDACTED"` という文字列に書き換える `redact_api_sensitive_data` を追加しました- デフォルトでは `true` - `event_metadata` の中身を `"REDACTED"` という文字列に書き換えます - [ADD] `sora.conf` に録画メタデータファイルに含まれるセンシティブな可能性があるデータを `"REDACTED"` という文字列に書き換える `redact_archive_metadata_sensitive_data` を追加しました- デフォルトでは `true` - `event_metadata` の中身を `"REDACTED"` という文字列に書き換えます ## 2021.2.8 **リリース**: 2022-04-11 **対応 Chrome**: M98 以降 **対応 Firefox**: 97 以降 **対応 Safari**: 15.3 以降 **対応 Edge**: 98 以降 ### 変更履歴 - [FIX] 依存ライブラリ OpenSSL を 1.1.1n にアップデートしました ## 2021.2.7 **リリース**: 2022-02-24 **対応 Chrome**: M98 以降 **対応 Firefox**: 97 以降 **対応 Safari**: 15.3 以降 **対応 Edge**: 98 以降 ### 変更履歴 - [CHANGE] 録画失敗時でも一時ファイルを削除しないようにしました - [FIX] PauseRtpStream API がイベントウェブフック connection.created を受け取ったタイミングで実行しても正常に動作しない問題を修正しました - [FIX] 録画ファイル分割出力のみの場合でも、一時ファイルが録画終了時まで削除されずに残っていた問題を修正しました ## 2021.2.1 **リリース**: 2021-12-20 **対応 Chrome**: M97 以降 **対応 Firefox**: 95 以降 **対応 Safari**: 15.1 以降 **対応 Edge**: 97 以降 - [FIX] 録画機能利用時に `sora.conf` の [archive_tmp_dir](SORA_CONF.html#4d75ea) と [archive_dir](SORA_CONF.html#ad2156) で指定される 2 つのディレクトリが異なるファイルシステムにある場合に、録画ファイルの生成に失敗する問題を修正しました ## 2021.2.0 **リリース**: 2021-12-15 **対応 Chrome**: M97 以降 **対応 Firefox**: 95 以降 **対応 Safari**: 15.1 以降 **対応 Edge**: 97 以降 ### ハイライト - クラスター機能を追加しました - DataChannel を利用したメッセージング機能を追加しました - 統計エクスポーター機能を追加しました - スポットライト機能のフォーカス/アンフォーカスを変更する API を追加しました - ICE コネクションステート機能を追加しました - シグナリング通知に録画開始/終了の通知を追加しました - セッションウェブフックを追加しました - 音声冗長化機能に対応しました - AV1 コーデック利用時の録画に対応しました ### 廃止情報 - CentOS 8 への対応を終了しました- 詳細は [CentOS 8 対応](OBSOLETE.html#14536f) をご確認ください - スポットライトレガシー機能を廃止しました- 詳細は [スポットライトレガシー機能の廃止](OBSOLETE.html#9bb8f9) をご確認ください - 統計機能の `rtp` にある `rtcp` を廃止しました- 詳細は [rtp にある RTCP 関連統計情報を廃止](OBSOLETE.html#4d430c) をご確認ください - `sora.conf` の `extmap_allow_mixed` 設定を廃止しました- 詳細は [extmap_allow_mixed 設定のデフォルト有効化と廃止](OBSOLETE.html#6099d7) をご確認ください - `sora.conf` の `dcsctp_association_max_retrans` 設定を廃止しました- 詳細は [sora.conf の dcsctp_association_max_retrans を廃止](OBSOLETE.html#63d7f7) をご確認ください - 実験的機能である `sora.conf` の `opus_param_clock_rate` 設定を廃止しました - [ListAllConnections](OBSOLETE_API.html#7a9c4e) API を廃止しました- 今後は [ListConnections](API_SIGNALING.html#d3da2a) API をご利用ください。 - [ListChannelClients](OBSOLETE_API.html#a65eee) API を廃止しました- 今後は [ListChannelConnections](API_SIGNALING.html#d388f3) API をご利用ください ### 互換性なしの変更情報 **変更点の不明点についてはサポートまでお問い合わせください** **猶予期間を儲けない変更となっておりますのでご注意ください** - [ListConnections](API_SIGNALING.html#d3da2a) API の戻り値に含まれる `connection_created_timestamp_sec` の項目名を `created_time` に変更、単位を秒からマイクロ秒に変更しております - [ListChannelConnections](API_SIGNALING.html#d388f3) API の戻り値に含まれる `connection_created_timestamp_sec` の項目名を `created_time` に変更しており、単位を秒からマイクロ秒に変更しております ### 変更履歴 - [CHANGE] `connection.log` のタイムスタンプを秒からマイクロ秒に変更しました - [CHANGE] Chrome 側の破壊的変更により Chrome M95 以前の AV1 への対応を廃止しました- AV1 を利用する場合は Chrome M96 以降をご利用ください - [ADD] `sora.conf` に TURN-TCP で Allocate-Success を遅延させる [turn_tcp_allocate_success_delay_time](SORA_CONF.html#60d922) を追加しました- デフォルトは `100 ms` です - 0-1000 ms の範囲で指定できます - [ADD] Sora 起動時に Sora のバージョンが INFO レベルで `sora.log` に出力されるようになりました- `2021-12-15 12:34:56.789 UTC [info] [-/-/-] <0.235.0> SORA | node_name=sora@127.0.0.1, version=2021.2.0` #### 移行 - [CHANGE] `sora.conf` の `use_re_offer` が `true` の場合 `type: update` を Sora に送るとエラーになるよう変更しました - [CHANGE] `sora.conf` の `use_re_offer` のデフォルト値を `true` に変更しました- この設定は 2022 年 6 月リリース予定の Sora にて廃止します - [CHANGE] `sora.conf` の `unuse_metadata_list` のデフォルト値を `true` に変更しました- この設定は 2022 年 6 月リリース予定の Sora にて廃止します #### 開発ツール - [CHANGE] デモ機能を **開発ツール** と名前を変更しました - [CHANGE] `sora.conf` の `demo` を `true` にした場合 `devtools` が有効になるように変更しました- `sora.conf` の `demo` は 2022 年 6 月のリリースにて廃止します - 詳細は [sora.conf の demo の廃止](OBSOLETE.html#12e7c9) をご確認ください - [ADD] `sora.conf` に `devtools` を追加しました- デフォルトは `false` です #### ウェブフック - [ADD] 認証ウェブフックに `node_name` を追加しました - [ADD] イベントウェブフックに `node_name` を追加しました - [ADD] イベントウェブフックの `recording.report` に `filename` と `file_path` を追加しました- `metadata_filename` と `metadata_file_path` は 2022 年 12 月リリース予定の Sora で廃止します - 廃止対象は JSON 内の `"data"` 直下のフィールドのみで、 `"archives"` 以下にある`metadata_filename` と `metadata_file_path` は変更ありません #### セッションウェブフック 詳細は [セッションウェブフック](SESSION_WEBHOOK.html) をご確認ください。 - [ADD] `sora.conf` にセッションウェブフックの URL を指定する [session_webhook_url](SORA_CONF.html#76fa79) を追加しました - [ADD] `sora.conf` にセッション生成時のタイムアウトを指定する [session_created_timeout](SORA_CONF.html#20c8c6) を追加しました- デフォルトは `5 s` です - [ADD] `sora.conf` に セッション破棄時のタイムアウトを指定する [session_destroyed_timeout](SORA_CONF.html#642cc4) を追加しました- デフォルトは `15 s` です - [ADD] `session.created` セッションウェブフックを追加しました- セッションが作成されたタイミングで送信します - [ADD] `session.destroyed` セッションウェブフックを追加しました- セッションが破棄されたタイミングで送信します - [ADD] `session.vanished` セッションウェブフックを追加しました- `block_new_connection` または `block_new_session` モード時にすべてのセッションが破棄されたタイミングで送信します - [ADD] `sora.conf` に `session.vanished` をウェブフックリクエストとして送信しない `ignore_session_vanished_webhook` を追加しました- デフォルトは `true` です - [ADD] セッションウェブフックリクエスト送信時の HTTP ヘッダーに `x-sora-session-webhook-type` を追加しました- ヘッダーの値は `type` の値が入ります - [ADD] セッションウェブフックのログを出力する `log/session_webhook.log` を追加しました - [ADD] セッションウェブフックの失敗ログを出力する `log/session_webhook_failed.log` を追加しました - [ADD] [GetStatsReport](EXPERIMENTAL_API_STATS.html#bbbfca) API に合計セッション生成回数 `total_session_created` を追加しました - [ADD] [GetStatsReport](EXPERIMENTAL_API_STATS.html#bbbfca) API に合計セッション破棄回数 `total_session_destroyed` を追加しました #### モード機能 詳細は [モード機能](MODE.html) をご確認ください。 - [ADD] 新規セッションやコネクションを受け付けなくするモードの仕組みを追加しました- 初期値は `normal` です - `sora.conf` にて `cluster` を有効にしたときの初期値は `block_new_connection` です - [ADD] モードを切り替える `ChangeMode API` を追加しました- `"mode": "normal"` を指定するとすべての新規コネクションを受け付けます - `"mode": "block_new_session"` を指定することで新規セッションをブロックすることができます - `"mode": "block_new_connection"` を指定することで新規コネクションをブロックすることができます - [ADD] 現在のモードを取得する `GetMode API` を追加しました #### クラスター機能 詳細は [クラスター機能](CLUSTER.html) をご確認ください。 - [ADD] クラスター機能利用時にどのノードへも接続ができない場合 `NO-ACCEPTABLE-NODE` を出力するようにしました - [ADD] 複数 Sora でクラスターを構築し、冗長化する機能を追加しました - [ADD] クラスター機能利用時に新規のチャネルへの接続する際、同時接続に余裕のある Sora ノードに割り当てる機能を追加しました - [ADD] クラスター機能利用時に既存のチャネルへの接続する際、そのチャネルへの接続が存在する Sora ノードに割り当てる機能を追加しました - [ADD] シグナリング接続時に別の Sora ノードにリダイレクトする `"type": "redirect"` を追加しました- リダイレクト先のシグナリング URL が `"location": "wss://node01.example.com/signaling"` に含まれます - [ADD] リダイレクト先のシグナリング URL を利用する際に `"redirect": true` を `"type": "connect"` に追加できるようにしました - [ADD] sora.conf にクラスター利用時にリダイレクトに利用する `cluster_signaling_url` の設定を追加しました- `cluster_signaling_url = wss://node01.example.com/signaling` - [ADD] sora.conf にクラスター利用時の Sora ノード名を指定する `cluster_node_name` の設定を追加しました- `cluster_node_name = node01@192.0.2.10` - [ADD] sora.conf にクラスター利用時に API URL を指定する `cluster_api_url` の設定を追加しました- `cluster_api_url = https://node01.example.com/` - [ADD] sora.conf にクラスター利用時のノード間通信に使用するポート番号を指定する [cluster_listen_min_port](SORA_CONF.html#7aa8c7) と [cluster_listen_max_port](SORA_CONF.html#354463) の設定を追加しました- デフォルトは [cluster_listen_min_port](SORA_CONF.html#7aa8c7) が `49010` で、 [cluster_listen_max_port](SORA_CONF.html#354463) が `49020` です - [ADD] クラスターに参加するための [JoinCluster](OBSOLETE_API.html#17f3f5) API を追加しました- クラスターからの離脱は `bin/sora stop` を実行します - [ADD] クラスターに参加しているノード一覧を取得するための [ListClusterNodes](API_CLUSTER.html#a70901) API を追加しました - [ADD] クラスターに割り当てられているチャネル ID 一覧を取得するための [ListClusterChannels](API_CLUSTER.html#0a4459) API を追加しました #### 音声冗長化機能 **この機能は Chrome 96 以降で利用できます** - [ADD] `sora.conf` に 音声冗長化機能を有効にする `audio_red` を追加しました。- デフォルトは `false` です - 音声冗長化についての詳細は[PSA: opus+red enabled by default in M96](https://groups.google.com/g/discuss-webrtc/c/5761etCrSuA/m/VrbQL3_LBwAJ) を参照ください - [ADD] 1 チャネルへの接続が `audio_red` への対応が混在していてもやりとりできるようにしました。 #### 録画機能 - [ADD] AV1 の録画に対応しました- この機能は Chrome 96 以降で利用できます - [ADD] [StartRecording](OBSOLETE_API_LEGACY_RECORDING.html#c5b527) API にて `metadata` を指定可能にしました- `metadata` は JSON オブジェクトである必要があります - `metadata` はオプションです - [ADD] `recording.report` や録画メタデータファイルに [StartRecording](OBSOLETE_API_LEGACY_RECORDING.html#c5b527) API で指定した `metadata` を出力するようにしました- 指定しなければ `metadata` が出力されません - [ADD] シグナリング通知を利用している場合、録画開始時に ["event_type": "recording.started"](SIGNALING_NOTIFY.html#7698a8) が通知されるようになりました - [ADD] シグナリング通知を利用している場合、録画終了時に ["event_type": "recording.stopped"](SIGNALING_NOTIFY.html#421054) が通知されるようになりました - [ADD] `sora.conf` に録画関連をシグナリング通知で送信するかどうかを指定する [signaling_notify_recording](SORA_CONF.html#cfe368) を追加しました #### 統計エクスポーター機能 クライアントから送られてきた統計情報を HTTP/2 経由で外部へ出力する機能です。 詳細は [統計エクスポーター機能](OBSOLETE_STATS_EXPORTER.html) をご確認ください。 - [ADD] `sora.conf` に統計エクスポーターの接続先を指定する `stats_collector_url` を追加しました- `stats_collector_url = http://h2c.example.com:5890/collector` - `stats_collector_url = https://h2.example.com/collector` - [ADD] 統計コレクターへ送信時の HTTP ヘッダーに `x-sora-stats-exporter-type` を追加しました- ヘッダーの値は `type` の値が入ります - [ADD] `sora.conf` に統計エクスポーターの数を指定する `stats_exporter_number` を追加しました- デフォルトは `5` です - [ADD] `sora.conf` に `stats_exporter_tls_fullchain_file` を追加しました - [ADD] `sora.conf` に `stats_exporter_tls_privkey_file` を追加しました - [ADD] `sora.conf` に `stats_exporter_tls_verify_cacert_file` を追加しました - [ADD] 頻繁に送らない項目を定義しました- 1 h に 1 回送ります - codec / local-candidate / remote-candidate / certificate / peer-connection / track-stream #### スポットライト機能 フォーカス/アンフォーカス挙動変更 API を追加しました。 - [ADD] スポットライトのフォーカス/アンフォーカス挙動を変更する [RequestSpotlightRid](API_SPOTLIGHT.html#5c2650) API` を追加しました - [ADD] スポットライトのフォーカス/アンフォーカス挙動をリセットする [ResetSpotlightRid](API_SPOTLIGHT.html#680344) API を追加しました - [ADD] スポットライトのフォーカス/アンフォーカス挙動を一括で変更する [BatchRequestSpotlightRid](API_SPOTLIGHT.html#a2e06c) API を追加しました #### ICE コネクションステート機能 詳細は [ICE コネクションステート機能](ICE_CONNECTION_STATE.html) をご確認ください。 - [ADD] `sora.conf` に `ice_connection_state_disconnected_timeout` を追加しました- デフォルトは `5 s` です - [ADD] `sora.conf` に `ice_connection_state_failed_timeout` を追加しました- デフォルトは `10 s` です - [ADD] `sora.log` に warning で `ICE-CONNECTION-DISCONNECTED` が出力されるようになりました- `1000 ms` 間隔で 5 秒間 `STUN Binding-Request` を送っても 1 度も `STUN Binding-Success` が返ってこない場合に出力されます - `1000 ms` は `sora.conf` の `ice_connection_state_disconnected_timeout` にて変更できます - [ADD] `sora.log` に `error` で `ICE-CONNECTION-FAILED` が出力されるようになりました- この場合 Sora は接続を切断します - `50 ms` 間隔で 10 秒間 `STUN Binding-Request` を送っても 1 度も `STUN Binding-Success` が返ってこない場合に出力されます - `50 ms` は `sora.conf` の `ice_connection_state_failed_timeout` にて変更できます #### DataChannel 機能 - [CHANGE] 利用しない DataChannel を作成しない仕組みを追加しました- `sora.conf` の [signaling_notify](SORA_CONF.html#d88348) が無効の場合は `label: notify` の DataChannel は作成しません - `sora.conf` の `sora_conf-e2ee` が無効の場合は `label: e2ee` の DataChannel は作成しません - `sora.conf` の `user_agent_stats` が無効の場合は `label: stats` の DataChannel は作成しません - [CHANGE] `dcsctp_association_max_retrans` を廃止しました- 切断判定には ICE コネクションステート機能が利用されます #### メッセージング機能 詳細は [リアルタイムメッセージング機能](MESSAGING.html) をご確認ください。 DataChannel を利用したメッセージをユーザーが提起して自由に送ることができる機能です。ラベルは `#` から始まる必要があります。 - [ADD] `type: connect` に `data_channels` を追加しました- メッセージ機能は `[{"label": "#abc", "direction": "sendrecv"}, ...]` で指定できます - メッセージのラベルを指定する `label` を追加しました- `^#[a-zA-Z0-9][a-zA-Z0-9-]{1,30}$` - メッセージのメッセージの方向を指定する `direction` を追加しました- `sendrecv` / `sendonly` / `recvonly` のどれかを指定して下さい - 方向はクライアントから見た視点で `role` と同様です - メッセージの順番を指定する [ordered](MESSAGING.html#17e8c5) を追加しました- デフォルトは `true` です - メッセージのリトライ時間を指定する [max_packet_life_time](MESSAGING.html#3b5bc1) を追加しました- デフォルト指定無しです - 単位はミリ秒です - メッセージのリトライ回数を指定する [max_retransmits](MESSAGING.html#02a10a) を追加しました- デフォルト指定無しです - メッセージの圧縮を指定する [compress](MESSAGING.html#fbaa9b) を追加しました- デフォルトは `false` です - [ADD] `sora.conf` に [data_channel_messaging](SORA_CONF.html#1d5746) を追加しました- デフォルトは `false` です - [ADD] 認証成功時の払い出しで `data_channels` を指定できるようにしました- `"type": "connect"` 時に、指定された `data_channels` を上書きできます - [ADD] `sora.conf` に [data_channel_messaging_only](SORA_CONF.html#93c61c) を追加しました- デフォルトは `false` です #### ユーザーエージェント統計 API リモート統計情報 API の名前を変更し整理した API です。 リモート統計情報 API は 2022 年 6 月リリースの Sora にて廃止しますので、 ユーザーエージェント統計情報 API に切り替えをお願いします。 - [CHANGE] `remote_stats` をデフォルト `false` にしました - [ADD] `sora.conf` に `user_agent_stats` を追加しました- デフォルトは `true` です - `remote_stats` は 2022 年 6 月にて廃止します - [ADD] [ListUserAgentStats](OBSOLETE_API_USER_AGENT_STATS.html#f9a4fe) API を追加しました- [GetAllRemoteStats](OBSOLETE_API.html#3a6504) の代替 API です - [ADD] [ListChannelUserAgentStats](OBSOLETE_API_USER_AGENT_STATS.html#df496a) API を追加しました- [GetChannelRemoteStats](OBSOLETE_API.html#bbd252) の代替 API です - [ADD] [GetUserAgentStats](OBSOLETE_API_USER_AGENT_STATS.html#a078ba) API を追加しました- [GetConnectionRemoteStats](OBSOLETE_API.html#2f926d) の代替 API です ## 2021.1.4 **リリース**: 2021-10-29 **対応 Chrome**: M95 以降 **対応 Firefox**: 93 以降 **対応 Safari**: 15.1 以降 **対応 Edge**: 95 以降 ### 変更履歴 - [FIX] ネットワークが不安定な場合に録画が失敗する問題を修正しました - [FIX] Safari を利用した場合に特定条件で復号が失敗する問題を修正しました ## 2021.1.2 **リリース**: 2021-09-17 **対応 Chrome**: M93 以降 **対応 Firefox**: 92 以降 **対応 Safari**: 14.1 以降 **対応 Edge**: 93 以降 ### 変更履歴 - [UPDATE] デモ機能で利用している sora-demo を 2021.1.6 にアップデートしました - [ADD] 切断 API の `reason` を指定した場合に、指定した `reason` が、イベントウェブフック `connection.destroyed` に `disconnect_api_reason` として含まれるようになりました- 今まで `reason` として入ってきていたのと同じ値が入ります - [ADD] `"type": "disconnect"` に `reason` を指定した場合に、指定した `reason` が、イベントウェブフック `connection.destroyed` に `type_disconnect_reason` として含まれるようになりました - [ADD] イベントウェブフック `connection.*` の `data` に `"created_time": "connection.created 時の UNIX 時刻"` を追加しました - [ADD] `sora.conf` にスポットライトでフォーカスされた後、一定時間追い出されなくなる [sora_conf-default_spotlight_focus_min_interval](SPOTLIGHT.html#9ba866) を追加しました- デフォルトは `2000 ms` です - [FIX] スポットライト機能で複数人が音を出し続けていると頻繁にフォーカスが入れ替わる問題を修正しました- アンフォーカス後のフォーカスは、最低でも [sora_conf-default_spotlight_delayed_focus_interval](SPOTLIGHT.html#a5df3b) だけ待つようになりました - [FIX] スポットライト機能でアンフォーカスからフォーカスに変わるタイミングで音声や映像が配信されなくなる場合がある問題を修正しました - [FIX] スポットライト機能で自動アンフォーカスが指定した時間よりも速く行われる問題を修正しました - [FIX] IPv6 のみで正常に接続できない場合がある問題を修正しました - [FIX] クライアントから `"type": "candidate"` を送ることができる回数を 20 から 50 に変更しました - [FIX] DataChannel におけるエンドポイント障害検出カウンターのリセットタイミングを修正しました - [FIX] 一部の HTTP API のバリデーションが正常に動作していない問題を修正しました - [FIX] シグナリングが DataChannel に切り替わったタイミングで WebSocket のアイドルタイムアウトが無制限になるように修正しました - [FIX] SRTP/SRTCP の暗号が AES-GCM の場合に、長時間配信すると正常に復号できなくなる問題を修正しました - [FIX] sora.conf の不要なコメントを削除しました ## 2021.1 **リリース**: 2021-06-23 **対応 Chrome**: M91 以降 **対応 Firefox**: 89 以降 **対応 Safari**: 14.1 以降 **対応 Edge**: 91 以降 ### 廃止情報 #### role の upstream と downstream を廃止 `role` の `upstream` と `downstream` を廃止しました。 詳細は [role の upstream と downstream を廃止](OBSOLETE.html#a8c580) をご確認ください。 #### allow_client_id_assignment 設定を廃止 接続時や認証成功時に、常に client_id を指定できるようになり、 `sora.conf` の `allow_client_id_assignment` を廃止しました。 詳細は [client_id を指定する設定の廃止](OBSOLETE.html#b2acda) をご確認ください。 #### 旧サイマルキャスト API を廃止 `Sora_20180820.ChangeSimulcastQuality` API を廃止しました。 詳細は [旧サイマルキャスト画質変更 API の廃止](OBSOLETE.html#9e15a8) をご確認ください。 ### 互換なしの変更情報 廃止以外の互換性がない機能変更はありません。 ### 実験的機能から正式機能へ昇格 - `Sora_20201120.PushChannelByRole` API - `Sora_20201120.DisconnectChannelByRole` API ### ハイライト - スポットライト機能に rid 指定機能を追加しました - スポットライト機能に遅延フォーカス機能を追加しました - スポットライト機能に自動アンフォーカス機能を追加しました - スポットライト機能にフォーカスなしの音声配信機能を追加しました - シグナリングを WebSocket から DataChannel へ切り替える機能を追加しました - DataChannel 経由のシグナリング利用時に WebSocket の切断を無視する機能を追加しました - より少ない CPU リソースでより多くの接続を処理できるようになりました ### 変更履歴 - [UPDATE] デモ機能で利用している sora-demo を 2021.1 にアップデートしました - [UPDATE] より少ない CPU リソースで多くの接続を処理できるようになりました - [ADD] TURN-TCP 利用時の [Proxy Protocol v1](https://www.haproxy.com/blog/haproxy/proxy-protocol/) へ対応しました- これに伴い [TURN-TLS、TURN-TCP、シグナリングで 443 番ポートを使用する](PRODUCTION.html#14258d) の内容が Sora 2021.1 向けに変更されています - nginx の変更はしなくても動作しますが、変更をお勧めします - [ADD] シグナリング `"type": "offer"` 時に配信で有効になっている `audio` または `video` の `mid` を含めるようにしました- 例: `"type": "offer", "mid": {"audio": "audio_lFaJYL", "video": "video_lMjsoq"}` - [ADD] `"type": "udpate"` の代わりに `"type": "re-offer"` を送れるように、 `sora.conf` に `use_re_offer` を追加しました- デフォルトは `false` です - この設定は 2021 年 12 月リリースの Sora にてデフォルト `true` に変更されます - この設定は 2022 年 6 月リリースの Sora にて廃止され、常に `"type": "re-offer"` が送られるようになります - [ADD] シグナリング通知メタデータの利用時に、 `metadata_list` の代わりに `data` を送れるように、 `sora.conf` に `unuse_metadata_list` を追加しました- デフォルトは `false` です - この設定は 2021 年 12 月リリースの Sora にてデフォルト `true` に変更されます - この設定は 2022 年 6 月リリースの Sora にて廃止され、常に `data` が送られるようになります - [FIX] 録画機能の利用時で映像が送られてこない際に WebM の PixelWidth / PixelHeight が 0 になる問題を修正しました - [FIX] 不安定な回線や音声パケットが送られてこなくなる場合にクライアント側でリップシンクが正常に行われず、音声と映像がずれてしまう問題を修正しました - [FIX] 音声クロックレートが 48000 Hz 固定になってしまう問題を修正しました - [FIX] スポットライトレガシーで recvonly が利用できてしまう問題を修正しました - [FIX] TURN-TCP で問題があった際に、シグナリングを切断しない限り接続が残り続ける問題を修正しました #### 統計機能 - [ADD] RTP ヘッダー拡張の統計情報を追加しました - [ADD] サイマルキャストの rid 単位の RTP 統計情報を追加しました - [ADD] サイマルキャストの rid 単位の RTP ヘッダー拡張統計情報を追加しました - [ADD] RTCP 統計情報を `rtcp` に移動しました- 2021 年 12 月のリリースにて `rtp` から RTCP 関連の統計情報を削除します #### スポットライト機能 **実験的機能** - [CHANGE] デフォルトの `r0` の `maxFramerate` を `1.0` から `5.0` に変更しました #### スポットライト機能: rid 指定 **実験的機能** スポットライト利用時にフォーカス、アンフォーカスそれぞれで受信する映像を接続ごとに指定できるようになりました。 これによりモバイル端末や回線が不安定な場合は映像を一切受信しないなどの設定ができます。 - [ADD] アンフォーカス時に受信する rid を指定できるように、 `sora.conf` に [default_spotlight_unfocus_rid](SORA_CONF.html#a7cd9b) を追加しました- デフォルトは `r0` - `none`, `r0`, `r1`, `r2` を指定可能 - [ADD] フォーカス時に受信する rid を指定できるように、 `sora.conf` に [default_spotlight_focus_rid](SORA_CONF.html#c71c97) を追加しました- デフォルトは `r1` - `none`, `r0`, `r1`, `r2` を指定可能 - [ADD] アンフォーカス時に受信する rid を指定できるように、シグナリング `"type": "connect"` に `spotlight_unfocus_rid` を追加しました- デフォルトは `sora.conf` の [default_spotlight_unfocus_rid](SORA_CONF.html#a7cd9b) の値が採用されます - `none`, `r0`, `r1`, `r2` を指定可能 - [ADD] フォーカス時に受信する rid を指定できるように、シグナリング `"type": "connect"` に `spotlight_focus_rid` を追加しました- デフォルトは `sora.conf` の [default_spotlight_focus_rid](SORA_CONF.html#c71c97) の値が採用されます - `none`, `r0`, `r1`, `r2` を指定可能 - [ADD] アンフォーカス時に受信する rid を指定できるように、認証成功時の払い出しに、 `spotlight_unfocus_rid` を追加しました- デフォルトは `sora.conf` の [default_spotlight_unfocus_rid](SORA_CONF.html#a7cd9b) の値が採用されます - `"type": "connect"` 時に、指定された `spotlight_unfocus_rid` を上書きできます - `none`, `r0`, `r1`, `r2` を指定可能 - [ADD] フォーカス時に受信する rid を指定できるように、認証成功時の払い出しに `spotlight_focus_rid` を追加しました- デフォルトは `sora.conf` の [default_spotlight_focus_rid](SORA_CONF.html#c71c97) の値が採用されます - `"type": "connect"` 時に、指定された `spotlight_focus_rid` を上書きできます - `none`, `r0`, `r1`, `r2` を指定可能 #### スポットライト機能: 遅延フォーカス **実験的機能** スポットライト利用時に、ちょっとした物音やあいづちではすぐにフォーカスされないように、フォーカスを遅延させる機能を追加しました。 この機能によりサーバーからクライアントへのパケット流量を減らすことができるようになりました。 - [ADD] アンフォーカス時にフォーカスを遅延させるかどうかを指定できるように、 `sora.conf` に [sora_conf-default_spotlight_delayed_focus](SPOTLIGHT.html#da30b6) を追加しました- デフォルトは `true` - [ADD] アンフォーカス時にフォーカスを遅延させる時間を指定できるように、 `sora.conf` に [sora_conf-default_spotlight_delayed_focus_interval](SPOTLIGHT.html#a5df3b) を追加しました- デフォルトは `2000 ms` #### スポットライト機能: フォーカスなしの音声配信 **実験的機能** スポットライト利用時に、他の人にフォーカスが移った場合でも音声を配信し続ける機能を追加しました。 この機能によりスポットライトの数が少ない場合でも、他の人がフォーカスされたことにより音声が送られなくなる、といったことがなくなりました。 - [ADD] フォーカスなしでも音声を配信するかどうかを指定できるように、 `sora.conf` に [sora_conf-default_spotlight_unfocus_audio](SPOTLIGHT.html#3bd7f7) を追加しました- デフォルトは `true` - [ADD] フォーカスなしでも音声を配信する上限レートを指定できるように、 `sora.conf` に [sora_conf-default_spotlight_unfocus_audio_rate_limit](SPOTLIGHT.html#27c5ad) を追加しました- デフォルトは `2` - 単位は `1 音声ストリーム = 50 packets / s` です #### スポットライト機能: 自動アンフォーカス機能 **実験的機能** スポットライト利用時に、一定時間音声が配信されていない場合はアンフォーカスする機能を追加しました。 この機能によりサーバーからクライアントへのパケット流量を減らすことができるようになりました。 - [ADD] 音がない場合に自動でアンフォーカスするかどうかを指定できるように、 `sora.conf` に [sora_conf-default_spotlight_auto_unfocus](SPOTLIGHT.html#d57acb) を追加しました- デフォルトは `true` - [ADD] 自動でアンフォーカスする無音時間を指定できるように、 `sora.conf` に [sora_conf-default_spotlight_auto_unfocus_interval](SPOTLIGHT.html#fcf07a) を追加しました- デフォルトは `10 s` - 1 ms 以上、30 s 以下 - API でフォーカスが固定されている場合は自動アンフォーカスの対象外になります #### DataChannel 機能: シグナリングの WebSocket から DataChannel への切り替え機能 **実験的機能** > **注釈** > > DataChannel は TURN を利用するため UDP が通らない場合でも問題なく繋がります。 > **重要** > > DataChannel 機能を利用する場合は Sora JavaScript SDK 2021.1 以降が必要になります シグナリングやシグナリング通知、プッシュ通知などで利用している WebSocket から DataChannel へ切り替えます。 **ただし WebSocket は切断判定に利用するため、Sora から切断することはありません** 。 - [ADD] `sora.conf` に [default_data_channel_signaling](SORA_CONF.html#adceef) を追加しました- デフォルトは `false` です - [ADD] シグナリング `"type": "connect"` で `data_channel_signaling: boolean` を指定できるようにしました- デフォルトは `sora.conf` の [default_data_channel_signaling](SORA_CONF.html#adceef) に設定された値です - [ADD] 認証成功時の払い出しで `data_channel_signaling: boolean` を指定できるようにしました- デフォルトは `sora.conf` の [default_data_channel_signaling](SORA_CONF.html#adceef) に設定された値です - `"type": "connect"` 時に、指定された `data_channel_signaling` を上書きできます - [ADD] シグナリング `"type": "offer"` 時に `data_channel_signaling: boolean` を払い出すようにしました- この払い出しは data_channel_signaling が true の時のみ有効です - [ADD] WebSocket から DataChannel へ切り替わった場合は `"type": "switched"` が WebSocket 経由で送られるようにしました- `"type": "switched"` を送ったタイミングからWebSocket 経由の `"type": "ping"` の間隔が 5 秒から 30 秒へ変更されます - `"type": "switched"` を送ったタイミングからWebSocket 経由の `"type": "pong"` を確認しなくなります 以下の機能が DataChannel に切り替わります。 - シグナリング- DataChannel の `label` は `signaling` です - 以下が利用できるメッセージタイプです- `"type": "re-offer"` - `"type": "re-answer"` - `"type": "disconnect"` - シグナリング通知- DataChannel の `label` は `notify` です - 以下が利用できるメッセージタイプです- `"type": "notify"` - プッシュ通知- DataChannel の `label` は `push` です - 以下が利用できるメッセージタイプです- `"type": "push"` - E2EE- DataChannel の `label` は `e2ee` です - 統計情報- DataChannel の `label` は `stats` です - 以下が利用できるメッセージタイプです- `"type": "req-stats"` - `"type": "stats"` #### DataChannel 機能: WebSocket の切断を無視する機能 **実験的機能** > **重要** > > WebSocket の切断を切断判定に利用しない場合、 DataChannel におけるエンドポイント障害検出が切断の判断に利用されます。 > この判断は `sora.conf` の `dcsctp_association_max_retrans` の値に依存します。 - [ADD] `sora.conf` に [default_ignore_disconnect_websocket](SORA_CONF.html#58fe04) を追加しました- デフォルトは `false` です - この値を `true` にした場合、 DataChannel 経由でのシグナリング有効時に WebSocket を切断しても、Sora はクライアントの切断と見なさずに接続が継続します - [ADD] `"type": "connect"` 時に `ignore_disconnect_websocket: boolean` を指定できるようにしました- デフォルトは `sora.conf` に設定された値です - この値を `true` にした場合、 DataChannel 経由でのシグナリング有効時に WebSocket を切断しても、Sora はクライアントの切断と見なさずに接続が継続します - [ADD] 認証成功時の払い出しに `ignore_disconnect_websocket: boolean` を指定できるようにしました- デフォルトは `sora.conf` に設定された値です - `"type": "connect"` 時に、指定された `ignore_disconnect_websocket` を上書きできます - この値を `true` にした場合、 DataChannel 経由でのシグナリング有効時に WebSocket を切断しても、Sora はクライアントの切断と見なさずに接続が継続します - [ADD] `"type": "offer"` 時に `data_channel_signaling` が `true` の場合 `ignore_disconnect_websocket: boolean` を払い出すようにしました #### DataChannel 機能: メッセージの圧縮機能 **実験的機能** DataChannel で送受信するメッセージを圧縮して送受信できる機能です。 `"type": "offer"` 時に送られてくる `data_channels: [{"label": "signaling", "compress": true}, ...]` のように compress が true になっている場合は圧縮して送る必要があります。 - [ADD] `"type": "offer"` 時に DataChannel の情報を送るようにしました- `data_channels: [{"label": "