再接続とネットワークの回復力
ネットワークスイッチや短い接続切断により、通話のメディアが中断されることがあります。SDKでは、ほとんどの場合、再接続が自動的に処理されます。メディアライフサイクルイベントや再接続APIを活用して、ユーザーに状況を通知し、可能な場合は復旧を図ってください。
自動再接続の仕組み
SDKがメディアの中断(ICE接続の失敗、ネットワークの切り替えなど)を検知すると、ピア接続に対してICEの再起動を実行することで、自動的に接続の復旧を試みます。
タイミングと再試行の挙動
| パラメータ | 価値 | 説明 |
|---|---|---|
| 自動再試行の最大回数 | 5 | SDKは、処理を中断する前に最大5回まで再試行を行います。 |
| 再試行間隔 | 3秒 | 再接続の試行ごとに固定の遅延を設定(指数関数的バックオフなし) |
| メディアタイムアウト | 10秒 | 接続の試行から10秒以内にメディアが確立されない場合、SDKはそれを失敗とみなします |
| 完全自動復旧ウィンドウ | 約15秒 | 5回の再試行 × 3秒間隔 = 失敗するまでの最大15秒間の自動回復 |
各段階での流れ
-
再接続 — SDKがメディアの中断を検知すると、以下の処理が実行されます
onCallMediaReconnecting. 3秒間隔で最大5回までICEの再起動を試行します。この段階では、開発者による操作は必要ありません。 -
再接続 — いずれかの再試行が成功すると、SDKが呼び出されます
onCallMediaReconnection. 音声ストリームが復旧し、通話は通常通り続行されます。 -
失敗 — 5回の自動再試行がすべて終了した場合、または再接続中にサーバーからエラーが返された場合、SDKは
onCallMediaDisconnect. この時点で:- 音声が停止しました
- サーバー上で通話セッションがまだアクティブな可能性があります
- 開発者は、以下を使用して手動での復旧を試みることができます。
reconnectCall(callId)ネットワーク接続が回復した場合 - 復旧が見られない場合、サーバーは最終的にその通話を切断し、
onCallHangup~で燃えるmediaTimeout理由
開発者の対応概要
- 再接続中: 何も操作する必要はありません。「再接続中」というUIインジケーターを表示してください。
- 再接続に成功した場合: インジケーターを非表示にし、通常の通話画面に戻る。
- 切断時(障害時): 必要に応じて試みる
reconnectCall(callId)ネットワークが復旧したことを検知した場合は、その旨を通知してください。そうでない場合は、通話がつながらなくなったことをユーザーに伝えてください。
セッションレベルの再接続
メディアの再接続とは別に、SDKは接続が切断された際にもWebSocketセッションを自動的に再接続します:
| パラメータ | 価値 |
|---|---|
| 再接続の最大試行回数 | 5 |
| 再接続の遅延 | 5秒 (ランダム化係数0.75) |
セッション再接続の発生 onReconnecting そして onReconnection イベント(上記の「コールメディアイベント」とは異なります)。
onCallMediaDisconnect
メディア接続が完全に切断された場合(自動再接続の試行が5回すべて失敗した後、または回復不可能なサーバーエラーが発生した後)に発生します。この時点でオーディオストリームは停止していますが、サーバー上では通話セッションがまだアクティブな場合があります。手動での復旧を試みるには、 reconnectCall(callId).
client.on(
'callMediaDisconnect',
(callId: string, reason: CallDisconnectReason) => {
if (reason === 'networkChange') {
console.log(`Call ${callId} was disconnected due to a network change`);
} else {
exhaustiveCheck(reason);
}
}
);
client.setOnCallMediaDisconnectListener { legId, reason ->
when (reason) {
CallDisconnectReason.networkChange -> println("Received call media disconnect $reason for Call $legId")
}
}
client.setOnCallMediaDisconnectListener((legId, reason) -> {
if (reason == CallDisconnectReason.networkChange) {
System.out.println("Received call media disconnect " + reason + " for Call " + legId);
}
return null;
});
func voiceClient(_ client: VGVoiceClient, didReceiveMediaDisconnectForCall callId: VGCallId, reason: VGCallDisconnectReason) {
print("leg \(callId) has received media disconnect for \(reason)")
}
- (void) voiceClient:(VGVoiceClient *)client didReceiveMediaDisconnectForCall:(VGCallId)callId reason:(VGCallDisconnectReason)reason {
NSLog(@"Leg %@ has received media disconnect for reason %ld", callId, reason);
}
onCallMediaの再接続中
SDKがメディアの中断(Wi-Fiとモバイル通信間のネットワーク切り替えなど)を検出し、自動的に接続の復旧を試みている際に発火します。ユーザーによる操作は不要です。UIに「再接続中」のインジケーターを表示してください。
client.on('callMediaReconnecting', (callId) => {
console.log(`Call media is reconnecting for call ${callId}`);
});
client.setOnCallMediaReconnectingListener { legId ->
println("Received call media reconnecting for Call $legId")
}
client.setOnCallMediaReconnectingListener((legId) -> {
System.out.println("Received call media reconnecting for Call " + legId);
return null;
});
func voiceClient(_ client: VGVoiceClient, didReceiveMediaReconnectingForCall callId: VGCallId) {
print("leg \(callId) is Reconnecting")
}
- (void) voiceClient:(VGVoiceClient *)client didReceiveMediaReconnectingForCall:(VGCallId)callId {
NSLog(@"Leg %@ is reconnecting", callId);
}
onCallMediaReconnection
SDKが、中断後にメディア接続の復旧に成功した際に発火します。再接続インジケーターを非表示にし、通常の通話UIに戻します。
client.on('callMediaReconnection', (callId) => {
console.log(`Call media is reconnected for call ${callId}`);
});
client.setOnCallMediaReconnectionListener { legId ->
println("Received call media reconnection for Call $legId")
}
client.setOnCallMediaReconnectionListener((legId) -> {
System.out.println("Received call media reconnection for Call " + legId);
return null;
});
func voiceClient(_ client: VGVoiceClient, didReceiveMediaReconnectionForCall callId: VGCallId) {
print("leg \(callId) has received media reconnection")
}
- (void) voiceClient:(VGVoiceClient *)client didReceiveMediaReconnectionForCall:(VGCallId)callId {
NSLog(@"Leg %@ has received media reconnection", callId);
}
手動での再接続
用途 reconnectCall(callId) アプリが明示的にリカバリをトリガーする場合――たとえば、受信後に onCallMediaDisconnect そして、ネットワーク接続が回復したことを確認します。
手動による再接続も、一度トリガーされると、同じ再試行ロジック(最大5回、3秒間隔)に従います。
const callId = 'callId';
await client.reconnectCall(callId);
// Callback
client.reconnectCall("callId") {
it?.let { err ->
// Handle Error in reconnecting call
println("Error in reconnecting call: $err")
}
}
// Coroutine
try {
client.reconnectCall("callId")
}
catch (e:Error) {
// Handle Error in reconnecting call
}
client.reconnectCall("callId", it -> {
if (it != null) {
// Handle Error in reconnecting call
System.out.println("Error in reconnecting call: " + it);
}
return null;
});
// Callback
client.reconnectCall("someCallId") { error in
guard error != nil else {
print("Failed to reconnect \(error?.localizedDescription ?? "")")
return
}
}
/// Async Await
Task.detached {
do {
try await client.reconnectCall("someCallId")
}
catch {
print("error")
}
}
[client reconnect:@"someCallId" callback:^(NSError * _Nullable error) {
if(error){
NSLog(@"Failed to reconnect: %@", error);
}
}];
Androidの要件
Androidでネットワーク変更時の自動復旧を行うには、以下の条件が必要です:
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
障害時の挙動とUX
- すべての自動再試行が失敗し、手動による再接続も成功しなかった場合、
onCallHangup最終的に、次のように発火します。mediaTimeout理由。 - 以下の場合に再接続インジケーターを表示する
onCallMediaReconnecting火災。 - 以下の条件を満たしてから、通常の通話UIに戻る
onCallMediaReconnection火災。 - について
onCallMediaDisconnect, ユーザーに通知し、必要に応じて、以下を呼び出す「再試行」ボタンを表示するreconnectCall(callId).