再接続とネットワークの回復力

ネットワークスイッチや短い接続切断により、通話のメディアが中断されることがあります。SDKでは、ほとんどの場合、再接続が自動的に処理されます。メディアライフサイクルイベントや再接続APIを活用して、ユーザーに状況を通知し、可能な場合は復旧を図ってください。

自動再接続の仕組み

SDKがメディアの中断(ICE接続の失敗、ネットワークの切り替えなど)を検知すると、ピア接続に対してICEの再起動を実行することで、自動的に接続の復旧を試みます。

タイミングと再試行の挙動

パラメータ 価値 説明
自動再試行の最大回数 5 SDKは、処理を中断する前に最大5回まで再試行を行います。
再試行間隔 3秒 再接続の試行ごとに固定の遅延を設定(指数関数的バックオフなし)
メディアタイムアウト 10秒 接続の試行から10秒以内にメディアが確立されない場合、SDKはそれを失敗とみなします
完全自動復旧ウィンドウ 約15秒 5回の再試行 × 3秒間隔 = 失敗するまでの最大15秒間の自動回復

各段階での流れ

  1. 再接続 — SDKがメディアの中断を検知すると、以下の処理が実行されます onCallMediaReconnecting. 3秒間隔で最大5回までICEの再起動を試行します。この段階では、開発者による操作は必要ありません。

  2. 再接続 — いずれかの再試行が成功すると、SDKが呼び出されます onCallMediaReconnection. 音声ストリームが復旧し、通話は通常通り続行されます。

  3. 失敗 — 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).