# 音声ストリーミング機能

> **注意**
>
> この機能を利用する場合は事前にサポートまでご連絡ください

> **警告**
>
> この機能は [実験的機能](EXPERIMENTAL.html) のため、正式版では仕様が変更される可能性があります

## 概要

Sora に WebRTC で送られてきた音声を、接続ごとに HTTP/2 で外部へ出力し、外部から受信した結果をクライアントへプッシュで通知する機能です。

## 注意

### OBS (WHIP) 機能利用時の Opus の設定

OBS の Opus のビットレートがデフォルトの場合は正常に動作しない場合があります。
その場合はビットレートを 128 kbps まで下げて見てください。

## HTTP/2

- 統計コレクターサーバーは HTTP/2 に対応している必要があります
- h2c と h2 の両方に対応しています
- `http://` から始めると h2c を利用します
- `https://` から始めると h2 を利用します

## 仕様

### マルチストリームでのみ利用可能

音声ストリーミング機能はマルチストリームを有効にした状態でのみ利用できます。

### 音声ストリーミングの配信

音声ストリーミング機能はセッション単位で有効になります。

実際に音声ストリーミングで音声が外部に配信されるのは、
`role` が `sendrecv` または `sendonly`、かつ `audio` が `true` になっている場合のみ有効になります。

> **注釈**
>
> 外部から受信した結果はロールなどは関係なく、サブスクライブしているすべてのクライアントが受信できます。

### 言語コードの指定

音声ストリーミングを利用する場合、 言語コードを指定する必要があります。

シグナリング接続時、または認証成功時の払い出しで `{"audio_streaming_language_code": "ja-JP"}` のように指定してください。
指定するのは **文字列であればなんでもかまいません** 。Sora 自体は言語コードには関与しません。あくまでただの文字列として扱います。

> **注意**
>
> 言語コードが指定されていない接続は、音声ストリーミングが開始している場合でも音声ストリーミングを行いません。
> 言語コードは音声を解析するにあたり必要になるためこのような仕様になっています。

### セッションウェブフック経由での開始

音声ストリーミングはセッション単位で開始、終了します。

セッション開始時から音声ストリーミングを開始したい場合、
セッションウェブフックの戻り値に `{"audio_streaming": true}` を指定することで音声ストリーミングが開始します。

そのセッションに参加してきた言語コードが指定されているクライアントはすべて音声ストリーミングが行われます。

### セッション終了時の音声ストリーミング終了

チャネルのセッションが終了したタイミングで音声ストリーミングは終了します。

### API 経由での開始と終了

