···11+[package]
22+name = "moqbox"
33+version = "0.1.0"
44+edition = "2021"
55+description = "Ultra-low latency shared media rooms over MoQ"
66+license = "MIT OR Apache-2.0"
77+88+[dependencies]
99+# ── Async ──────────────────────────────────────────────────────────
1010+tokio = { version = "1", features = ["full"] }
1111+anyhow = "1"
1212+thiserror = "2"
1313+1414+# ── HTTP / SSR ─────────────────────────────────────────────────────
1515+axum = { version = "0.8", features = ["ws"] }
1616+tower = "0.5"
1717+tower-http = { version = "0.6", features = ["cors", "trace", "fs", "compression-gzip"] }
1818+tracing = "0.1"
1919+tracing-subscriber = { version = "0.3", features = ["env-filter"] }
2020+serde = { version = "1", features = ["derive"] }
2121+serde_json = "1"
2222+2323+# ── Templates ──────────────────────────────────────────────────────
2424+askama = "0.13"
2525+2626+# ── CLI ────────────────────────────────────────────────────────────
2727+clap = { version = "4", features = ["derive", "env"] }
2828+2929+# ── WebSocket / MoQ Transport ───────────────────────────────────────
3030+tokio-tungstenite = "0.24"
3131+futures-util = "0.3"
3232+3333+# ── TLS (reserved for future use) ─────────────────────────────────────
3434+rustls = { version = "0.23", features = ["ring"] }
3535+rcgen = "0.13"
3636+3737+# ── Identifiers ────────────────────────────────────────────────────
3838+uuid = { version = "1", features = ["v4", "serde"] }
3939+4040+# ── Database ────────────────────────────────────────────────────────
4141+sqlx = { version = "0.8", features = ["sqlite", "runtime-tokio", "chrono"] }
4242+chrono = { version = "0.4", features = ["serde"] }
4343+bytes = "1"
4444+4545+[dev-dependencies]
4646+reqwest = { version = "0.12", features = ["json"] }
4747+4848+[profile.release]
4949+lto = "fat"
5050+codegen-units = 1
5151+strip = true
+22
README.md
···11+# moqbox
22+33+Shared media rooms. Paste a URL, everyone watches together.
44+Requires `ffmpeg` and `yt-dlp` on PATH. Run with `cargo run`, open `localhost:3000`.
55+66+## Architecture
77+88+One Axum binary serving SSR pages, REST API, and a custom media streaming
99+protocol over WebSocket on the same port. Per-room mpsc actor processes commands
1010+(queue, skip, chat, register) sequentially — no locks. Room state persisted to
1111+SQLite (WAL mode).
1212+1313+yt-dlp resolves URLs to direct stream addresses. FFmpeg transcodes to fragmented
1414+MP4 at real-time speed (`-re`). fMP4 boxes are read from stdout as moof+mdat
1515+pairs and published over per-room broadcast channels. The video init segment
1616+(ftyp+moov) is cached separately. Forward tasks send cached init first, then
1717+catch up to the broadcast live edge before forwarding, so late joiners start at
1818+the live position.
1919+2020+Clients use MSE with a single SourceBuffer in segments mode. A state track
2121+(watch channel) delivers current playback position, queue, and history as JSON.
2222+Chat is persisted to SQLite, replayed on subscribe (last N), then live.