1. 从Track到SDP的映射原理

在WebRTC的媒体协商过程中,每个MediaStreamTrack对应的参数最终都会通过SDP(Session Description Protocol)进行交换。这个转换过程发生在PeerConnection的createOffer/createAnswer阶段,由底层引擎自动完成。具体来说,每个Track会被映射到SDP的m=行(媒体描述块),而它的编解码参数、SSRC等信息则存储在对应的a=属性中。

以视频Track为例,当调用addTrack()方法时:

  1. PeerConnection会为这个Track分配唯一的SSRC
  2. 根据当前支持的编解码器生成rtpMap参数
  3. 收集当前候选的ICE信息
  4. 将这些信息结构化后写入SDP的对应section

2. SDP中Track参数的关键字段解析

2.1 媒体类型声明

每个Track会在SDP中生成独立的m=section,例如:

m=video 9 UDP/TLS/RTP/SAVPF 96 97 98

其中:

  • video表示媒体类型(audio/video)
  • 9是传统端口号(实际使用中会被忽略)
  • UDP/TLS/RTP/SAVPF表示传输协议栈
  • 96-98表示支持的payload type列表

2.2 编解码器参数

通过a=rtpmap属性声明:

a=rtpmap:96 VP8/90000
a=rtpmap:97 H264/90000
a=rtpmap:98 rtx/90000

每个payload type对应具体的编解码器及其时钟频率。

2.3 传输控制参数

包括:

a=mid:video  // 媒体标识符
a=ssrc:12345678 cname:xxxx // SSRC及其关联信息
a=rtcp-fb:96 nack  // 反馈机制
a=fmtp:97 profile-level-id=42e01f  // 编解码器特定参数

3. 参数写入的完整流程

3.1 Track添加阶段

当调用pc.addTrack(track, stream)时:

  1. 检查Track的kind(audio/video)
  2. 为Track创建对应的transceiver
  3. 分配初始SSRC和mid
  4. 缓存当前支持的编解码器列表

3.2 SDP生成阶段

createOffer/createAnswer时:

  1. 为每个transceiver创建m=section
  2. 根据direction属性设置a=sendrecv/a=sendonly等
  3. 填充当前可用的编解码器参数
  4. 添加ICE候选信息和DTLS指纹

3.3 关键代码路径

在Chromium实现中:

  • PC::CreateOffer → SdpOfferAnswerHandler::DoCreateOffer
  • 最终通过SdpSerializer生成文本格式

4. 实战中的参数控制技巧

4.1 强制使用特定编解码器

通过setCodecPreferences可以调整优先级:

const transceiver = pc.getTransceivers()[0];
transceiver.setCodecPreferences([
  {mimeType: 'video/H264'}
]);

4.2 自定义SSRC

在addTrack前设置:

pc.onnegotiationneeded = async () => {
  const offer = await pc.createOffer({
    offerToReceiveAudio: true,
    offerToReceiveVideo: true
  });
  // 修改SSRC
  offer.sdp = offer.sdp.replace(
    /a=ssrc:.*\n/g,
    'a=ssrc:12345678 cname:custom_ssrc\n'
  );
  await pc.setLocalDescription(offer);
};

4.3 带宽控制参数

通过b=AS和a=bw控制:

b=AS:2000
a=bw:2000

5. 常见问题排查指南

5.1 编解码器不匹配

症状:SDP中有offer但无answer 检查:

  1. 双方setCodecPreferences是否冲突
  2. SDP中a=rtpmap是否包含共同支持的编码

5.2 SSRC冲突

症状:媒体流无法建立 解决方案:

  1. 检查是否有重复的a=ssrc行
  2. 确保每个Track有唯一mid

5.3 方向不一致

症状:一方收不到流 检查:

  1. a=sendrecv/a=recvonly是否配置正确
  2. transceiver.direction是否与预期一致

6. 高级参数调优

6.1 RTX重传配置

在SDP中添加:

a=rtpmap:98 rtx/90000
a=fmtp:98 apt=96

表示payload 98是96的冗余编码

6.2 Simulcast配置

通过rid实现:

a=rid:1 send
a=rid:2 send
a=simulcast: send 1;2

6.3 自定义扩展头

添加x-自定义参数:

a=extmap:3 http://example.com/myextension

在实际项目中,理解这些参数映射关系对于调试复杂WebRTC场景至关重要。建议开发者使用chrome://webrtc-internals观察完整的SDP交换过程,并配合Wireshark分析实际传输的数据包特征。

Logo

火山引擎视频云技术社区,是面向 AI 音视频开发者的技术交流平台。这里汇聚源自抖音、豆包等亿级 DAU 产品的 RTC、直播、点播、AI 媒体处理、音视频互动技术,提供接入指南、最佳实践、性能调优、场景案例、Demo 代码、开源项目、白皮书和 API 文档。社区汇聚官方工程师与一线开发者,为 AI 视频通话、数字人、AI 视频处理等应用的开发与落地提供技术支持。

更多推荐