Ffmpeg 合并 TS 文件完整教程(附批量脚本+常见报错解决)
目录
- 不想装软件的情况
- 安装 FFmpeg
- 核心命令:concat 解复用器 + 流复制
- 列表生成:顺序不出错才是关键
- Windows bat 脚本:双击合并
- Python 脚本:批量处理多个文件夹
- 常见报错与解决
- 什么时候只能重新编码
一、不想装软件的情况
实拍(2026-10-30):已选择 segment_000.ts、segment_001.ts、segment_002.ts,并点击「按编号排序」;确认列表后再点「开始合并」。来源:EZ在线工具网;使用合成测试素材演示,点击图片可放大。
如果只是偶尔合一次、文件也不大,先不必折腾安装配置。浏览器里就能完成,比如 ezwebtools.net/ts-merge,把 TS 拖进去、确认顺序、点合并。
挑这类工具时,先看清一件事:它是在你本机处理,还是要把文件上传到服务器。
判断方法:打开页面 → F12 → Network 面板 → 断开网络 → 拖文件进去点合并。还能跑完,就说明处理确实发生在本地;网络不通还能合,总不至于把文件传出去了。
浏览器方案也有边界。它跑的是编译到 WebAssembly 的 FFmpeg,比原生慢一截,而且受浏览器可用内存约束。几个 GB 的量级,还是装个本地 FFmpeg 踏实。
二、安装 FFmpeg
TS 合并这件事基本绕不开 FFmpeg,多数带界面的工具底层也是调它。
Windows
- 打开 ffmpeg.org/download.html
- Windows 区域选 gyan.dev 或 BtbN 的构建
- 下载 release-full 版本(
.7z用 7-Zip 解压),解压到固定位置,比如C:\ffmpeg - 把
C:\ffmpeg\bin加进系统环境变量 Path - Win+R →
powershell→ 执行ffmpeg -version,输出版本信息就装好了
macOS:brew install ffmpeg
Linux(Debian/Ubuntu 系):sudo apt install ffmpeg
三、核心命令:concat 解复用器 + 流复制
图:适用于编码参数兼容的 TS 分片;命令和脚本见正文。
1 | ffmpeg -y -f concat -safe 0 -i list.txt -c copy -bsf:a aac_adtstoasc output.mp4 |
| 参数 | 含义 |
|---|---|
-y |
输出文件已存在时直接覆盖,不交互等待 |
-f concat |
使用 concat 解复用器,按列表顺序读取多个输入 |
-safe 0 |
允许列表里出现绝对路径、.. 等特殊写法 |
-i list.txt |
输入文件列表 |
-c copy |
流复制,不解码不重新编码,画质零损失 |
-bsf:a aac_adtstoasc |
将 AAC 的 ADTS 封装转换为 AudioSpecificConfig 并移除 ADTS 头,适配 MP4;不是时间戳修复工具 |
list.txt 长这样:
1 | file 'segment_000.ts' |
实拍(2026-10-30):浏览器直接打开本次合并使用的原始 list.txt,每行是一个分片,顺序为 000、001、002。这是文件内容截图,不是终端截图。
核对时检查三件事:第一行是不是首个分片、有没有漏片、文件名是否与实际文件一致。可查看本次原始列表,或下载合成测试包自己复现;解压后在该目录执行文中的合并命令。
-c copy 是整个操作的关键。 没有它,ffmpeg 会把每个分片解码再重编一遍,画质必定下降,耗时也会高一个数量级。
合并后的实际检查结果
实拍(2026-10-30):三段合成 TS 合并后执行 ffprobe -hide_banner output.mp4,将实际输出保存为文本并在浏览器中打开。截图不是模拟的终端界面;日志仅将临时目录路径省略为文件名。
看 Duration 是否符合预期,再看是否同时出现 Video: h264 与 Audio: aac。本次样例为 640×360、时长约 6.19 秒,输出文件为 643438 字节;这些数值只是本次合成素材的结果,不是所有视频的固定参数。检测到音轨也不代表听感一定正常,仍应播放并抽查分片衔接。可查看原始检测输出和下载测试包。

