引言
之前我们已经分享过很多关于音视频处理的文章。其中最绕不开的就是ffmpg工具,这个命令行工具构建了当今大小智能设备音频,视频,图片等多媒体文件处理的方方面面。
可是有很多读者反映ffmpg入门门槛太高。面对英文的文档几乎无从下手,其涵盖众多流处理的指令根本就记不住。
那么我们本着先难后易的精神,今天就从一行较为复杂的指令开始说起。文中将会给您分析每一个指令所代表的意义。把这行指令吃透了,摸清了,你可能真的就晋级了。
一行指令
虽然说是一行,但是根本写不下或者一行看上去。比较凌乱。在命令行中我们可以使用空格加上右斜杠的方式,把一行指令拆分为多行,这样比较直观,也容易修改和定位。
大家看到了吧,这一行指令足足可以拆分为42个单元进行讲解。
处理输入
首先是指定待处理的文件:
代码语言:javascript复制ffmpeg -f rawvideo -pix_fmt yuv422p -s 720x486 -r 29.97 -i /tmp/vpipe
-i 选项之前的所有内容,都描述了输入文件 /tmp/vpipe 中包含的内容。
在这种情况下,我们的输入视频是 yuv422p 格式的原始(未压缩)帧数据,宽720像素,高486像素,帧速率为每秒29.97帧。
请注意,这些选项必须在 -i 选项之前。如果这些选项中的任何一个在 -i 之后,则ffmpeg会认为它们属于指定的下一个输入文件。
代码语言:javascript复制-ar 48000 -f s16le -ac 2 -i /tmp/apipe
这一行,我们告诉 ffmpeg 输入文件 /tmp/apipe 中的音频是什么样的。采样率为每秒48000个样本;每个样本都是带符号的16位低端字节序,并且有2个音频通道。
处理输出
下一组选项描述了音频和视频的输出格式。这些选项中的顺序并不重要,但希望对其进行逻辑分组,以便所有音频选项写在一起,而所有视频选项写在一起。
代码语言:javascript复制 -vol 4096 -acodec libfaac -ac 2 -ab 192k -ar 44100 -async 1
-vol 选项表示将调整音频电平。基准值为256。这里可以使用使用512、1024、2048和4096等值来提高音量。
这几个参数的设置,很大程度上取决于原始素材的质量,还有开发者的经验。
上面我们指定使用 libfaac 编码器输出 AAC 音频。后面的参数:
- -ac 2通道
- -ab 比特率 192kps
- -ar 采样频率 44100 Hz
最后一个选项 -async,指定使用音视频同步方式1。该方法可以调整视频和音频轨道的开始,但是在轨道的整个过程中都不会做任何拉伸。
代码语言:javascript复制-vcodec libx264 -vpre default -threads 0
-croptop 6 -cropbottom 6 -cropleft 9 -cropright 9
-r 20 -g 45 -s 432x324 -b 1024k -bt 100k
-deinterlace
上面这一段是视频处理相关的,放在了一起。
使用 libx264 库提供的H.264压缩。-vpre 选项意味着将使用默认的质量预设。需要注意的是,使用 libx264 进行编码时,可以指定两个-vpre选项。第一个是quality,第二个是要使用的配置文件(main,baseline等),默认设置为“ main”。
-threads 0 选项指示 ffmpeg 在编码时使用最佳线程数。
-crop 开始的 top bottom left right 指令,指定在视频画面的边框周围,视频裁去一部分,因为在源视频的边缘会出现一些噪点。
-r 选项指定输出为每秒20帧。
-g 选项是“图片组”(GOP)的大小,它是关键帧之间的帧数。数量越少,输出将具有更多的关键帧,这意味着如果客户端出于某种原因丢弃数据包,它们将能够更快地恢复。这也会对文件大小产生不利影响。
-s 选项指定帧大小。
-b 选项指定所需的比特率。
-bt 选项为比特率容限。ffmpeg会尝试将视频保持在所需的比特率附近,并且在容差值范围内。
-deinterlace 由于源是NTSC隔行扫描视频,因此我们将对视频进行去隔行扫描。如果不进行逐行扫描,则可以在数字化视频中,看到“竖状条纹”,十分影响观感。
代码语言:javascript复制-y '/tmp/encoding-0001.mp4'
这一行指定了输出文件名,-y 选项告诉 ffmpeg 如果目标文件存在,直接覆盖。
追加输出
现在,我们添加一些 RTP 格式的输出流。通过网络将此 RTP 流推送到 Wowza 服务器,该服务器可以将 RTP 转换为 RTMP 以便在客户端中播放。
跟写入 MPEG4 文件不同,RTP 要求将音频和视频分成两个单独的流。
代码语言:javascript复制-an
-vcodec libx264 -vpre default -threads 0
-croptop 6 -cropbottom 6 -cropleft 9 -cropright 9
-r 20 -g 45 -s 432x324 -b 1024k -bt 100k
-deinterlace
-vglobal 1
-f rtp rtp://127.0.0.1:9012
这一大堆选项,看起来是不是头大?没关系,原理都是一致的。我们逐行分析。
上面说了,我们把音频和视频分开写,这样便于讲解。这一段,都是关于音频的选项。大家看是不是与上一节讲的十分相似。相同的部分就不过多赘述了,说说特殊的选项。
-an 选项告诉 ffmpeg 从输出中删除音频流。
-vglobal 1选项表示 ffmpeg 在视频流中使用 out-of-band 全局标头。这可以帮助一些播放器规范解释视频流。
-f 选项将输出格式指定为“ rtp”,而非文件名。使用 URL 指示 ffmpeg 将 RTP 数据包推送地址。
接下来说音频输出。
代码语言:javascript复制-vn
-vol 4096
-acodec libfaac -ac 2 -ab 192k -ar 44100
-async 1
-flags global_header
-f rtp rtp://127.0.0.1:9014
-newaudio
这一段选项,是不是上面都见过?
-vn 选项指示此输出不包含视频。
-flags global_header 用于强制 ffmpeg 在其生成的 SDP 中分离出一些重要的音频规范。在Wowza服务器上使用 SDP 文件将 RTMP 流连接到 RTP 流;Wowza 需要了解所有音频和视频的信息,以便正确解析。
-f 选项指定 rtp 格式,并提供流推送的地址 URL。需要注意,端口号不同。RTP 流通常使用两个端口,并且两个端口之间有一个开放端口。每个 RTP 端口之后的端口将用于 RTCP 接收方和发送方的通信。在示例中,我们使用 9013 和 9015。
-newaudio 恢复先前被 -an 选项过滤掉的音频流。注意 -newaudio 是一个特殊选项;它仅修改紧接其之前的输出。所以选项顺序在这里很关键。
追加 RTP 流
我们的第一个 RTP 流使用 1200 Kbps 的音频和视频组合。让我们再创建一个可供带宽不足的用户使用的流。
再添加一对输出,一个是音频,一个是视频。
代码语言:javascript复制-an
-vcodec libx264 -vpre default -threads 0
-croptop 6 -cropbottom 6 -cropleft 9 -cropright 9
-r 15 -g 45 -s 432x324 -b 256k -bt 50k
-deinterlace
-vglobal 1
-f rtp rtp://127.0.0.1:9008
-newvideo
-vn
-vol 4096
-acodec libfaac -ac 1 -ab 64k -ar 44100
-async 1
-flags global_header
-f rtp rtp://127.0.0.1:9010
-newaudio
第二组 RTP 输出与第一组 RTP 输出之间存在一些差异:
- 视频帧率是15(-r 15)
- 视频比特率是256kbps,容差是50kbps(-b 256k -bt 50k)
- 音频为单声道(-ac 1)
- 音频为64kbps(-ab 64k)
- RTP URL中的端口不同
还应该注意,视频 RTP 网址后面有一个 -newvideo 选项。那是因为 -vn 选项标识之前的输出仅是音频。使用 -newvideo 选项可将视频流恢复到此输出。没有这个选项,就没有音频(-an)和视频(vn)。
写在最后
经过一个个的分析,大家明白文章开头那一行指令的功能了吧:就是把输入文件拆解为一个 mp4 文件的输出,和两路 rtp 流输出。
这么复杂的功能,ffmpeg 准备了如此简洁的实现方式,不可谓不强大!
Happy coding :_)