← 博客

如何使用FFmpeg合并和拼接视频(2026指南)

全面指南:使用FFmpeg合并和拼接多个视频文件。涵盖concat分离器、滤镜、协议方法,以及免费的一键替代方案。

3 min read

有多个视频片段需要合并成一个文件?FFmpeg 提供了几种拼接视频的方法——但正确的方法取决于你的片段是否具有相同的格式、编解码器和分辨率。

本指南涵盖所有三种方法及精确命令。对于不想在终端中调试编解码器不匹配问题的用户,文末还提供了一个免费的拖放替代方案


前提条件:安装 FFmpeg

FFmpeg

macOS:

brew install ffmpeg

Ubuntu/Debian:

sudo apt update && sudo apt install ffmpeg

Windows:ffmpeg.org 下载,解压后将 bin 目录添加到 PATH。


方法一:Concat Demuxer(相同格式——最快)

这是最快也最简单的方法。适用于所有视频具有相同编解码器、分辨率和帧率的情况。

第一步:创建文件列表

创建一个名为 files.txt 的文本文件:

file 'clip1.mp4'
file 'clip2.mp4'
file 'clip3.mp4'

第二步:执行拼接命令

ffmpeg -f concat -safe 0 -i files.txt -c copy output.mp4
  • -f concat — 使用 concat demuxer
  • -safe 0 — 允许绝对/相对路径
  • -c copy — 无需重新编码(即时完成)

自动生成文件列表

Linux/macOS:

for f in *.mp4; do echo "file '$f'" >> files.txt; done
ffmpeg -f concat -safe 0 -i files.txt -c copy output.mp4

Windows(PowerShell):

Get-ChildItem *.mp4 | ForEach-Object { "file '$($_.Name)'" } | Out-File -Encoding ascii files.txt
ffmpeg -f concat -safe 0 -i files.txt -c copy output.mp4

方法二:Concat Filter(不同格式——最灵活)

当片段具有不同的编解码器、分辨率或帧率时,需要使用 concat filter。该方法会对所有内容重新编码以统一规格。

两个视频:

ffmpeg -i clip1.mp4 -i clip2.mov \
  -filter_complex "[0:v][0:a][1:v][1:a]concat=n=2:v=1:a=1[outv][outa]" \
  -map "[outv]" -map "[outa]" output.mp4

三个视频:

ffmpeg -i clip1.mp4 -i clip2.mov -i clip3.avi \
  -filter_complex "[0:v][0:a][1:v][1:a][2:v][2:a]concat=n=3:v=1:a=1[outv][outa]" \
  -map "[outv]" -map "[outa]" output.mp4
  • n=3 — 输入片段数量
  • v=1 — 输出一路视频流
  • a=1 — 输出一路音频流

拼接前统一分辨率

如果片段分辨率不同,先进行缩放处理:

ffmpeg -i clip1.mp4 -i clip2.mp4 \
  -filter_complex \
    "[0:v]scale=1920:1080:force_original_aspect_ratio=decrease,pad=1920:1080:(ow-iw)/2:(oh-ih)/2[v0]; \
     [1:v]scale=1920:1080:force_original_aspect_ratio=decrease,pad=1920:1080:(ow-iw)/2:(oh-ih)/2[v1]; \
     [v0][0:a][v1][1:a]concat=n=2:v=1:a=1[outv][outa]" \
  -map "[outv]" -map "[outa]" output.mp4

方法三:Concat Protocol(仅限 MPEG-TS)

对于 MPEG 传输流,可以直接使用 concat 协议:

# 首先转换为 MPEG-TS
ffmpeg -i clip1.mp4 -c copy -bsf:v h264_mp4toannexb clip1.ts
ffmpeg -i clip2.mp4 -c copy -bsf:v h264_mp4toannexb clip2.ts

# 然后拼接
ffmpeg -i "concat:clip1.ts|clip2.ts" -c copy -bsf:a aac_adtstoasc output.mp4

此方法通常不再推荐使用——concat demuxer(方法一)更简单且更可靠。


特殊场景

合并视频轨道和音频轨道

将视频文件与独立的音频文件合并:

ffmpeg -i video.mp4 -i audio.mp3 -c:v copy -c:a aac -shortest output.mp4
  • -shortest — 在较短的流结束时停止

替换视频中的音频

ffmpeg -i video.mp4 -i new_audio.mp3 -c:v copy -c:a aac -map 0:v -map 1:a output.mp4

拼接不同帧率的视频

拼接前将所有输入强制转换为 30fps:

ffmpeg -i clip1.mp4 -i clip2.mp4 \
  -filter_complex \
    "[0:v]fps=30[v0];[1:v]fps=30[v1]; \
     [v0][0:a][v1][1:a]concat=n=2:v=1:a=1[outv][outa]" \
  -map "[outv]" -map "[outa]" output.mp4

无音频的视频

如果某些片段缺少音频轨道,添加静默音频:

ffmpeg -i clip_no_audio.mp4 -f lavfi -i anullsrc=r=44100:cl=stereo \
  -c:v copy -c:a aac -shortest clip_with_silence.mp4

然后正常拼接。


常见错误及修复方法

“Discarding non-monotonous DTS”

片段之间的时间戳不对齐。重新编码:

ffmpeg -f concat -safe 0 -i files.txt -c:v libx264 -c:a aac output.mp4

“Stream 0 codec does not match”

你的片段使用了不同的编解码器。请使用 concat filter(方法二)而非 concat demuxer。

“Discarding 1 additional packets” / 同步问题

添加 -fflags +genpts 重新生成时间戳:

ffmpeg -fflags +genpts -f concat -safe 0 -i files.txt -c copy output.mp4

输出在片段之间出现黑帧

这是由于片段像素格式不同导致的。强制使用统一格式:

ffmpeg -i clip1.mp4 -i clip2.mp4 \
  -filter_complex "[0:v]format=yuv420p[v0];[1:v]format=yuv420p[v1];[v0][0:a][v1][1:a]concat=n=2:v=1:a=1[outv][outa]" \
  -map "[outv]" -map "[outa]" output.mp4

跳过终端:改用 WaveSpeed Desktop

使用 FFmpeg 合并视频意味着要在三种不同方法之间做选择、创建文件列表、处理编解码器不匹配问题、调试时间戳问题,以及编写看起来像正则表达式噩梦的 filter_complex 字符串。

WaveSpeed Desktop 内置了媒体合并功能,让一切变得简单:

  • 拖放你的视频片段
  • 按需调整顺序
  • 点击合并——一个文件,搞定

不同格式?不同分辨率?应用程序自动处理。

WaveSpeed Desktop Media Merger

免费下载 WaveSpeed Desktop: https://github.com/WaveSpeedAI/wavespeed-desktop/releases


常见问题

应该使用哪种拼接方法? 如果所有片段具有相同的编解码器和分辨率,使用方法一(demuxer)——即时完成。如果片段在任何方面有差异,使用方法二(filter)

可以在片段之间添加转场效果吗? FFmpeg 支持使用 xfade filter 实现基本的交叉淡入淡出转场,但操作较为复杂。对于转场效果,使用可视化编辑器通常更简便。

合并视频会降低质量吗? 使用 -c copy(方法一)不会降低质量。使用 concat filter(方法二)会进行重新编码,可能造成轻微的质量损失。使用较低的 CRF 值(18–20)可将损失降至最低。

可以合并的视频数量有限制吗? FFmpeg 没有硬性限制。实际上,内存和处理时间会随输入数量的增加而增加。