实拍(2026-10-30):浏览器已加载本次实际生成的 MP4,显示 640×360 的合成测试画面及约 6 秒总时长。这里展示的是检测结果对应的同一个文件,不是网上找到的示例成片。
可以打开这段测试成片,检查开头、中间、结尾能否正常播放;自己的视频还需要确认内容连续、声音和画面同步。
参数含义参见 FFmpeg 官方位流过滤器文档。
aac_adtstoasc不负责修复音画不同步。
容易混淆的两个东西
很多人说的”concat 协议”,严格讲不是一回事:
- concat 解复用器(
-f concat):读一个列表文件,适合文件多、要走磁盘的情况,容错和处理能力更好 - concat 协议:直接把文件用管道符串起来,例如:
1 | ffmpeg -i "concat:s1.ts|s2.ts|s3.ts" -c copy output.mp4 |
文件少的时候方便,但文件名里不能出现特殊字符,也不能处理分辨率/编码不一致的输入。文件一多就不如列表方式可靠,所以一般用列表。
四、列表生成:顺序不出错才是关键
图:以下用 1、2、10、100 四个分片说明两种排序的区别。
TS 合并最常出的问题不是命令写错,而是顺序。文件系统默认给的是字典序:
1 | 字典序:1.ts → 10.ts → 100.ts → 2.ts |
如果文件名是补零的(segment_0001.ts),字典序和数字序一致,直接用默认排序没问题。没补零就必须做自然排序。
macOS / Linux
1 | # 命名补零时 |
Windows PowerShell
1 | Get-ChildItem -Filter *.ts | |
这个写法把文件名里的数字左侧补零到 12 位再排序,video(2).ts 就能正确排在 video(10).ts 前面。
IDM 那种 video(1).ts 命名,数字在括号里,单独提取括号内的数字更准:
1 | Get-ChildItem "video(*).ts" | |
生成完一定用记事本打开 list.txt 扫一眼,确认第一行是第一个分片。这一步省不得——顺序错了,合出来的视频会在中间跳画面、断声音,而且排查起来很费时间。
如果你有 index.m3u8,它的片段顺序就是权威答案,比猜文件名靠谱。
文件名里有单引号怎么办
concat 列表用单引号包裹路径,文件名自带 ' 时会把格式搞坏。规范写法是转义成 '\'':
1 | file 'it's_a_test.ts' ← 错误 |
实际场景少见,但脚本里最好处理掉,下面 Python 脚本已经处理了。
五、Windows bat 脚本:双击合并
每次都敲命令太麻烦。把下面内容存成 merge_ts.bat(保存编码选 ANSI/GBK,脚本首行已切 UTF-8 代码页),丢到 TS 文件所在目录,双击运行:
1 | @echo off |
几个细节:
- 用 PowerShell 而不是
for %%i in (*.ts)生成列表,是因为后者按目录枚举顺序走,遇到未补零的编号会出错 -nostdin防止 ffmpeg 消耗标准输入,脚本里跑循环时容易因为这个卡住[char]39是单引号,这么写是为了避开 cmd 对引号的处理- 想改输出名就把
merged.mp4换成你要的
六、Python 脚本:批量处理多个文件夹
下载下来的视频往往一个视频一个文件夹,逐个处理太慢。下面这个脚本会遍历所有子文件夹,逐个合并。
1 | """ |
失败信息只取最后三行是为了不让输出被 ffmpeg 的日志淹没。真要排查时,把 capture_output=True 去掉,让日志直接打到终端更方便。
如果 TS 是跟着 M3U8 下载的,更稳的做法是直接解析 M3U8 里的片段顺序,而不是靠文件名排序——M3U8 是权威顺序,文件名可能是混淆过的。
七、常见报错与解决
1. Unsafe file name
1 | [concat @ ...] Unsafe file name 'C:\videos\segment_000.ts' |
原因:命令里漏了 -safe 0,或者列表里用了 ffmpeg 认为不安全的路径写法。
解决:加上 -safe 0。仍报错就把列表里的路径改成相对路径(列表文件和 TS 放同一目录时,直接写文件名最短最省事)。
2. Could not find tag for codec ... in stream
伴随 Stream mapping 输出后退出的情况。
原因:TS 里有一路 MP4 写不了的流——常见于字幕流、数据流(比如 teletext)。TS 容器什么都能装,MP4 不行。
解决:只挑视频和音频流:
1 | ffmpeg -y -f concat -safe 0 -i list.txt -c copy -map 0:v -map 0:a output.mp4 |
需要保留字幕的话,输出成 MKV,或者用 -map 0 输出 MKV(见下一条)。
3. 合并后有画面没声音
原因:MP4 容器不支持源里的音频编码。TS 里常见 AC3、DTS、PCM 等,MP4 对它们的支持不完整。
解决 A(推荐,保持无损):输出成 MKV,容器兼容性好得多:
1 | ffmpeg -y -f concat -safe 0 -i list.txt -c copy output.mkv |
解决 B:只转音频,视频保持原样:
1 | ffmpeg -y -f concat -safe 0 -i list.txt -c:v copy -c:a aac -b:a 192k output.mp4 |
4. Invalid data found / Packet loss
原因:某个 TS 片段在下载或录制时损坏了。
解决:先定位是哪个文件。Windows cmd 里逐个试:
1 | for %i in (*.ts) do @ffmpeg -v error -i "%i" -f null - 2>&1 | findstr /i error |
Linux / macOS:
1 | for f in *.ts; do ffmpeg -v error -i "$f" -f null - 2>&1 | grep -i error; done |
找到之后看体积:几百字节的基本是空文件,删掉即可;体积正常但报错的,可以试试重封装一遍修复:
1 | ffmpeg -i broken.ts -c copy fixed.ts |
5. 合并后顺序是乱的
现象:播放到一半突然跳到另一个画面,然后又跳回来。
原因:生成列表时用了字典序(见第四节)。
解决:用自然排序重新生成列表。有 M3U8 的话,按 M3U8 里的顺序排。
6. 音画不同步,并且越到后面越明显
原因:源分片的时间戳(PTS/DTS)不连续或不规范,concat 直接沿用导致累积偏移。
解决:先让 ffmpeg 重建时间戳:
1 | ffmpeg -y -fflags +genpts -f concat -safe 0 -i list.txt -c copy output.mp4 |
-fflags +genpts 是输入选项,要放在 -i 前面,放后面不生效。
还不行的情况下只能重新编码,这会带来画质损失,但能把时间轴彻底理顺:
1 | ffmpeg -y -f concat -safe 0 -i list.txt -c:v libx264 -crf 18 -c:a aac -b:a 192k output.mp4 |
八、什么时候只能重新编码
-c copy 的前提是所有分片的编码参数完全一致。以下情况它会失败或者结果不对,只能走编码路线:
- 分片来自不同设备/不同录制过程(分辨率、帧率、编码格式不一致)
- 需要裁剪片段、加水印、改分辨率
- 输出容器不支持源编码(比如源是 HEVC,目标播放器只认 H.264)
- concat 各种调整都试过仍然报错
1 | ffmpeg -y -f concat -safe 0 -i list.txt \ |
| 参数 | 说明 |
|---|---|
-crf 18 |
恒定质量控制,数值越小画质越好体积越大,18 约等于”视觉无损” |
-preset medium |
编码速度与压缩率的权衡,越慢压得越小 |
小结
| 场景 | 做法 |
|---|---|
| 偶尔合一次、文件不大 | 浏览器工具 ezwebtools.net/ts-merge |
| 常规本地合并 | ffmpeg -f concat -safe 0 -i list.txt -c copy -bsf:a aac_adtstoasc out.mp4 |
| 想双击就用 | 第五节的 bat 脚本 |
| 几十上百个文件夹 | 第六节的 Python 脚本 |
| 合并后没声音 / 不同步 / 报错 | 对照第七节的症状表 |
| 分片参数不一致 | 只能重新编码 |
三个最容易踩的坑:漏掉 -c copy、列表顺序用的是字典序、输出 MP4 却塞了 MP4 不支持的流。避开这三条基本一次过。
本文的命令基于 2026 年 9 月的 FFmpeg 版本,各平台的构建源(gyan.dev / BtbN)下载方式可能调整,安装步骤以 ffmpeg.org 当前页面为准。
