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
相关产品推荐
相关产品推荐

