介绍几个前端视频相关的场景应用

654 阅读2分钟

我们都知道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()

image.png 我们可以看到,右侧的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);

效果如下:

image.png

录制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);
    });
};

最后

感谢阅读!