node-音视频开发入门

FFmpeg 是常用的视频处理开源软件,它功能强大,可以实现常用的音视频剪辑,压缩,格式转换,也是许多音频和视频格式的标准编码/解码实现。

FFmpeg

FFmpeg 本身是一个庞大的项目,包含许多组件和库文件

* ffmpeg——一个命令行工具,用来对视频文档转换格式,也支持对电视卡即时编码
* ffserver——一个HTTP多媒体即时广播流服务器,支持回溯
* ffplay——一个简单的播放器,基于SDL与FFmpeg库
* libavcodec——包含全部FFmpeg音频/视频编解码库
* libavformat——包含demuxers和muxer库
* libavutil——包含一些工具库
* libpostproc——对于视频做前处理的库
* libswscale——对于影像作缩放的库

音视频的基本概念

比特率

比特率即码率,在不同领域有不同的含义,在多媒体领域,指单位时间播放音频或视频的比特数

码率(kbps)= 文件大小(kb)/ 时长(s)

帧率

用于测量显示帧数的量度。单位为 FPS(Frames per Second,每秒显示帧数)或赫兹(Hz)。

帧率越高,画面越流畅、逼真,对显卡的处理能力要求越高,数据量越大。

封装格式

封装格式一览表

名称 推出机构 流媒体 支持的视频编码 支持的音频编码 目前使用领域
AVI Microsoft Inc. 不支持 几乎所有格式 几乎所有格式 BT下载影视
MP4 MPEG 支持 MPEG-2, MPEG-4, H.264, H.263等 AAC, MPEG-1 Layers I, II, III, AC-3等 互联网视频网站
TS MPEG 支持 MPEG-1, MPEG-2, MPEG-4, H.264 AAC, MPEG-1 Layers I, II, III, AC-3等 IPTV,数字电视
FLV Adobe Inc. 支持 Sorenson, VP6, H.264 MP3, ADPCM, Linear PCM, AAC等 互联网视频网站
MKV CoreCodec Inc. 支持 几乎所有格式 几乎所有格式 互联网视频网站
RMVB Real Networks Inc. 支持 RealVideo 8, 9, 10 AAC, Cook Codec, RealAudio Lossless BT下载影视

流媒体

常用的流媒体协议有RTSP+RTP,RTMP,RTMFP,MMS,HTTP

RTSP+RTP经常用于IPTV领域。因为其采用UDP传输视音频,支持组播,效率较高。但其缺点是网络不好的情况下可能会丢包,影响视频观看质量。因为互联网网络环境的不稳定性,所以RTSP+RTP较少用于互联网视音频传输

而像RTMP,MMS,HTTP这类的协议广泛用于互联网视音频服务之中。这类协议不会发生丢包,因而保证了视频的质量,但是传输的效率会相对低一些。

此外RTMFP是Adobe公司开发的一套新的通信协议,全称Real Time Media Flow Protocol, 该协议可以让使用Adobe Flash Player的终端用户之间进行直接通信。

FFmpeg在node中的实践

node中可使用fluent-ffmpeg模块,简化了命令,提高了编码效率。

  • ffprobe 可以查看视频的具体信息如下:
1
2
3
4
5
6
7
var FFmpeg = require('fluent-ffmpeg');

FFmpeg.setFfmpegPath('D:/ffmpeg/ffmpeg.exe')
FFmpeg.setFfprobePath('D:/ffmpeg/ffprobe.exe')
FFmpeg.ffprobe('D:/ffmpeg/demo.mp4', function (err, metadata) {
console.dir(metadata);
});

打印如下:

上图可以看出,视频的编码为HEVC编码,分辨率为1920*1080
颜色空间为YUV420p,fps为一秒30帧,时长为11秒,大小为7731027字节

  • ffmpeg主要用于对视频的操作

常用操作

  • 转换格式

    1
    2
    3
    4
    //视频由mp4 => avi
    FFmpeg()
    .input('D:/ffmpeg/demo.mp4')
    .save('./video/output.avi');
  • 裁剪

    1
    2
    3
    4
    5
    6
    7
    //以下代码修改了视频的格式,长度,fps
    FFmpeg()
    .input('D:/ffmpeg/demo.mp4')
    .fpsInput(10)
    .seekInput(5)
    .duration(5)
    .save('./video/output.avi');
  • 添加水印

ffmpeg具有上下优先级,即第一个input输入视频流后,紧接着后面的调用都是使用的的这个视频流,所以要特别注意输入流(input方法)位置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
FFmpeg()
.input('./demo.mp4')
.duration(5)
.seekInput(5)
.fpsInput(10)
.input('./water.jpg')
.complexFilter([{
filter: 'overlay',
options: {
x: 'w/2',
y: 15
},
inputs: ['0:v', '1:v']
}])
.save('./video/output.avi');

  • 添加背景

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    FFmpeg()
    .input('D:/ffmpeg/demo.mp4')
    .duration(5)
    .seekInput(5)
    .fpsInput(10)
    .input('c:/Users/tfsmy/Desktop/project/formdata/video/water.jpg')
    .complexFilter([{
    filter: 'pad',
    options: {
    w: 'iw*2',
    h: 'ih',
    color: 'green',
    x: 'iw/2'
    },
    inputs: '0:v',
    outputs: 'a'
    }, {
    filter: 'overlay',
    options: {
    x: 'w',
    y: 15
    },
    inputs: ['a', '1:v']
    }])
    .save('./video/output.avi');
  • 推直播流

    由于没申请直播推流地址,可以参考大佬博客

  • ffplay 打开一个视频
1
ffplay 路径

最终效果