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

WebcamJS在Safari中隐藏摄像头元素时重复捕获旧图像问题

Safari隐藏摄像头元素时捕获重复旧图像的问题及解决方案

问题详情

开发监控系统时,需在用户许可下定时捕获图像,且摄像头HTML元素需对用户不可见。但在Safari 16.0中,当摄像头节点通过移出视口的方式隐藏时,会出现捕获旧图像的问题,仅在隐藏状态下可复现。

当前隐藏摄像头的样式:

#webcam{
  position: fixed;
  top: -10000px;
  left: -10000px;
}

复现条件

环境规格

  • 浏览器:Safari 16.0
  • 操作系统:MacOS 12.6
  • WebcamJS版本:1.0.26

复现步骤

  1. 在Safari中打开演示页面,页面每10秒捕获一次图像并渲染到DOM;
  2. 观察DOM中会重复出现旧图像。

核心代码

function loadWebcamJS(){
  const webcam = document.getElementById("webcam");
  Webcam.set({
    width: 640,
    height: 480
  });
  Webcam.attach(webcam);
  Webcam.on('load', afterLoad);
}
const getTime = (d) =>
    `${d.getHours()}:${d.getMinutes()}:${d.getSeconds()}`;

function snap(){
  Webcam.snap((dataURI) => {
    const results = document.getElementById('results');
    const date = new Date();
    const time = getTime(date);
    
    results.innerHTML += `
    <div class="image">
      <img src=${dataURI} alt="Snapped Image">
      <h4>${time}</h4>
    </div>
    `
  })
}
loadWebcamJS();
function afterLoad(){
  setInterval(() => {
    snap();
  }, 1000 * 10); // 每10秒捕获一次图像
}

问题原因

Safari的性能优化机制会暂停移出视口的视频元素的流更新,WebcamJS依赖的<video>元素被移出视口后,Safari会停止获取新的摄像头帧,导致捕获的是缓存的旧画面。

解决方案

方案1:修改隐藏样式,保持元素在视口内

改用以下样式,让摄像头元素在视口内但完全不可见,避免Safari暂停流更新:

#webcam {
  position: fixed;
  width: 1px;
  height: 1px;
  left: 0;
  top: 0;
  opacity: 0;
  pointer-events: none;
  z-index: -1;
}

方案2:捕获前临时激活视频流

如果必须保持移出视口的方式,可在每次捕获前临时将元素移回视口,完成后再隐藏:

function snap(){
  const webcam = document.getElementById("webcam");
  // 临时移回视口
  webcam.style.top = '0';
  webcam.style.left = '0';
  
  // 延迟捕获,确保流恢复
  setTimeout(() => {
    Webcam.snap((dataURI) => {
      const results = document.getElementById('results');
      const date = new Date();
      const time = getTime(date);
      
      results.innerHTML += `
      <div class="image">
        <img src=${dataURI} alt="Snapped Image">
        <h4>${time}</h4>
      </div>
      `;
      
      // 重新隐藏元素
      webcam.style.top = '-10000px';
      webcam.style.left = '-10000px';
    });
  }, 100);
}

方案3:使用原生MediaDevices API替代WebcamJS

WebcamJS基于旧API封装,原生API能更直接控制视频流,避免Safari优化机制的影响:

let stream;
async function loadWebcam(){
  const webcam = document.getElementById("webcam");
  stream = await navigator.mediaDevices.getUserMedia({ video: { width: 640, height: 480 } });
  webcam.srcObject = stream;
  await webcam.play();
  afterLoad();
}

function snap(){
  const webcam = document.getElementById("webcam");
  const canvas = document.createElement('canvas');
  canvas.width = webcam.videoWidth;
  canvas.height = webcam.videoHeight;
  const ctx = canvas.getContext('2d');
  ctx.drawImage(webcam, 0, 0);
  const dataURI = canvas.toDataURL('image/png');
  
  const results = document.getElementById('results');
  const date = new Date();
  const time = getTime(date);
  
  results.innerHTML += `
  <div class="image">
    <img src=${dataURI} alt="Snapped Image">
    <h4>${time}</h4>
  </div>
  `;
}

loadWebcam();
function afterLoad(){
  setInterval(() => {
    snap();
  }, 1000 * 10);
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 18:55:21