๐ฌ arcly-stream
A high-performance, open-extensible live-media streaming kernel for Rust
Lock-free zero-copy fan-out ยท instant-start GOP replay ยท a pluggable multi-protocol ingestion layer ยท a feature-gated pure-Rust media plane โ with zero baked-in config, metrics singleton, or HTTP runtime.
๐ At a Glance
Every streaming server re-solves the same hard core: fan one publisher's frames out to thousands of late-joining subscribers โ without copying payloads, without locks on the hot path, and without silently dropping the slow ones. Everything else โ which wire protocol you ingest, how you package egress, where you store, how you authorize and observe โ is deployment-specific.
arcly-stream is exactly that core, extracted and hardened into an embeddable
kernel. You implement a few small traits for the parts unique to your system;
the kernel owns the lock-free pub/sub bus, instant-start replay, back-pressure,
lifecycle, and QoS. It ships no opinion about your runtime: no global
registry, no TOML schema, no HTTP server.
use *;
let engine = builder
.max_publishers
.application // instant-start replay
.build;
assert_eq!;
๐ฆ Capability Matrix
| Capability | Status | Reach it via |
|---|---|---|
| Zero-copy broadcast fan-out | โ Core | StreamHandle::subscribe_resilient |
| Instant-start GOP replay | โ Core | AppSpec::gop_cache(n) + replay_buffer() |
| Publish/play authorization | โ Core | StreamAuthenticator (permit-all default) |
| Live QoS (bitrate / fps) | โ Core | StreamHandle::qos() |
| Slow-subscriber eviction | โ Core | Subscription::max_lag |
| Idle-stream reaper | โ Core | EngineBuilder::idle_timeout |
| Coordinated graceful shutdown | โ Core | Engine::serve_until_signal |
| Pluggable protocol ingestion | โ Core | InboundProtocol trait |
| RTMP publish / play | โ
rtmp |
protocol::rtmp::RtmpHandler |
| RTSP ingest (IP cameras) | โ
rtsp |
protocol::rtsp::RtspHandler โ client-pull, OPTIONSโPLAY, SDP, TCP-interleaved RTP (H.264) |
| SRT ingest (broadcast feeds) | โ
srt |
protocol::srt::SrtHandler โ listener handshake + MPEG-TS demux (unencrypted) |
| WebRTC WHIP/WHEP ingest | โ
webrtc |
protocol::webrtc::WhipEndpoint โ SDP signaling + RTP/RTCP routing over a pluggable DtlsSrtpTransport |
| MPEG-TS muxing (playable) | โ
mpegts |
packager::MpegTsMuxer |
| Fragmented-MP4 / CMAF muxing | โ
fmp4 |
packager::Fmp4Muxer โ H.264 avc1 + AV1 av01 (+codec-av1) + VVC vvc1 (+codec-vvc) init, codec-generic fragments (LL-HLS) |
| Production token auth | โ
auth-token |
auth::TokenAuthenticator โ HMAC-SHA-256, dependency-free |
| Audit trail / structured telemetry | โ Core | FileAuditSink, StandardTelemetry |
| H.264/265 ยท AV1 ยท VP9 ยท VVC ยท AAC parsing | ๐งฉ codec* |
codec::{h264,h265,av1,vp9,vvc,aac} |
| HLS / LL-HLS packaging | ๐งฉ hls |
HlsSegmenter + HlsPlaylist |
| Recording (VOD / DVR) | ๐งฉ record |
RecordingSink |
| Filesystem storage | ๐งฉ storage-fs |
FsStorage |
| Prometheus metrics | ๐งฉ metrics |
PrometheusObserver |
| Hardware transcode / ABR | ๐งญ Seam | implement Transcoder |
| Edge federation | ๐งญ Seam | implement ClusterRelay |
โ Core/feature = shipped, native-Rust,
unsafe-free. ๐งญ Seam = a documented public trait you implement in your own crate; the kernel never drags in a native transport or codec you didn't ask for.WebRTC scope note: the
webrtcfeature ships the WHIP/WHEP signaling (SDP offer/answer), RTP/RTCP routing, and PLI/FIR feedback natively. The DTLS/SRTP/ICE crypto transport is injected by the host through theDtlsSrtpTransporttrait (back it withstr0m/webrtc-rs) โ so the kernel stays crypto-free and#![forbid(unsafe_code)]. SRT ships unencrypted (handshake + MPEG-TS demux); AES-encrypted SRT is out of scope.
๐ Architecture
Three tiers โ an always-on Open Kernel, an Injected Multi-Protocol Layer, and a Feature-Gated Media Plane:
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ OPEN KERNEL โ
โ (always compiled) โ
publisher โโโโโโโโโถ โ Engine ยท StreamHandle โ โโโโโโถ subscribers
(any protocol) โ โข broadcast fan-out (zero-copy Arc<Frame>) โ (packager / SFU /
โ โข GOP cache โ instant-start replay โ recorder / edge)
โ โข live QoS (bitrate / fps) โ
โ PublishRegistry ยท PlaybackRegistry ยท EventBus โ
โ Observer ยท StreamAuthenticator ยท AuditSink โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โฒ implements โฒ feature-gated, pure Rust
โโโโโโโโโโโโโโโโโโโดโโโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโดโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ INJECTED MULTI-PROTOCOL LAYER โ โ MEDIA PLANE โ
โ (trait: InboundProtocol) โ โ (opt-in features) โ
โ RtmpHandler reference impl โ
โ โ MpegTsMuxer playable .ts โ
โ
โ IngestContext ยท PublishSession โ โ codec H.264/265 ยท AV1/VP9/VVC ยท AAC โ
โ โโ your crate โโโโโโโโโโโโโโโโโโ โ โ hls Packager + segmenter โ
โ MyRtspHandler ยท MyWhipHandler โฆ โ โ record RecordingSink (VOD/DVR) โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
A new wire protocol is one InboundProtocol impl in your own crate,
registered on the builder โ no kernel fork. RtmpHandler is just the first
reference implementation of that public trait.
Workspace layout
arcly-stream/ the published library crate (this README documents it)
arcly-stream-macros/ optional proc-macros (the `macros` feature)
examples/
minimal_ingest/ MediaSource + Observer, drive the bus
custom_protocol/ legacy ProtocolHandler + Engine::serve
custom_protocol_plugin/ custom InboundProtocol registered alongside RTMP
enterprise_gateway/ RTMP + token auth + FS recording + metrics + audit
multi_protocol_gateway/ RTMP + RTSP pull + SRT + WHIP under one engine
codec_inspect/ per-codec random-access + HLS codec strings
rtmp_to_hls/ real RTMP ingest โ MPEG-TS HLS on disk
Design invariants
- Zero-copy โ one publish clones an
Arc<MediaFrame>pointer per subscriber, never the payload (bytes::Bytes). - Lock-free hot path โ
tokio::broadcastfan-out;ArcSwap+ atomics for cached config, GOP head, and QoS. - No global state โ telemetry, auth, and audit are injected traits with safe defaults; instantiate as many engines per process as you like.
- Contracts are traits โ protocols depend on
PublishRegistry, not the concreteEngine, so a host can swap the bus. #![forbid(unsafe_code)]+#![deny(missing_docs)]โ nounsafe, and every public item documented; both compiler-enforced.
๐ Quick Start
A real RTMP-in โ HLS-out origin
The rtmp handler ingests from OBS or FFmpeg; the mpegts muxer writes playable
HLS. Run the bundled, fully-wired version:
# ffmpeg -re -i input.mp4 -c:v libx264 -c:a aac -f flv rtmp://localhost:1935/live/cam
# โ playable HLS under ./hls/live/cam/index.m3u8
The origin itself is a few lines โ register the handler on the builder and serve:
use *;
use RtmpHandler;
async
Plug in a custom third-party protocol
Teach the engine a brand-new wire protocol from your own crate โ implement the
public InboundProtocol trait and register it on the builder alongside the
native RTMP handler. Both run concurrently under one coordinated shutdown.
use *;
use ;
use RtmpHandler;
let engine = builder
.application
.protocol // native
.protocol // yours
.build;
A full runnable version lives in
examples/custom_protocol_plugin.
Runtime contract: workers are Send + Sync + 'static, must observe
shutdown and return promptly, and run on a Tokio runtime. Returning Err
trips the engine's coordinated teardown, winding sibling workers down too.
Existing ProtocolHandler impls keep working โ a blanket bridge makes every one
an InboundProtocol automatically.
๐งฉ Extension points (the traits you implement)
| Trait | Purpose |
|---|---|
InboundProtocol |
Teach the engine a new wire protocol (RTMP, RTSP, SRT, WHIP all shipped โ and your own is one impl away) |
DtlsSrtpTransport |
Plug a WebRTC crypto backend (DTLS/SRTP/ICE) behind the native WHIP/WHEP signaling |
MediaSource / MediaSink |
Produce / consume frames (driven by Engine::pump_source) |
StorageBackend |
Object storage for segments & recordings |
Muxer |
Container byte-format for HLS segments (MPEG-TS shipped; fMP4/CMAF DIY) |
Transcoder |
Decode/scale/encode into an ABR ladder |
StreamAuthenticator |
Authorize publish / play (permit-all by default) |
Observer / AuditSink / HealthCheck |
Telemetry, audit trail, readiness |
ClusterRelay |
Origin/edge discovery & stream federation |
PublishRegistry / PlaybackRegistry / EventBus |
Swap the engine for your own bus |
โ๏ธ Cargo features
| Feature | Effect |
|---|---|
| (none) | Pure kernel: frame model, bus, auth/audit/health/cluster contracts |
codec |
H.264 NAL/SPS + AAC ADTS parsers |
codec-h265 / -av1 / -vp9 / -vvc / codecs-all |
Next-gen codec parsers |
ingest |
Shared TCP accept loop, keyframe gate, rate limiter, NAL scan |
rtmp |
Working RTMP publish/play (RtmpHandler) |
rtsp |
Native RTSP client-pull ingest (RtspHandler) โ IP cameras over TCP-interleaved RTP |
srt |
Native SRT listener ingest (SrtHandler) โ handshake + MPEG-TS demux (unencrypted) |
webrtc |
WHIP/WHEP signaling + RTP/RTCP routing (WhipEndpoint) over a pluggable DtlsSrtpTransport |
mpegts |
Native MPEG-TS muxer (MpegTsMuxer) โ playable .ts |
fmp4 |
Native fragmented-MP4/CMAF muxer (Fmp4Muxer) โ LL-HLS init + fragments |
hls |
HLS/LL-HLS packager + segmenter + playlists |
record |
Segment/recording sink over a StorageBackend |
storage-fs |
Filesystem StorageBackend |
metrics |
Prometheus Observer |
auth-token |
Production HMAC-signed token StreamAuthenticator (dependency-free) |
macros |
#[derive(MediaSink)], #[protocol] |
full |
Everything |
๐งฐ Examples
๐ก Guarantees
#![forbid(unsafe_code)]โ nounsafein the kernel, compiler-enforced.#![deny(missing_docs)]โ every public item is documented.- Zero-copy payloads (
bytes::Bytes), lock-free fan-out. - No singletons โ many engines per process; ideal for tests.
๐ Minimum Supported Rust Version
arcly-stream supports Rust 1.85 and later. An MSRV bump is a minor-version
change.
๐ Documentation
Full API docs are on docs.rs/arcly-stream. See
BLUEPRINT.md for the extraction analysis and the mapping from
the original 25-crate stream-center to this single crate.
๐ License
MIT.