如何使用原生 JavaScript Canvas API 实现视频中的绿幕背景替换功能 All In One
如何使用原生 JavaScript Canvas API 实现视频中的绿幕背景替换功能 All In One
Canvas & Video
demos
chroma-keying / green screen effect
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();
});
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, 禁止转载 🈲️,侵权必究⚠️!
本文首发于博客园,作者:xgqfrms,原文链接:https://www.cnblogs.com/xgqfrms/p/17621857.html
未经授权禁止转载,违者必究!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· C#/.NET/.NET Core技术前沿周刊 | 第 29 期(2025年3.1-3.9)
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异
2022-08-10 leetcode 螺旋矩阵算法题解 All In One
2022-08-10 custom control the vscode's terminal print log length All In One
2022-08-10 在线 Java 语言编程 All In One
2021-08-10 vue keep-alive & dynamic components All In One
2021-08-10 npm ignore scripts All In One
2020-08-10 How to create a folder symbol link on macOS All In One
2020-08-10 Python & file operation mode