WebRTC Safari无本地摄像头时无ICE候选回调无法接收视频流问题
问题:Safari无需本地摄像头权限接收WebRTC视频流的解决方案
问题现象
在Safari浏览器中使用WebRTC时,若未添加本地视频轨道,ICE候选回调始终不会触发,导致无法接收远端视频流;而Chrome浏览器无此限制。具体测试表现:
- Chrome中点击"Without Local Camera",会触发ICE候选回调并弹出提示;
- Safari中点击该按钮无响应,仅在点击"With Local Camera"并授权本地摄像头后,ICE回调才会生效。
原始测试代码
function handleICECandidateEvent(event) { alert("ICE callback"); console.log(event); } async function start_(arg) { alert("Starting " + arg); let peerConnection = new RTCPeerConnection({iceServers:[{urls: 'stun:stun1.l.google.com:19302'}]}); peerConnection.onicecandidate = handleICECandidateEvent; if (arg) { const s = await navigator.mediaDevices.getUserMedia({video:true}); s.getTracks().forEach(track => {peerConnection.addTrack(track, s);}); } const offer = await peerConnection.createOffer({offerToReceiveAudio: true, offerToReceiveVideo: true}); await peerConnection.setLocalDescription(offer); }
解决方案
Safari的WebRTC实现要求RTCPeerConnection必须关联至少一条本地媒体轨道,才会启动ICE候选收集流程。我们可以通过添加虚拟空轨道绕过这一限制,无需请求用户摄像头权限。
修改后的代码如下:
function handleICECandidateEvent(event) { alert("ICE callback"); console.log(event); } async function start_(arg) { alert("Starting " + arg); let peerConnection = new RTCPeerConnection({iceServers:[{urls: 'stun:stun1.l.google.com:19302'}]}); peerConnection.onicecandidate = handleICECandidateEvent; if (arg) { const s = await navigator.mediaDevices.getUserMedia({video:true}); s.getTracks().forEach(track => {peerConnection.addTrack(track, s);}); } else { // 创建空视频轨道,无需摄像头权限 const emptyVideoTrack = document.createElement('canvas').captureStream().getVideoTracks()[0]; peerConnection.addTrack(emptyVideoTrack); } const offer = await peerConnection.createOffer({offerToReceiveAudio: true, offerToReceiveVideo: true}); await peerConnection.setLocalDescription(offer); }
原理说明
通过canvas.captureStream()生成一个空的视频轨道,该轨道不需要访问真实摄像头,因此不会触发权限请求。将其添加到RTCPeerConnection后,即可满足Safari对本地轨道的要求,触发ICE候选回调,正常建立WebRTC连接并接收远端视频流。
内容的提问来源于stack exchange,提问作者gregoiregentil
相关产品推荐
相关产品推荐

