如何将MPEG2-TTS格式转换为可被ffplay播放的标准MPEG2-TS格式?
看起来你已经找对了方向——MPEG2-TTS和标准TS的包大小确实差了4字节,但仅仅删掉前4字节是不够的,ffmpeg/ffplay认不出这种“半成品”的TS包。我来帮你梳理问题和解决办法:
你当前做法的核心问题
标准MPEG2-TS的188字节包是有固定结构的:开头必须是同步字节0x47,后面跟着3字节的TS头部(包含PID、负载起始标识等关键信息),最后才是媒体负载。你删掉的TTS前4字节大概率是TTS特有的自定义头部,但直接截断后剩下的内容并没有标准TS包的起始标识和头部信息,ffplay自然无法识别。
正确的转换步骤
明确TTS包结构
先确认你去掉的前4字节是什么——通常MPEG2-TTS的前4字节是自定义的时间戳或同步信息,剩下的188字节才是真正的媒体负载内容,这部分是我们需要用到的。给每个负载添加标准TS头部
你需要为每个188字节的负载拼接一个标准的TS头部,而不是直接截断。这里给你修改后的转换函数示例:def conv_tts2ts(rtp_payload): payload_len = len(rtp_payload) if payload_len % 192 != 0: raise ValueError("Payload length must be a multiple of 192") pkt_num = int(payload_len / 192) ts_data = bytearray() # 标准TS头部示例:同步字节0x47 + 3字节头部(可根据实际流调整参数) # 这里PID设为0x0000(节目关联表),负载起始标识设为1,适配字段长度为0 ts_header = bytearray([0x47, 0x40, 0x00, 0x10]) for i in range(pkt_num): spos = 192 * i epos = spos + 192 tts_pkt = rtp_payload[spos:epos] # 提取TTS包中的188字节媒体负载 ts_payload = tts_pkt[4:] # 拼接头部和负载,组成完整的188字节TS包 full_ts_pkt = ts_header + ts_payload ts_data.extend(full_ts_pkt) return ts_data注意:示例中的TS头部参数(比如PID)需要根据你的实际流调整——如果是视频流,PID会是特定值,音频流又是另一个,你需要确认原TTS流对应的媒体PID,再修改头部中的PID字段。
验证转换后的流
转换完成后,先用ffprobe检查流是否能被识别:ffprobe -i udp://你的UDP地址:端口号如果ffprobe能输出流的详细信息(比如视频编码格式、音频采样率),说明转换基本正确;如果还是不行,可能需要调整TS头部的负载单元起始指示位(如果第一个包是PES包的起始,需要把这个位设为1)。
额外注意:PCR时钟同步
有些MPEG2-TTS流包含PCR(节目时钟参考)信息,这是保证音视频同步的关键。如果你的原流有PCR,需要把它添加到TS包的适配字段中,否则ffplay可能会出现卡顿或不同步的情况。
备注:内容来源于stack exchange,提问作者Asustor

