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

iOS 11.3 Safari中getUserMedia调用摄像头显示黑屏问题咨询

iOS 11.3 Safari中getUserMedia渲染到Canvas的黑色方块问题解决

我之前帮不少开发者踩过iOS 11.3 Safari这个getUserMedia转Canvas的坑,确实这个版本的Safari对媒体流渲染到Canvas存在兼容性bug,导致你提到的测试页面都只能显示黑色方块。结合实际排查经验,给你几个关键的解决思路:

  • 必须等待视频元数据加载完成再绘制:iOS Safari在视频的loadedmetadata事件触发前,视频的实际宽高都是0,直接调用drawImage只会绘制出黑色区域。一定要监听这个事件后再启动绘制循环。
  • 正确设置Canvas的缓冲区尺寸:别只靠CSS给Canvas设置宽高,必须手动把Canvas的width和height属性设置为视频的videoWidth和videoHeight——CSS尺寸只是显示用的,绘图缓冲区尺寸才决定渲染内容的清晰度和是否正常显示。
  • 添加playsinline属性:iOS 11.3里视频默认会强制全屏播放,加上playsinline才能让视频在页面内嵌入播放,否则根本无法捕获画面到Canvas。

这里给你一段经过验证的代码示例:

<video id="cameraVideo" playsinline></video>
<canvas id="outputCanvas"></canvas>
<button id="startBtn">启动摄像头</button>

<script>
// 通过用户交互触发,规避iOS自动播放限制
document.getElementById('startBtn').addEventListener('click', () => {
  navigator.mediaDevices.getUserMedia({ video: true })
    .then(stream => {
      const video = document.getElementById('cameraVideo');
      const canvas = document.getElementById('outputCanvas');
      const ctx = canvas.getContext('2d');

      video.srcObject = stream;

      video.addEventListener('loadedmetadata', () => {
        // 同步Canvas尺寸到视频实际分辨率
        canvas.width = video.videoWidth;
        canvas.height = video.videoHeight;

        // 循环绘制视频帧到Canvas
        function renderFrame() {
          ctx.drawImage(video, 0, 0, canvas.width, canvas.height);
          requestAnimationFrame(renderFrame);
        }
        renderFrame();
      });

      video.play().catch(err => console.error('视频播放失败:', err));
    })
    .catch(err => console.error('获取摄像头权限失败:', err));
});
</script>

另外还要注意iOS的自动播放限制:媒体播放必须由用户主动交互(比如点击按钮)触发,如果你在页面加载完成后直接调用play(),大概率会被Safari阻止,导致视频无法播放,Canvas自然还是黑色。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.22 08:30:02