HTML5 不支持 alpha 通道视频(例如 MOV 32 位等)。
唯一的选择是使用哑光合成,就像您的视频结合画布元素一样。但是,canvas 只能合成已经存在的 alpha 通道,并且由于 matte 是一个纯层而不是 alpha,所以您必须将其转换为 alpha。
这意味着您必须在画布上绘制和迭代每一帧,并将灰度转换为透明度级别。但是,这会占用大量 CPU 资源,并且会影响计算机性能/资源。视频还必须满足 CORS 要求才能不污染画布(在这种情况下,您无法提取像素)。
方法如下
对于每一帧:
- 从任何通道为每个像素获取一个级别,我们将在这里使用红色
- 从 255 中减去该值,因为此处的哑光白色将成为目标(反转,将显示)
- 清除 图像 数据,这是遮罩本身,否则您会得到白色遮罩泄漏到数据中
- 将计算值设置为新的 Alpha 通道值
示例循环(假设视频是动态创建的,已设置其源并已触发启动事件 - 画布放置在您要屏蔽的位置并初始化上下文 ctx):
ctx.globalCompositeOperation = "copy"; // will clear previous alpha
function unmask() {
ctx.drawImage(video, 0, 0); // draw current video frame
var idata = ctx.getImageData(0, 0, ctx.canvas.width, ctx.canvas.height),
data = idata.data,
len = data.length, i = 0; // ..image data from canvas
while(i < len) {
var alpha = 255 - data[i]; // in this matte, white = fully transparent
data[i] = data[i+1] = data[i+2] = 0; // clear matte to black
data[i+3] = alpha; // set alpha
i += 4; // next pixel
}
ctx.putImageData(idata, 0, 0); // update canvas
requestAnimationFrame(unmask); // todo: add criteria to stop this
}
加速技巧:使用黑色(或预先反转哑光视频),然后对数据使用 Uint32Array 视图,将像素长字 (
使用新的CSS custom filters(又名 CSS 着色器)有可能实现此目的,但在撰写本文时尚未得到广泛支持。它还需要使用着色器语言 (GLSL)。但我觉得至少值得一提。