Mac上使用FFmpeg合并TS文件的完整指南

0 次阅读

TS(Transport Stream)文件经常出现在网络视频分片、直播录制以及部分下载任务中。一个完整的视频可能被拆分成多个 .ts 文件,例如 001.ts002.ts003.ts 等。单独播放没有问题,但想获得一个完整的视频文件,就需要进行合并。

对于 Mac 用户来说,FFmpeg 是处理这类任务非常实用的工具。它支持 macOS,并且可以通过命令行快速完成 TS 文件合并,同时避免重新编码带来的画质损失。

一、Mac安装FFmpeg

如果 Mac 尚未安装 FFmpeg,可以使用 Homebrew 安装。打开“终端”,执行:

Bash
brew install ffmpeg

安装完成后检查版本:

Bash
ffmpeg -version

能够看到 FFmpeg 的版本信息,就说明安装成功。

如果系统提示 brew: command not found,说明还没有安装 Homebrew,需要先完成 Homebrew 的安装。

二、准备需要合并的TS文件

假设当前目录中有以下文件:

001.ts
002.ts
003.ts
004.ts

首先进入这些文件所在的目录。例如文件保存在桌面的 video 文件夹:

Bash
cd ~/Desktop/video

可以使用 ls 查看当前文件:

Bash
ls

确认所有 TS 文件都在同一个目录中。

文件顺序非常重要

TS 文件通常具有严格的播放顺序。如果原始视频依次是:

001.ts
002.ts
003.ts
004.ts

那么合并时也必须按照这个顺序处理。

如果文件名称是:

1.ts
2.ts
10.ts
11.ts

直接使用某些通配符命令时,可能得到:

1.ts
10.ts
11.ts
2.ts

这显然不是正确的视频顺序。

因此,建议将文件命名为:

001.ts
002.ts
003.ts
...
010.ts
011.ts

通过补零方式保证文件名具有正确的字典排序。

三、使用FFmpeg直接合并TS文件

对于编码格式一致、分片结构正常的 TS 文件,最简单的方法是使用 concat 协议:

Bash
ffmpeg -i "concat:001.ts|002.ts|003.ts|004.ts" -c copy output.ts

这里的参数含义如下:

  • -i:指定输入文件。

  • concat::使用 FFmpeg 的 concat 协议连接多个 TS 文件。

  • |:分隔不同的 TS 文件。

  • -c copy:直接复制音视频数据,不进行重新编码。

  • output.ts:合并后的文件名。

这种方式速度通常非常快,因为 FFmpeg 不需要重新压缩视频和音频。

四、TS文件较多时使用文件列表

如果需要合并几十甚至几百个 TS 文件,把所有文件写在命令中会比较麻烦。这种情况下,更推荐使用 concat demuxer。

首先创建一个文本文件:

Bash
touch filelist.txt

然后编辑:

Bash
nano filelist.txt

写入:

file '001.ts'
file '002.ts'
file '003.ts'
file '004.ts'

保存后执行:

Bash
ffmpeg -f concat -safe 0 -i filelist.txt -c copy output.ts

这种方法更加适合批量合并。

其中:

Bash
-f concat

表示使用 concat demuxer。

Bash
-safe 0

允许使用更灵活的文件路径。如果列表中使用绝对路径,通常建议保留这个参数。

Bash
-c copy

仍然表示直接复制原始音视频流。

五、自动生成TS文件列表

如果一个目录中存在大量按照顺序命名的 TS 文件,可以利用 Shell 命令自动生成列表。

例如:

Bash
for f in *.ts; do echo "file '$f'"; done > filelist.txt

随后查看:

Bash
cat filelist.txt

可能得到:

file '001.ts'
file '002.ts'
file '003.ts'
file '004.ts'

确认顺序正确后执行:

Bash
ffmpeg -f concat -safe 0 -i filelist.txt -c copy output.ts

这种方式特别适合处理大量分片文件。

不过需要注意,*.ts 的排序依赖文件名。对于 1.ts、2.ts、10.ts 这种命名方式,建议先重新命名,或者使用更可靠的排序方式生成列表。

例如:

Bash
printf "%s
" *.ts | sort -V | while read f; do
    echo "file '$f'"
done > filelist.txt

生成的列表可以通过:

Bash
cat filelist.txt

检查。

六、直接合并并输出MP4

很多情况下,最终目的并不是得到一个 TS 文件,而是获得可以方便播放和分享的 MP4。

