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

如何在安卓端Firefox浏览器中切换摄像头视频流

安卓端Firefox摄像头切换问题解决方案

问题根因

  • 现有代码仅在报错触发handleError时才停止旧流,正常切换摄像头时未主动释放之前的摄像头硬件占用。安卓Firefox对摄像头硬件独占权限要求比Chrome/Safari更严格,旧流未完全释放就请求新流会直接触发启动失败
  • 未在请求新流前清理video元素的srcObject绑定,旧流的引用残留会导致Firefox无法完成新流的挂载
  • 部分版本安卓Firefox对facingMode约束的格式兼容性差,直接传值的写法无法被正确识别
  • 摄像头硬件释放是异步操作,未加等待逻辑直接立即请求新流会导致硬件还处于占用状态

修复方案

第一步:调整流释放逻辑,每次请求新流前先主动清理旧资源

请求新的getUserMedia前,先停止已有流的所有track,清空video元素的srcObject,并增加短时间等待确保硬件完全释放。

第二步:适配Firefox的facingMode约束写法

用ideal包裹facingMode参数,适配Firefox的约束解析规则。

修改后的完整代码如下:

// 封装旧流释放工具方法,确保硬件资源完全释放
function releaseOldStream() {
  return new Promise((resolve) => {
    if (stream) {
      stream.getTracks().forEach(track => track.stop());
      stream = null;
    }
    if (videoElement.srcObject) {
      videoElement.srcObject = null;
    }
    // 给Firefox预留100ms硬件释放时间,可根据实际情况调整时长
    setTimeout(resolve, 100);
  });
}

async function getStream() {
  // 先释放旧资源再请求新流
  await releaseOldStream();
  const facingMode = Session.get('facingMode');
  const constraints = {
    video: { 
      // 用ideal包裹facingMode适配Firefox的约束解析规则
      facingMode: { ideal: facingMode }
    }
  };
  return navigator.mediaDevices.getUserMedia(constraints)
    .then(gotStream)
    .catch(handleError);
}

function gotStream(_stream) {
  stream = _stream
  videoElement.srcObject = stream;
}

function handleError(error) {
  // 报错后依然执行资源清理避免硬件占用
  if (stream) {
    stream.getTracks().forEach(track => track.stop());
    stream = null;
  }
  videoElement.srcObject = null;
  console.error('Error: ', error);
}

额外验证点

  • 确认安卓Firefox的系统应用权限设置中已经授予相机权限,且没有其他后台应用/标签页占用摄像头
  • 若仍有问题可尝试将facingMode配置中的ideal改为exact,强制要求匹配对应摄像头

内容的提问来源于stack exchange,提问作者Timo Frionnet

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 10:45:03