我正在尝试使用 ffmpeg 对输入视频进行多次复用/重新编码/复制操作,但尝试的方法遇到了障碍;在继续测试之前,我想确认该软件是否真的可以做到这一点。(这是针对实时流媒体设置,它从我的 LAN 上的另一台 PC 接收一个实时流,并将其存档/重新流式传输到多个 RTMP 目标,因此需要标记-re
并需要在一次操作中完成所有操作。)
输入视频有一个高比特率的h.264视频流和四个PCM音轨。
我需要的三个输出:
- 一个 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 实现?如果可以,如何实现?
答案1
我们可能会使用tee 解复用器重新使用编码的 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
编码器(我没有尝试解决这个问题)。