WebRTC连接摄像头无权限/未找到时如何关闭视频避免报错
解决方案
报错的核心原因是你在调用createOffer时硬编码了强制协商视频轨道的参数,当本地无可用摄像头、用户拒绝摄像头权限时,WebRTC无法完成视频相关的媒体协商逻辑,就会抛出异常。按以下步骤处理即可实现摄像头异常时自动降级为仅音频模式,避免报错:
- 提前做媒体能力检测,捕获视频申请异常
不要跳过getUserMedia的异常处理直接创建offer,先申请媒体权限,在申请阶段就识别视频不可用的场景,自动降级:let localStream = null; let videoAvailable = true; try { // 优先尝试同时申请音视频权限 localStream = await navigator.mediaDevices.getUserMedia({ audio: true, video: true }); // 二次校验实际是否拿到有效视频轨道,避免设备返回空轨道的异常场景 videoAvailable = localStream.getVideoTracks().length > 0; } catch (err) { // 识别视频相关的异常:设备不存在、用户拒绝权限、设备被占用、参数不匹配 const videoRelatedErrors = ['NotFoundError', 'NotAllowedError', 'NotReadableError', 'OverconstrainedError']; if (videoRelatedErrors.includes(err.name)) { console.warn('视频功能不可用,自动降级为仅音频模式', err); videoAvailable = false; // 降级仅申请音频权限,保证基础通话能力 try { localStream = await navigator.mediaDevices.getUserMedia({ audio: true, video: false }); } catch (audioErr) { console.error('音频设备也不可用', audioErr); } } else { // 非视频相关异常直接抛出,不做吞错 throw err; } } // 将成功获取的媒体轨道添加到PeerConnection if (localStream) { localStream.getTracks().forEach(track => { peerConnection.addTrack(track, localStream); }); } - 动态生成offer参数,不硬编码视频协商要求
你当前使用的offerToReceiveAudio/offerToReceiveVideo是遗留的非标准参数,建议根据前面检测到的videoAvailable状态动态传参,或者直接使用更稳定的Transceiver API:- 兼容旧版浏览器的传参方式:
const offer = await peerConnection.createOffer({ offerToReceiveAudio: 1, // 视频可用才协商视频轨道,否则关闭视频协商 offerToReceiveVideo: videoAvailable ? 1 : 0 }); await peerConnection.setLocalDescription(offer); // 后续正常将offer发送给对端即可- 新版标准Transceiver写法(推荐,逻辑更清晰):
// 固定添加音频收发器 peerConnection.addTransceiver('audio', { direction: 'sendrecv' }); // 仅当视频可用时才添加视频收发器 if (videoAvailable) { peerConnection.addTransceiver('video', { direction: 'sendrecv' }); } // 不需要额外传offer参数,会自动根据已添加的收发器生成合法SDP const offer = await peerConnection.createOffer(); await peerConnection.setLocalDescription(offer); - 极端场景兼容:如果因为特殊原因无法提前检测媒体状态,可以在生成offer SDP后手动修改SDP内容,将
m=video开头的媒体行端口修改为0,等价于告知对端本端不支持视频,也能避免协商报错。
注意:不要在未确认本地媒体能力的前提下,强制在offer中声明要收发视频,否则不仅
createOffer会抛出错误,后续ICE连接、媒体流传输阶段也大概率出现异常。
内容的提问来源于stack exchange,提问作者Someone
相关产品推荐
相关产品推荐

