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

基于视频流颜色修改页面背景色异常:始终返回rgb(0,0,0)

问题原因与修复方案

你的代码始终返回rgb(0,0,0)的核心原因是画布数据读取与视频绘制的顺序颠倒,同时存在定时器参数的错误,以下是具体修复:

核心问题分析

  • 你先调用cx.getImageData(0, 0, w, h)获取画布数据,之后才用cx.drawImage(i, 0, 0, w, h)把视频帧画到画布上。此时读取到的是空白画布的像素数据(全为0),计算出的RGB值自然都是0。
  • setInterval的第二个参数传了-1,会被浏览器解析为0,导致回调函数执行过于频繁,严重影响性能。

修复后的代码

'use strict';
try {
    const windowRef = window,
          doc = document,
          navigatorRef = navigator,
          getById = e => doc.getElementById(e),
          canvas = getById('lh'),
          video = getById('i'),
          outputImg = getById('o'),
          ctx = canvas.getContext('2d', { willReadFrequently: true }),
          initCamera = step => navigatorRef.mediaDevices.getUserMedia({
              video: { facingMode: { exact: 'user' } }
          }).then(stream => {
              video.srcObject = stream;
              video.onloadedmetadata = () => {
                  setInterval(() => {
                      let pixelCount = 0;
                      let rTotal = 0, gTotal = 0, bTotal = 0;
                      // 先设置画布尺寸并绘制视频帧
                      const videoHeight = video.videoHeight;
                      const videoWidth = video.videoWidth;
                      canvas.height = videoHeight;
                      canvas.width = videoWidth;
                      ctx.drawImage(video, 0, 0, videoWidth, videoHeight);
                      // 再读取画布像素数据
                      const imageData = ctx.getImageData(0, 0, videoWidth, videoHeight);
                      const data = imageData.data;
                      const dataLength = data.length;
                      // 遍历像素计算颜色平均值
                      for (let i = 0; i < dataLength; i += step * 4) {
                          pixelCount++;
                          rTotal += data[i];
                          gTotal += data[i + 1];
                          bTotal += data[i + 2];
                      }
                      // 计算平均RGB值,替代不安全的eval写法
                      const avgR = ~~(rTotal / pixelCount);
                      const avgG = ~~(gTotal / pixelCount);
                      const avgB = ~~(bTotal / pixelCount);
                      // 设置背景色
                      const rgbStr = `rgb(${avgR},${avgG},${avgB})`;
                      doc.body.style.background = rgbStr;
                      // 更新预览图(可选)
                      outputImg.src = canvas.toDataURL('image/webp');
                  }, 16); // 约60fps的间隔,平衡流畅度与性能
              };
          });
    initCamera(4);
} catch (e) {
    alert(e.message);
}

关键修改点

  1. 调整绘制与读取顺序:先执行drawImage将视频帧绘制到画布,再调用getImageData读取有效像素数据。
  2. 修复定时器间隔:将-1改为16(约60帧/秒),避免过度占用CPU。
  3. 替换eval写法:直接计算平均RGB值,消除安全风险,提升代码可读性。
  4. 优化变量命名:将缩写变量改为语义化名称,便于后续维护。

内容的提问来源于stack exchange,提问作者HEMANT ABHIRAM SOMARAJU SCJC I

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 01:55:03