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

Screen Capture API自动截图生成白色Base64问题排查

问题原因及解决方案

你的代码中,自动捕获出现空白画面的核心问题是错误地直接执行了resolve函数,而非将其绑定到onplaying事件的回调逻辑中,导致Promise在视频还未完成画面渲染时就提前完成,此时调用takeScreenshot()无法捕获到有效帧。

具体问题分析

原代码中这一行存在逻辑错误:

return new Promise(resolve => video.onplaying = resolve(captureStream));

这里直接执行了resolve(captureStream),并将执行结果(undefined)赋值给video.onplaying,相当于Promise立刻进入resolved状态,此时视频元素还没完成媒体流的加载和第一帧的渲染,自然只能捕获到空白画面。而手动点击按钮时,已经过了足够时间让视频完成渲染,所以能正常工作。

修正后的代码

const video = document.getElementById("video");
const canvas = document.getElementById("canvas");
const text = document.getElementById("text");
const startButton = document.getElementById("startButton");
const captureButton = document.getElementById("captureButton");
const context = canvas.getContext("2d");

captureButton.addEventListener("click", function() {
  try {
    navigator.mediaDevices.getDisplayMedia({
      audio: false
    }).then(captureStream => {
      video.srcObject = captureStream;
      // 关键修正:将resolve放入onplaying的回调函数中,等待事件触发再执行
      return new Promise(resolve => video.onplaying = () => resolve(captureStream));
    }).then((captureStream) => {
      takeScreenshot();
    })
  } catch (err) {
    console.error("Error: " + err);
  }
});

startButton.addEventListener("click", function() {
  takeScreenshot();
});

function takeScreenshot() {
  // 复用已获取的context,无需重复调用getContext
  context.drawImage(video, 0, 0, 300, 150);
  const frame = canvas.toDataURL("image/png");
  text.innerHTML = frame;
}

额外优化说明

  1. 将takeScreenshot声明为标准函数,避免隐式全局变量
  2. 复用提前获取的context对象,减少不必要的DOM API调用
  3. 如果需要更精准地捕获第一帧,也可以考虑使用video.onloadeddata事件,该事件会在视频的第一帧加载完成后触发

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 21:23:27