現象
iOS 15.1 Safari (確認したところiOSのChromeでも) を利用して、WebRTCのコネクションを張ったあとの通話中などに、カメラのオン・オフを切り替えると、画面がリロードされ、ブラウザがクラッシュ(?)し、通話が切れるなどの不具合があります。
コードを変えてないにも関わらず、最新OSでのお問い合わせが多発したため、最初自分のコードを疑い、getUserMediaの実装方法が悪いのだと思い込んで、かなり調べても理由がわからなかったのですが、webkitのバグ報告にたどりつき、こちらの対応できました。
不具合内容はこちら
https://bugs.webkit.org/show_bug.cgi?id=232006
記事を読むと、H.264のコーデックを利用していると不具合がおきるらしく、コメントがあるように、他のビデオコーデックVP9を利用してみる事にしました。
現象、H.264を利用してWebRTCのサービス提供は不可能に近く、Appleのアップデートを待つしかない。
利用環境
NTTコミュニケーションズが提供している WebRTCのサービス「SkyWay」を利用しています。
SkyWayでは、通話のコーデックを、H.264、V8、V9の3種類から選択できます。
peer.call
、mediaConnection.answer
時にパラメータとして、videoCodecが指定でき、指定していないと問題のH.264が、defaultになっています。
コードサンプル
<!DOCTYPE HTML>
<html lang="ja" prefix="og: http://ogp.me/ns#">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
<script type="text/javascript" src="//cdn.webrtc.ecl.ntt.com/skyway-latest.js"></script>
</head>
<body>
<video id="remote_video" autoplay playsinline style="width:360px"></video><br>
<video id="my_video" muted="true" autoplay playsinline style="width: 360px; transform: scaleX(-1);"></video><br>
<button id="camera">camera off</button><br>
<div id="my_peer_id"></div>
<input type="text" id="peer_id"></input>
<button id="call" style="display: none">call</button><br>
</body>
<script>
window.__SKYWAY_KEY__ = "SKYWAY_API_KEY";
let localStream;
navigator.mediaDevices.getUserMedia({audio: true, video: true})
.then(function (stream) {
localStream = stream;
const localVideo = document.getElementById('my_video');
localVideo.srcObject = stream;
localVideo.play();
});
const camera_button = document.getElementById('camera');
camera_button.addEventListener('click', () => {
const enabled = localStream.getVideoTracks()[0].enabled;
localStream.getVideoTracks()[0].enabled = !enabled;
camera_button.innerHTML = enabled ? 'camera on' : 'camera off';
});
const call_button = document.getElementById('call');
call_button.addEventListener('click', () => {
const peer_id = document.getElementById('peer_id').value;
let conn = peer.call(peer_id, localStream, {
videoCodec: 'VP9',
});
conn.on("stream", (stream) => {
const remoteVideo = document.getElementById('remote_video');
remoteVideo.srcObject = stream;
remoteVideo.play();
});
});
const peer = new Peer({
key: window.__SKYWAY_KEY__,
debug: 0,
});
peer.on('open', () => {
call_button.style.display = "block";
const my_peer_id = document.getElementById('my_peer_id');
my_peer_id.innerHTML = peer.id;
});
peer.on("call", (mediaConnection) => {
mediaConnection.answer(localStream, {
videoCodec: 'VP9',
});
mediaConnection.on("stream", (stream) => {
const remoteVideo = document.getElementById('remote_video');
remoteVideo.srcObject = stream;
remoteVideo.play();
});
});
</script>
</html>