イベント¶
概要¶
Sora Flutter SDK のイベントは、主に Stream<SoraConnectionEvent> と Stream<SoraDebugEvent> で提供されます。
Stream<SoraConnectionEvent> では、接続状態、リモートトラックの追加・削除、シグナリング、DataChannel (通知・メッセージング・RPC 等)、タイムアウトを購読できます。
Stream<SoraDebugEvent> では、構造化されたログとタイムラインを購読できます。
統合イベント Stream¶
Stream<SoraConnectionEvent> は統合イベント Stream です。イベント型ごとに switch で分岐して処理します。
conn.events.listen((event) {
switch (event) {
case SoraConnectionStateChangedEvent(:final state):
print('state: $state');
case SoraConnectionErrorEvent(:final code, :final message):
print('error: ${code ?? 'unknown'} ${message ?? ''}');
case SoraTrackEvent(:final track):
print('track added: ${track.trackId}');
case SoraRemoveTrackEvent(:final track):
print('track removed: ${track.trackId}');
case SoraNotifyEvent(:final message):
print('notify: $message');
case SoraPushEvent(:final message):
print('push: $message');
case SoraSwitchedEvent(:final message):
print('switched: $message');
case SoraSignalingMessageEvent(:final event):
print('signaling: ${event.transportType} ${event.direction}');
case SoraDataChannelOpenEvent(:final event):
print('datachannel open: ${event.label}');
case SoraDataChannelMessageEvent(:final message):
print('message: ${message.label}');
case SoraTimeoutEvent():
print('timeout');
}
});
接続状態の変更¶
SoraConnectionStateChangedEvent は接続状態が変わったときに通知されます。
conn.events.listen((event) {
if (event case SoraConnectionStateChangedEvent(:final state)) {
switch (state) {
case SoraConnectingState():
print('connecting');
case SoraConnectedState():
print('connected');
case SoraDisconnectedState(:final closeInfo):
print('disconnected');
if (closeInfo != null) {
print('close code: ${closeInfo.code}');
print('close reason: ${closeInfo.reason}');
}
}
}
});
通知される状態は次の 3 種類です。
SoraConnectingStateSoraConnectedStateSoraDisconnectedState
SoraConnectingState¶
接続処理の開始後、シグナリング接続の確立に入ったタイミングで通知されます。
conn.events.listen((event) {
if (event case SoraConnectionStateChangedEvent(state: SoraConnectingState())) {
print('connecting');
}
});
SoraConnectedState¶
Sora との PeerConnection が接続済になったタイミングで通知されます。
conn.events.listen((event) {
if (event case SoraConnectionStateChangedEvent(state: SoraConnectedState())) {
print('connected');
}
});
SoraDisconnectedState¶
Sora から切断したタイミングで通知されます。
closeInfo を持つ場合は、切断時の code と reason を参照できます。
conn.events.listen((event) {
if (event case SoraConnectionStateChangedEvent(
state: SoraDisconnectedState(:final closeInfo),
)) {
print('disconnected');
if (closeInfo != null) {
print('close code: ${closeInfo.code}');
print('close reason: ${closeInfo.reason}');
}
}
});
接続エラー¶
接続エラーは SoraConnectionErrorEvent で通知されます。
conn.events.listen((event) {
if (event case SoraConnectionErrorEvent(:final code, :final message)) {
print('connection error: ${code ?? 'unknown'} ${message ?? ''}');
}
});
code にはエラー種別が、 message にはエラーの詳細が含まれます。
message は null になる可能性があるため、利用の際は null チェックを行ってください。
retriable にはリトライ可能かどうかが bool? で入ります。
details には SoraConnectionErrorDetails? として attempts (リトライ試行回数) と platformError (プラットフォーム固有のエラー情報) が入る場合があります。
SoraConnectionErrorEvent.code に入る既知のエラーコードは、公開 API の SoraErrorCode が定義する次の 18 個です。
SoraErrorCode.eventChannelError: イベントチャネルのエラー- エラーコード:
event_channel_error
- エラーコード:
SoraErrorCode.websocketError:WebSocketのエラー- エラーコード:
websocket_error
- エラーコード:
SoraErrorCode.connectionTimeout: WebRTC 接続確立のタイムアウト ( タイムアウト機能 )- エラーコード:
connection_timeout
- エラーコード:
SoraErrorCode.disconnectTimeout: 切断処理のタイムアウト ( タイムアウト機能 )- エラーコード:
disconnect_timeout
- エラーコード:
SoraErrorCode.signalingCandidateTimeout: シグナリング候補 URL の接続タイムアウト ( タイムアウト機能 )- エラーコード:
signaling_candidate_timeout
- エラーコード:
SoraErrorCode.observerBridgeCreationFailed: observer bridge の生成失敗- エラーコード:
observer_bridge_creation_failed
- エラーコード:
SoraErrorCode.observerBridgeObserverCreationFailed:PeerConnectionObserverの生成失敗- エラーコード:
observer_bridge_observer_creation_failed
- エラーコード:
SoraErrorCode.audioInputInitializationFailed: iOS の音声入力初期化失敗- エラーコード:
audio_input_initialization_failed
- エラーコード:
SoraErrorCode.cameraOpenError: カメラのオープン失敗- エラーコード:
camera_open_error
- エラーコード:
SoraErrorCode.offerInvalid: Sora から受け取った offer の SDP がnull、またはPeerConnectionを用意できない- エラーコード:
offer_invalid
- エラーコード:
SoraErrorCode.reofferInvalid: Sora から受け取った re-offer の SDP がnull、または再利用するPeerConnectionがない- エラーコード:
reoffer_invalid
- エラーコード:
SoraErrorCode.setRemoteDescriptionFailed: リモート SDP の設定に失敗- エラーコード:
set_remote_description_failed
- エラーコード:
SoraErrorCode.createAnswerFailed: answer の生成に失敗- エラーコード:
create_answer_failed
- エラーコード:
SoraErrorCode.setLocalDescriptionFailed: ローカル SDP の設定に失敗- エラーコード:
set_local_description_failed
- エラーコード:
SoraErrorCode.createPeerConnectionFailed:PeerConnectionの生成に失敗- エラーコード:
create_peer_connection_failed
- エラーコード:
SoraErrorCode.addAudioTrackFailed: ローカルの音声トラックの追加に失敗- エラーコード:
add_audio_track_failed
- エラーコード:
SoraErrorCode.addVideoTrackFailed: ローカルの映像トラックの追加に失敗- エラーコード:
add_video_track_failed
- エラーコード:
SoraErrorCode.unexpectedNativeEvent: ネイティブから想定外のイベントが届いた- エラーコード:
unexpected_native_event
- エラーコード:
SoraConnectionErrorEvent.code の型は String? です。イベントによっては null になる可能性があります。
この一覧は SDK が定義する既知の定数一覧であり、ネイティブの接続状態やプラットフォーム側のイベントから渡される実行時の文字列が、この 18 個に限定されることを示すものではありません。
切断理由コード¶
SoraDisconnectReason は、 disconnect メッセージの理由コードと、 SDK が切断を分類するためにネイティブから受け取る理由タグです。 SoraConnectionErrorEvent.code のエラーコード一覧には含まれません。
定数 |
値 |
|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
track¶
リモートトラックが追加されたときは SoraTrackEvent が通知されます。
トラックは RemoteMediaStreamTrack として渡され、 kind で音声か映像かを判別できます。
kind == 'audio': 音声トラック (textureIdはnull)kind == 'video': 映像トラック (textureIdは non-null)
conn.events.listen((event) {
if (event case SoraTrackEvent(:final track)) {
if (track.kind == 'audio') {
print('audio track added: ${track.trackId}');
} else {
print('video track added: ${track.trackId}');
print('textureId: ${track.textureId}');
}
}
});
RemoteMediaStreamTrack のフィールドは以下の通りです。
trackId: トラック IDkind:audioまたはvideoconnectionId: Sora のconnection_idtextureId:kind == 'video'の場合のみ値を取得できます
映像トラックの追加イベントでは、 textureId をそのまま Texture に渡せます。
if (event case SoraTrackEvent(:final track) when track.kind == 'video') {
return Texture(textureId: track.textureId!);
}
removetrack¶
リモートトラックが削除されたときは SoraRemoveTrackEvent が通知されます。
conn.events.listen((event) {
if (event case SoraRemoveTrackEvent(:final track)) {
print('track removed: ${track.trackId}');
}
});
削除イベントでも追加イベント時と同様に RemoteMediaStreamTrack 型となります。UI 側は通常 trackId で対象を特定して除去します。
接続単位でトラックを扱いたい場合は、 SoraConnection.remoteMediaStreams も利用できます。 connectionId をキーに RemoteMediaStream が入り、 audioTrack / videoTrack にそれぞれのトラックが格納されます。
notify¶
Sora からシグナリング通知を受け取ったときは SoraNotifyEvent が通知されます。
Sora のシグナリング通知の詳細は Sora のドキュメント シグナリング通知 をご確認ください。
conn.events.listen((event) {
if (event case SoraNotifyEvent(:final message)) {
print('notify: $message');
}
});
connection.created などの通知をここで受け取ることができます。
push¶
Sora からのプッシュ通知を受け取ったときは SoraPushEvent が通知されます。
conn.events.listen((event) {
if (event case SoraPushEvent(:final message)) {
print('push: $message');
}
});
switched¶
シグナリングが WebSocket から DataChannel に切り替わったときは SoraSwitchedEvent が通知されます。
conn.events.listen((event) {
if (event case SoraSwitchedEvent(:final message)) {
print('switched: $message');
}
});
timeout¶
PeerConnection の接続確立前に、WebSocket が reason TIMEOUT で閉じられた場合に SoraTimeoutEvent が通知されます。切断処理中は通知されません。
conn.events.listen((event) {
if (event case SoraTimeoutEvent()) {
print('timeout');
}
});
message¶
DataChannel を利用したリアルタイムメッセージング機能でメッセージを受信したときは SoraDataChannelMessageEvent が通知されます。
conn.events.listen((event) {
if (event case SoraDataChannelMessageEvent(:final message)) {
print('label: ${message.label}');
print('data: ${message.data}');
}
});
datachannel¶
DataChannel が利用可能になったときは SoraDataChannelOpenEvent が通知されます。
conn.events.listen((event) {
if (event case SoraDataChannelOpenEvent(:final event)) {
print('label: ${event.label}');
print('direction: ${event.direction}');
}
});
メッセージング機能を使う場合は、このイベントを送信可能の目安として扱えます。
signaling¶
シグナリングメッセージの送受信を確認したいときは SoraSignalingMessageEvent を利用します。
conn.events.listen((event) {
if (event case SoraSignalingMessageEvent(:final event)) {
print('${event.transportType} ${event.direction}');
print(event.data);
}
});
transportType は websocket または datachannel です。
direction は sent または received です。
data には、シグナリングメッセージの内容がそのまま入ります。 offer / answer / candidate などの内容を確認することができます。
デバッグイベント Stream¶
conn.debugEvents はデバッグイベント専用 Stream です。構造化された log と timeline を受け取りたい場合に利用します。
conn.debugEvents.listen((event) {
switch (event) {
case SoraLogDebugEvent(:final event):
print('${event.title}: ${event.message}');
case SoraTimelineDebugEvent(:final event):
print('${event.logType.value} ${event.type}');
print(event.data);
}
});
log¶
SDK の構造化ログは SoraLogDebugEvent で受け取ることができます。
conn.debugEvents.listen((event) {
if (event case SoraLogDebugEvent(:final event)) {
print('${event.title}: ${event.message}');
}
});
timeline¶
タイムラインの構造化ログは SoraTimelineDebugEvent で受け取ることができます。
conn.debugEvents.listen((event) {
if (event case SoraTimelineDebugEvent(:final event)) {
print('${event.logType.value} ${event.type}');
print(event.data);
}
});
このイベントに含まれる SoraTimelineEvent では、主に次の情報を参照します。
type: イベント種別logType:websocket/datachannel/peerconnection/soradata: イベントの詳細データdataChannelId: DataChannel に紐づく場合の IDdataChannelLabel: DataChannel に紐づく場合の label
接続確立後の識別子¶
offer を受信すると、次の getter がサーバーから割り当てられた値で更新されます。
connectionIdserverClientIdbundleIdsessionId
接続前や offer 未到達のときは null です。RPC のパラメータ組み立てなどで利用できます。
イベント購読の終了¶
conn.events や conn.debugEvents を購読した場合は、 conn.dispose() の前に購読を解除してください。
late final StreamSubscription<SoraConnectionEvent> eventSubscription;
late final StreamSubscription<SoraDebugEvent> debugEventSubscription;
void setup(SoraConnection conn) {
eventSubscription = conn.events.listen((event) {
// イベント処理
});
debugEventSubscription = conn.debugEvents.listen((event) {
// debug event 処理
});
}
Future<void> dispose(SoraConnection conn) async {
await eventSubscription.cancel();
await debugEventSubscription.cancel();
await conn.dispose();
}