如何用FFmpeg实现4个不同时长视频的分屏顺序播放拼接?
用FFmpeg实现按顺序播放的横向分屏视频
核心思路
先为每个视频生成对应时间线的流:播放前显示首帧、播放时段正常播放、播放结束后显示末帧,最后用hstack将四个480x1080的流拼成1920x1080的分屏,音频按顺序拼接(非播放时段静音)。
准备工作
- 四个视频文件:命名为
1.mp4、2.mp4、3.mp4、4.mp4(分辨率480x1080带音频) - 各视频的首帧/末帧截图:命名规则如
2_first.jpg(视频2首帧)、2_last.jpg(视频2末帧),分辨率需与视频一致(480x1080)
Shell脚本实现
将以下内容保存为split_screen.sh,赋予执行权限后运行:
#!/bin/bash # 定义各视频时长(单位:秒) t1=60 # 1.mp4时长 t2=95 # 2.mp4时长 t3=80 # 3.mp4时长 t4=65 # 4.mp4时长 # 计算总时长及各视频结束时间点 total=$((t1 + t2 + t3 + t4)) t1_end=$t1 t2_end=$((t1 + t2)) t3_end=$((t2_end + t3)) # FFmpeg命令 ffmpeg -i 1.mp4 -i 2.mp4 -i 3.mp4 -i 4.mp4 \ -loop 1 -i 1_last.jpg \ -loop 1 -i 2_first.jpg -loop 1 -i 2_last.jpg \ -loop 1 -i 3_first.jpg -loop 1 -i 3_last.jpg \ -loop 1 -i 4_first.jpg \ -filter_complex " # 处理视频1:播放60秒,之后显示末帧至总时长 [0:v] trim=0:$t1, setpts=PTS-STARTPTS [v1_main]; [4:v] trim=0:$((total - t1)), setpts=PTS-STARTPTS [v1_post]; [v1_main][v1_post] concat=n=2:v=1:a=0 [v1]; # 处理视频2:前60秒显示首帧,播放95秒,之后显示末帧至总时长 [5:v] trim=0:$t1, setpts=PTS-STARTPTS [v2_pre]; [1:v] trim=0:$t2, setpts=PTS-STARTPTS [v2_main]; [6:v] trim=0:$((total - t1_end)), setpts=PTS-STARTPTS [v2_post]; [v2_pre][v2_main][v2_post] concat=n=3:v=1:a=0 [v2]; # 处理视频3:前155秒显示首帧,播放80秒,之后显示末帧至总时长 [7:v] trim=0:$t2_end, setpts=PTS-STARTPTS [v3_pre]; [2:v] trim=0:$t3, setpts=PTS-STARTPTS [v3_main]; [8:v] trim=0:$((total - t3_end)), setpts=PTS-STARTPTS [v3_post]; [v3_pre][v3_main][v3_post] concat=n=3:v=1:a=0 [v3]; # 处理视频4:前235秒显示首帧,播放65秒至结束 [9:v] trim=0:$t3_end, setpts=PTS-STARTPTS [v4_pre]; [3:v] trim=0:$t4, setpts=PTS-STARTPTS [v4_main]; [v4_pre][v4_main] concat=n=2:v=1:a=0 [v4]; # 横向拼接四个视频流 [v1][v2][v3][v4] hstack=n=4:shortest=0 [v_out]; # 处理音频:顺序播放,非播放时段静音 [0:a] atrim=0:$t1, asetpts=PTS-STARTPTS [a1_main]; anullsrc=channel_layout=stereo:sample_rate=44100, trim=0:$((total - t1)) [a1_post]; [a1_main][a1_post] concat=n=2:v=0:a=1 [a1]; anullsrc=channel_layout=stereo:sample_rate=44100, trim=0:$t1 [a2_pre]; [1:a] atrim=0:$t2, asetpts=PTS-STARTPTS [a2_main]; anullsrc=channel_layout=stereo:sample_rate=44100, trim=0:$((total - t1_end)) [a2_post]; [a2_pre][a2_main][a2_post] concat=n=3:v=0:a=1 [a2]; anullsrc=channel_layout=stereo:sample_rate=44100, trim=0:$t2_end [a3_pre]; [2:a] atrim=0:$t3, asetpts=PTS-STARTPTS [a3_main]; anullsrc=channel_layout=stereo:sample_rate=44100, trim=0:$((total - t3_end)) [a3_post]; [a3_pre][a3_main][a3_post] concat=n=3:v=0:a=1 [a3]; anullsrc=channel_layout=stereo:sample_rate=44100, trim=0:$t3_end [a4_pre]; [3:a] atrim=0:$t4, asetpts=PTS-STARTPTS [a4_main]; [a4_pre][a4_main] concat=n=2:v=0:a=1 [a4]; # 混合所有音频流 [a1][a2][a3][a4] amix=inputs=4:duration=longest [a_out] " \ -c:v libx264 -c:a aac -threads auto output.mp4
关键参数说明
-loop 1:让图片循环播放,用于填充非播放时段trim:截取视频/音频的指定时段setpts/asetpts:重置时间戳,避免拼接后出现跳帧concat:将多个视频/音频流按顺序拼接hstack=n=4:横向拼接4个视频流,自动适配1920x1080分辨率amix:混合多个音频流,实现顺序播放效果(非播放时段为静音,不影响正常音频)
注意事项
- 若图片分辨率与视频不一致,需在图片流后添加
scale=480:1080滤镜 - 若原音频的声道/采样率不一致,需用
aresample统一参数(比如在anullsrc中匹配原音频参数) - 可根据实际时长修改脚本中的
t1至t4数值
内容的提问来源于stack exchange,提问作者rst630
相关产品推荐
相关产品推荐

