顺晟科技
2021-06-16 11:02:28
271
结合HTML5下的视频和画布功能,可以实时处理视频数据,为正在播放的视频添加各种视觉效果。本教程演示了如何使用JavaScript代码来实现色度键控
本文中使用的XHTML文档如下。
!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Transitional//EN '
http://www . w3 . org/TR/XHTML 1/DTD/XHTML 1-transitional . DTD '
html xmlns=' http://www . w3 . org/1999/XHTML '
头
风格
body {
背景:黑色;
color : # CCCCCC;
}
#c2 {
background-image : URL(foo . png);
背景-repeat:不重复;
}
div {
向左浮动:
边框:1px实心# 444444;
padding:10px
margin: 10px
background: # 3B3B3B
}
/style
脚本类型=' text/JavaScript;version=1.8 ' src=' main . js '/脚本
/head
body onload='processor.doLoad()'
差异
视频id=' video ' src=' video . ogv ' controls=' true '/
/div
差异
画布id='c1 '宽度='160 '高度='96'/
画布id='c2 '宽度='160 '高度='96'/
/div
/body
/html
上述代码的关键部分如下:
1.创建了两个画布元素,它们的id分别是c1和c2。C1用于显示当前帧的原始视频,c2用于显示执行色度键控后的视频。C2预装了一张静态图片,将用于替换视频的背景色部分。
2.JavaScript代码从main.js文件导入;这个脚本使用了JavaScript 1.8的特性,所以当导入脚本时,版本在第22行指定。
3.加载网页时,main.js中的processor.doLoad()方法会运行。
JavaScript代码
main.js中的JS代码包含三种方法。
初始化色度键
最初加载XHTML文档时,会调用doLoad()方法。这种方法的作用是为色度键处理代码准备必要的变量,并设置一个事件监听器,我们可以在用户开始播放视频时检测到它。
doLoad:函数(){
this . video=document . getelementbyid(' video ');
this . C1=document . GetElementbyID(' C1 ');
this . CTX 1=this . C1 . GetContext(' 2d ');
this . C2=document . GetElementbyID(' C2 ');
this . CTX 2=this . C2 . GetContext(' 2d ');
让自我=这个;
this . video . addevent listener(' play ',function() {
self . width=self . video . video width/2;
self . height=self . video . video height/2;
self . timercall back();
},false);
},
该代码获取XHTML文档中视频元素和两个画布元素的引用,还获取两个画布的图形上下文的引用。这些将在我们实现色度键控时使用。
AddEventListener()侦听视频元素,并在用户按下视频上的播放按钮时被调用。为了应对用户的回放,这段代码获取视频的宽度和高度,并将其减半(我们在执行色度键控效果时会将视频的大小减半),然后调用timerCallback()方法开始视频捕捉和视觉效果计算。
计时器回调
视频开始播放时(发生“播放”事件时)调用定时器回调函数,然后负责自己的周期调用,实现每帧视频的键控。
timerCallback:函数(){
if (this.video .暂停| | this . video . end){
返回;
}
this . ComputeFrame();
让自我=这个;
setTimeout(函数(){
self . timercall back();
}, 0);
},
回调函数首先检查视频是否在播放;如果没有,回调函数什么也不做,立即返回。
然后调用computeFrame()方法,对当前视频帧执行色度键控。
回调函数做的最后一件事就是调用setTimeout(),以便能尽快再次调用。在实际环境中,您可以根据视频的帧速率来设置呼叫频率。
处理视频帧数据
如下所示的computeFrame()方法实际上负责捕获每一帧的数据,并执行色度键控。
computeFrame:函数(){
this.ctx1.drawImage(this.video,0,0,this.width,this . height);
设frame=this.ctx1.getImageData(0,0,this.width,this . height);
设l=frame . data . length/4;
for(设I=0;I l;i ) {
设r=frame . data[I * 4 0];
设g=frame . data[I * 4 ^ 1];
设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);
返回;
}
在第二行中,视频帧被复制到个画布ctx1的图形上下文中,并且高度和宽度值被指定为我们之前保存的帧大小的一半。请注意,您可以通过将视频元素传递给绘图上下文的drawImage()方法来绘制当前视频帧。结果是:
第三行代码通过调用个画布上下文的getImageData()方法获取原始图像数据的当前视频帧的副本。它提供了原始的32位像素图像数据,让我们可以操作。第四行代码通过将帧图像数据的总长度除以4来计算图像的总像素数。
第六行代码循环扫描所有像素,获取每个像素的红色、绿色和蓝色值,并将它们与预定义的背景颜色进行比较,这些颜色将被从foo.png导入的背景图像替换。
对于检测为背景的每个像素,将其alpha值替换为零,表示该像素完全透明。结果,最终图像的背景部分是透明的,所以在第13行代码中被绘制到目标的上下文中时,效果是内容叠加在静态背景上。
这在视频回放期间重复进行,以便在一帧之后呈现色度键的特殊效果。
29
2022-11
16
2022-09
15
2022-09
15
2022-09
15
2022-09
15
2022-09