Skip to content

System Architecture

Monibuca V6 is a high-performance streaming media server engine written in Rust. This article introduces its overall architecture design.

Monibuca v6 can be understood from two complementary angles; both diagrams are previewed below.

  • Runtime view (media data flow): the full life cycle of a single frame — from the ingest side through protocol hand-off, atomic write, and the zero-copy ring buffer, out to tens of thousands of subscribers; includes the QUIC cluster cascading channel.
  • Build-time view (crate dependencies): the compile-time dependency graph spanning the three HTTP surface layers, built-in engine services, 29 pluggable crates, monibuca-sdk, and the codec base layer; includes three plugin loading modes.
Monibuca v6 runtime architecture preview
Runtime · Media Data Flow
The full life cycle of one frame, from ingest to tens of thousands of subscribers: protocol hand-off → atomic write → zero-copy ring buffer → single-reader dispatcher broadcast, plus the QUIC cluster cascading channel.
4 views: Media Main Path · Plugin Contract · Control & Ops Plane · QUIC Cluster Cascade
14 nodes · 11 connections · 16 repo evidence anchors
View full screen →
Monibuca v6 build-time architecture preview
Build-time · Crate Dependencies
The compile-time dependency graph across the three HTTP surface layers, built-in engine services, 29 pluggable crates, monibuca-sdk, and the codec base layer, plus three plugin loading modes.
4 views: Main Dependency Chain · HTTP Surface Layers · Plugin Ecosystem · SDK Contract
14 nodes · 13 connections · 4 src/ boundaries · 5 plugins sub-layers
View full screen →

Also available: hand-written full overview — a single diagram covering all 26 plugins, the 8 codec modules, three HTTP surface versions, and bottom Architecture Notes.

flowchart TB
  subgraph Engine["Monibuca Engine"]
    PP["Protocol Plugins<br/>RTMP / RTSP / HLS / WebRTC / SRT…"]
    subgraph SM["StreamManager"]
      Reg["Registry"]
      Life["Lifecycle"]
      WQ["WaitQueue"]
    end
    PM["PluginManager<br/>init / start / stop / reload"]
    EC["EngineContext<br/>IoC Container"]
    CM["ConfigManager<br/>YAML + API"]
    subgraph SI["Stream Instance"]
      Pub["Publisher"]
      VT["VideoTrack"]
      AT["AudioTrack"]
      RB["RingBuffer"]
      Disp["Dispatcher / DispatcherPool"]
      Subs["Subscribers"]
      Pub --> VT & AT
      VT & AT --> RB
      RB --> Disp --> Subs
    end
    PP --> SM
    PM --> SM
    SM --> SI
  end
flowchart TB
  Pub["Publisher (Ingest)"]
  SM["StreamManager.create_publisher(stream_path)"]
  VT["VideoTrack → RingBuffer<br/>256 slots, lock-free"]
  AT["AudioTrack → RingBuffer<br/>64 slots, lock-free"]
  WQ["WaitQueue (Wait List)"]
  Disp["Dispatcher / DispatcherPool"]
  Q1["Queue 1 (bounded)"]
  Q2["Queue 2 (bounded)"]
  QN["Queue N (bounded)"]
  S1["Subscriber (Playback)"]
  S2["Subscriber (Playback)"]
  SN["Subscriber (Playback)"]

  Pub --> SM
  SM --> VT & AT & WQ
  VT & AT --> Disp
  Disp --> Q1 & Q2 & QN
  Q1 --> S1
  Q2 --> S2
  QN --> SN

The core modules are located in src/core/ and are responsible for the underlying data structures and processing logic of the streaming engine:

ModuleFileResponsibility
bufferbuffer.rsLock-free SPMC ring buffer for frame storage
frameframe.rsAVFrame audio/video frame data structure
tracktrack.rsAudio/video track management (VideoTrack / AudioTrack)
publisherpublisher.rsPublisher, manages tracks and subscriber list
subscribersubscriber.rsSubscriber, consumes frame data from RingBuffer
dispatcherdispatcher.rsFrame dispatcher, single read broadcasts to all subscribers
poolpool.rsObject pool (BytesPool, ObjectPool, ThreadLocal pool)
tasktask.rsHierarchical task system with cascading cancellation
proxyproxy.rsPull/Push proxy (Pull Proxy / Push Proxy)
recorderrecorder.rsStream recording framework (FLV / MP4 / fMP4 / HLS)
transformertransformer.rsStream transformer (subscribe source → process → publish new stream)
playbackplayback.rsPlayback speed control and timestamp scaling
storagestorage.rsAsync storage trait (io_uring ready)

