使用FFmpeg Dash混合器创建多比特率Dash内容的方法

12

ffmpeg 文档 中提到,我们可以使用dash多路复用器仅通过一个命令创建dash分段和清单文件,例如:



ffmpeg -re -i <input> -map 0 -map 0 -c:a libfdk_aac -c:v libx264
-b:v:0 800k -b:v:1 300k -s:v:1 320x170 -profile:v:1 baseline
-profile:v:0 main -bf 1 -keyint_min 120 -g 120 -sc_threshold 0
-b_strategy 0 -ar:a:1 22050 -use_timeline 1 -use_template 1
-window_size 5 -adaptation_sets "id=0,streams=v id=1,streams=a"
-f dash /path/to/out.mpd

我有一些高清视频文件,并希望将这些视频通过DASH提供以不同比特率的形式,以便客户端可以根据当前网络状况自动选择替代方案。这些是否可以通过单个ffmpeg命令完成,就像上面所述的那样?

我知道使用ffmpeg + mp4box可以解决问题,但我想知道是否可以仅使用ffmpeg来完成。

3个回答

11

好的,这是我解决问题的方法。以下命令对于实现伪直播dash内容很有用(当您想将现有视频文件流式传输,就好像它是一个直播视频),但是相同的方法也适用于点播视频。首先,我们将输入视频文件(sample.divx)转换为另一个准备进行dash流媒体的视频文件 - sample_dash.mp4:

ffmpeg -y -i sample.divx ^
  -c:v libx264 -x264opts "keyint=24:min-keyint=24:no-scenecut" -r 24 ^
  -c:a aac -b:a 128k ^
  -bf 1 -b_strategy 0 -sc_threshold 0 -pix_fmt yuv420p ^
  -map 0:v:0 -map 0:a:0 -map 0:v:0 -map 0:a:0 -map 0:v:0 -map 0:a:0 ^
  -b:v:0 250k  -filter:v:0 "scale=-2:240" -profile:v:0 baseline ^
  -b:v:1 750k  -filter:v:1 "scale=-2:480" -profile:v:1 main ^
  -b:v:2 1500k -filter:v:2 "scale=-2:720" -profile:v:2 high ^
  sample_dash.mp4

我想说sample_dash.mp4已经准备好了,因为它采用了适合dash格式的编码方式——H264 / ACC,并且包含多个(3个)不同质量的视频流(基线、主要、高级)。ffmpeg dash混流器将把这3个视频流转换为相应的备选视频质量deash片段文件。具体操作如下:

ffmpeg -y -re -i sample_dash.mp4 ^
  -map 0 ^
  -use_timeline 1 -use_template 1 -window_size 5 -adaptation_sets "id=0,streams=v id=1,streams=a" ^
  -f dash sample.mpd

-re 标志告诉 ffmpeg 以实时方式处理输入视频,这对于伪直播流非常有用。


1
您最初的问题是是否可能在一个命令中完成所有这些操作? - Saurabh
它可以被视为一个命令。如果您正在使用Java,则其余部分可以作为命令参数提供。 - silentsudo
看起来将命令分开会导致ffmpeg在第二个命令上重新编码,这是预期的行为吗? - Ell
@Ell 可能不需要,为了避免这种情况,只需添加“-c copy”。 - mcont

10

在这篇答案文档的帮助下,以下是一种用单个命令完成此操作的方法:

ffmpeg -i $inputFile \
  -map 0:v:0 -map 0:a\?:0 -map 0:v:0 -map 0:a\?:0 -map 0:v:0 -map 0:a\?:0 -map 0:v:0 -map 0:a\?:0 -map 0:v:0 -map 0:a\?:0 -map 0:v:0 -map 0:a\?:0  \
  -b:v:0 350k  -c:v:0 libx264 -filter:v:0 "scale=320:-1"  \
  -b:v:1 1000k -c:v:1 libx264 -filter:v:1 "scale=640:-1"  \
  -b:v:2 3000k -c:v:2 libx264 -filter:v:2 "scale=1280:-1" \
  -b:v:3 245k  -c:v:3 libvpx-vp9 -filter:v:3 "scale=320:-1"  \
  -b:v:4 700k  -c:v:4 libvpx-vp9 -filter:v:4 "scale=640:-1"  \
  -b:v:5 2100k -c:v:5 libvpx-vp9 -filter:v:5 "scale=1280:-1"  \
  -use_timeline 1 -use_template 1 -window_size 6 -adaptation_sets "id=0,streams=v  id=1,streams=a" \
  -hls_playlist true -f dash output/output.mpd

如果你遇到了错误信息 Only '-vf scale=320:-1' read, ignoring remaining -vf options: Use ',' to separate filters,实际上这并不会影响过滤器的使用。 - slhck

0
问题在于您认为过滤器应该应用在哪里。在 ffmpeg 的逻辑中,视频过滤器是在流解码“后”和编码“前”应用的(无论您在命令行中将它们放在哪个位置)。
因此,它们不能以您现在使用它们的方式使用。您的情况可能最好的方法是使用一个过滤复合体,在解码后立即将视频分割成 4 个不同的中间视频,然后对每个视频应用不同的缩放,最后取出它们的输出并进行编码。
像这样(我为简洁起见只列出了两个变量,但我相信您可以为 6 个重新调整):
ffmpeg -i $inputFile -filter_complex "[0]split=6[mid0][mid1];[mid0]scale=320:-1[out0];[mid1]scale=640:-1[out1]" -map [out0] -map 0:a -map [out1] -map 0:a -c:a aac -c:v:0 libx264 -c:v:1 libvpx-vp9 -use_timeline 1 -use_template 1 -window_size 6 -adaptation_sets "id=0,streams=v  id=1,streams=a" -hls_playlist true -f dash output/output.mpd

这只是一个示例,希望它能让你走上正确的轨道 :)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接