1个音视频输入,拆解为1个MP4文件和2路RTP流,ffmpeg这么写

2020-05-29 16:18:55 浏览数 (1)

引言

之前我们已经分享过很多关于音视频处理的文章。其中最绕不开的就是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 :_)

0 人点赞