如何在Safari浏览器中将canvas.captureStream输出到video元素?
问题根因
这个现象是Safari对canvas.captureStream的实现特性导致的,核心有三个问题:
- Safari要求canvas捕获的媒体流有持续的帧输出,仅绘制一次的静态canvas生成的流会被判定为无有效内容,不会渲染到video元素上
- 静态canvas生成的流不会触发video的
canplaythrough事件,你绑定的播放逻辑永远不会执行 - 你的代码里
canvas1.globalCompositeOperation写法错误,该属性是2D上下文的属性,不是canvas元素本身的属性,赋值到元素上不生效
修复方案
按以下几点修改代码即可兼容Safari:
- 调用
captureStream时主动传入帧率参数,告知浏览器需要按指定帧率生成流 - 赋值
srcObject后直接调用video.play(),无需等待canplaythrough事件 - 修正合成模式的赋值位置,添加低消耗的定时重绘逻辑保证流持续有帧输出
修复后完整代码
JS代码
let img_source = document.getElementById('img_source'); let canvas1 = document.getElementById('canvas1'); let video = document.getElementById('videoOutput'); let animationId = null; img_source.crossOrigin = "Anonymous"; document.getElementById('start').addEventListener('click', async function(){ // 先停止之前的重绘逻辑避免重复执行 if (animationId) cancelAnimationFrame(animationId); canvas1.width = img_source.naturalWidth; canvas1.height = img_source.naturalHeight; let ctx1 = canvas1.getContext('2d'); // 合成模式要赋值给上下文对象 ctx1.globalCompositeOperation = 'copy'; ctx1.drawImage(img_source, 0, 0); // 传入帧率参数 let stream = canvas1.captureStream(10); video.srcObject = stream; try { // 直接调用播放,无需等待事件 await video.play(); } catch (e) { console.error('播放失败', e); } // 持续重绘保证流有输出,静态内容消耗极低 function redraw() { ctx1.drawImage(img_source, 0, 0); animationId = requestAnimationFrame(redraw); } redraw(); });
CSS代码
body{ background-color: #ccc; } canvas, img { display: none; }
HTML代码
<button id="start">start</button> <img id="img_source" src="https://image.shutterstock.com/image-vector/sample-stamp-grunge-texture-vector-260nw-1389188336.jpg" /> <canvas id="canvas1" ></canvas> <video id="videoOutput" muted playsinline loop></video>
内容的提问来源于stack exchange,提问作者william_dev
相关产品推荐
相关产品推荐

