新SkyWayにおけるモバイルブラウザのスリープ・サスペンド対策

新SkyWay(@skyway-sdk/room)を使ったWebRTCアプリケーションを
スマートフォンやタブレットで運用すると、PCでは起きない特有の問題が発生します。

特に多いのが、

  • 画面ロック後に映像・音声が復帰しない
  • バックグラウンド復帰後に接続が切れたままになる
  • iOS Safariで数十秒放置すると通信が完全停止する

といった スリープ・サスペンド関連のトラブルです。

本記事では、新SkyWay × モバイルブラウザで安定した通信を実現するための方法を詳しく解説します。

なぜモバイルは不安定になるのか?

モバイルブラウザでは、省電力のためにOSが強制的にプロセスを制御します。

主な挙動

状態挙動
画面OFFJSタイマー停止 / WebRTC通信停止
バックグラウンドJS実行停止 / WebSocket切断
タブ非アクティブsetInterval / requestAnimationFrame 停止
低電力モードCPU / ネットワーク制限

特に iOS Safari は制限が厳しいため、

「通信が勝手に切断される」
「復帰後にイベントが発火しない」

という現象が頻発します。


新SkyWayにおける問題の本質

新SkyWayは、

  • Room
  • Member
  • Publication
  • Subscription

という状態を すべてクライアント側で保持します。

モバイル環境で JSが一時停止 → 復帰 すると、

  • WebSocketが切断
  • PeerConnectionが破棄
  • 内部状態が破綻

という状態になり、

Room上は存在しているが、実通信は死んでいる

という ゾンビ接続状態 に陥ります。


基本方針:復帰時は「必ず再構築」

モバイルでは、復帰時にすべてを作り直す設計が最も安定します。

項目方針
Room再Join
Member新規生成
LocalStream再取得
Publication再publish
Subscription再subscribe

つまり:

復帰 = フル再接続

と割り切る設計が正解です。


Page Visibility API を使った復帰検知

まず、画面状態の変化を確実に検知します。

document.addEventListener("visibilitychange", async () => {
  if (document.visibilityState === "visible") {
    await reconnectSkyway();
  }
});

iOS / Android / Chrome / Safari 全対応で、
バックグラウンド → 復帰 を検知できます。


安定した再接続フロー設計

推奨フロー:

visibilitychange (visible)
  ↓
現在の Room を完全破棄
  ↓
SkyWayContext 再生成
  ↓
Room 再Join
  ↓
LocalStream 再取得
  ↓
再 publish
  ↓
既存 Publication を再 subscribe

再接続処理 実装例(実戦用)

async function reconnectSkyway() {
  console.log("SkyWay reconnect start");

  if (room) {
    try {
      await room.leave();
    } catch (e) {}
  }

  const context = await SkyWayContext.Create(token);

  room = await SkyWayRoom.FindOrCreate(context, {
    type: "p2p",
    name: roomName,
  });

  member = await room.join();

  const { audio, video } =
    await SkyWayStreamFactory.createMicrophoneAudioAndCameraStream();

  await member.publish(video);
  await member.publish(audio);

  setupSubscriptions(room, member);

  console.log("SkyWay reconnect completed");
}

iOS Safari 特有の罠

① WebRTC が強制終了される

iOS Safari は、バックグラウンド時に WebRTCスタックを強制破棄します。

復帰後に PeerConnection を再利用できません

対策

  • 必ず LocalStream を再生成
  • publish をやり直す

② 画面ONでも通信が止まる

iOS は、

  • 通話以外の WebRTC通信

バックグラウンドで完全停止 します。

→ 復帰後も内部状態が壊れたまま

対策

  • visibilitychange で即再構築

③ setInterval が止まる

setInterval(...)

は、
iOS Safari では バックグラウンド時に完全停止 します。

→ KeepAlive 実装が無意味になります。


ハートビート監視による切断検出

バックグラウンド復帰時に、

  • まだRoomに接続されているか
  • 実通信が生きているか

論理的に判定 するため、
ハートビート監視 を入れると安定します。

let lastAlive = Date.now();

room.onStreamPublished.add(() => {
  lastAlive = Date.now();
});

setInterval(() => {
  if (Date.now() - lastAlive > 15000) {
    reconnectSkyway();
  }
}, 5000);

Android Chrome の注意点

Android Chrome では、

  • バックグラウンド時に JS 実行制限
  • CPU / ネットワーク制限

がかかるため、

  • 映像がカクつく
  • 音声が途切れる

現象が発生します。

対策

  • SFU構成を利用
  • 映像ビットレートを制限
  • フレームレートを15fps程度に抑制

モバイル安定化 設計指針まとめ

項目推奨
復帰処理フル再構築
Stream再生成
publish必ず再実行
subscribe既存全件再購読
切断検知visibility + heartbeat
iOS対策再接続前提設計

まとめ

新SkyWayをモバイル環境で安定稼働させるには、

「切れる前提」で設計する

ことが最も重要です。

特に、

  • iOS Safari
  • タブレット端末
  • 低電力モード

では 通信断は必ず発生 します。

新SkyWayの

  • Room
  • Publication
  • Subscription

という構造を正しく理解し、
復帰時に全再構築する設計 を採用することで、
安定したリアルタイム通信を実現できます。