|
|
||
|---|---|---|
| src | ||
| tests | ||
| .gitignore | ||
| AGENTS.md | ||
| Cargo.lock | ||
| Cargo.toml | ||
| README.md | ||
| api.md | ||
README.md
Rave
纯 Rust 实现的全协议流媒体服务器引擎,零第三方依赖。
受 lal (Go) 和 Monibuca v6 (Rust) 启发,但除 tokio 异步运行时外不依赖任何外部 crate。
协议支持
| 协议 | 推流 | 拉流 | 状态 |
|---|---|---|---|
| RTMP | ✅ | ✅ | 握手、Chunk 协议、AMF0、Publish/Play |
| RTSP/RTP | ✅ | ✅ | ANNOUNCE/RECORD 推流;DESCRIBE/PLAY 拉流 |
| HTTP-FLV | — | ✅ | HTTP 长连接 + FLV 实时流 |
| WebSocket-FLV | — | 🚧 | 框架已搭建 |
| HLS | — | 🚧 | 框架已搭建 |
编解码支持
- 视频: H.264 (AnnexB + AVCC)、H.265/HEVC
- 音频: AAC (ADTS + raw)、G.711 (A-law / μ-law)
- 容器: FLV、MPEG-TS
快速开始
# 构建
cargo build --release
# 启动服务器
cargo run --release
# 可选:指定配置文件
cargo run --release -- rave.conf
推流与拉流
# RTMP 推流
ffmpeg -re -i video.mp4 -c copy -f flv rtmp://localhost:1935/live/test
# RTSP 推流(TCP 传输)
ffmpeg -re -i video.mp4 -c copy -f rtsp -rtsp_transport tcp rtsp://localhost:5544/live/test
# RTMP 拉流
ffplay rtmp://localhost:1935/live/test
# HTTP-FLV 拉流
ffplay http://localhost:8080/live/test.flv
# RTSP 拉流
ffplay rtsp://localhost:5544/live/test
跨协议转发
推流端和拉流端可以使用不同协议,服务器自动进行协议转换:
| 推流 → 拉流 | RTMP | HTTP-FLV | RTSP |
|---|---|---|---|
| RTMP | ✅ | ✅ | ✅ |
| RTSP | ✅ | ✅ | ✅ |
HTTP API 接口
所有 HTTP 端点运行在 HTTP-FLV 服务器端口(默认 8080):
| 端点 | 方法 | 说明 |
|---|---|---|
/api/stats |
GET | 服务器运行统计(带宽、帧率、连接数) |
/api/streams |
GET | 活跃流列表(编解码器、订阅者数、GOP 缓存) |
/{app}/{stream}.flv |
GET | HTTP-FLV 实时拉流 |
详细接口文档见 api.md。
配置
默认端口和插件开关可在 rave.conf (TOML 格式) 中配置:
rtmp.port = 1935
httpflv.port = 8080
rtsp.port = 5544
log.level = "info"
# 插件开关(设为 false 禁用对应协议)
# rtmp.enabled = false
# rtsp.enabled = false
架构
src/
├── main.rs # 入口:配置加载、插件注册、banner、优雅关闭
├── lib.rs # 模块根
├── config.rs # 手写 TOML 解析器
├── logger.rs # 最小化 stderr 日志
├── stats.rs # 服务器统计
├── core/ # 引擎内核
│ ├── buffer.rs # 无锁 SPMC 环形缓冲区
│ ├── dispatcher.rs # 单读广播分发器
│ ├── publisher.rs # 发布者(写入轨道)
│ ├── subscriber.rs # 订阅者(有界队列 + 背压)
│ ├── stream.rs # 流(GOP 缓存 + 订阅者管理)
│ ├── group.rs # StreamManager(流注册表)
│ └── track.rs # 音视频轨道
├── sdk/ # 插件契约层
│ ├── types.rs # AVFrame、编解码器枚举、StreamPath
│ ├── traits.rs # PublisherApi、SubscriberApi、StreamManagerApi
│ ├── plugin.rs # Plugin / ProtocolPlugin trait
│ ├── context.rs # EngineContext(IoC 容器)
│ └── registry.rs # PluginRegistry(生命周期管理 + 配置开关)
├── codec/ # 编解码器
│ ├── h264.rs # H.264 NALU 解析、AVCC 编码
│ ├── h265.rs # H.265 NALU 类型
│ ├── aac.rs # AAC ADTS 解析
│ ├── flv.rs # FLV tag 编解码
│ └── ts.rs # MPEG-TS 打包
├── protocol/ # 协议实现
│ ├── mod.rs # all_plugins() 内置插件清单函数
│ ├── rtmp/ # RTMP 插件、握手、Chunk、AMF0、Session
│ ├── rtsp/ # RTSP 插件、信令、RTP、Depacketizer
│ ├── httpflv*.rs # HTTP-FLV 插件 + 服务端
│ ├── hls.rs # HLS 框架
│ └── wsflv.rs # WebSocket-FLV 框架
└── remux/ # 协议转换
├── rtmp2flv.rs # RTMP ↔ FLV
└── flv2ts.rs # FLV ↔ MPEG-TS
性能设计
- 无锁 SPMC 环形缓冲区: Publisher 通过
fetch_add原子操作写入,Subscriber 各自维护读取游标 - 零拷贝: 帧数据通过
Arc<Vec<u8>>共享,Subscriber 间不复制媒体负载 - 单读广播: Dispatcher 每帧只读取一次,分发给所有 Subscriber
- 背压控制: 每个 Subscriber 有独立有界队列(1024 帧),慢消费者丢帧不阻塞发布者
SDK 插件架构
插件仅依赖 sdk/ 层的 trait 契约,不直接引用 core/ 内部实现:
sdk/types.rs → sdk/traits.rs → sdk/plugin.rs → sdk/context.rs → sdk/registry.rs
↑
core/ (实现 sdk traits) |
|
protocol/ (仅依赖 sdk:: traits + types) ───────────────────┘
内置插件通过 protocol::all_plugins() 自动注册,新增内置协议只需:
- 在
protocol/<name>/plugin.rs实现Plugin+ProtocolPlugintrait - 在
protocol/mod.rs的all_plugins()中添加一行
外部插件通过 registry.register() 手动注册。
测试
# 运行全部测试(513 个)
cargo test
# 运行特定测试
cargo test test_rtmp_handshake
cargo test test_fu_a_reassembly
cargo test test_depacketize_aac
设计约束
- 零第三方依赖(除
tokio异步运行时):所有编解码、协议解析、并发原语均手写实现 - Edition 2024,使用最新 Rust 惯用法
- 全部代码中文注释,技术术语保留英文原文
致谢
- lal — Group 模式、GOP 缓存、Remux 层架构参考
- Monibuca v6 — SDK 插件解耦、零拷贝分发架构参考