rtmp-rs
Async RTMP server and client library for Rust - Build live video streaming infrastructure with Tokio.
rtmp-rs is an RTMP server library written in Rust, built to handle the messy reality of live streaming. Encoders like OBS and FFmpeg all have their quirks, so rtmp-rs uses lenient parsing to roll with it instead of rejecting non-conforming streams. Late joiners get instant playback with keyframe caching, and smart backpressure handling keeps audio flowing for slow subscribers while selectively dropping video frames. If you're building a streaming service or relay and want RTMP ingest that just works, this might be what you're looking for.
Features
- Async/Await - Built on Tokio for high-performance concurrent connections
- Zero-Copy - Uses
bytes::Bytesthroughout for efficient memory handling - Backpressure Handling - Slow subscribers drop video frames while audio keeps flowing, so viewers hear continuous sound instead of staring at a frozen buffer
- Pub/Sub - Stream key routing with full publisher/subscriber support
- Late-Joiner GOP Cache - Buffers keyframes so viewers don't wait for the next IDR frame
- Lenient Parsing - Handles encoder quirks like empty app names and timestamp regression (OBS, Twitch compatible)
- Extensible - Implement the
RtmpHandlertrait to add custom auth and media processing
Quick Start
1. Add dependency:
2. Create a server:
use ;
use SessionContext;
use ;
;
async
3. Stream to it:
# OBS: Server: rtmp://localhost/live Stream Key: test
# ffmpeg:
Client Example (Pull Stream)
use ;
async
Handler Callbacks
The RtmpHandler trait provides hooks into the RTMP lifecycle:
| Callback | Use Case |
|---|---|
on_connection |
IP blocklist, rate limiting |
on_connect |
Validate app name, parse auth tokens from tcUrl |
on_fc_publish |
Early stream key validation (OBS sends this first) |
on_publish |
Main stream key authentication |
on_play |
Subscriber authorization |
on_metadata |
Capture stream info (resolution, bitrate, codec) |
on_video_frame |
Process H.264 NALUs |
on_audio_frame |
Process AAC frames |
on_keyframe |
Track GOP boundaries |
Configuration
use Duration;
use ServerConfig;
let config = default
.bind
.max_connections
.chunk_size
.connection_timeout
.idle_timeout;
Testing
# Run all tests
# Stream with ffmpeg
# Play with ffplay
AI disclaimer
This repo is a Rust rewrite of my RTMP Go server, which was my first time dabbling in video codecs and streaming. Almost all of the code in this Rust version was written by AI (Claude Opus 4.5).
I recently had an idea that required an RTMP server, so I used it as an excuse to write some Rust and try out some agentic programming. This repo is partly an experiment to see how far I could get by vibecoding the entire thing with Claude Code. The answer? Far!
The whole thing took around 8 hours. It probably could have been faster if I auto-accepted edits without reading the code, but I like to review everything the agent generates. I started with Plan Mode to define the requirements, then moved on to implementation.
That said, there was a tricky timestamp bug that caused audio/video stuttering, and Claude kept hallucinating answers instead of helping. After a deep-dive on my own, I found the root cause. I also noticed some parts of the code that could be improved, but I decided to keep things as-is for now. Any future improvements I'll have Claude handle.
License
Licensed under MIT license