了解本节内容技术点:
安装模块“fluent-ffmpeg” https://github.com/fluent-ffmpeg/node-fluent-ffmpeg
API地址:http://www.ffmpeg.org/
需求背景,我们的软件可以插入视频,并且播放视频。
但是WebKit内核的nw.js跟chrome一样用HTML5的标签<video>去播放视频,支持的格式只有三种 Ogg、MPEG4、WebM,但是我们想支持更多的视频格式,这就需要在插入视频的时候进行格式转换,这样我们支持的视频格式可以有这么多种".webm,.ogv,.ogg,.mp4,.mov,.avi,.wmv,.mpg,.mpeg,.mkv,.rmvb"。
下面我们插入一个mov格式的视频
fileInput弹框选择后获取文件路径,onchange事件定义如下:
我们调用videoInsertProcess函数对插入的视频进行处理,如下图:
videoInsertProcess函数首先检测文件大小是否在100M之内,我们软件只支持100M以内的文件,为避免软件占用过多内存。代码如下图:
判断视频是否需要进行转码的过程如下图:
代码里也没有过多注释,主要是根据我们软件的业务需求写的逻辑,主要就是循环判断streams流,codec_type是否为video;如果是继续判断codec_name是否是我们支持的vp8,vp9,h264编码格式,如果不是的话就需要进行转码
插入的视频如果需要转码的话,会提醒用户是否要进行转码插入,如下图提示框:
点击转码按钮。创建ffmpeg命令, var videoEncoder = new Common.VideoEncoder(filePathStr);//filePathStr插入视频的源路径
调用convertToWebm方法,传入目标路径,成功处理回调函数,失败处理回调函数。
如下过程:
函数convertToWebm的具体代码如下:
1 //视频转换为webm格式
2 convertToWebm(targetPath, onComplete: Function, onError: Function) {
3 var that = this;
4 var bit_rate = Number(targetPath["bitRate"]);
5 var channelsgt2 = targetPath['channelsgt2'] || false;
6 var bit_rate_str;
7 var options = [];
8 //计算bitRate信息,封装options
9 if (isFinite(bit_rate)) {
10 if (bit_rate < 1024) {
11 bit_rate_str = Math.round(bit_rate).toString();
12 }
13 else if (bit_rate < 1024 * 1024) {
14 bit_rate_str = Math.round(bit_rate / 1024).toString() + 'K';
15 }
16 else {
17 bit_rate_str = Math.round(bit_rate / (1024 * 1024)).toString() + 'M';
18 }
19 options.push('-b:v ' + bit_rate_str);
20 }
21 if (channelsgt2 === true) {
22 options.push('-ac 2');
23 }
24 options.push('-deadline realtime');
25
26 targetPath = targetPath.valueOf();//还原target 路径
27
28 that.encoder.videoCodec('libvpx')
29 .outputOptions(options) //cpu-used -5
30 .on('start', function (cmd) {
31 index.showProgressBar("0%", SoftWare.transcoding_going, "", function () {
32 that.encoder.kill();
33 });
34 })
35 .on('end', function () {
36 document.getElementById("progress_bar").style.display = "none";
37 onComplete(false);
38 })
39 .on('error', function (err) {
40 document.getElementById("progress_bar").style.display = "none";
41 if (err.message === "ffmpeg was killed with signal SIGKILL") {
42 index.showMask(true);
43 index.showWaitMoment(true);
44 return;
45 }
46 onError(err);
47 })
48 .on('progress', function (progress) {
49 var percent: number = progress.percent;
50 if (percent) {
51 index.showProgressBar(percent.toFixed(1) + "%", SoftWare.transcoding_going, "");
52 }
53 })
54 .save(targetPath);
55 }