【问题标题】:How to create multi bit rate dash content using ffmpeg dash muxer如何使用 ffmpeg dash muxer 创建多比特率 dash 内容
【发布时间】:2018-06-23 17:05:06
【问题描述】:

ffmpegdocumentation 说我们可以使用 dash muxer 只用一个命令来创建 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 来完成。

【问题讨论】:

    标签: ffmpeg mpeg-dash


    【解决方案1】:

    好的,这就是我解决问题的方法。以下命令对于实现伪实时短划线内容很有用(当您想要流式传输现有视频文件时,就好像它是实时视频一样),但同样的方法也可用于点播视频。首先,我们将一个输入视频文件 (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 muxer 会将这 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
    

    -reflags 告诉 ffmpeg 实时处理输入视频,这对于伪直播很有用。

    【讨论】:

    • 就像您最初问的那样,是否有可能在单个命令中完成所有这些操作?
    • 它只能被视为一个命令。如果您使用的是 java,rest 可以作为参数提供给命令
    • 似乎分离命令会导致 ffmpeg 在第二个命令上重新编码,这是预期的行为吗?
    【解决方案2】:

    借助 answerdocumentation,以下是在单个命令中执行此操作的方法:

    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,这实际上不会影响过滤器。
    【解决方案3】:

    问题在于您认为过滤器的应用位置。 在 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
    

    这只是一个例子,希望它能带你走上正轨:)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-05-24
      • 2018-10-22
      • 1970-01-01
      • 2018-12-06
      • 1970-01-01
      相关资源
      最近更新 更多