如何使用原生 JavaScript Canvas API 实现视频中的绿幕背景替换功能 All In One

发布时间 2023-08-10 23:14:04作者: xgqfrms

如何使用原生 JavaScript Canvas API 实现视频中的绿幕背景替换功能 All In One

Canvas & Video

demos

chroma-keying / green screen effect

image

const processor = {};

processor.doLoad = function doLoad() {
  const video = document.getElementById("video");
  this.video = video;
  // canvas 1
  this.c1 = document.getElementById("c1");
  this.ctx1 = this.c1.getContext("2d");
  // canvas 2
  this.c2 = document.getElementById("c2");
  this.ctx2 = this.c2.getContext("2d");
  // event
  video.addEventListener(
    "play",
    () => {
      this.width = video.videoWidth / 2;
      this.height = video.videoHeight / 2;
      this.timerCallback();
    },
    false,
  );
};

processor.timerCallback = function timerCallback() {
  if (this.video.paused || this.video.ended) {
    return;
  }
  // computeFrame
  this.computeFrame();
  setTimeout(() => {
    this.timerCallback();
  }, 0);
};

processor.computeFrame = function () {
  // 绘制视频
  this.ctx1.drawImage(this.video, 0, 0, this.width, this.height);
  // 读取视频画面
  const frame = this.ctx1.getImageData(0, 0, this.width, this.height);
  // RGBA
  const data = frame.data;
  for (let i = 0; i < data.length; i += 4) {
    const red = data[i + 0];
    const green = data[i + 1];
    const blue = data[i + 2];
    // 绿色像素,置 0 ❓ 黑色
    if (green > 100 && red > 100 && blue < 43) {
      data[i + 3] = 0;
    }
  }
  // 绘制修改后的视频画面,背景来自背景图片 ✅
  this.ctx2.putImageData(frame, 0, 0);
};


<!doctype html>
<html lang="en-US">
  <head>
    <meta charset="UTF-8" />
    <title>Video test page</title>
    <style>
      body {
        background: black;
        color: #cccccc;
      }
      #c2 {
        /* 背景图片 ✅*/
        background-image: url(media/foo.png);
        background-repeat: no-repeat;
      }
      div {
        float: left;
        border: 1px solid #444444;
        padding: 10px;
        margin: 10px;
        background: #3b3b3b;
      }
    </style>
  </head>

  <body>
    <div>
      <video
        id="video"
        src="media/video.mp4"
        controls="true"
        crossorigin="anonymous" />
    </div>
    <div>
      <canvas id="c1" width="160" height="96"></canvas>
      <canvas id="c2" width="160" height="96"></canvas>
    </div>
    <script src="processor.js"></script>
  </body>
</html>

let processor = {
    timerCallback: function() {
      if (this.video.paused || this.video.ended) {
        return;
      }
      this.computeFrame();
      let self = this;
      setTimeout(function () {
          self.timerCallback();
        }, 0);
    },
    doLoad: function() {
      this.video = document.getElementById("video");
      this.c1 = document.getElementById("c1");
      this.ctx1 = this.c1.getContext("2d");
      this.c2 = document.getElementById("c2");
      this.ctx2 = this.c2.getContext("2d");
      let self = this;
      this.video.addEventListener("play", function() {
          self.width = self.video.videoWidth / 2;
          self.height = self.video.videoHeight / 2;
          self.timerCallback();
        }, false);
    },
    computeFrame: function() {
      this.ctx1.drawImage(this.video, 0, 0, this.width, this.height);
      let frame = this.ctx1.getImageData(0, 0, this.width, this.height);
      let l = frame.data.length / 4;
      for (let i = 0; i < l; i++) {
        let r = frame.data[i * 4 + 0];
        let g = frame.data[i * 4 + 1];
        let b = frame.data[i * 4 + 2];
        if (g > 100 && r > 100 && b < 43)
          frame.data[i * 4 + 3] = 0;
      }
      this.ctx2.putImageData(frame, 0, 0);
      return;
    }
  };

document.addEventListener("DOMContentLoaded", () => {
  processor.doLoad();
});

(? 反爬虫测试!打击盗版⚠️)如果你看到这个信息, 说明这是一篇剽窃的文章,请访问 https://www.cnblogs.com/xgqfrms/ 查看原创文章!

refs

https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API/Manipulating_video_using_canvas

https://github.com/mdn/dom-examples/tree/main/canvas/chroma-keying



©xgqfrms 2012-2021

www.cnblogs.com/xgqfrms 发布文章使用:只允许注册用户才可以访问!

原创文章,版权所有©️xgqfrms, 禁止转载 ?️,侵权必究⚠️!