# DotNetMediasoup
**Repository Path**: smallcore/dot-net-mediasoup
## Basic Information
- **Project Name**: DotNetMediasoup
- **Description**: 一个基于 .NET 8 的完整实时音视频通信解决方案,采用 Mediasoup SFU 架构实现高性能的 WebRTC 媒体服务。
- **Primary Language**: C#
- **License**: MIT
- **Default Branch**: master
- **Homepage**: https://mp.weixin.qq.com/s/Rk8otOXnPJrG_sRTQyKW3w
- **GVP Project**: No
## Statistics
- **Stars**: 8
- **Forks**: 5
- **Created**: 2025-12-25
- **Last Updated**: 2025-12-27
## Categories & Tags
**Categories**: Uncategorized
**Tags**: 音视频, OpencvSharp, webrtc, SignalR, WPF
## README
>声明:网络内容,仅供学习,尊重版权,侵权速删,歉意致谢!
[ **.NET 8 + Mediasoup 可落地的实时音视频通信架构(收藏版)** ](https://mp.weixin.qq.com/s/Rk8otOXnPJrG_sRTQyKW3w)
[](https://dotnet.microsoft.com/)
[](https://docs.microsoft.com/en-us/dotnet/desktop/wpf/)
[](https://github.com/versatica/mediasoup)
[]()
一个基于 .NET 8 的完整实时音视频通信解决方案,采用 Mediasoup SFU 架构实现高性能的 WebRTC 媒体服务。项目包含 Mediasoup 核心库(C# 实现)、libuv 异步 I/O 绑定、ASP.NET Core 集成中间件、SignalR 信令服务器,以及 WPF 桌面客户端和 Vue.js Web 客户端。支持 Open/Pull/Invite 三种服务模式,提供房间管理、音视频采集传输、多端互通等功能。技术栈涵盖 WebRTC、SignalR、SIPSorcery、OpenCvSharp、NAudio 等,适用于在线会议、远程协作、直播互动等场景。
## 核心特性
- **完整 SFU 架构** - 基于 Mediasoup 的选择性转发单元,支持大规模并发
- **多端互通** - WPF 桌面客户端 + Vue.js Web 客户端无缝互通
- **三种服务模式** - Open(开放)、Pull(拉取)、Invite(邀请)灵活适配不同场景
- **实时音视频** - 低延迟、高质量的音视频采集、编码、传输和渲染
- **房间管理** - 完整的房间生命周期管理和成员控制
- **活跃发言者检测** - 基于音频级别的发言者识别
- **JWT 认证** - 安全的用户身份验证机制
- **多编解码器支持** - VP8、VP9、H.264、Opus 等主流编解码器
---
## 解决方案架构
```
Dorisoy.Mediasoup.sln
│
├── src/ # 源代码目录
│ │
│ ├── Dorisoy.Mediasoup/ # [核心库] Mediasoup SFU C# 实现
│ │ ├── Router/ # 路由器 - 管理 Transport、Producer、Consumer
│ │ ├── Transport/ # 传输层抽象基类
│ │ ├── WebRtcTransport/ # WebRTC 传输实现
│ │ ├── PlainTransport/ # Plain RTP 传输(用于 FFmpeg/GStreamer)
│ │ ├── PipeTransport/ # 管道传输(用于路由器间通信)
│ │ ├── DirectTransport/ # 直接传输
│ │ ├── Producer/ # 媒体生产者
│ │ ├── Consumer/ # 媒体消费者
│ │ ├── DataProducer/ # 数据通道生产者
│ │ ├── DataConsumer/ # 数据通道消费者
│ │ ├── Worker/ # Worker 进程管理
│ │ ├── Channel/ # 与原生 worker 的通信通道
│ │ ├── WebRtcServer/ # WebRTC 服务器(端口复用)
│ │ ├── RtpObserver/ # RTP 观察者基类
│ │ ├── AudioLevelObserver/ # 音频级别观察者
│ │ ├── ActiveSpeakerObserver/ # 活跃发言者观察者
│ │ ├── Settings/ # 配置设置类
│ │ ├── ORTC/ # ORTC 能力协商
│ │ ├── MediasoupServer.cs # 服务器入口类
│ │ └── MediasoupOptions.cs # 配置选项
│ │
│ ├── Dorisoy.Libuv/ # [底层库] libuv 异步 I/O 的 .NET 绑定
│ │ └── src/ # TCP/UDP/Pipe 异步通信实现
│ │
│ ├── Dorisoy.Mediasoup.Common/ # [共享库] 公共模型和工具
│ │ ├── ClientRequest/ # 客户端请求模型(21个)
│ │ ├── RtpParameters/ # RTP 参数定义
│ │ ├── SctpParameters/ # SCTP 参数定义
│ │ ├── FBS/ # FlatBuffers 序列化定义(28个子目录)
│ │ ├── EventEmitter/ # 事件发射器实现
│ │ ├── H264ProfileLevelId/ # H.264 配置解析
│ │ ├── ScalabilityMode/ # 可伸缩模式解析
│ │ └── Constants/ # 常量定义
│ │
│ ├── Dorisoy.Mediasoup.AspNetCore/ # [集成库] ASP.NET Core 集成中间件
│ │ └── Microsoft/Extensions/ # DI 扩展方法
│ │
│ ├── Dorisoy.Meeting.Server/ # [服务端] 会议信令服务器
│ │ ├── SignalR/ # SignalR Hub 和服务
│ │ │ ├── MeetingHub.cs # 会议 Hub(1400+ 行核心逻辑)
│ │ │ ├── Models/ # 消息通知模型
│ │ │ └── Services/ # Hub 相关服务
│ │ ├── Models/ # 业务模型(11个)
│ │ ├── Authorization/ # JWT 认证和授权
│ │ ├── Settings/ # 服务器配置
│ │ ├── Exceptions/ # 自定义异常(6个)
│ │ ├── Room.cs # 房间管理(音频观察、成员管理)
│ │ ├── Peer.cs # Peer 管理(Transport/Producer/Consumer)
│ │ ├── Scheduler.cs # 调度器(房间创建、成员加入离开)
│ │ └── ServeMode.cs # 三种服务模式枚举
│ │
│ ├── Dorisoy.Meeting.Web/ # [Web后端] ASP.NET Core 应用
│ │ ├── Controllers/ # REST API 控制器
│ │ ├── Startup.cs # 应用配置(认证、CORS、Mediasoup)
│ │ ├── Program.cs # 应用入口
│ │ ├── mediasoupsettings.json # Mediasoup 详细配置
│ │ ├── appsettings.json # 应用配置
│ │ ├── dtls-cert.pem / dtls-key.pem # DTLS 证书
│ │ └── wwwroot/ # 静态文件
│ │
│ ├── Dorisoy.Meeting.Client/ # [桌面端] WPF 客户端
│ │ ├── WebRtc/ # WebRTC 实现
│ │ │ ├── MediasoupDevice.cs # Mediasoup 设备封装
│ │ │ ├── MediasoupTransport.cs # 传输层实现(55KB 核心)
│ │ │ ├── MediasoupSdpBuilder.cs # SDP 构建器
│ │ │ ├── AudioEncoders.cs # 音频编码器(Opus/PCMA)
│ │ │ ├── VideoEncoders.cs # 视频编码器(VP8/H264)
│ │ │ ├── VideoDecoders.cs # 视频解码器
│ │ │ ├── RtpMediaDecoder.cs # RTP 媒体解码
│ │ │ └── FFmpegConfig.cs # FFmpeg 配置
│ │ ├── Services/ # 服务层
│ │ │ ├── SignalRService.cs # SignalR 通信服务
│ │ │ └── WebRtcService.cs # WebRTC 服务
│ │ ├── ViewModels/ # MVVM 视图模型
│ │ ├── Models/ # 数据模型
│ │ ├── Views/ # 视图控件
│ │ ├── Converters/ # 值转换器
│ │ ├── Helpers/ # 工具类
│ │ ├── MainWindow.xaml # 主窗口(31KB 完整 UI)
│ │ └── App.xaml.cs # 应用入口和 DI 配置
│ │
│ ├── Dorisoy.Meeting.Web.Client/ # [Web前端] Vue.js 客户端
│ │ ├── src/
│ │ │ ├── App.vue # 主应用组件(40KB 完整实现)
│ │ │ ├── lib/ # 依赖库
│ │ │ └── assets/ # 静态资源
│ │ ├── package.json # NPM 依赖配置
│ │ └── vite.config.js # Vite 构建配置
│ │
│ ├── Dorisoy.Utils/ # [工具库] 通用工具
│ │ ├── Extensions/ # 扩展方法(21个)
│ │ ├── Cryptography/ # 加密工具
│ │ ├── Json/ # JSON 序列化工具
│ │ └── Models/ # 通用模型
│ │
│ └── Dorisoy.Mediasoup.Runtimes.Builder/ # [构建工具] 原生运行时构建脚本
│ ├── build_nuget.ps1 # Windows 构建脚本
│ └── build_nuget.sh # Linux/macOS 构建脚本
│
└── tools/TokenGenerator/ # Token 生成工具
└── Program.cs # JWT Token 生成器
```
---
## 技术栈
### 后端技术
| 技术 | 版本 | 用途 |
|------|------|------|
| .NET | 8.0 | 运行时框架 |
| ASP.NET Core | 8.0 | Web 框架 |
| SignalR | 8.0 | 实时双向通信 |
| Mediasoup | 3.15.7 | SFU 媒体服务器 |
| FlatBuffers | - | 高效序列化 |
| Redis | - | 分布式缓存 |
| Serilog | - | 结构化日志 |
| Swagger | - | API 文档 |
### 客户端技术
| 技术 | 用途 |
|------|------|
| WPF | 桌面客户端 UI 框架 |
| SIPSorcery | .NET WebRTC 实现 |
| NAudio | 音频采集和处理 |
| OpenCvSharp | 视频采集和处理 |
| FFmpeg | 编解码支持 |
| CommunityToolkit.Mvvm | MVVM 框架 |
| Vue.js 3 | Web 前端框架 |
| mediasoup-client | 浏览器 WebRTC 客户端 |
### 支持的编解码器
| 类型 | 编解码器 |
|------|---------|
| 音频 | Opus (48kHz, 立体声) |
| 视频 | VP8, VP9, H.264 (多种 Profile) |
---
## 三种服务模式
### 1. Open 模式(开放模式)
```
适用场景:自由会议、开放讨论
```
- 用户进入后立即开始推流
- 自动消费房间内其他用户的媒体流
- 媒体流即使无人消费也不会自动停止
- 其他用户被动接收媒体流
### 2. Pull 模式(拉取模式)
```
适用场景:大型会议、按需观看
```
- 用户主动选择要拉取的媒体流
- 按需触发其他用户推流
- 无人消费时自动停止推流(节省带宽)
- 其他用户不会被动接收
### 3. Invite 模式(邀请模式)
```
适用场景:正式会议、课堂直播
```
- 仅管理员可邀请用户推流
- 用户可申请推流,需管理员同意
- 管理员可关闭任意用户的媒体流
- 媒体流断开后需重新申请
---
## 系统架构
```
┌─────────────────────────────────────────────────────────────────────┐
│ Client Layer │
├─────────────────────────────────┬───────────────────────────────────┤
│ WPF Desktop Client │ Vue.js Web Client │
│ ┌───────────────────────────┐ │ ┌─────────────────────────────┐ │
│ │ SIPSorcery WebRTC │ │ │ mediasoup-client │ │
│ │ NAudio + OpenCvSharp │ │ │ WebRTC Native API │ │
│ │ FFmpeg Encoders │ │ │ Browser Media API │ │
│ └───────────────────────────┘ │ └─────────────────────────────┘ │
└────────────────┬────────────────┴────────────────┬──────────────────┘
│ SignalR WebSocket │
└────────────────┬────────────────┘
│
┌─────────────────────────────────▼───────────────────────────────────┐
│ Signaling Layer │
│ ┌────────────────────────────────────────────────────────────────┐ │
│ │ MeetingHub (SignalR) │ │
│ │ • GetRouterRtpCapabilities • CreateWebRtcTransport │ │
│ │ • Join / JoinRoom • ConnectWebRtcTransport │ │
│ │ • LeaveRoom • Produce / CloseProducer │ │
│ │ • Consume / ResumeConsumer • Pull / Invite │ │
│ └────────────────────────────────────────────────────────────────┘ │
│ ┌─────────────────┐ ┌─────────────────┐ ┌────────────────────┐ │
│ │ Scheduler │ │ Room │ │ Peer │ │
│ │ 房间生命周期 │ │ 成员管理 │ │ Transport/Producer│ │
│ │ 成员调度 │ │ 音频观察 │ │ Consumer 管理 │ │
│ └─────────────────┘ └─────────────────┘ └────────────────────┘ │
└─────────────────────────────────┬───────────────────────────────────┘
│
┌─────────────────────────────────▼───────────────────────────────────┐
│ SFU Media Layer │
│ ┌────────────────────────────────────────────────────────────────┐ │
│ │ MediasoupServer │ │
│ │ ┌──────────────────────────────────────────────────────────┐ │ │
│ │ │ Worker(s) │ │ │
│ │ │ ┌─────────────────────────────────────────────────────┐ │ │ │
│ │ │ │ Router │ │ │ │
│ │ │ │ ┌─────────────┐ ┌─────────────┐ ┌───────────────┐ │ │ │ │
│ │ │ │ │ Transport │ │ Producer │ │ Consumer │ │ │ │ │
│ │ │ │ │ (WebRTC/ │ │ (Audio/ │ │ (Audio/ │ │ │ │ │
│ │ │ │ │ Plain) │ │ Video) │ │ Video) │ │ │ │ │
│ │ │ │ └─────────────┘ └─────────────┘ └───────────────┘ │ │ │ │
│ │ │ │ ┌─────────────────────────────────────────────────┐│ │ │ │
│ │ │ │ │ RtpObserver (AudioLevel/ActiveSpeaker) ││ │ │ │
│ │ │ │ └─────────────────────────────────────────────────┘│ │ │ │
│ │ │ └─────────────────────────────────────────────────────┘ │ │ │
│ │ └──────────────────────────────────────────────────────────┘ │ │
│ └────────────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────┘
```
---
## 快速开始
### 环境要求
- .NET 8.0 SDK
- Node.js 18+ (Web 客户端)
- Redis (可选,用于分布式缓存)
- mediasoup-worker 原生二进制文件
### 1. 克隆项目
```bash
git clone https://github.com/dorisoy/Dorisoy.Mediasoup.git
cd Dorisoy.Mediasoup
```
### 2. 配置服务端
编辑 `src/Dorisoy.Meeting.Web/mediasoupsettings.json`:
```json
{
"MediasoupStartupSettings": {
"MediasoupVersion": "3.15.7",
"NumberOfWorkers": 1,
"UseWebRtcServer": true
},
"MediasoupSettings": {
"WebRtcServerSettings": {
"ListenInfos": [
{
"Protocol": "udp",
"Ip": "0.0.0.0",
"AnnouncedAddress": "你的公网或局域网IP",
"Port": 44444
}
]
}
},
"MeetingServerSettings": {
"ServeMode": "Open" // Open, Pull 或 Invite
}
}
```
### 3. 启动服务端
```bash
cd src/Dorisoy.Meeting.Web
dotnet run
```
服务端启动后:
- HTTP API: `http://localhost:9000`
- SignalR Hub: `ws://localhost:9000/hubs/meetingHub`
- Swagger 文档: `http://localhost:9000/swagger`
### 4. 启动 Web 客户端
```bash
cd src/Dorisoy.Meeting.Web.Client
npm install
npm run dev
```
### 5. 启动 WPF 客户端
```bash
cd src/Dorisoy.Meeting.Client
dotnet run
```
---
## SignalR API 参考
### Hub 方法
| 方法 | 参数 | 返回值 | 说明 |
|------|------|--------|------|
| `GetServeMode` | - | `{ serveMode }` | 获取服务模式 |
| `GetRouterRtpCapabilities` | - | `RtpCapabilities` | 获取路由器 RTP 能力 |
| `Join` | `JoinRequest` | `MeetingMessage` | 加入会议 |
| `JoinRoom` | `JoinRoomRequest` | `{ peers[] }` | 加入房间 |
| `LeaveRoom` | - | `MeetingMessage` | 离开房间 |
| `CreateSendWebRtcTransport` | `CreateWebRtcTransportRequest` | `TransportInfo` | 创建发送 Transport |
| `CreateRecvWebRtcTransport` | `CreateWebRtcTransportRequest` | `TransportInfo` | 创建接收 Transport |
| `ConnectWebRtcTransport` | `ConnectRequest` | `MeetingMessage` | 连接 Transport |
| `Produce` | `ProduceRequest` | `{ id, source }` | 生产媒体 |
| `Consume` | `ConsumeRequest` | `ConsumerInfo` | 消费媒体 |
| `ResumeConsumer` | `consumerId` | `MeetingMessage` | 恢复消费者 |
| `CloseProducer` | `producerId` | `MeetingMessage` | 关闭生产者 |
| `Ready` | - | `MeetingMessage` | 通知准备就绪 |
| `Pull` | `PullRequest` | `MeetingMessage` | 拉取媒体流 (Pull 模式) |
| `Invite` | `InviteRequest` | `MeetingMessage` | 邀请推流 (Invite 模式) |
### 服务端通知
| 通知类型 | 数据 | 说明 |
|----------|------|------|
| `peerJoinRoom` | `{ peer }` | 用户加入房间 |
| `peerLeaveRoom` | `{ peerId }` | 用户离开房间 |
| `newConsumer` | `ConsumerInfo` | 新消费者可用 |
| `consumerClosed` | `{ consumerId }` | 消费者已关闭 |
| `consumerPaused` | `{ consumerId }` | 消费者已暂停 |
| `consumerResumed` | `{ consumerId }` | 消费者已恢复 |
| `producerClosed` | `{ producerId }` | 生产者已关闭 |
| `produceSources` | `{ sources[] }` | 请求生产媒体源 |
| `closeSources` | `{ sources[] }` | 请求关闭媒体源 |
| `activeSpeaker` | `{ peerId, volume }` | 活跃发言者变化 |
---
## 项目依赖
### 服务端 NuGet 包
```xml
```
### 客户端 NuGet 包
```xml
```
---
## 部署指南
### Docker 部署
```dockerfile
FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base
WORKDIR /app
EXPOSE 9000
EXPOSE 44444/udp
EXPOSE 44444/tcp
FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
WORKDIR /src
COPY . .
RUN dotnet publish "src/Dorisoy.Meeting.Web/Dorisoy.Meeting.Web.csproj" -c Release -o /app/publish
FROM base AS final
WORKDIR /app
COPY --from=build /app/publish .
ENTRYPOINT ["dotnet", "Dorisoy.Meeting.Web.dll"]
```
### 生产环境配置
1. **配置 HTTPS**
```json
{
"Kestrel": {
"Endpoints": {
"Https": {
"Url": "https://0.0.0.0:443",
"Certificate": {
"Path": "/path/to/cert.pfx",
"Password": "your-password"
}
}
}
}
}
```
2. **配置公网 IP**
```json
{
"MediasoupSettings": {
"WebRtcServerSettings": {
"ListenInfos": [{
"Ip": "0.0.0.0",
"AnnouncedAddress": "公网IP或域名"
}]
}
}
}
```
3. **开放端口**
- TCP 9000 (HTTP/WebSocket)
- UDP/TCP 44444 (WebRTC)
- UDP 40000-49999 (媒体传输)
---
## 容量规划(局域网部署)
> **基准环境**:10000MB 无线路由器,2.5Gbps 局域网带宽
### 视频质量档位参数
| 档位 | 分辨率 | 比特率 | 帧率 | 适用场景 |
|------|--------|--------|------|----------|
| **Low(低画质)** | 320×240 | 300 Kbps | 15 fps | 低带宽环境、大型培训 |
| **Standard(标准)** | 640×480 | 1 Mbps | 25 fps | 日常会议、协作办公 |
| **High(高清)** | 1280×720 | 2.5 Mbps | 30 fps | 小型高清会议 |
| **Ultra(超清)** | 1920×1080 | 5 Mbps | 30 fps | 小型 1080p 会议 |
### 编解码器效率对比
| 编解码器 | 压缩效率 | 相同质量所需带宽 | CPU 负载 | 硬件加速 | 推荐场景 |
|----------|----------|------------------|----------|----------|----------|
| **VP8** | 基准 (1.0x) | 100% | 中等 | 无 | 兼容性优先 |
| **VP9** | 高效 (~1.4x) | ~70% | 较高 | 部分 | 大规模会议、带宽敢感 |
| **H264** | 基准 (1.0x) | 100% | 低 | 广泛支持 | 硬件编码场景 |
### 2.5Gbps 网络最大客户端数量
> **计算公式**(SFU 架构):服务器出站带宽 ≈ N × (N-1) × 单路比特率
> **预留 20%** 网络开销,可用带宽 ≈ **2000 Mbps**
| 质量档位 | VP8 | VP9 | H264 | 说明 |
|----------|-----|-----|------|------|
| **Low (300 Kbps)** | ~82 人 | ~98 人 | ~82 人 | 适合大型会议/培训 |
| **Standard (1 Mbps)** | ~45 人 | ~54 人 | ~45 人 | 适合中型会议 |
| **High (2.5 Mbps)** | ~29 人 | ~35 人 | ~29 人 | 适合小型高清会议 |
| **Ultra (5 Mbps)** | ~20 人 | ~24 人 | ~20 人 | 适合小型 1080p 会议 |
### 详细带宽消耗表(服务器出站带宽)
| 客户端数 | Low (300K) | Standard (1M) | High (2.5M) | Ultra (5M) |
|----------|------------|---------------|-------------|------------|
| **5 人** | 6 Mbps | 20 Mbps | 50 Mbps | 100 Mbps |
| **10 人** | 27 Mbps | 90 Mbps | 225 Mbps | 450 Mbps |
| **20 人** | 114 Mbps | 380 Mbps | 950 Mbps | 1.9 Gbps |
| **30 人** | 261 Mbps | 870 Mbps | 2.2 Gbps | 4.4 Gbps ⚠️ |
| **50 人** | 735 Mbps | 2.5 Gbps ⚠️ | 6.1 Gbps ❌ | 12.3 Gbps ❌ |
| **100 人** | 2.97 Gbps ⚠️ | 9.9 Gbps ❌ | 24.8 Gbps ❌ | 49.5 Gbps ❌ |
> ⚠️ 接近带宽上限 ❌ 超出带宽限制
### 推荐配置方案
| 会议规模 | 推荐档位 | 推荐编解码器 | 原因 |
|----------|----------|--------------|------|
| **5-10 人** | High / Ultra | H264 | 硬件加速,低 CPU 占用 |
| **10-30 人** | Standard | VP9 | 高压缩效率,节省带宽 |
| **30-50 人** | Low / Standard | VP9 | 最大化参会人数 |
| **50+ 人** | Low | VP9 | 带宽优先,保障稳定性 |
### 容量规划注意事项
1. **VP9 优势**:相同视觉质量下比 VP8/H264 节省约 **30%** 带宽
2. **H264 优势**:支持硬件编解码,CPU 负载最低
3. **音频带宽**:需预留 **10-20%** 给音频(Opus 约 32-64 Kbps/人)
4. **网络余量**:建议保持 **30%** 带宽余量应对网络波动
5. **多路由器**:超过 50 人建议使用 `PipeTransport` 跨路由器通信
---
## 常见问题
### Q: WebRTC 连接失败?
1. 检查 `AnnouncedAddress` 配置是否正确
2. 确保 UDP/TCP 端口已开放
3. 检查防火墙和 NAT 配置
4. 查看服务端日志中的 ICE 候选信息
### Q: 音视频无法显示?
1. 确认浏览器已授权摄像头/麦克风权限
2. 检查编解码器兼容性
3. 查看 Console 和 Network 错误信息
### Q: 如何调整视频质量?
修改 `mediasoupsettings.json` 中的比特率设置:
```json
{
"WebRtcTransportSettings": {
"InitialAvailableOutgoingBitrate": 1000000,
"MaximumIncomingBitrate": 1500000
}
}
```
### Q: 如何支持更多用户?
1. 增加 `NumberOfWorkers` 数量
2. 使用负载均衡分发到多个服务器
3. 考虑使用 `PipeTransport` 跨路由器通信
### Q: 编解码器信息传递流程是?
```
┌─────────────┐ ┌─────────────────┐ ┌─────────────┐
│ 客户端 A │ │ Mediasoup 服务器 │ │ 客户端 B │
│ (VP9 发送) │ │ │ │ (接收方) │
└──────┬──────┘ └────────┬────────┘ └──────┬──────┘
│ │ │
│ 1. produce(video/VP9, PT=103) │ │
│ ────────────────────────────────► │ │
│ │ │
│ │ 2. newConsumer 通知 │
│ │ rtpParameters.codecs[0].mimeType │
│ │ = "video/VP9" │
│ │ ──────────────────────────────► │
│ │ │
│ │ │ 3. 从 rtpParameters
│ │ │ 提取 mimeType
│ │ │ 使用 VP9 解码器
```
---
### Q:264 RTP 打包流程(RFC 6184)?
```
H264 关键帧数据 (Annex B 格式):
┌─────────────────────────────────────────────────────────────────┐
│ 00 00 00 01 │ SPS │ 00 00 00 01 │ PPS │ 00 00 00 01 │ IDR slice │
└─────────────────────────────────────────────────────────────────┘
↓ ExtractNalUnits() 分离
NAL[0]: SPS (类型 7) → Single NAL Unit Packet
NAL[1]: PPS (类型 8) → Single NAL Unit Packet
NAL[2]: IDR (类型 5) → FU-A 分片发送(如果超过 MTU)
每个 NAL 单元按 RTP 包发送,最后一个 NAL 的最后一个包设置 marker bit
```
## 许可证
本项目采用 MIT 许可证。详见 [LICENSE](LICENSE) 文件。
---
## 贡献
欢迎提交 Issue 和 Pull Request!
1. Fork 本仓库
2. 创建特性分支 (`git checkout -b feature/AmazingFeature`)
3. 提交更改 (`git commit -m 'Add some AmazingFeature'`)
4. 推送到分支 (`git push origin feature/AmazingFeature`)
5. 开启 Pull Request
---
## 联系方式
- GitHub: [@dorisoy](https://github.com/dorisoy)
- 项目地址: [Dorisoy.Mediasoup](https://github.com/dorisoy/Dorisoy.Mediasoup)