如果 TS 文件中的音视频编码格式本身适合 MP4 容器,可以尝试:

Bash
ffmpeg -f concat -safe 0 -i filelist.txt -c copy output.mp4

FFmpeg 会将音视频流直接封装到 MP4 容器中,不重新编码。

因此,处理速度通常很快,而且不会因为重新编码造成额外画质损失。

不过需要注意,TS 能够直接复制到 MP4,并不意味着所有 TS 文件都可以无损封装成 MP4。最终是否成功取决于其中的视频、音频编码以及时间戳等信息。

七、为什么推荐使用-c copy

合并视频时,经常会看到两种处理方式。

第一种是直接复制:

Bash
ffmpeg -f concat -safe 0 -i filelist.txt -c copy output.mp4

第二种是重新编码:

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

两者最大的区别就是是否重新编码。

使用:

Bash
-c copy

FFmpeg 不会重新压缩视频和音频,因此具有几个明显优势:

  1. 处理速度快;

  2. CPU占用相对较低;

  3. 不会产生重新编码导致的画质损失;

  4. 文件合并过程更加适合大量TS分片。

重新编码则需要重新压缩整个视频,耗时会明显增加。

因此,如果 TS 文件本身没有编码兼容性问题,优先使用 -c copy

八、合并后出现画面或声音异常怎么办

并不是所有 TS 分片都可以简单地通过 -c copy 合并。有些 TS 文件可能来自不同的视频流、直播切片或者经过特殊处理的视频源。

常见问题包括:

  • 合并后只有声音没有画面;

  • 视频播放到某处出现卡顿;

  • 音频逐渐不同步;

  • 文件无法正常拖动进度条;

  • MP4 输出失败;

  • 合并后视频时长显示错误。

遇到这种情况,可以先检查单个 TS 文件:

Bash
ffprobe 001.ts

也可以查看更详细的流信息:

Bash
ffprobe -v error -show_streams 001.ts

重点观察视频编码、音频编码、分辨率、帧率以及时间基等信息。

如果多个分片的编码参数并不一致,那么直接进行流复制可能无法得到正常结果。

九、必要时重新编码

如果确认 TS 分片之间存在兼容性问题,可以尝试重新编码:

Bash
ffmpeg -f concat -safe 0 -i filelist.txt 
-c:v libx264 
-preset medium 
-crf 18 
-c:a aac 
-b:a 192k 
output.mp4

其中:

Bash
-c:v libx264

表示使用 H.264 编码视频。

Bash
-crf 18

用于控制视频质量。CRF 数值越低,通常画质越高,同时文件体积也越大。

Bash
-c:a aac

表示使用 AAC 编码音频。

Bash
-b:a 192k

设置音频码率为 192 kbps。

重新编码的兼容性通常更好,但处理时间会明显增加,而且属于有损压缩过程。

十、处理时间戳异常

部分 TS 分片来自直播流,可能存在时间戳不连续的问题。这时 FFmpeg 可能输出类似警告:

Non-monotonous DTS

或者:

DTS out of order

如果最终视频可以正常播放,可以先检查实际效果。如果出现明显的音画不同步或播放异常,则需要进一步处理时间戳。

可以尝试:

Bash
ffmpeg -f concat -safe 0 -i filelist.txt -c copy -avoid_negative_ts make_zero output.mp4

对于比较复杂的直播切片,还可能需要重新生成时间戳或重新编码。具体参数应根据 ffprobe 检查结果决定,不建议盲目堆叠参数。

十一、使用通配符直接合并是否可行

很多人会尝试:

Bash
ffmpeg -i "*.ts" -c copy output.ts

这种写法通常并不能按照预期工作。

原因是:

Bash
*.ts

是 Shell 文件通配符,而 FFmpeg 的 -i 参数并不会把多个匹配文件自动理解为一个视频序列。

正确方式是先生成 concat 列表:

Bash
for f in *.ts; do echo "file '$f'"; done > filelist.txt

然后:

Bash
ffmpeg -f concat -safe 0 -i filelist.txt -c copy output.ts

这样处理更加稳定,也方便人工检查文件顺序。

十二、使用绝对路径合并TS文件

如果 TS 文件分布在其他目录,也可以在 filelist.txt 中使用绝对路径:

file '/Users/username/Desktop/video/001.ts'
file '/Users/username/Desktop/video/002.ts'
file '/Users/username/Desktop/video/003.ts'

