You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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:
    1. 兼容旧版浏览器的传参方式:
    const offer = await peerConnection.createOffer({
      offerToReceiveAudio: 1,
      // 视频可用才协商视频轨道,否则关闭视频协商
      offerToReceiveVideo: videoAvailable ? 1 : 0
    });
    await peerConnection.setLocalDescription(offer);
    // 后续正常将offer发送给对端即可
    
    1. 新版标准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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 22:27:27