使用FFmpeg高效垂直堆叠不同分辨率演讲视频的最优方案咨询
我的问题背景与当前流程
我想用FFmpeg把演讲的两个视频垂直堆叠在一起——一个是演示幻灯片,一个是主讲人画面。因为要处理好几场演讲,我希望能找到通用且高效的方法,而且大多数情况下这两个视频的分辨率和宽高比都不一样。
我目前的工作流程是:
- 把分辨率较低的视频 upscale 到和另一个视频一致:
ffmpeg -i video1.mp4 -s 1920x1080 -c:a copy video1_upscaled.mp4
- 堆叠两个视频:
ffmpeg -i video1_scaled.mp4 -i video2.mp4 -filter_complex vstack=inputs=2 combined.mp4
这些视频时长在1-2小时,执行命令要花不少时间。有没有办法节省时间?另外,给较小的视频加黑边而不是缩放成另一个视频的尺寸,会不会更快?能不能把堆叠和缩放/加黑边的步骤合并成一条命令?
优化方案解答
嗨,我来给你捋捋怎么优化这个流程~首先你现在的两步操作确实会浪费时间,因为要先转码一次再堆叠,完全可以把所有操作合并到一条FFmpeg命令里,避免中间文件的生成,这能省不少时间。
核心优化思路:合并滤镜,减少转码次数
FFmpeg的滤镜链可以一次性完成“适配尺寸+垂直堆叠”的操作,不用单独生成中间文件,这是提升效率的关键。下面分两种场景给你具体方案:
场景1:给小视频加黑边(优先推荐,更快更保真)
这种方法确实比缩放更快,因为不需要对像素进行插值计算,只是给画面补黑边,计算量小很多。而且能保留原视频的清晰度,不会因为upscale导致画质下降。
命令示例(适配到1920x1080画布后垂直堆叠,自动保持原宽高比居中):
ffmpeg -i slides.mp4 -i speaker.mp4 -filter_complex "[0:v]scale=1920:1080:force_original_aspect_ratio=decrease,pad=1920:1080:(ow-iw)/2:(oh-ih)/2[slides];[1:v]scale=1920:1080:force_original_aspect_ratio=decrease,pad=1920:1080:(ow-iw)/2:(oh-ih)/2[speaker];[slides][speaker]vstack=inputs=2[v]" -map "[v]" -map 0:a -map 1:a -c:a copy combined.mp4
关键参数解释:
scale=1920:1080:force_original_aspect_ratio=decrease:先把视频缩放到不超过目标尺寸的最大可能大小,严格保留原宽高比pad=1920:1080:(ow-iw)/2:(oh-ih)/2:给缩放后的视频补黑边,自动居中显示,填满目标画布-c:a copy:直接复制音频,跳过音频转码,节省大量时间
如果其中一个视频已经是目标尺寸,滤镜会自动跳过不必要的操作,不影响效率。
场景2:必须缩放小视频到匹配大视频尺寸
如果你的需求是让两个视频完全填满堆叠后的画面(无黑边),那还是需要缩放,但同样可以合并到一条命令里,避免中间文件:
假设大视频是1920x1080,小视频是1280x720,命令可以写成:
ffmpeg -i slides.mp4 -i speaker.mp4 -filter_complex "[1:v]scale=1920:1080[scaled];[0:v][scaled]vstack=inputs=2[v]" -map "[v]" -map 0:a -map 1:a -c:a copy combined.mp4
这里直接在滤镜链里完成缩放和堆叠,省去了生成中间文件的转码与读写时间。
额外效率提升技巧
- 硬件加速转码:如果你的FFmpeg支持硬件编码(比如NVIDIA的NVENC、AMD的AMF),可以加上硬件编码参数大幅缩短时间。比如把上面的命令编码部分改成
-c:v h264_nvenc:
ffmpeg -i slides.mp4 -i speaker.mp4 -filter_complex "[0:v]scale=1920:1080:force_original_aspect_ratio=decrease,pad=1920:1080:(ow-iw)/2:(oh-ih)/2[slides];[1:v]scale=1920:1080:force_original_aspect_ratio=decrease,pad=1920:1080:(ow-iw)/2:(oh-ih)/2[speaker];[slides][speaker]vstack=inputs=2[v]" -map "[v]" -map 0:a -map 1:a -c:a copy -c:v h264_nvenc combined.mp4
- 匹配原视频编码参数:用
ffprobe先查看原视频的码率、帧率等参数(比如ffprobe -v error -select_streams v:0 -show_entries stream=width,height,r_frame_rate,bit_rate -of default=noprint_wrappers=1:nokey=1 slides.mp4),然后在命令里加上-b:v <原码率>、-r <原帧率>等参数,减少FFmpeg的计算量。
速度对比总结
给视频加黑边的操作确实比缩放快很多,因为缩放需要对每个像素进行重新计算(尤其是upscale时的插值运算),而补黑边只是简单填充黑色像素,计算量小了不止一个量级。如果没有必须填满画面的硬性需求,优先选择加黑边的方案。
备注:内容来源于stack exchange,提问作者technical_difficulty

