简介:一款面向数字电视开发与初学者的 TS 码流分析工具,适合需要快速掌握传输流结构的工程师、学生或运维人员。软件以 Tree 树形结构直观展示 PAT、PMT、SDT、EIT 以及 Subtitle 的 PES 包,树结构与 SI 数据一一对应;除常规 SI 解析外,还额外解析 LCN 与 Subtitle 数据,并能将字幕图像仿真显示出来。双击 Subtitle 的 PES 节点即可在右侧查看字幕图片;可仿真搜台过程并将结果列于右侧;支持仿真 EPG;双击 EIT 表可将所有 EIT 存成网页,打开 parsing_result.html 即可查看;解析完成后点击 HTML 按钮还能将 PAT、PMT、SDT、NIT 保存为网页格式;双击 EIT 中的 eventid 会弹出窗口显示该事件的详细数据;码流大小不受限制。资源包共 30 个文件,以 exe 可执行程序、C 源码、HTML 解析结果页、JavaScript 树形控件及 GIF 图标等类型为主,压缩包仅 161KB,轻量实用,方便直接运行或阅读源码学习 TS 原理。已有 1912 人学习下载,适合 DTV 入门者对照实例边看边学。
1. 拿到一个 .ts 文件,你最该先做的是「拆开看」
做 DVB、IPTV 或播放器相关开发的人,大概率都有过这种经历:播放器能放、画面也没问题,但一旦上级问「这个码流里到底有几路视频、音频是什么编码、有没有丢包」,你就只能对着一个几十 MB 的 .ts 文件发呆。TS 结构不像 MP4 那样有清晰的 box 索引,它本质上是一串 188 字节的小包排成的长队,所有信息都藏在包的头部和负载里,肉眼完全不可读。这时候,你需要的不是更好的播放器,而是一个能把这串二进制包拆开、把 PID 映射、PSI/SI 表、PCR、连续性计数器全部摊开给你看的码流分析工具。本文就围绕 ts analysis tool 这个方向,从 TS 结构的最小知识讲起,给出我能复现的最小命令、输出解读方式、常见误判和排错路径,让你下次拿到陌生码流时,能在十分钟内说清楚「这是什么、结构是否正常、问题大概出在哪」。
2. TS 结构速成:188 字节小包里的四个关键信息,不懂这个谈不上分析
2.1 为什么 TS 一定要定长 188 字节
TS(Transport Stream,传输流)在设计之初就是面向容易出错的信道,比如卫星、地面广播和有线网络。定长包的最大好处是:接收端一旦找到同步字节 0x47,就能以 188 字节为步长连续跳读,即使中间丢了几包,也可以从下一个完整包重新同步。这个设计在实时广播场景里远比「文件内索引」可靠,因为它不依赖随机访问,只依赖顺序解析。你在分析工具里看到的所有统计,比如包总数、丢包率、PID 分布,本质上都是基于「188 字节定长」这个前提算出来的。如果某个文件不是标准 188 包长(比如 204 字节,带 RS 校验的版本),工具需要先做包长探测,否则从第二个包开始就全部错位。
TS 包头的结构只有 4 字节固定部分:同步字节 0x47、1 比特传输错误指示、1 比特载荷单元起始指示、1 比特传输优先级、13 比特 PID、2 比特加扰控制、2 比特自适应字段控制、4 比特连续性计数器。这里面对分析最有价值的就是 PID 和连续性计数器。PID 决定这个包属于哪一条「逻辑通道」,连续性计数器则用来判断这条通道上有没有丢包。工具的本质工作,就是把这些字段全部解码出来,按 PID 归类,再进一步解析包里的 PSI/SI 表或 PES 数据。
2.2 PAT 和 PMT:TS 流的「总目录」和「分目录」
TS 流里可以同时承载多路节目,但接收端怎么知道哪路视频在哪?答案是靠两张表。PAT(Program Association Table)的 PID 固定为 0,它列出的内容是「节目号 → PMT PID」的映射。比如 PAT 里写节目 1 的 PMT PID 是 0x100,节目 2 的 PMT PID 是 0x110。PMT(Program Map Table)再由各自的 PID 标识,它列出的是「这个节目包含哪些流 → 各自的 PID、流类型」。视频是 H.264(流类型 0x1B)还是 HEVC(0x24),音频是 AAC(0x0F)还是 AC-3(0x81),统统在这里声明。分析工具跑完一个文件后给你的第一张表,通常就是 PAT 和所有 PMT 的解析结果,这个结果决定了你对整个码流的基本判断:几路节目、每路几路视频几路音频、编码格式是什么。
这里有一个新手最容易搞混的细节:PAT 的 PID 固定是 0,但 PMT 的 PID 不是固定的,它由 PAT 里的字段指定。所以分析工具的输出里,你应该先看 PAT 表拿到了哪些 PMT PID,然后再逐个请求这些 PMT 的 PID 做解析。如果工具直接去扫所有 PID 找 PMT,虽然也能找到,但那不是标准的解析顺序,遇到 PID 重复或表不完整时会产生误导。
2.3 连续性计数器(CC)和 PCR:丢包与同步抖动的证据
连续性计数器是 TS 包头里的 4 比特字段,取值 0 到 15,每个 PID 单独计数,每发一个同一个 PID 的包就加 1,到 15 后回绕到 0。接收端只要发现同一个 PID 的 CC 不是「上一包加 1」就说明中间丢了包(排除重复包和加扰的情况)。分析工具统计每个 PID 的 CC 不连续次数,是判断码流在录制或传输过程中有没有丢包的最直接手段。你拿到一个文件后,如果工具报告某个 PID 的 CC 错误几百次,那这个码流的画面大概率会在对应位置出现花屏或卡顿,因为丢失的可能是视频 PES 的中间数据,解码器无法完整重建一帧。
PCR(Program Clock Reference)则捎带在自适应字段里,用于恢复编码器的 27 MHz 系统时钟。分析工具对 PCR 的处理通常是:按 PID 提取 PCR 值,计算相邻两个 PCR 之间的实际间隔和理论间隔的偏差,输出最大抖动值。PCR 抖动过大时,解码器端的时钟恢复会出现音视频不同步或缓冲上溢下溢。你在工具界面里看到的「PCR 间隔」和「PCR 抖动」两项,就是干这个用的。
2.4 分析工具的常见形态:离线解析与实时监测
TS 分析工具按使用场景大致分两类。一类是离线文件分析,你把录制的 .ts 文件拖进去,工具对整个文件做完整扫描,输出所有表、PID 统计、错误分布,适合做码流合规性检查和问题定位。另一类是实时码流监测,工具直接接收来自网口或串口的实时 TS 数据,边收边统计,适合在播出链路或接收端现场排查问题。两类工具的核心解析逻辑是一样的,区别只在于数据源是「读到 EOF 停止」还是「持续接收」。实际从业方案中,我一般会先用手边的离线工具对文件做全量分析,确认结构性问题的概率,再决定要不要上实时监测。如果文件本身是好的但播放端有问题,那再去链路上抓实时码流看是不是传输环节丢包。
3. 用分析工具跑通一个真实 TS 文件:最小命令与输出解读
3.1 先看全局:ffprobe 三行命令摸清码流底细
拿到一个陌生 .ts 文件时,我不会直接上重型分析工具,先用 FFmpeg 自带的 ffprobe 做一个快速摸底。它能直接告诉你码流里有几路流、什么编码、什么分辨率、有没有音视频。下面这个命令是最小可行的:
ffprobe -v error -show_entries stream=index,codec_name,codec_type,width,height,bit_rate -of csv input.ts命令的含义是:-v error让 ffprobe 只输出错误级别以上的日志,避免噪音;-show_entries stream=...指定只输出每个流里的这几个字段,而不是把整个文件的所有元数据都打出来;-of csv指定输出格式为 CSV,方便直接粘贴到表格里。index是流序号,codec_name是编码器名,width/height只对视频流有意义。修改参数时,如果你想看时间基或帧率,可以在stream=后面追加avg_frame_rate和time_base。
这一步的作用是告诉你「这个 TS 里大概率有什么」,但它不会告诉你「TS 结构本身健不健康」。比如,ffprobe 能正确读到视频流,不代表 PAT/PMT 周期、CC 连续性和 PCR 都是达标的。所以 ffprobe 只做第一层摸底,真正的结构分析要交给专门的 TS 分析工具。
3.2 结构级分析:tsp 的全量扫描与错误报告
说到专门的 TS 分析工具,目前从业者用得比较多的是某开源 TS 工具集里的tsp命令。它是一个命令行工具,支持从文件读取 TS、对每个包做处理、再输出统计或修复结果。下面是我常用的一条全量扫描命令:
tsp -I file input.ts -P analyze -P continuity -P pcr -O file output.ts这段命令用-I file input.ts指定输入文件;-P analyze做全量 PSI/SI 解析,会统计 PAT/PMT/SDT 等表出现的次数、PID 分布、节目信息;-P continuity做连续性计数器检查,逐 PID 统计 CC 错误次数;-P pcr做 PCR 间隔和抖动分析;最后的-O file output.ts是输出到另一个文件,因为分析插件本身不修改数据,你大可以省掉输出端,只用-O drop丢弃数据。实际使用中省略输出端也能跑,但我习惯显式写一个输出,方便后续用其他工具继续处理。
跑完之后,终端会输出一张汇总表,里面有每个 PID 的包数量、流类型、CC 错误数和 PCR 信息。你要重点关注三列:Continuity errors(CC 错误次数)、PCR interval(相邻 PCR 的最大间隔,单位是毫秒)、PCR accuracy(抖动指标)。如果 CC 错误是 0,说明这个 PID 的传输过程没有丢包;如果 PCR interval 突然出现几百毫秒的跳变,说明编码器或再复用器的时间基准有问题。
3.3 细看表结构:tsanalyze 与图形化界面
除了命令行,还有一款图形化的分析工具,通常名字里带「analyze」字样,界面左侧是 PID 树,右侧是每个 PID 的包统计和表解析结果。它的好处是交互式点选:你点 PAT,右侧就展开「节目 1 → PMT PID 0x100」这一行;点 PMT,右侧就列出「视频 PID 0x101(H.264)」「音频 PID 0x102(AAC)」这种明细。对于刚入门 TS 的人来说,图形界面比命令行更直观,因为你不用记住命令参数,只需要会「点」。
需要注意的是,图形工具的「实时刷新」模式在分析大文件时容易卡顿。我见过有人拿 GUI 工具拖一个 2 GB 的 TS 文件进去,结果界面卡死,最后只能强制关闭。这种情况下,正确做法是先用命令行工具做全量统计,再用 GUI 对指定 PID 做局部查看。命令行工具的输出是纯文本,处理大文件更快,而且能通过管道或重定向把结果保存下来,方便后续用脚本做回归检查。
4. 深挖码流:从工具输出里定位三类典型问题
4.1 表不完整:PAT/PMT 周期发送不达标
广播级 TS 对 PSI/SI 表的发送频率有明确要求:PAT 和 PMT 的发送间隔不能超过 100 毫秒左右,SDT 和 EIT 的要求会宽松一些。分析工具会统计每个表的出现次数,再根据文件时长算出平均重复周期。如果一个半小时的文件里 PAT 只出现了几十次,说明再复用器配置有问题,接收端可能长时间无法快速调台。用命令行工具的自定义表统计插件,可以只输出 PAT 相关的统计:
tsp -I file input.ts -P psi -p 0x00 -O drop-P psi是 PSI/SI 解析插件,-p 0x00指定关注 PID 0(PAT)。工具会输出 PAT 在文件中共出现多少次、section 版本号变化了几次、有无 CRC 错误。如果版本号变化超过 1,说明节目信息在录制过程中被动态更新过,这在多节目再复用流里是正常的,但单节目文件里频繁变化就值得警惕。检查周期是否达标时,用文件时长除以 PAT 出现次数即可,结果应远小于 100 毫秒。
4.2 连续性计数错误与丢包的关联判断
CC 错误是 TS 分析里最常遇到的「实锤」问题。它有两种形态:一种是某个 PID 的 CC 从 0 到 15 乱跳,说明这个 PID 大量丢包;另一种是 CC 出现重复值但没跳变,说明有重复包被插入。分析工具会把重复包标记为duplicate,把丢失包标记为missing。处理建议完全不一样:重复包通常无害,播放器一般会忽略;但连续性错误(missing)可能导致视频解码出现不可恢复的错误。判断一个 CC 错误是否影响观感,要看它发生在哪个 PID 以及错误密度。如果只是 PCR PID 的 CC 偶发错误,可能不影响音视频解码;如果是视频 PID 连续几十包 CC 错误,那个时间点的画面几乎必然出问题。
经验做法是把工具输出的 CC 错误时间点(通常带有相对时间戳)和录制侧日志对应起来。比如某次录制是在网络传输过程中出现了瞬时拥塞,那 CC 错误会集中在某一个时间段;如果是录制设备本身丢包,错误可能均匀散布在整个文件里。两种分布对应的修复路径完全不同:前者查网络链路,后者查录制设备。
4.3 PCR 抖动过大时的排查思路
PCR 抖动的单位是纳秒,工具一般会输出最大抖动和平均抖动两个值。参考经验是:最大抖动超过 500 ns 时,部分要求严格的接收设备就可能出现音视频不同步。但如果只是文件录制后离线分析,抖动值本身可能被文件读取速度影响,所以不要只看绝对值,要看「趋势」。命令行工具支持按时间窗口输出 PCR 统计,如果抖动只在某个时间点飙升,那大概率是录制时的系统中断或磁盘写入导致;如果全程都高,那是编码器或再复用器的时钟源本身就不稳。
排查 PCR 问题时,可以先确认 PCR PID 是否和视频 PID 相同。单节目流里常见做法是让 PCR 跟着视频 PID 走;如果 PCR 放在一个空包 PID 上,接收端需要额外处理,更容易出现同步漂移。工具输出里会标明 PCR PID,你在 PMT 解析结果里也能看到 PCR PID 字段,两者应该一致才是最常见的设计。
5. 避坑指南:TS 分析里五个最容易翻车的细节
5.1 包长不是 188,工具全部误判
现象:工具报告的包数严重偏少,所有 PID 统计看起来一团乱麻,甚至找不到一个正确的 PAT。
原因:文件实际是 204 字节包长(带 RS 前向纠错),但工具默认按 188 字节解析,导致每包末尾 16 字节被当成下一个包的包头,同步字节 0x47 自然对不齐。
解决:先用十六进制工具看文件开头能否找到连续多个 0x47,且间隔恒定为 188 字节。如果是 204 字节间隔,在命令行工具里指定包长为 204,或者在 GUI 工具的设置项里把包长从「自动」改为「204」。遇到包长混用的情况,先按每段开头重新探测,分段设置包长再解析。
5.2 只看合计包数,忽略了 PID 过滤
现象:工具报告某个 PID 有大量 CC 错误,但替换播放器后画面正常,怀疑工具误报。
原因:有些工具在「全 PID 分析」模式下会把空包 PID(0x1FFF)也纳入统计,而空包不要求 CC 连续,或者工具默认过滤掉空包但没过滤掉私有数据 PID。私有数据 PID 的 CC 不连续不代表真实丢包。
解决:在工具里开启 PID 过滤,只统计 PAT/PMT/视频 PID/音频 PID 这几个关键 PID。如果工具支持按 PID 导出统计,把视频 PID 单独拿出来看 CC。空包 PID 应该被完全忽略,它对节目解码没有任何贡献。
5.3 混淆 PCR 与 PTS,拿错时间戳排查同步
现象:分析工具输出里 PCR 抖动正常,但实际播放时音画不同步,怀疑分析结果不可信。
原因:PCR 是系统时钟参考,PTS 是每帧画面的呈现时间戳。PCR 正常不代表 PTS 正常。工具通常分别统计 PCR 和 PTS/DTS,你在界面里可能只看了 PCR 那一栏。
解决:在工具里找到 PTS/DTS 统计,或者用命令行工具加 PTS 分析插件单独看每个 PID 的 PTS 变化。如果 PTS 出现回退或跳变,即使 PCR 完美,播放端照样会乱。PTS 检查要逐 PID 做,视频和音频的 PTS 基准不一样是正常的,但各自不能乱跳。
5.4 加扰流被当作普通流解析
现象:工具报告某个 PID 的负载全是不可识别数据,甚至报 section 错误。
原因:这个 PID 是加扰流,负载里的 PES 头或 section 数据是加密后的密文,工具如果不知道对应 ECM 信息,无法解出明文内容。
解决:区分「结构错误」和「加扰未解」。工具输出里如果某个 PID 标记为 scrambled,就不要再拿它的负载做深度解析,只保留 PID 存在性和包数统计即可。如果要深入分析,需要先走解扰流程,这涉及 CA 系统,不在通用分析工具的职责范围内。分析报告里应该明确标注「该流已加扰,负载内容不可见」而不是「数据损坏」。
5.5 文件尾部不完整,误判为丢包
现象:工具报告文件末尾最后一个 PID 的 CC 错误异常多,但画面从头到尾都正常。
原因:录制文件在停止时,最后一个 TS 包可能只写了一半,或者整个文件在录制中断时丢失了结尾的几个包。工具把这些「没来得及发完」的包也算进 CC 统计。
解决:对文件末尾的 CC 错误单独做判断。把文件时长去掉最后 1 到 2 秒再统计一次,如果 CC 错误消失,说明问题只在文件截断处,不是传输丢包。正规做法是在录制完成后做文件收尾校验,确保最后一个包完整落盘。
6. 进阶:把 TS 分析固化成一个自动回归脚本
做到这一步,你已经能手动跑通一款 TS 分析工具,也能从输出里定位常见问题。但这个能力如果不沉淀成脚本,每次拿到新文件还是得重复敲命令、翻输出。我的做法是写一个批处理脚本,对一批 TS 文件统一跑全量分析,把关键指标汇总成一个 CSV,这样既能做人肉巡检,也能在 CI 里做回归检查。脚本的核心思路是:调工具输出 JSON 格式的统计结果,再用脚本提取关键字段。
for f in *.ts; do tsp -I file "$f" -P analyze -P continuity -P pcr \ -O json "out_${f%.ts}.json" 2>&1 python3 parse_ts_report.py "out_${f%.ts}.json" >> summary.csv done这段脚本遍历当前目录下所有 .ts 文件,对每个文件跑同一套分析插件,结果存成 JSON 文件,再由一个 Python 脚本提取 PAT 出现次数、CC 错误总数、PCR 最大抖动这三个关键指标,追加写入同一个 CSV。修改参数时,-O json换成-O txt可以看文本输出;-P后面追加别的插件可以扩展检查项。实际使用中如果某个文件特别大,我会在命令末尾加-P progress显示进度,避免误以为卡死。
提取脚本里,我一般会设置阈值:CC 错误大于 0 的文件标记为失败,PCR 最大抖动超过 500 ns 的标记为警告。这样每次批量检查后扫一眼 CSV 就能定级。要注意的是,脚本里用的临时 JSON 文件记得在末尾清理,不然积攒多了会占磁盘。另一个容易忽略的点是文件名里的特殊字符,循环变量加上引号能避免带空格的文件名在执行时报错。
这套方法的价值在于:TS 分析从一次性的「玄学排查」变成了可重复、可比较的工程动作。你不会再对着同一类问题反复翻车,因为脚本会把每一次的检查结果留下来,下次遇到类似码流时直接翻 CSV 就能看到之前那次是什么现象、是不是同类问题。我的习惯是每次处理完一批码流后,把 CSV 和时间戳一起存成新文件名,一个月下来就能积累出一份「哪些环节最爱出问题」的统计,比靠记忆判断可靠得多。希望这个工作流能帮到你,也欢迎你在自己的场景里把阈值和插件调整成更贴合业务的组合——毕竟分析工具是死的,码流是活的。
本文还有配套的精品资源,点击获取