我正在尝试使用 ffmpeg 对输入视频进行多次混合/重新编码/复制操作,但我尝试过的方法遇到了障碍;在继续测试之前,我想确认该软件是否真的可以做到这一点。(这是一个实时流媒体设置,它从 LAN 上的另一台 PC 接收一个实时流,并将其存档/重新流式传输到多个 RTMP 目标,因此需要标记-re
并需要在一次操作中完成所有操作。)
输入视频具有 1 个高比特率 h.264 视频流和 4 个 PCM 音轨。
我需要的三个输出:
- 1 个 8Mbps 的 h.246 编码,仅音轨 1 的 aac 编码
- 一个 12Mbps 的 h.264 编码,仅对音轨 1 进行 aac 编码(理想情况下使用与第一个输出相同的编码,即只需对音频进行一次编码)
- .mkv 的整个输入的一份纯流副本
(这些命令可能充满错误和不好的做法,只是我要走的方向的总体思路。)
我已经尝试将split
/asplit
过滤器与复用器结合使用tee
,这在理论上似乎可以工作,只是使用过滤器不允许流复制/编解码器直通(讽刺的是,在这种情况下,没有对视频流进行实际过滤,除了通过它之外)。
ffmpeg -re -init_hw_device qsv=hw -filter_hw_device hw -hwaccel qsv -hwaccel_output_format qsv -c:v h264_qsv -i $INPUT \
-filter_complex "[0:v]split=3[twitch][youtube][passv];[0:a]asplit[stream][passa]" \
-map:v "[twitch]" -map:v "[youtube]" -map:v "[passv]" -map:a "[stream]:0" -map:a "[passa]" \
-c:v:0 h264_qsv -profile:v:0 high -preset:v:0 medium -g 120 -b:v:0 8M -maxrate:v:0 8M -bufsize:v:0 4M \
-c:v:1 h264_qsv -profile:v:1 high -preset:v:0 medium -g 120 -b:v:1 12M -maxrate:v:1 12M -bufsize:v:1 6M \
-c:v:2 copy \
-c:a:0 aac -b:a:0 320k \
-c:a:1 copy \
-f tee "[select=\'v:0,a:0\']8mbps.mkv|[select=\'v:1,a:0\']12mbps.mkv|[select=\'v:2,a:1\']copy.mkv"
我还尝试了简单的流映射到多个输出,但看起来它实际上只处理一个视频和音频输出,而且我不确定流映射是否可以用这种方式使用,所以这可能是一团糟。
ffmpeg -re -init_hw_device qsv=hw -filter_hw_device hw -hwaccel qsv -hwaccel_output_format qsv -c:v h264_qsv -i $INPUT \
-map 0:0 -c h264_qsv -profile high -preset medium -g 120 -b 8M -maxrate 8M -bufsize 4M \
-map 0:0 -c h264_qsv -profile high -preset medium -g 120 -b 12M -maxrate 12M -bufsize 6M \
-map 0:1 -c aac -b 320k \
-map 0:a -c copy \
-f tee "[select=\'v:0,a:0\']8mbps.mkv|[select=\'v:1,a:1\']12mbps.mkv|[select=\'v:2,a:1\']copy.mkv"
让事情变得更加复杂的是,我在这里使用快速同步硬件编码,并且希望在-vf hwupload=extra_hw_frames=64,format=qsv
可能的情况下应用于每个重新编码,但在我的初始测试中,不清楚是否可以使用两组过滤器,即使在不同的编码上也是如此。
无论如何,这可以通过 ffmpeg 实现吗?如果可以的话又如何呢?
我们可以使用tee demuxer来重用编码的 aac 音频,并使用流映射和流说明符:
ffmpeg -y -c:v h264_qsv -i in.mkv -map 0:v -map 0:v -map 0:a -c:v:0 h264_qsv -profile:v:0 high -preset:v:0 medium -g 120 -b:v:0 8M -minrate:v:0 8M -maxrate:v:0 8M -c:v:1 h264_qsv -profile:v:1 high -preset:v:1 medium -g 120 -b:v:1 12M -minrate:v:1 12M -maxrate:v:1 12M -c:a:0 aac -b:a:0 320k -f tee "[select=\'v:0,a\']8mbps.mkv|[select=\'v:1,a\']12mbps.mkv" -map 0 -c copy copy.mkv
根据需要添加
-re
和替换输入和输出。-c:v h264_qsv
- 应用QSV H.264硬件加速解码(我们也可以使用-hwaccel qsv
)。-map 0:v -map 0:v -map 0:a
- 将输入视频流映射到“第一”(0
) 和“第二”(1
) 输出视频流(并映射音频流)。-c:v:0 h264_qsv -profile:v:0 high -preset:v:0 medium -g 120 -b:v:0 8M -minrate:v:0 8M -maxrate:v:0 8M
- 选择h264_qsv
视频编码器,以及适用于输出视频流的所有参数0
。-c:v:1 h264_qsv -profile:v:1 high -preset:v:1 medium -g 120 -b:v:1 12M -minrate:v:1 12M -maxrate:v:1 12M
- 选择h264_qsv
视频编码器,以及适用于输出视频流的所有参数1
。-c:a:0 aac -b:a:0 320k
- 选择音频编码器和比特率。-f tee "[select=\'v:0,a\']8mbps.mkv|[select=\'v:1,a\']12mbps.mkv"
- “复用”相同编码的音频流与两个不同的视频流。第一个输出视频流 (
0
) 被“混合”到8mbps.mkv
输出文件。第二个输出视频流 (
1
) 被“复用”到12mbps.mkv
输出文件。-map 0 -c copy copy.mkv
- 应用第二个输出(因为它出现在第一个输出之后)。-map 0
- 将所有输入流从输入映射到输出。-c copy
- 复制所有输入流而不重新编码。为了进行测试,我创建了一个合成视频文件
in.mkv
:ffmpeg -y -f lavfi -i mandelbrot=size=1920x1080:rate=30 -f lavfi -i sine=frequency=400 -c:v libx264 -strict -2 -c:a dca -ar 44100 -pix_fmt yuv420p -t 5 in.mkv
笔记:
-b:v:0 4M -minrate:v:0 4M -maxrate:v:0 4M
应用恒定比特率(我不确定您是否真的需要它)。bufsize
参数不适用于h264_qsv
编码器(我没有尝试解决这个问题)。