Management HTTP APIs use a multi-surface architecture: each surface owns the HTTP shape (paths, methods, JSON fields, status codes) while sharing a single AppFacade application layer that delegates to StreamManager and plugin services. gRPC management handlers funnel through the same AppFacade, avoiding duplicated business logic.

SurfacePrefixDescription
V5CompatSurface/api/*v5-compatible layer with legacy paths and response envelope; default for existing integrations
V6Surface/v6/api/*Native v6 REST API; recommended for new integrations
ZegoCompatSurface/zego/api/*ZEGO action-style compatibility layer (api-compat-zego feature)
gRPCShares AppFacade with HTTP surfaces

Central registration: register_http_plugins() in src/server/http_plugins/register.rs. Surfaces are mounted at startup based on Cargo features (e.g. api-v5-compat, api-v6).

Migration policy: legacy clients keep /api/*; new capabilities land on /v6/api/* first. The v5 layer evolves for compatibility (additive fields, no breaking semantic changes).

Monibuca V6 uses a Cargo Workspace to organize code, split into multiple independent crates:

monibuca/ # Main crate (engine + binary)
├── src/
│ ├── core/ # Core data structures
│ ├── manager/ # StreamManager / PluginManager
│ ├── api/ # AppFacade + HTTP surfaces (v5 / v6 / zego)
│ ├── config/ # Configuration management
│ ├── grpc/ # gRPC API (via AppFacade)
│ ├── server/http_plugins/ # HTTP plugin and surface registration
│ └── room/ # Built-in room service
├── crates/
│ ├── codec/ # codec crate — codecs + enums + traits
│ ├── monibuca-sdk/ # SDK crate — plugin development SDK
│ ├── monibuca-sdk-macros/ # SDK proc macros
│ ├── m7s-config-framework/ # Configuration framework
│ └── m7s-config-macros/ # Configuration framework macros
└── plugins/ # 25 plugin crates
├── rtmp/
├── rtsp/
├── flv/
├── hls/
├── webrtc/
└── ...
flowchart BT
  plugins["plugins/*<br/>All plugins depend only on the SDK"] --> engine["monibuca (engine)<br/>Main engine crate"]
  engine --> sdk["monibuca-sdk<br/>Sole contract layer for plugin development"]
  sdk --> codec["codec<br/>Bottom layer, zero deps on other monibuca crates"]
  • codec: Defines all shared types — AVFrame, VideoCodec, AudioCodec, VideoFrameType, trait interfaces (PublisherApi / SubscriberApi / StreamManagerApi)
  • SDK: Wraps codec and provides plugin registration, HTTP routing, config schema, and other development tools
  • Main crate: Engine implementation, containing core logic such as StreamManager, Dispatcher, RingBuffer, etc.
  • plugins/: Protocol and feature plugins, depending only on the SDK crate

Monibuca V6 supports three plugin loading modes:

ModeDescriptionCharacteristics
Built-in pluginsOfficial pre-built binariesBest performance, default; enable via config.yaml
Dynamic loadingplugins_dir directory.so/.dylib/.dll loaded at runtime
WASM sandboxExperimentalIsolated execution, highest security

Official binaries include all built-in plugins. Enable or disable them in configuration — compiling the engine from source is not required.

ComponentLibraryPurpose
Async runtimeTokioEvent-driven concurrency
Mutexparking_lotHigh-performance Mutex / RwLock
Concurrent hash mapDashMapLock-free stream registry
Atomic pointer swapArcSwapLock-free IDR list, subscriber list
QUIC transportQuinnWebTransport / QUIC protocol support
Zero-copy bytesBytesZero-copy frame data sharing
WebRTCrustrtcWebRTC protocol stack
gRPCTonicAPI service
DatabaseSQLxRecording index, configuration persistence
SerializationSerde + serde_json/serde_yamlConfiguration and API data formats
  1. Lock-free first: RingBuffer write operations use fetch_add atomic instructions, read operations achieve lock-free access through ArcSwap
  2. Zero-copy: Frame data is shared via Arc<AVFrame>, no data copying between subscribers
  3. Single-read broadcast: Dispatcher reads frame data from the RingBuffer only once, then broadcasts to all subscribers
  4. Backpressure control: Uses bounded channels, slow subscribers drop frames instead of blocking other subscribers
  5. Object pool reuse: BytesPool and ThreadLocal pools reduce memory allocation on hot paths