然后:

Bash
ffmpeg -f concat -safe 0 -i filelist.txt -c copy output.ts

这里使用:

Bash
-safe 0

是为了允许 concat demuxer 使用这些路径。

如果路径中包含空格,使用单引号包围路径:

file '/Users/username/Desktop/My Videos/001.ts'

十三、文件名包含特殊字符怎么办

如果 TS 文件名包含空格、单引号等特殊字符,手动创建列表时要格外注意。

例如:

file 'video 001.ts'
file 'video 002.ts'

对于大量文件,更建议使用脚本自动生成列表,减少转义错误。

如果文件名称比较复杂,最简单的解决方式通常是先统一重命名,例如:

001.ts
002.ts
003.ts

再进行合并。

十四、合并完成后检查视频

合并完成后,不要只看 FFmpeg 是否执行结束,还应该检查最终文件。

可以使用:

Bash
ffprobe output.mp4

或者:

Bash
ffprobe -v error -show_format -show_streams output.mp4

检查:

  • 视频是否存在;

  • 音频是否存在;

  • 视频时长是否正确;

  • 编码格式是否符合预期;

  • 文件容器是否正常。

也可以直接使用 Mac 上的播放器打开视频,拖动进度条测试开头、中间和结尾部分。

十五、一个完整的实用流程

假设桌面目录:

~/Desktop/ts-video/

里面有:

001.ts
002.ts
003.ts
004.ts
005.ts

首先进入目录:

Bash
cd ~/Desktop/ts-video

自动生成列表:

Bash
for f in *.ts; do echo "file '$f'"; done > filelist.txt

查看列表:

Bash
cat filelist.txt

确认顺序无误后直接合并:

Bash
ffmpeg -f concat -safe 0 -i filelist.txt -c copy output.ts

如果希望输出 MP4,可以尝试:

Bash
ffmpeg -f concat -safe 0 -i filelist.txt -c copy output.mp4

如果 MP4 兼容性不好,再考虑重新编码:

Bash
ffmpeg -f concat -safe 0 -i filelist.txt 
-c:v libx264 -crf 18 
-c:a aac -b:a 192k 
output.mp4

这套流程基本覆盖了 Mac 上常见的 TS 文件合并需求。

十六、几个容易忽略的问题

1. 不要删除原始TS文件

确认输出视频能够正常播放之前,建议保留所有原始分片。这样即使合并失败,也可以重新调整参数处理。

2. 合并不是重新编码

所谓“合并视频”并不一定需要重新压缩。对于编码一致的 TS 分片,使用:

Bash
-c copy

通常是更合理的选择。

3. 文件顺序比命令本身更重要

如果分片顺序错误,即使 FFmpeg 命令执行成功,最终视频也可能出现剧情跳跃、声音错乱或者画面顺序异常。

4. 不要仅凭扩展名判断编码

所有文件都是 .ts,并不代表内部的视频和音频编码完全相同。遇到无法合并的问题时,应使用 ffprobe 检查实际流信息。

5. 输出MP4并非总能直接复制

TS 是一种传输流容器,而 MP4 是另一种媒体容器。两者支持的编码和时间戳机制存在差异,因此 -c copy 输出 MP4 失败并不意味着 TS 文件损坏。

十七、常用命令汇总

直接连接少量 TS 文件:

Bash
ffmpeg -i "concat:001.ts|002.ts|003.ts" -c copy output.ts

通过列表合并:

Bash
ffmpeg -f concat -safe 0 -i filelist.txt -c copy output.ts

合并并封装为 MP4:

Bash
ffmpeg -f concat -safe 0 -i filelist.txt -c copy output.mp4

重新编码为 H.264 + AAC:

Bash
ffmpeg -f concat -safe 0 -i filelist.txt 
-c:v libx264 -crf 18 
-c:a aac -b:a 192k 
output.mp4

检查媒体信息:

Bash
ffprobe -v error -show_streams output.mp4

自动生成文件列表:

Bash
for f in *.ts; do echo "file '$f'"; done > filelist.txt

对于 Mac 上的 TS 文件合并任务,优先推荐“整理文件顺序 → 生成 filelist.txt → FFmpeg concat → -c copy 无损合并 → 检查输出文件”这条路线。只有在编码不兼容、时间戳异常或输出容器存在兼容性问题时,再考虑重新编码。这样既能提高处理速度,也能尽可能保留原始视频质量。