新SkyWayにおけるモバイルブラウザのスリープ・サスペンド対策
新SkyWay(@skyway-sdk/room)を使ったWebRTCアプリケーションを
スマートフォンやタブレットで運用すると、PCでは起きない特有の問題が発生します。
特に多いのが、
- 画面ロック後に映像・音声が復帰しない
- バックグラウンド復帰後に接続が切れたままになる
- iOS Safariで数十秒放置すると通信が完全停止する
といった スリープ・サスペンド関連のトラブルです。
本記事では、新SkyWay × モバイルブラウザで安定した通信を実現するための方法を詳しく解説します。
なぜモバイルは不安定になるのか?
モバイルブラウザでは、省電力のためにOSが強制的にプロセスを制御します。
主な挙動
| 状態 | 挙動 |
|---|---|
| 画面OFF | JSタイマー停止 / 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
という構造を正しく理解し、
復帰時に全再構築する設計 を採用することで、
安定したリアルタイム通信を実現できます。