一个做PHP后端的同事跟我提过一个需求:直播录制文件要回放切片,但切片点不能按常规时间戳来,得按直播间里真实发生的"答题卡下发时刻"来切。这些业务标记不在数据库里,而是写进了视频编码层的SEI字段里。我当时第一反应是"那就用FFmpeg把SEI读出来呗",结果真正动手才发现,PHP侧怎么优雅地调用FFmpeg、怎么解析SEI、怎么在写入时不让数据被转封装丢掉,每个环节都有不少门道。
这篇文章就来系统讲一套PHP+FFmpeg处理SEI的完整方案:从SEI是什么、为什么业务里用得上,到PHP环境怎么选型、FFmpeg怎么调,再到读取SEI、写入SEI的具体实现,最后用一个真实案例把链路串起来。适合PHP后端、音视频开发、以及所有需要跟视频流打交道的同学参考。整个方案不依赖复杂扩展,PHP原生能力加FFmpeg就能落地。
1. 先搞懂SEI到底是什么:一个"视频附赠信息通道"的底层逻辑
1.1 H.264码流里的"信息牌"长什么样
视频文件看起来是一个整体,但到了编码层,其实是无数个NAL单元拼接而成的。H.264码流里,每个NAL单元前面都有一段起始码,常见的可以是00 00 01,也可以是00 00 00 01。不同的NAL单元各司其职:SPS、PPS描述编码参数,IDR帧是解码器重新同步的关键帧,普通帧承载画面数据。
SEI的全称是Supplemental Enhancement Information,翻译过来是"辅助增强信息"。它本身不参与画面解码,不承载像素数据,而是以独立NAL单元的形式插在码流里,给解码器或者后端处理系统传递一些"附赠信息"。你可以把它理解成高速公路主干道旁边的可变情报板:车流(图像数据)正常走自己的车道,情报板不载车,但路过的人都能看到上面的提示。
在H.264里,SEI的NAL单元类型是6;到了H.265,SEI分为前缀SEI(类型39)和后缀SEI(类型40)。SEI内部有很多payloadType,其中业务上最常用的是payloadType=5,也就是user_data_unregistered(用户自定义未注册数据),它允许你放一个16字节的UUID加任意字节内容。我们自己做业务标记,基本都走这个类型。
1.2 业务上什么时候值得上SEI
SEI最大的特点是"跟视频帧强绑定"。它活在编码层里,只要视频流不被重新编码,无论你把它封装成MP4、TS、FLV,还是通过HLS、RTMP、DASH分发,SEI都能跟着走。这就让它非常适合下面这几类场景:
- 直播互动对齐:弹幕、答题卡、礼物特效的触发时机,如果走网络通道单独下发,很容易跟画面不同步。写进SEI后,观众端播放器解码到那一帧,就能同步触发互动指令。
- 录制文件的业务标记:直播间录制下来的文件,可能要交给审核、剪辑、切片等下游系统。把房