セッションの途中で音声ストリーミングを開始する場合は [StartAudioStreaming](EXPERIMENTAL_API_AUDIO_STREAMING.html#0f1087) API を利用する必要があります。

また、セッションの途中で音声ストリーミングを終了する場合は [StopAudioStreaming](EXPERIMENTAL_API_AUDIO_STREAMING.html#bad1bb) API を利用する必要があります。


### 自動開始/停止機能

サブスクライブ中のコネクション数が 1 つ以上に増えたとき、自動的に音声ストリーミングが開始します。
逆に、サブスクライブ中のコネクション数が 0 になったときには、音声ストリーミングが自動的に停止します。

この機能を有効にすることで、サブスクライブが 0 の時は音声ストリーミングを行わなくなり、
転送量などを抑えることができます。

以下の方法でこの機能を有効にできます:

- セッションウェブフックの `session.created` 時の払い出しで `{"audio_streaming": true, "audio_streaming_auto": true}` を指定した場合

> **注意**
>
> この機能が有効化されているときには、
> [StartAudioStreaming](EXPERIMENTAL_API_AUDIO_STREAMING.html#0f1087) API と [StopAudioStreaming](EXPERIMENTAL_API_AUDIO_STREAMING.html#bad1bb) API は利用できません。
>
> この機能を停止するにはセッションを終了する必要があります。
> API を使用してセッションを終了する場合には、 [TerminateSession](EXPERIMENTAL_API_SESSION.html#ba022b) API を利用してください。


### 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": "<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.1.0-canary.43",
  "max_connections": 1,
  "node_name": "sora@127.0.0.1",
  "session_id": "DYPX8R6F4D11ZEG6XCX6N8EEWM",
  "channel_id": "sora",
  "multistream": true,
  "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.1.0-canary.43",
  "max_connections": 1,
  "node_name": "sora@127.0.0.1",
  "session_id": "DYPX8R6F4D11ZEG6XCX6N8EEWM",
  "channel_id": "sora",
  "multistream": true,
  "spotlight": false,
  "created_time": 1682929437,
  "total_connections": 1,
  "created_timestamp": "2023-05-01T08:23:57.274844Z"
}
```

## 設定

### audio_streaming_url

**デフォルト**: 指定なし

音声ストリーミングゲートウェイの URL を指定してください。
音声ストリーミングゲートウェイは HTTP/2 に対応している必要があります。

https または http から始まる URL を指定してください。

詳細は [audio_streaming_url](SORA_CONF.html#6b5dd6) をご確認ください。

### 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) をご確認ください。

## API

### StartAudioStreaming API

セッションが存在し、音声ストリーミングが開始していないチャネルに対して音声ストリーミングを開始します。

詳細は [StartAudioStreaming](EXPERIMENTAL_API_AUDIO_STREAMING.html#0f1087) をご確認ください。

> **注釈**
>
> この API は audio_streaming_auto が true の場合は利用できません。

### StopAudioStreaming API

セッションが存在し、音声ストリーミングが開始しているチャネルに対して音声ストリーミングを停止します。

> **注釈**
>
> 音声ストリーミングを終了すると、すべての接続のサブスクライブしている状態は初期化され、デフォルトの値に戻ります。

詳細は [StopAudioStreaming](EXPERIMENTAL_API_AUDIO_STREAMING.html#bad1bb) をご確認ください。

> **注釈**
>
> この API は audio_streaming_auto が true の場合は利用できません。





### SubscribeAudioStreamingResultPush API

指定した接続が、音声ストリーミングゲートウェイからの戻り値のプッシュ通知をサブスクライブするよう設定します。

詳細は [SubscribeAudioStreamingResultPush](EXPERIMENTAL_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](EXPERIMENTAL_API_AUDIO_STREAMING.html#b63656) をご確認ください。

### ListAudioStreamingResultPushState API

指定したチャネルのセッションのコネクション毎のサブスクライブの状態を確認します。

```javascript
[
  {
    "connection_id": "B2JPGFZPMD3H973Y811MF8ZZ70",
    "subscribe": true
  },
  {
    "connection_id": "KT116Z11KX5Y547KA1V12HW8PG",
    "subscribe": false
  },
  {
    "connection_id": "A5GYXGRYAX6590M3AFH7F9Z2H4",
    "subscribe": false
  }
]
```

詳細は [ListAudioStreamingResultPushState](EXPERIMENTAL_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 クライアント
    participant Sora
    participant Suzu
    participant AWS Transcribe
    クライアント->>Sora: SRTP
    クライアント->>Sora: SRTP
    クライアント->>Sora: SRTP
    note over クライアント, AWS Transcribe: StartAudioStreaming API 実行
    クライアント->>Sora: SRTP
    Sora->>Suzu: Opus over HTTP/2
    Suzu->>AWS Transcribe: Ogg over HTTP/2
    クライアント->>Sora: SRTP
    Sora->>Suzu: Opus over HTTP/2
    Suzu->>AWS Transcribe: Ogg over HTTP/2
    クライアント->>Sora: SRTP
    Sora->>Suzu: Opus over HTTP/2
    Suzu->>AWS Transcribe: Ogg over HTTP/2
    AWS Transcribe->>Suzu: JSON over HTTP/2
    Suzu->>Sora: JSON over HTTP/2
    Sora->>クライアント: シグナリングプッシュ通知
```

### 自動開始/停止

```mermaid
sequenceDiagram
  autonumber
  participant クライアント
  participant Sora
  participant App
  participant Suzu
  Sora->>+App: セッションウェブフック<br>session.created
  App-->>-Sora: "audio_streaming": true<br>"audio_streaming_auto": true
  クライアント->>Sora: SRTP
  クライアント->>Sora: SRTP
  クライアント->>Sora: SRTP
  App-->>+Sora: SubscribeAudioStreamingResultPush API 実行
  Sora->>-App: 200 OK
  note right of Sora: Subscribe しているクライアントが 1 になった
  Sora->>+App: セッションウェブフック<br>audio-streaming.started
  App-->>-Sora: 200 OK
  note over Sora, Suzu: Suzu への HTTP/2 コネクション接続
  クライアント->>Sora: SRTP
  Sora->>Suzu: Opus over HTTP/2
  クライアント->>Sora: SRTP
  Sora->>Suzu: Opus over HTTP/2
  Suzu->>Sora: JSON over HTTP/2
  Sora->>クライアント: シグナリングプッシュ通知
  クライアント->>Sora: SRTP
  Sora->>Suzu: Opus over HTTP/2
      App-->>+Sora: UnsubscribeAudioStreamingResultPush API 実行
  Sora->>-App: 200 OK
  note right of Sora: Subscribe しているクライアントが 0 になった
  note over Sora, Suzu: Suzu への HTTP/2 コネクション切断
  クライアント->>Sora: SRTP
```
