HTMLCanvasElement.captureStream返回MediaStream视频流而非原始像素数据,用于录屏、WebRTC等场景;需持续重绘canvas才能更新帧,不依赖await且默认60fps。

HTMLCanvasElement.captureStream 本身不直接提供“原始像素数据”,而是返回一个 MediaStream,用于实时捕获画布的渲染画面(即视频帧流)。它本质上是异步采集**已绘制内容的视频流**,而非逐帧读取 RGBA 数组。若目标是获取原始像素(如 Uint8ClampedArray),需配合 canvas.getContext('2d').getImageData() 或 OffscreenCanvas + transferToImageBitmap 等方式——但这些与 captureStream 是两条不同路径。
captureStream 的核心用途:输出可播放/传输的视频流
该方法适用于录屏、WebRTC 推流、实时预览等场景,底层由浏览器自动按帧率抓取 canvas 当前渲染状态,封装为 VideoTrack:
- 调用后立即返回
MediaStream,无需 await(它本身是同步的) - 流中的视频轨道会随 canvas 内容更新而自动刷新帧(依赖 canvas 是否重绘、是否在 document 中、是否启用
willReadFrequently等) - 默认帧率为 60fps;可传入参数指定最小帧率,如
canvas.captureStream(30)
确保流持续更新的关键条件
captureStream 不会“主动轮询”或监听 canvas 变化,它依赖浏览器渲染循环和 canvas 的实际重绘行为:
- canvas 必须已挂载到 DOM(或使用
OffscreenCanvas配合 worker,但 captureStream 目前仅支持 on-screen canvas) - 每次想推送新帧,必须显式调用
ctx.clearRect()+ctx.drawImage()等绘制操作(哪怕只重绘一次) - 若使用
requestAnimationFrame动画,需确保每帧都触发重绘;静止画面不会产生新帧 - 部分浏览器对隐藏标签页会降频或暂停流,可用
visibilitychange监听并手动恢复绘制
如何与原始像素处理协同工作
若既要原始像素分析,又要推流,建议分两路处理,避免阻塞:
立即学习“前端免费学习笔记(深入)”;
- 主线程:用
captureStream()获取流,交给MediaRecorder或RTCPeerConnection - 另起一个定时任务(如
setInterval或 rAF)读取像素:ctx.getImageData(0, 0, width, height),注意该操作较重,勿高频调用 - 更高效方案:使用
OffscreenCanvas在 Worker 中离屏渲染 + 像素计算,再将结果 postMessage 回主线程绘制到 visible canvas(从而驱动 captureStream 出帧)
简单可用示例(含错误防护)
以下代码创建可工作的 captureStream 流,并连接到 video 元素预览:
const canvas = document.getElementById('myCanvas');
const ctx = canvas.getContext('2d');
<p>// 启动流(建议在用户手势后调用,避免被浏览器拦截)
const stream = canvas.captureStream(30); // 30fps</p><p>// 检查是否获取到视频轨道
const videoTrack = stream.getVideoTracks()[0];
if (!videoTrack) {
console.warn('captureStream returned no video track');
}</p><p>// 播放预览(可选)
const video = document.getElementById('preview');
video.srcObject = stream;</p><p>// 必须持续重绘才能出帧(例如动画循环)
function animate() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.fillStyle = <code>hsl(${Date.now() * 0.1 % 360}, 100%, 50%)</code>;
ctx.fillRect(10, 10, 100, 100);
requestAnimationFrame(animate);
}
animate();</p>



















