@类人猿Blog 欢迎来到我的博客,您好! 这是本人第一次写博客,请多多指教。nodejs中使用 fluent-ffmpeg(详细方法和系统配置,适应于 windows和 linux,特别是在 redhat6.x中得以验证通过)

简介

我们都知道,在nodejs中有一个模块非常实用,可以帮助我们处理各种类型的视频,编辑,修改等等,他就是fluent-ffmpeg模块,该模块简化了复杂的命令操作,使我们很简单、很轻松的就能运用到我们的项目中。以下是使用过程中的一些详细解释和使用方法及步骤(本文分主要基于windows和redhat6.x两种环境分别做出阐述),如有不慎,请多多包涵。

Windows环境下使用

我们对windows环境而言配置比较简单,使用比较方便:首先是运行环境 ,windows x64,node8.11.2,fluent-ffmpeg2.1.2,ffmpeg3.x~4.x【或更新的版本】;其次是使用步骤:

  1. 确保在windows中安装ffmpeg软件和解码器,安装简单,运行**.exe文件,按提示操作即可,尽量不要安装在C:盘(或是下载免安装文件包,解压复制到需要放置的位置),避免配置环境变量时路径找不到【下载地址(找到windows版本下载):http://ffmpeg.org/download.html】
  2. 安装完成后配置环境变量:
    高级系统设置->环境变量->
    找到Path变量
    双击Path打开,并在最末尾加上【;D:\Program Files\ffmpeg\bin】注意是您安装ffmpeg的位置,然后,依次确定,应用即可。

    检查环境变量是否成功:win+R运行cmd命令打开控制台,输入ffmpeg,若成功,则有以下输出:
  3. 安装node8.11.2(此处略,不做详解);
  4. 安装fluent-ffmpeg,npm或者cnpm安装,npm install fluent-ffmpeg --save
  5. 使用方法(以上传视频并取视频的某一针作为封面图为例)代码片段
const express = require('express'),
    router = express.Router(),
    url = require('url'),
    fs = require('fs'),
    path = require('path'),
    async = require('async'),
    thenjs = require('thenjs'),
    ffmpeg = require('fluent-ffmpeg'),
    formidable = require('formidable'),
    dateUtils=require('../../service/dateUtils.js');
const MAX_SIZE_IMG = 5*1024*1024;//图片
const MAX_SIZE_VIDEO = 150*1024*1024;//视频
const captureImageOne = (src)=> {
    return new Promise((reslove, reject) => {
        try {
            let imageName = '';
            let fileName = src.substring(src.lastIndexOf('/') + 1).split(".")[0];
            ffmpeg(src)
                .on('filenames', (filenames)=> {
                    imageName = filenames[0];
                    console.log(imageName);
                })
                .on('end', ()=> {
                    reslove(imageName);
                })
                .screenshots({
                    // Will take screens at 20%, 40%, 60% and 80% of the video
                    //timestamps: [30.5, '50%', '01:10.123'],
                    timestamps: ['00:01.000'],
                    folder: './dist/upload/img/',
                    filename: fileName + '.png',
                });
        } catch(err) {
            reject(err);
        }
    })
}
router.post('/uploadVideo', (req, res)=> {
    try {
        let form = new formidable.IncomingForm();
        form.uploadDir = './dist/upload/tmp';
        let msger = {
            fileName:[],
            imageName:[]
        };
        form.parse(req, (error, fields, files)=> {
            (function (fileLen) {
                let current = 0;
                for (let key in files) {
                    let file = files[key];
                    let fName =  key;
                    dateUtils.logMsg("filename==="+fName);
                    if(file.size>MAX_SIZE_VIDEO){
                        res.json({code: -1, msg: '视频大小不能超过150MB!'});
                        return false;
                    }
                    switch (file.type) {
                        case "video/mpeg":
                            fName = fName + ".mpeg";
                            break;
                        case "video/mpg":
                            fName = fName + ".mpg";
                            break;
                        case "video/mp4":
                            fName = fName + ".mp4";
                            break;
                        case "video/mpeg4":
                            fName = fName + ".mp4";
                            break;
                        case "video/ogg":
                            fName = fName + ".ogg";
                            break;
                        case "video/webm":
                            fName = fName + ".webm";
                            break;
                        default :
                            fName = fName + ".mp4";
                            break;
                    }
                    dateUtils.logMsg(file.size);
                    let uploadDir = "./dist/upload/video/" + fName;
                    fs.rename(file.path, uploadDir,async (err)=> {
                        if (err) {
                            throw new Error(err);
                        }else{
                            captureImageOne(uploadDir).then(async (imgname)=> {
                                msger.imageName.push(imgname);
                                msger.fileName.push(fName);
                                current++;
                                if(current==fileLen){
                                    res.json({code: 0, msg: msger,filePath:'/upload/video/',imagePath:'/upload/img/'});
                                }
                            },async (err)=>{
                                console.log(err);
                                throw new Error(err);
                            });
                        }
                    });
                }
            })(Object.keys(files).length);
        });
    }
    catch (err) {
        res.json({code: -1, msg: err});
    }
});

