# 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)
[![.NET 8](https://img.shields.io/badge/.NET-8.0-512BD4)](https://dotnet.microsoft.com/) [![WPF](https://img.shields.io/badge/WPF-Windows-0078D6)](https://docs.microsoft.com/en-us/dotnet/desktop/wpf/) [![mediasoup](https://img.shields.io/badge/mediasoup)](https://github.com/versatica/mediasoup) [![License](https://img.shields.io/badge/License-Proprietary-red)]()
一个基于 .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) ![输入图片说明](DotNet%E6%8A%80%E6%9C%AF%E5%8C%A0.jpg)