# イベントウェブフック

## 概要

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 設定指定](SIGNALING.html#b7556a) をご確認ください
- data.video_av1_params- **この項目はオプションです**
  - `video` が `false` の場合は含まれません
  - 詳細は [ビデオの AV1 設定指定](SIGNALING.html#48f92d) をご確認ください
- data.video_h264_params- **この項目はオプションです**
  - `video` が `false` の場合は含まれません
  - 詳細は [ビデオの H.264 設定指定](SIGNALING.html#ffc4cb)  をご確認ください
- data.video_h265_params- **この項目はオプションです**
  - `video` が `false` の場合は含まれません
  - 詳細は [ビデオの H.265 設定指定](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": "<String>",
  "group_id": "<Base32-UUIDv4>",
  "session_id": "<Base32-UUIDv4>",
  "client_id": "<String | Base32-UUIDv4>",
  "bundle_id": "<String | Base32-UUIDv4>",
  "connection_id": "<Base32-UUIDv4>",
  "timestamp": "<UTC RFC3339 Timestamp>",
  "event_metadata": "<JSON Object>",
  "data": {
    "ice_connection_state": {
      "total_checking_duration_ms": "<Integer>",
      "total_disconnected_duration_ms": "<Integer>"
    },
    "recording_block": "<Boolean>",
    "created_time": "<UNIX-Time>",
    "created_timestamp": "<UTC RFC3339 Timestamp>",
    "audio": "<Boolean>",
    "audio_codec_type": "<String>",
    "channel_connections": "<Integer>",
    "channel_recvonly_connections": "<Integer>",
    "channel_sendonly_connections": "<Integer>",
    "channel_sendrecv_connections": "<Integer>",
    "minutes": "<Integer>",
    "total_received_bytes": "<Integer>",
    "total_sent_bytes": "<Integer>",
    "turn_transport_type": "<String>",
    "video": "<Boolean>",
    "video_bit_rate": "<Integer>",
    "video_codec_type": "<String>"
  },
  "id": "<Base32-UUIDv4>",
  "label": "<String>",
  "node_name": "<String>",
  "log_written": "<Boolean>",
  "role": "<sendrecv | sendonly | recvonly>",
  "simulcast": "<Boolean>",
  "spotlight": "<Boolean>",
  "version": "<String>"
}
```


### connection.destroyed

**切断**

シグナリングの接続が切断した時に送信します。

- data.type_disconnect_reason- クライアントから ["type": "disconnect"](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": "<String>",
  "group_id": "<Base32-UUIDv4>",
  "session_id": "<Base32-UUIDv4>",
  "client_id": "<String | Base32-UUIDv4>",
  "bundle_id": "<String | Base32-UUIDv4>",
  "connection_id": "<Base32-UUIDv4>",
  "timestamp": "<UTC RFC3339 Timestamp>",
  "event_metadata": "<JSON Object>",
  "data": {
    "ice_connection_state": {
      "total_checking_duration_ms": "<Integer>",
      "total_disconnected_duration_ms": "<Integer>"
    },
    "recording_block": "<Boolean>",
    "created_time": "<UNIX-Time>",
    "created_timestamp": "<UTC RFC3339 Timestamp>",
    "destroyed_time": "<UNIX-Time>",
    "destroyed_timestamp": "<UTC RFC3339 Timestamp>",
    "audio": "<Boolean>",
    "audio_codec_type": "<String>",
    "channel_connections": "<Integer>",
    "channel_recvonly_connections": "<Integer>",
    "channel_sendonly_connections": "<Integer>",
    "channel_sendrecv_connections": "<Integer>",
    "minutes": "<Integer>",
    "reason": "<String>",
    "type_disconnect_reason": "<String>",
    "total_received_bytes": "<Integer>",
    "total_sent_bytes": "<Intger>",
    "turn_transport_type": "<String>",
    "video": "<Boolean>",
    "video_bit_rate": "<Integer>",
    "video_codec_type": "<String>"
  },
  "id": "<Base32-UUIDv4>",
  "label": "<String>",
  "node_name": "<String>",
  "log_written": "<Boolean>",
  "role": "<sendrecv | sendonly | recvonly>",
  "simulcast": "<Boolean>",
  "spotlight": "<Boolean>",
  "version": "<String>"
}
```


### 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": "<String>",
  "group_id": "<Base32-UUIDv4>",
  "session_id": "<Base32-UUIDv4>",
  "client_id": "<String | Base32-UUIDv4>",
  "bundle_id": "<String | Base32-UUIDv4>",
  "connection_id": "<Base32-UUIDv4>",
  "timestamp": "<UTC RFC3339 Timestamp>",
  "event_metadata": "<JSON>",
  "data": {
    "ice_connection_state": {
      "total_checking_duration_ms": "<Integer>",
      "total_disconnected_duration_ms": "<Integer>"
    },
    "recording_block": "<Boolean>",
    "audio": "<Boolean>",
    "audio_codec_type": "<String>",
    "channel_connections": ,
    "channel_recvonly_connections": "<Integer>",
    "channel_sendonly_connections": "<Integer>",
    "channel_sendrecv_connections": "<Integer>",
    "created_time": "<UNIX-Time>",
    "created_timestamp": "<UTC RFC3339 Timestamp>",
    "minutes": "<Integer>",
    "total_received_bytes": "<Integer>",
    "total_sent_bytes": "<Integer>",
    "turn_transport_type": "<String>",
    "video": "<Boolean>",
    "video_bit_rate": "<Integer>",
    "video_codec_type": "<String>"
  },
  "id": "<Base32-UUIDv4>",
  "label": "<String>",
  "node_name": "<String>",
  "log_written": "<Boolean>",
  "role": "<sendrecv | sendonly | recvonly>",
  "simulcast": "<Boolean>",
  "spotlight": "<Boolean>",
  "version": "<String>"
}
```


### 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": "<Base32-UUIDv4>",
  "role": "<sendrecv | sendonly | recvonly>",
  "channel_id": "<String>",
  "client_id": "<String | Base32-UUIDv4>",
  "bundle_id": "<String | Base32-UUIDv4>",
  "connection_id": "<Base32-UUIDv4>",
  "timestamp": "<UTC RFC3339 Timestamp>",
  "data": {
    "message": "<String>",
    "channel_connections": "<Integer>",
    "channel_sendrecv_connections": "<Integer>",
    "channel_sendonly_connections": "<Integer>",
    "channel_recvonly_connections": "<Integer>",
    "total_received_bytes": "<Integer>",
    "total_sent_bytes": "<Integer>"
  },
  "label": "<String>",
  "node_name": "<String>",
  "log_written": "<Boolean>",
  "simulcast": "<Boolean>",
  "spotlight": "<Boolean>",
  "version": "<String>"
}
```

## 録画・録音保存イベント


### archive.started

**録画ファイル保存開始**

- data.start_timestamp- この録画が開始された時間 (UTC) を RFC 3339 形式 (マイクロ秒) で表しています
- data.format- 録画ファイルのフォーマット
  - `webm` または `mp4` が入ります

```javascript
{
  "type": "archive.started",
  "id": "<Base32-UUIDv4>",
  "version": "<String>",
  "label": "<String>",
  "node_name": "<String>",
  "log_written": "<Boolean>",
  "channel_id": "<String>",
  "group_id": "<Base32-UUIDv4>",
  "session_id": "<Base32-UUIDv4>",
  "client_id": "<String | Base32-UUIDv4>",
  "bundle_id": "<String | Base32-UUIDv4>",
  "connection_id": "<Base32-UUIDv4>",
  "timestamp": "<UTC RFC3339 Timestamp>",
  "event_metadata": "<JSON>",
  "data": {
    "channel_id": "<String>",
    "recording_id": "<Base32-UUIDv4>",
    "session_id": "<Base32-UUIDv4>",
    "group_id": "<Base32-UUIDv4>",
    "client_id": "<String | Base32-UUIDv4>",
    "bundle_id": "<String | Base32-UUIDv4>",
    "connection_id": "<Base32-UUIDv4>",
    "created_at": "<Unix Time>",
    "audio": true,
    "audio_codec_type": "<String>",
    "video": true,
    "video_codec_type": "<String>",
    "video_bit_rate": "<Integer>",
    "start_time": "<Unix Time>",
    "start_time_offset": "<Integer>",
    "start_timestamp": "<UTC RFC3339 Timestamp>",
    "format": "<String{webm, mp4}>"
  }
}
```


### 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": "<Base32-UUIDv4>",
  "version": "<String>",
  "label": "<String>",
  "node_name": "<String>",
  "log_written": "<Boolean>",
  "channel_id": "<String>",
  "group_id": "<Base32-UUIDv4>",
  "session_id": "<Base32-UUIDv4>",
  "client_id": "<String | Base32-UUIDv4>",
  "bundle_id": "<String | Base32-UUIDv4>",
  "connection_id": "<Base32-UUIDv4>",
  "timestamp": "<UTC RFC3339 Timestamp>",
  "event_metadata": "<JSON>",
  "data": {
    "channel_id": "<String>",
    "recording_id": "<Base32-UUIDv4>",
    "group_id": "<Base32-UUIDv4>",
    "session_id": "<Base32-UUIDv4>",
    "client_id": "<String | Base32-UUIDv4>",
    "bundle_id": "<String | Base32-UUIDv4>",
    "connection_id": "<Base32-UUIDv4>",
    "created_at": "<Unix Time>",
    "file_path": "<String>",
    "filename": "<String>",
    "metadata_file_path": "<String>",
    "metadata_filename": "<String>",
    "size": "<Integer>",
    "audio": true,
    "audio_codec_type": "<String>",
    "video": true,
    "video_codec_type": "<String>",
    "video_bit_rate": "<Integer>",
    "video_height": "<Integer>",
    "video_width": "<Integer>",
    "stats": {},
    "start_time": "<Unix Time>",
    "start_time_offset": "<Integer>",
    "start_timestamp": "<UTC RFC3339 Timestamp>",
    "stop_time": "<Unix Time>",
    "stop_time_offset": "<Integer>",
    "stop_timestamp": "<UTC RFC3339 Timestamp>",
    "format": "<String{webm, mp4}>"
  }
}
```


### 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": "<Base32-UUIDv4>",
  "version": "<String>",
  "label": "<String>",
  "node_name": "<String>",
  "log_written": "<Boolean>",
  "channel_id": "<String>",
  "group_id": "<Base32-UUIDv4>",
  "session_id": "<Base32-UUIDv4>",
  "client_id": "<String | Base32-UUIDv4>",
  "bundle_id": "<String | Base32-UUIDv4>",
  "connection_id": "<Base32-UUIDv4>",
  "timestamp": "<UTC RFC3339 Timestamp>",
  "event_metadata": "<JSON>",
  "data": {
    "channel_id": "<String>",
    "recording_id": "<Base32-UUIDv4>",
    "split_index": "<String>",
    "group_id": "<Base32-UUIDv4>",
    "session_id": "<Base32-UUIDv4>",
    "client_id": "<String | Base32-UUIDv4>",
    "bundle_id": "<String | Base32-UUIDv4>",
    "connection_id": "<Base32-UUIDv4>",
    "created_at": "<Unix Time>",
    "file_path": "<String>",
    "filename": "<String>",
    "metadata_file_path": "<String>",
    "metadata_filename": "<String>",
    "size": "<Integer>",
    "audio": true,
    "audio_codec_type": "<String>",
    "video": true,
    "video_codec_type": "<String>",
    "video_bit_rate": "<Integer>",
    "video_height": "<Integer>",
    "video_width": "<Integer>",
    "stats": {
    },
    "start_time": "<Unix Time>",
    "start_time_offset": "<Integer>",
    "start_timestamp": "<UTC RFC3339 Timestamp>",
    "stop_time": "<Unix Time>",
    "stop_time_offset": "<Integer>",
    "stop_timestamp": "<UTC RFC3339 Timestamp>",
    "format": "<String{webm, mp4}>"
  }
}
```

> **注釈**
>
> 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": "<Base32-UUIDv4>",
  "version": "<String>",
  "label": "<String>",
  "node_name": "<String>",
  "log_written": "<Boolean>",
  "channel_id": "<String>",
  "group_id": "<Base32-UUIDv4>",
  "session_id": "<Base32-UUIDv4>",
  "client_id": "<String | Base32-UUIDv4>",
  "bundle_id": "<String | Base32-UUIDv4>",
  "connection_id": "<Base32-UUIDv4>",
  "timestamp": "<UTC RFC3339 Timestamp>",
  "event_metadata": "<JSON>",
  "data": {
    "split_last_index": "<String>",
    "recording_id": "<Base32-UUIDv4>",
    "channel_id": "<String>",
    "group_id": "<Base32-UUIDv4>",
    "session_id": "<Base32-UUIDv4>",
    "client_id": "<String | Base32-UUIDv4>",
    "bundle_id": "<String | Base32-UUIDv4>",
    "connection_id": "<Base32-UUIDv4>",
    "audio": true,
    "audio_codec_type": "<String>",
    "video": true,
    "video_codec_type": "<String>",
    "video_bit_rate": "<Integer>",
    "file_path": "<String>",
    "filename": "<String>",
    "stats": {},
    "start_time": "<Unix Time>",
    "start_time_offset": "<Integer>",
    "start_timestamp": "<UTC RFC3339 Timestamp>",
    "stop_time": "<Unix Time>",
    "stop_time_offset": "<Integer>",
    "stop_timestamp": "<UTC RFC3339 Timestamp>",
    "format": "<String{webm, mp4}>"
  }
}
```


### archive.failed

**録画ファイル保存失敗**

このウェブフックが発生するのは、ディスク容量が足らなかったり、ディスクが故障してたり、
パーミッションにより書き込めなかった場合です。

一括録画、分割録画関係なくクライアントの録画ファイル保存に失敗した場合には発生し、クライアントの録画は停止されます。
書き込めない可能性がとても高いため、分割録画の場合でも録画はその時点で停止します。

もし問題を解決できた場合は、一度録画を停止し、再度録画を開始するようにしてください。

```javascript
{
  "type": "archive.failed",
  "id": "<Base32-UUIDv4>",
  "version": "<String>",
  "label": "<String>",
  "node_name": "<String>",
  "log_written": "<Boolean>",
  "timestamp": "<UTC RFC3339 Timestamp>",
  "channel_id": "<String>",
  "group_id": "<Base32-UUIDv4>",
  "session_id": "<Base32-UUIDv4>",
  "client_id": "<String | Base32-UUIDv4>",
  "bundle_id": "<String | Base32-UUIDv4>",
  "connection_id": "<Base32-UUIDv4>",
  "event_metadata": "<JSON>",
  "data": {
    "recording_id": "<Base32-UUIDv4>",
    "group_id": "<Base32-UUIDv4>",
    "session_id": "<Base32-UUIDv4>",
    "split": "<Boolean>",
    "split_only": "<Boolean>",
    "file_path": "<String>",
    "filename": "<String>",
    "audio": true,
    "audio_codec_type": "<String>",
    "video": true,
    "video_codec_type": "<String>",
    "video_bit_rate": "<Integer>",
    "video_height": "<Integer>",
    "video_width": "<Integer>",
    "stats": {},
    "start_time": "<Unix Time>",
    "start_timestamp": "<UTC RFC3339 Timestamp>",
    "stop_time": "<Unix Time>",
    "stop_timestamp": "<UTC RFC3339 Timestamp>",
    "format": "<String{webm, mp4}>"
  }
}
```

## スポットライト機能


### spotlight.focused

**フォーカス設定**

フォーカスされた際にウェブフックを送信します。

```javascript
{
  "type": "spotlight.focused",
  "channel_id": "<String>",
  "client_id": "<String | Base32-UUIDv4>",
  "bundle_id": "<String | Base32-UUIDv4>",
  "connection_id": "<Base32-UUIDv4>",
  "timestamp": "<UTC RFC3339 Timestamp>",
  "spotlight_number:": "<Integer>",
  "fixed": "<Boolean>",
  "id": "<Base32-UUIDv4>",
  "label": "<String>",
  "version": "<String>",
  "node_name": "<String>",
  "log_written": "<Boolean>",
  "audio": "<Boolean>",
  "video": "<Boolean>"
}
```


### spotlight.unfocused

**フォーカス解除**

フォーカスが外れた際にウェブフックを送信します。

```javascript
{
  "type": "spotlight.unfocused",
  "channel_id": "<String>",
  "client_id": "<String | Base32-UUIDv4>",
  "bundle_id": "<String | Base32-UUIDv4>",
  "connection_id": "<Base32-UUIDv4>",
  "timestamp": "<UTC RFC3339 Timestamp>",
  "spotlight_number:": "<Integer>",
  "audio": "<Boolean>",
  "id": "<Base32-UUIDv4>",
  "label": "<String>",
  "version": "<String>",
  "node_name": "<String>",
  "log_written": "<Boolean>",
  "audio": "<Boolean>",
  "video": "<Boolean>"
}
```

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


### audio-streaming.failed

音声ストリーミング URL への接続を諦めた際にウェブフックを送信します。

```javascript
{
  "type": "audio-streaming.failed",
  "id": "<Base32-UUIDv4>",
  "timestamp": "<UTC RFC3339 Timestamp>",
  "label": "<String>",
  "version": "<String>",
  "node_name": "<String>",
  "log_written": "<Boolean>",
  "channel_id": "<String>",
  "group_id": "<Base32-UUIDv4>",
  "session_id": "<Base32-UUIDv4>",
  "client_id": "<String | Base32-UUIDv4>",
  "bundle_id": "<String | Base32-UUIDv4>",
  "connection_id": "<Base32-UUIDv4>",
  "data": {
    "failed_reason": "<String>"
  },
  "role": "<sendrecv | sendonly | recvonly>",
  "simulcast": "<Boolean>",
  "spotlight": "<Boolean>"
}
```

## 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: イベントウェブフック<br/>"type": "connection.created"
    A-->>-S: 200 OK
    note over C,S: 接続から 1 分経過
    S->>+A: イベントウェブフック<br/>"type": "connection.updated"
    A-->>-S: 200 OK
    C->>S: "type": "disconnect"
    S->>+A: イベントウェブフック<br/>"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<br>"allowed: true,<br>"event_metadata": {"pk": 1}
    S->>C: "type": "offer"
    C->>S: "type": "answer"
    note over C,S: WebRTC 確立
    S->>+A: イベントウェブフック<br/>"type": "connection.created",<br>"event_metadata": {"pk": 1}
    A-->>-S: 200 OK
    note over C,S: 接続から 1 分経過
    S->>+A: イベントウェブフック<br/>"type": "connection.updated",<br>"event_metadata": {"pk": 1}
    A-->>-S: 200 OK
    C->>S: "type": "disconnect"
    S->>+A: イベントウェブフック<br/>"type": "connection.destroyed",<br>"event_metadata": {"pk": 1}
    A-->-S: 200 OK
    S->>C: WebSocket Close
```
