WebRTC踩坑记:为什么你的视频编码格式总被"偷偷"转换?

103 阅读4分钟

VPS、SPS、PPS、SS简介 视频编码格式中的“元数据”部分,就像一本书的“目录、序言、说明页”一样,是为了解释视频的结构和解码方式的。

VPS 是视频整体信息,SPS 是某段视频的说明书,PPS 是每一帧的详细设置,SS 才是真正的视频画面本体。

1. VPS(Video Parameter Set)

🗂 视频参数集(主要出现在 H.265/HEVC 中)

  • 描述整段视频的通用参数,比如最大帧率、分辨率范围、解码等级等。
  • 它是最高层的参数,告诉解码器:“我这段视频整体都长什么样。”

📌 类比:就像一本小说的封面、作者简介、总字数那类信息。

2. SPS(Sequence Parameter Set)

📖 序列参数集

  • 描述一个“视频序列”的结构,比如:

    • 分辨率(1920x1080)
    • 帧率(30fps)
    • 颜色格式(YUV420)
  • 每个视频序列通常只会有一个 SPS。

📌 类比:一本书的“前言”或“说明页”,说明你要读的这一整章是什么风格。

3. PPS(Picture Parameter Set)

🖼 图像参数集

  • 描述具体的编码细节,比如:

    • 每一帧怎么分块编码
    • 参考帧的数量
  • 每一帧可能使用不同的 PPS。

📌 类比:一本书中“某一页”的排版方式(这页是表格,那页是段落等)。

4. SS(Slice Segment)

📏 切片段 / 帧的片段

  • 视频中真正包含图像内容的数据部分。
  • 一帧画面可以分成多个 slice segment,方便并行处理或者错误恢复。
  • Slice segment 才是“画面内容本身”,前面那几个是“说明书”。

📌 类比:书的正文内容,比如你真正要读的“第一章”、“第二章”。

image.png

H.265 (HEVC) 视频流的核心结构

在 H.265 编码中,视频流通常由如下 NALU 单元组成:

名称全称作用
VPSVideo Parameter Set视频参数集,描述整个视频解码所需的高层信息(H.265 独有)
SPSSequence Parameter Set序列参数集,描述分辨率、帧率、色彩空间等
PPSPicture Parameter Set图像参数集,描述图像级别的压缩设置
SEISupplemental Enhancement Info附加信息(如时间戳、HDR 数据、字幕等)
IDR/I帧Intra-coded Frame关键帧,完整帧数据
P帧/B帧Predicted/Bidirectionally predicted Frame预测帧,依赖其他帧

这些内容基本在解码前就要被完整送达,尤其 VPS/SPS/PPS,一般在编码后的起始位置(或关键帧前)打包发送。

WebRTC 的兼容性:

  • 原生 WebRTC 浏览器(Chrome、Safari)并 不支持 H.265,仅支持 VP8 / VP9 / H.264
  • 但如果是你自己在服务器或端上做 P2P relay / media bridge(例如 Janus、mediasoup),你可以“偷偷”传 H.265,前提是对端也能解码。

🔧 模块划分(WebRTC 视频传输链)

1️⃣ 采集端(摄像头输入)

目标:从本地摄像头采集帧,编码为 H.264 / H.265

  • ✅ 通常用 libavdevice + libavcodec(FFmpeg)或者直接调用 V4L2(Linux)
  • ✅ 编码器选项:x264, x265, nvenc, v4l2 硬编

2️⃣ RTP打包 + 送入 WebRTC 栈

WebRTC 的 Track(MediaStreamTrack)是音视频数据的逻辑通道,而底层的数据是通过 RTP(实时传输协议) 传输的。每个音频或视频通道都称为一个 Track,每个 Track 对应一个 RTP 媒体流,把 Track 想象成 “音视频管道”,但底层其实就是 RTP 包在流动。

目标:将 H.265 编码好的帧切割打包成 RTP 并推送

  • 🔁 你可以直接操作 NALU 单元,根据类型(VPS/SPS/PPS/IDR)构建 RTP 包

  • ✅ 推荐方案:

    • 使用 libwebrtc(谷歌原生)
    • 或者用开源 C 实现:如 Pion(虽然是 Go 的,但有 C 包装)
    • 低配版:自写 RTP sender(C 实现)

3️⃣ 中转(SFU/网关)

目标:WebRTC relay、多路推流,音视频转发、编解码

方案 1:自研中转逻辑(C 层裸写)

  • ✅ 你自己收 RTP → 重打包 → 发 RTP → 对端
  • 可插入你的业务策略:降码率、录制、混音、广播

方案 2:集成成熟 SFU(如 Janus、mediasoup)

  • Janus C 写的,可以嵌入
  • mediasoup 用 Node 或 C++,可做桥接

4️⃣ 播放端(浏览器/客户端)

  • ⚠️ 浏览器不支持 H.265(除 Safari 部分版本)
  • 如果目标是移动端/桌面应用,你可以用 WebRTC native SDK(安卓/iOS 原生解码器支持)