我们都知道Video标签可以让视频在web页面中播放,某种程度上替代了flash。今天介绍几个关于Video视频在web页面的几个应用场景:变速播放、实时绘制视频流到画布。 这是我参与8月更文挑战的第19天,活动详情查看:8月更文挑战
变速播放
首先,我们来介绍一下变速播放。
这个其实是浏览器Video标签内置的功能了,不需要开发者做任何其他的设置或开发。
语法:videoElement.playbackRate = value;1 表示正常速度,大于1表示加速,小于1表示慢速。
<video src="./video.mp4" controls></video>
var video = document.querySelector("video");
console.log(video.playbackRate);//获取视频播放的速率
video.playbackRate = 0.5;// 0.5速率播放(慢速)
video.playbackRate = 2;// 2速率播放(加速)
实时绘制视频流到画布
其实canvas提供了将video内容绘制到画布的能力。
下面例子:用户点击按钮获取当前视频图像帧数据,并绘制到相同大小的画布上。
<button onclick="getCurFrame()">获取当前播放的视频帧</button>
<video src="./video.ogv" controls></video>
<canvas></canvas>
<script>
var video = document.querySelector('video');
var canvas = document.querySelector('canvas');
//视频第一帧数据加载完毕时,获取视频的宽高
video.onloadeddata = ()=>{
canvas.width = video.videoWidth;
canvas.height = video.videoHeight;
}
function getCurFrame(){
const ctx = canvas.getContext('2d');
ctx.drawImage(video,0,0)
}
</script>
接下来我们稍微改进一下代码,让程序实时绘制:
function getCurFrame(){
setTimeout(getCurFrame,0)
const ctx = canvas.getContext('2d');
ctx.drawImage(video,0,0)
}
getCurFrame()
我们可以看到,右侧的canvas上的图像实时更新,跟左边的视频在播放一样。
接下来我们想将视频中的浅色背景替换成红色的,怎么实现呢? 我们思考一下:
- 每次绘制时,获取图像像素点,将浅色的背景像素点换成我们想要的
- 然后,再将新的数据绘制到canvas上
我们只需要加几行代码即可:
let frame = ctx.getImageData(0, 0, canvas.width, canvas.height);
// 获取像素长度,每个像素rgba占四个位置。
const 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];
// 浅色背景的像素。我们将其改为红色rgb(255,0,0)
if (g > 100 && r > 100 && b < 43){
frame.data[i*4 + 0] = 255;
frame.data[i*4 + 1] = 0;
frame.data[i*4 + 2] = 0;
}
}
//将处理好的帧重新绘制到canvas
ctx.putImageData(frame, 0, 0);
效果如下:
录制canvas绘制过程保存
上文我们已经将视频转换到canvas绘制过程了,那么如何将这一过程保存为一个新的视频文件?
//借助canvas的captureStream方法和媒体录制对象MediaRecorder
var stream = canvas.captureStream();
var recorder = new MediaRecorder(stream, { mimeType: 'video/webm' });
var data = [];
recorder.ondataavailable = function (event) {
if (event.data && event.data.size) {
data.push(event.data);
}
};
recorder.onstop = () => {
//创建二进制对象并借助a标签完成本地下载
var url = URL.createObjectURL(new Blob(data, { type: 'video/webm' }));
const a = document.createElement("a");
a.href = url;
a.download = "video.webm"
a.click();
window.URL.revokeObjectURL(url);
};
video.onplay = ()=>{
//开始录制
recorder.start();
}
video.onended = ()=>{
//结束录制
recorder.stop();
}
将下载的文件打开后发现一个尴尬的问题是:
const videoDuration = 1000*20;//(ms单位)
recorder.onstop = () => {
const buggyBlob = new Blob(data, { type: 'video/webm' });
ysFixWebmDuration(buggyBlob, videoDuration, function(fixedBlob) {
var url = URL.createObjectURL(fixedBlob);
const a = document.createElement("a");
a.href = url;
a.download = "video.webm"
a.click();
window.URL.revokeObjectURL(url);
});
};
最后
感谢阅读!