代码说明: 请不要复制代码,可能报错,因为这是适合于当前的项目环境,并不能保证适合所有项目环境,重点注意一个方法即可,那就是captureImageOne()方法,其中src是文件路径,其中是调用fluent-ffmpeg模块的API。
6. ffmpeg的命令使用及fluent-ffmpeg模块功能使用可参见: https://www.npmjs.com/package/fluent-ffmpeg

Linux环境下使用

我们对Inux环境而言配置相对复杂,但是使用也比较方便和windows环境是一样的,这里以redhat6.x的系统为例:首先是运行环境 ,redhat6.x x64,node8.11.2,fluent-ffmpeg2.1.2,ffmpeg3.x~4.x【或更新的版本】;其次是使用步骤:

  1. 同样确保在Redhat6.x中安装ffmpeg软件和解码器【下载地址(找到Linux版本下载):http://ffmpeg.org/download.html】
  2. node安装和环境搭建参考:
  3. 安装fluent-ffmpeg,npm或者cnpm安装,npm install fluent-ffmpeg --save
  4. 在这里重点说明ffmpeg在Linux下的安装流程,同样以Redhat6.x x64为例。首先,下载以下几个包,并按照顺序依次安装:
    yasm,lame,libogg,libvorbis,xvid ,x264,
    libdts,a52,faad2,faac,fdk-aac,amr-nb,amr-wb ,vo-amrwbenc,nasm,opencore-amr
    安装示例(注意按照实际文件所在目录进行操作,这里只展示其中一个的安装示例,其他包安装亦如此)代码片段
[root@webserver ~]# cd /usr/
[root@webserver usr]# cd local/
[root@webserver local]# cd Packages/
[root@webserver Packages]# tar -zxvf libvorbis-1.3.6.tar.gz
[root@webserver Packages]# cd libvorbis-1.3.6
[root@webserver libvorbis-1.3.6]# ./configure --enable-shared
[root@webserver libvorbis-1.3.6]# make&&make install

其次,安装ffmpeg,同样需要下载ffmpeg包,然后进行安装,安装示例(注意按照实际文件所在目录进行操作)代码片段

[root@webserver ~]# cd /usr/
[root@webserver usr]# cd local/
[root@webserver local]# cd Packages/
[root@webserver Packages]# cd ffmpeg-f85fa10
[root@webserver ffmpeg-f85fa10]# ./configure --prefix=/usr/local --enable-libmp3lame --enable-gpl --enable-version3 --enable-nonfree --enable-pthreads --enable-libfdk-aac --enable-libopencore-amrnb --enable-libx264 --enable-postproc --enable-ffplay --enable-shared
[root@webserver libvorbis-1.3.6]# make&&make install

代码说明: 在安装x264的时候一定要使用- -enable-shared,否则在ffmpeg安装或运行时报错no such file找不到文件,在安装ffmpeg的时候,- -prefix配置的路径问题,网上好多资料显示可以配任意路径,但是如果你需要配合使用fluent-ffmpeg模块的时候,切记使用/usr/local或者/usr/即可,虽然fluent-ffmpeg模块API文档中说可以定义FFMPEG_PATH和 FFPROBE_PATH两个环境变量,但是很遗憾测试没有通过,依然报错找不到ffmpeg模块
因此,在这里建议直接默认安装配置到/usr/或者/usr/local目录下,即- -prefix=/usr/local或者- -prefix=/usr。对于环境变量的配置,执行vim /etc/profile,并在最后一行加上【这里说的是你如果配置的安装路径不在/usr/或者/usr/local/根目录下,则最后一行加上】:代码块

export PATH = $PATH:/usr/local/ffmpeg/bin

代码说明: /usr/local/ffmpeg/bin指的是你安装ffmpeg的位置,也就是上面提到的- -prefix的值。

  1. 使用方法(以上传视频并取视频的某一针作为封面图为例)代码片段与windows下的使用方法一致。请参考前面第5条中的代码或说明。
  2. 安装完成后,测试环境变量,在任意位置输入ffmpeg -version即可,如果正确,则会输出类似以下信息:

    其他说明: 如出现错误,找不到文件,则请执行vim /etc/ld.so.conf命令,如果安装路径是/usr/local,则在最后加上一行/usr/local/lib,如果安装路径是/usr,则在最后加上一行/usr/lib。

总结

个人觉得,总体使用下来,ffmpeg非常强大,适合处理视频资源以及视频流,压缩,编辑,改变等功能都非常好用。如果要使用nodejs开发,那么建议使用fluent-ffmpeg模块,简化了命令操作,而且配合文件上传以及视频流的处理在这里未提及ffplay、ffprobe等非常实用,更多信息,请自行查阅ffmpeg官方文档,而外发现一个非常好用的工具图片压缩不改变原始大小,保持分辨率高清,无水印,非常清晰,压缩后体积非常小。

【更多知识来源,请参考】
[1]: https://nodejs.org/zh-cn/

[2]: http://ffmpeg.org

[4]: https://www.npmjs.com/package/fluent-ffmpeg