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

如何在Safari浏览器中将canvas.captureStream输出到video元素?

问题根因

这个现象是Safari对canvas.captureStream的实现特性导致的,核心有三个问题:

  • Safari要求canvas捕获的媒体流有持续的帧输出,仅绘制一次的静态canvas生成的流会被判定为无有效内容,不会渲染到video元素上
  • 静态canvas生成的流不会触发video的canplaythrough事件,你绑定的播放逻辑永远不会执行
  • 你的代码里canvas1.globalCompositeOperation写法错误,该属性是2D上下文的属性,不是canvas元素本身的属性,赋值到元素上不生效
修复方案

按以下几点修改代码即可兼容Safari:

  1. 调用captureStream时主动传入帧率参数,告知浏览器需要按指定帧率生成流
  2. 赋值srcObject后直接调用video.play(),无需等待canplaythrough事件
  3. 修正合成模式的赋值位置,添加低消耗的定时重绘逻辑保证流持续有帧输出
修复后完整代码

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.08 08:57:02