前言
在做视频处理相关工具时,经常会遇到一个很常见的需求:
把一堆
.ts分片视频合并成一个 MP4 文件。
这种情况在很多场景都会出现,例如:
- HLS 视频流下载
- 课程平台视频缓存
- 直播流录制
- M3U8 视频下载
通常你会得到一堆文件:
0001.ts
0002.ts
0003.ts
...
如果你用过视频处理工具,大概率知道这件事可以用 FFmpeg 一条命令完成。但对于大多数用户来说,命令行始终是个门槛。
于是我尝试用 ffmpeg.wasm 做了一个浏览器端 TS 合并工具,让整个流程变成:
拖入 TS 文件 → 点击合并 → 下载 MP4
不需要安装软件,也不需要上传视频到服务器。
一、为什么 TS 文件经常需要合并
TS(Transport Stream)是 MPEG‑TS 格式,常见于 HTTP Live Streaming(HLS) 视频流。
HLS 的工作方式是:
- 视频被切成很多
.ts小片段 - 用
.m3u8文件记录播放顺序 - 播放器按顺序加载这些 TS
例如:
index.m3u8
segment0001.ts
segment0002.ts
segment0003.ts
如果你通过工具下载视频,往往就只会得到这些 .ts 文件。这时候最常见的需求就是:
把这些 TS 文件重新拼成一个完整视频。
二、传统解决方案的问题
传统做法一般有三种。
1 使用 FFmpeg 命令
最标准的方法是:
ffmpeg -f concat -safe 0 -i list.txt -c copy output.mp4
但问题是:
- 要安装 FFmpeg
- 要写文件列表
- 要使用命令行
对于非技术用户来说并不友好。
2 使用桌面软件
例如:
- 格式工厂
- 剪映
- Premiere
但这些工具存在几个问题:
- 安装体积大
- 打开速度慢
- 操作复杂
3 使用在线网站
很多在线工具要求:
- 上传视频到服务器
但 TS 文件往往:
- 几百 MB
- 几 GB
上传速度慢,而且很多人也不希望视频离开本地设备。
三、ffmpeg.wasm:让浏览器运行 FFmpeg
为了解决这个问题,我选择了 ffmpeg.wasm。简单来说,它做了一件很有意思的事情:
把 FFmpeg 编译成 WebAssembly。
也就是说:
浏览器可以直接运行 FFmpeg。
整个流程变成:
浏览器
↓
WebAssembly
↓
FFmpeg
↓
本地视频处理
优点非常明显:
- 不需要安装软件
- 不需要上传视频
- 数据完全在本地处理
- 跨平台(Windows / Mac / Linux / 手机)
四、实现一个 TS 在线合并工具的思路
我在实现这个工具时,整体流程大致是这样的。
第一步:加载 FFmpeg wasm
浏览器启动时加载 FFmpeg wasm 核心。
示例代码:
import {
createFFmpeg } from "@ffmpeg/ffmpeg"
const ffmpeg = createFFmpeg({
log: true
})
await ffmpeg.load()
第一次加载会稍慢,因为需要下载 wasm 文件。
第二步:上传 TS 文件
用户可以:
- 拖拽文件
- 或选择多个 TS 文件
示例:
for (const file of files) {
ffmpeg.FS("writeFile", file.name, await fetchFile(file))
}
这些文件会被写入 FFmpeg 的虚拟文件系统。

第三步:生成 concat 列表
FFmpeg 合并 TS 的标准方法是使用 concat demuxer。
例如:
file '0001.ts'
file '0002.ts'
file '0003.ts'
浏览器中动态生成:
let list = files
.map(f => `file '${
f.name}'`)
.join("\n")
ffmpeg.FS("writeFile", "list.txt", list)
第四步:执行合并命令
核心命令:
ffmpeg -f concat -safe 0 -i list.txt -c copy output.mp4
在 wasm 中运行:
await ffmpeg.run(
"-f","concat",
"-safe","0",
"-i","list.txt",
"-c","copy",
"output.mp4"
)
这里的关键点是:
-c copy
表示:
不重新编码,只做封装转换
因此速度非常快。

第五步:导出 MP4 文件
最后从虚拟文件系统读取结果:
const data = ffmpeg.FS("readFile", "output.mp4")
然后触发浏览器下载。

五、最终实现效果
整个用户体验变成:
1️⃣ 打开网页
2️⃣ 拖入 TS 文件
3️⃣ 点击合并
4️⃣ 下载 MP4
整个过程:
- 不上传视频
- 不安装软件
- 不需要命令行
浏览器直接完成视频处理。
如果你想体验类似的工具,可以参考这个在线 TS 合并工具:
https://ezwebtools.net/ts-merge
它的交互流程和设计思路与我实现的版本比较接近。
六、浏览器端视频处理的优势
使用 ffmpeg.wasm 做视频工具,其实有几个非常明显的优势。
1 隐私安全
视频始终在本地处理:
- 不上传服务器
- 不经过第三方存储
2 几乎零运维成本
服务器只需要:
- 静态文件
- CDN
不需要:
- GPU
- 编码服务器
- 视频存储
3 跨平台
只要有浏览器:
- Windows
- macOS
- Linux
- Android
- iOS
都可以使用。
七、开发过程中的一些坑
在实现这个工具时,也遇到了一些实际问题。
1 浏览器内存限制
TS 文件如果:
- 几 GB
浏览器可能会出现内存压力。
2 wasm 首次加载较慢
首次加载 ffmpeg.wasm:
- 需要下载十几 MB
可以通过:
- CDN
- 缓存
优化体验。
八、总结
以前做视频处理:
需要安装软件、写命令、配置环境。
现在通过 ffmpeg.wasm,浏览器本身就可以成为一个轻量级的视频处理平台。
像 TS 合并这种常见需求,其实只需要:
- 文件上传
- concat 列表
- FFmpeg 执行
三步就能完成。
而用户体验也从:
复杂命令行操作
变成:
拖文件 → 点击 → 下载
这也是 WebAssembly 在前端工具领域一个非常典型的应用场景。