首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >使用阿尔法通道视频掩蔽HTML内容

使用阿尔法通道视频掩蔽HTML内容
EN

Stack Overflow用户
提问于 2015-03-27 18:25:05
回答 3查看 2.4K关注 0票数 2

我正在努力实现目前在“后效应”中可能出现的效果,其效果是关于剪辑-掩蔽(luma matte)一个视频与另一个视频,因此最终输出将是一个透明的视频。但我正在尝试制作一个动态透明的HTML内容。

视频应该是这样的:https://www.youtube.com/watch?v=jfzcrO4694E

基本上显示HTML内容与变化的透明度。

这必须是关于+的内容,但在谷歌大约一个小时之后,无法找到任何能够描述和影响黑白视频的内容,从而改变HTML内容的透明度。

有什么想法吗?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2015-03-27 19:23:34

HTML5不支持alpha信道视频(例如MOV 32位等)。

唯一的选择是使用与画布元素相结合的像视频一样合成的哑光体。然而,canvas只组合了已经存在的alpha通道,而作为一个纯层而不是alpha层,您必须将其转换为alpha。

这意味着您必须绘制每个帧并将其迭代到画布上,并将灰度转换为透明级别。然而,这是非常密集的CPU,将影响计算机的性能/资源。为了不污染画布,视频还必须满足CORS的要求(在这种情况下,您不能提取像素)。

以下是如何

对于每一帧:

  • 从每个像素的任何通道获取一个级别,我们将在这里使用红色
  • 从255减去值,因为这里的白光将是目标(反转,将显示)
  • 清除图像数据,这是冰霜本身,否则您将得到白色的数据泄漏到数据。
  • 将计算值设置为新的alpha通道值

示例循环(假设视频是动态创建的,其源设置并已触发启动事件-将画布放置在您想要掩码的位置,并初始化上下文ctx ):

代码语言:javascript
运行
复制
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视图,将像素长字(<<24)移回原处。

有一个微小的可能性,你将能够做到这与新的https://www.adobe.com/devnet/archive/html5/articles/css-shaders.html (又名CSS着色器),但这并不是广泛支持在撰写本文时。它还需要使用着色语言(https://en.wikipedia.org/wiki/OpenGL_Shading_Language)。但我觉得至少值得一提。

票数 3
EN

Stack Overflow用户

发布于 2015-03-30 15:37:40

到目前为止,其他答案假设为2D画布上下文。使用WebGL可以更有效地完成这一任务。这样,所有真正的工作都是在GPU中完成的。

您需要一个片段着色器,它可以实现循环在的回答中所做的基本操作:找到每个像素的亮度,从最大值中减去它(一个是GLSL,而不是255),然后使用这个值作为alpha值。我将跟随他的领导,(a)只使用绿色通道作为亮度,(b)将输出颜色通道设置为黑色。我是这样做的:

代码语言:javascript
运行
复制
precision lowp float;
uniform sampler2D sampler0;
varying vec2 v_texCoord;
void main(void) {
  vec4 color = texture2D(sampler0, v_texCoord);
  float alpha = 1.0 - color.g;
  gl_FragColor = vec4(0.0, 0.0, 0.0, alpha);
}

然后,对于每一帧,您将一个矩形呈现到WebGL画布上,以视频作为纹理源,并使用上面的片段着色器。--我已经开始写一个如何做到这一点的例子,但是这需要做一些工作。有多少利息?让我知道,如果有足够的需求,我会尽力完成的。

编辑:您也许可以通过使用WebGL避免学习太多关于glfx.js的知识。我并没有很深入地研究它,但我认为它可以作为图像源与视频一起工作。

票数 2
EN

Stack Overflow用户

发布于 2015-03-27 18:51:19

您的示例视频的白色区域越来越多地被逐渐缩小的黑色区域所显示。

您可以使用现有的视频+画布显示隐藏的html内容.

创建一个包含您已经制作的视频的视频元素。

使用计时器来抓取播放视频的帧。requestAnimationFrame被高度推荐,因为它与您的显示刷新同步。

在每个动画循环中,在画布上画一个视频帧。您可以在画布上绘制视频,因为画布可以使用视频元素作为其图像源。

一旦画布上有一帧黑色的薄雾,就可以通过以下方法使画布的任何白色区域透明:

  • 使用context.getImageData获取画布上每个像素的颜色数据
  • 如果任何像素的颜色为“白色-ish”,则可以将该像素的alpha值更改为0(意思是透明的)。
  • 使用context.putImageData将修改后的像素数据放回画布上

因此,总的来说:

  • 隐藏播放视频元素
  • 使用CSS将您的画布元素置于您希望显示的html内容之上。
  • 创建一个动画循环,在画布上绘制一个视频帧,并将白色像素转换为透明的。
  • html内容将由你的视频的画布播放帧显示,白色像素被敲成完全透明。
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/29307675

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档