ts 文件怎么合并成 MP4?三种方法对比(命令行 vs 浏览器 vs 桌面工具,2026 版)
抓视频的时候你大概率遇到过这种场景:F12 打开网络面板,发现页面在播放视频,但下载下来的不是一个 mp4,而是一堆编号连续的 .ts 小文件——segment_001.ts、segment_002.ts,几百个躺在文件夹里。
90% 的教程上来就让你装 ffmpeg 写一行 concat: 命令,这能跑通,但跳过了一个更重要的问题:ts 是什么?为什么视频被切成 ts?合并的时候会踩什么坑? 这篇文章按「先理解 → 再选方案 → 最后避坑」的顺序讲清楚 ts 合并 MP4 的所有路径,并对比命令行、浏览器、桌面工具三种方案,让你拿到 ts 之后能立刻判断哪条路最短。
ts 文件到底是什么
ts 全称 MPEG-2 Transport Stream(MPEG-2 传输流),最早是为数字电视广播设计的容器格式,1990 年代就有了。它的核心特点是「任意位置可解码」——每个 188 字节的小包都自带同步头和时间戳,意味着你从中间截一段照样能播。这个特性让它非常适合流媒体分段:服务器把一个完整视频切成几秒一个的 ts 片段,客户端按需下载播放,丢一两个段也不影响整体观看。
这就是 HLS(HTTP Live Streaming)协议的工作机制:一个 .m3u8 索引文件 + 一堆 .ts 分段。m3u8 像目录,ts 是真正的视频肉。所以你抓到一堆 ts,本质上是 HLS 流的「碎片化产物」,需要按 m3u8 里记录的顺序拼回去才是完整视频。
顺便区分一下:现在新一些的 HLS 流会用 .m4s(fMP4 分段)替代 ts,逻辑一样但容器不同;m4s 通常配合 CMAF 用于低延迟直播。本文主要讲 ts,但浏览器方案对 m4s 同样适用。
你为什么会拿到一堆 ts 文件
最常见的来源有三类:
1. F12 抓 m3u8 后批量下载:在浏览器开发者工具的 Network 面板里筛选 .m3u8,复制链接后用 N_m3u8DL-RE 或 yt-dlp 之类的工具批量拉取,工具默认会把每个分段保存为独立 ts 文件,最后留下一个目录的 ts。
2. 边看边录的录屏代理:有些人用本地代理录直播,CDN 推什么本地存什么,结果就是几小时长的 ts 序列堆在硬盘上。
3. 浏览器或播放器缓存:移动端的某些视频 App 把缓存的 HLS 分段直接用原文件名落盘,删了 App 数据也能恢复。
不管是哪种来源,关键问题永远是「分段的顺序对不对」「编码是否一致」——顺序错了画面就乱跳,编码不一致 ffmpeg 直接报错。如果你手上有 .m3u8 索引文件,恭喜你顺序问题已经解决了一半;如果只有一堆裸 ts,那就要靠文件名排序去猜,难度上一个台阶。想先搞清楚自己手上的 m3u8 描述了什么,可以丢给 m3u8 元数据查看 解析分段数量、时长、编码,再决定下一步。
三种合并方法横评
先放一张对比表,再展开说每个方案的细节:
| 维度 | ffmpeg 命令行 | cutfa.st 浏览器 | 桌面工具(如 N_m3u8DL-CLI / OBS) |
|---|---|---|---|
| 安装成本 | 需要装 ffmpeg + 配置 PATH | 0,浏览器打开即可 | 需要下载客户端(Win 居多) |
| 学习曲线 | 高(concat protocol vs demuxer + 编码参数) | 低(拖入 → 点一下) | 中(GUI 但参数不少) |
| 隐私 | 100% 本地 | 100% 本地(WebCodecs 不上传) | 多数本地,部分会调云端 |
| 速度 | 最快(极少数情况秒合) | 快(流式处理,不写中间产物) | 中等 |
| 常见报错 | AAC bitstream / DTS 时间戳乱跳 | 极少(Mediabunny 容错好) | 闭源黑盒难排查 |
| 跨平台 | 全平台 | 全平台(Chrome/Edge/Safari 17+) | 多数仅 Windows |
| 超大文件(10GB+) | 强 | 受浏览器内存限制(建议 < 4GB) | 强 |
| 批量自动化 | 强(脚本可调度) | 弱(需要手动操作) | 中等 |
| 加密 ts 处理 | 需手动配 -decryption_key | 不支持(只读 DRM 元数据) | 部分支持 |
一句话选型:
- 想快速搞定单个视频、不想装环境 → cutfa.st 浏览器方案
- 要批量处理几十上百个视频、有脚本基础 → ffmpeg
- Windows 用户 + 需要边下边合 → N_m3u8DL-RE 之类的桌面工具
浏览器方案:cutfa.st 实战流程
cutfa.st 是基于 Mediabunny + WebCodecs 的浏览器内视频工具,所有处理都在你电脑的浏览器里完成,ts 文件不会上传到任何服务器。这对版权敏感、网速慢、或者懒得装 ffmpeg 的人来说是最省事的。
完整流程:
- 打开 m3u8 转 MP4 工具
- 把
.m3u8文件 + 同目录下的所有 ts 文件一起拖进来(如果 m3u8 里写的是相对路径,就需要 ts 在同一个文件夹) - 工具会自动解析 m3u8、按顺序读取每个 ts、原封不动复用编码(remux,不重新编码所以不损失画质)
- 点「转换」,几秒到几十秒后下载 MP4
关键优势:
- 零损失:ts 里大多是 H.264/H.265 + AAC,MP4 也支持这些编码,所以可以直接 remux(搬运),不需要重新编码——速度快、画质 100% 保留。
- 流式处理:Mediabunny 是流式架构,不会把整个视频加载进内存,所以处理 1-2GB 的视频很轻松。但浏览器内存上限大约 4GB,超过这个量级建议用 ffmpeg。
- 零上传:WebCodecs 直接调用浏览器内置的硬件解码器,文件不离开本地。
如果你手上的不是 m3u8,而是从别处下来的纯 ts 序列(没有索引文件),可以先用 HLS 多格式转换 试试,它对裸 ts 列表也能处理;或者用文本编辑器手写一个 m3u8 索引(下面会讲)。
不支持的场景要诚实说:
- ❌ WebVTT 字幕混流(Mediabunny 1.44 暂不支持把 vtt 字幕烧进 MP4)
- ❌ DRM 加密的 ts(只能读元数据,不能解密输出)
- ❌ 多分辨率自适应输出(只能输出单个码率,不会生成 master playlist)
- ❌ 低延迟 HLS(LL-HLS)的实时录制
如果你的需求踩中以上限制,回去用 ffmpeg。
ffmpeg 命令行实战
ffmpeg 处理 ts 合并主要有两条路:concat protocol 和 concat demuxer。两者用法和适用场景完全不同,搞混了就会报错。
方法一:concat protocol(最快,但限制多)
适用场景:所有 ts 是同一个视频切出来的,编码完全一致。
# Windows(cmd)
ffmpeg -i "concat:001.ts|002.ts|003.ts" -c copy output.mp4
# macOS/Linux
ffmpeg -i "concat:001.ts|002.ts|003.ts" -c copy output.mp4
# 文件多的话用通配符(Linux/macOS)
ffmpeg -i "concat:$(ls *.ts | tr '\n' '|' | sed 's/|$//')" -c copy output.mp4
-c copy 表示直接复用编码(remux),秒级完成。但这种方式只对 ts/mpegts 容器有效,对 mp4/mkv 无效。
方法二:concat demuxer(更通用,更稳)
先建一个 list.txt 文件:
file '001.ts'
file '002.ts'
file '003.ts'
然后跑:
ffmpeg -f concat -safe 0 -i list.txt -c copy -bsf:a aac_adtstoasc output.mp4
注意结尾的 -bsf:a aac_adtstoasc——这是 90% 报错的根源。
最常见的报错:
[mp4 @ 0x...] Malformed AAC bitstream detected: use the audio bitstream filter 'aac_adtstoasc' to fix it
ts 里的 AAC 用的是 ADTS 头格式,MP4 容器要求 AAC 用 ASC(AudioSpecificConfig)头,所以必须加 -bsf:a aac_adtstoasc 转一下,否则音频在 MP4 里播放器认不出。这个 flag 几乎是 ts → mp4 的标配,建议直接背下来。
另一个常见报错是 DTS 时间戳乱跳:
Non-monotonous DTS in output stream / DTS X < DTS Y
这通常意味着分段编号顺序有问题,或者中间漏了几段。修复方式:用 +genpts 重建时间戳:
ffmpeg -fflags +genpts -f concat -safe 0 -i list.txt -c copy -bsf:a aac_adtstoasc output.mp4
常见踩坑
1. 音视频不同步:通常因为分段编号顺序错乱(按文件名字典序排可能 2.ts 排在 10.ts 后面)。解决:把文件名补零成等长(002.ts / 010.ts),或直接用 m3u8 里记录的顺序。
2. 片段缺失:下载工具丢了几段,合并后画面会突然跳。先用 m3u8 元数据查看 对比 m3u8 里的总段数和你硬盘里实际段数,缺多少补多少再合并。
3. 码率/编码不一致:极少见,但一旦碰到 -c copy 必报错。这种情况只能重新编码:
ffmpeg -f concat -safe 0 -i list.txt -c:v libx264 -c:a aac output.mp4
代价是会损失一点画质 + 处理时间从秒级变分钟级。
4. 加密 ts 解密:HLS 经常用 AES-128 加密分段。ffmpeg 处理需要把 m3u8 里的 EXT-X-KEY 行去掉密钥后让 ffmpeg 自动拉取,或者手动用 openssl 解密每个 ts 后再合并。这块超出本文范围,但要知道浏览器方案完全帮不上忙——这是 ffmpeg 的主场。
5. 没有 m3u8 怎么办:手写一个最简单的就行:
#EXTM3U
#EXT-X-VERSION:3
#EXT-X-TARGETDURATION:10
#EXTINF:10.0,
001.ts
#EXTINF:10.0,
002.ts
#EXT-X-ENDLIST
把 EXTINF 时长写大一点(比如 10)当占位,丢给 cutfa.st 或 ffmpeg 都能跑。
FAQ
Q1: 没有 m3u8 索引文件,只有一堆乱序的 ts,能合并吗?
可以,但顺序需要你自己确认。先按文件名排序(注意补零问题),用 ffmpeg concat demuxer 试合并,播放后看画面是否连贯。如果原始视频是直播录的,文件修改时间排序通常也准。
Q2: 合并会损失画质吗?
不会,前提是用 -c copy(ffmpeg)或 cutfa.st 这类基于 remux 的工具——它们只是把视频流换个容器装,不重新编码。只有当编码不兼容必须 re-encode 时才会损失。
Q3: 几千个 ts 文件超大量怎么处理?
ffmpeg 的 concat demuxer 没有数量上限,list.txt 写多少行都行;浏览器方案受内存限制,建议总大小 < 4GB。如果是几十 GB 的素材,老老实实 ffmpeg。
Q4: 加密 ts(AES-128)能在浏览器里合并吗?
不能。cutfa.st 基于的 Mediabunny 1.44 只读取 DRM 元数据,不解密输出。这种情况用 ffmpeg + 解密后的 key.bin 处理。
Q5: Mac/Linux/Windows 哪个平台最好用?
cutfa.st 全平台一致(Chrome / Edge / Safari 17+ 都行);ffmpeg 三个平台都有官方二进制;桌面工具如 N_m3u8DL-RE 主要 Windows 体验最好。如果你跨平台办公,浏览器方案和 ffmpeg 是更通用的选择。
Q6: 合并完想直接转成 mp3/wav 怎么办?
合并出 MP4 后再用 ffmpeg -vn -c:a libmp3lame 抽音轨;或者跳过中间步骤,直接用 HLS 多格式转换 把 m3u8 一次性输出 MP3/WAV/AAC,省一步。
小结
ts 合并 MP4 的本质是「把 HLS 分段重新拼回完整文件」。三种方案各有适合的场景:cutfa.st 浏览器适合一次性、隐私敏感、不想装环境的人;ffmpeg 适合批量、自动化、有脚本基础的人;桌面工具适合 Windows 用户的边下边合需求。无论选哪条路,记住三件事——先确认分段顺序、aac_adtstoasc 必加、-c copy 优先以保画质——基本就能避开 90% 的坑。