Getting Started with MOQ: A Developer's Guide
Everything you need to know to start experimenting with Media over QUIC, from setting up a relay to publishing your first stream.
Prerequisites
Before diving into MOQ development, you'll need:
- Rust toolchain (for moq-rs) or Go (for moqtransport)
- FFmpeg for media encoding/decoding
- A TLS certificate (self-signed works for development)
- Basic understanding of QUIC and media encoding concepts
Option 1: moq-rs (Recommended for Getting Started)
Install
git clone https://github.com/kixelated/moq-rs
cd moq-rs
cargo build --release
Generate Development Certificates
# Generate a self-signed certificate for localhost
openssl req -x509 -newkey ec -pkeyopt ec_paramgen_curve:prime256v1 \
-keyout key.pem -out cert.pem -days 365 -nodes \
-subj "/CN=localhost"
Run the Relay
cargo run --bin moq-relay -- \
--tls-cert cert.pem \
--tls-key key.pem \
--bind 0.0.0.0:4443
Publish a Stream
# Publish a test pattern
ffmpeg -f lavfi -i testsrc=size=1280x720:rate=30 \
-f lavfi -i sine=frequency=440:sample_rate=48000 \
-c:v libx264 -preset ultrafast -tune zerolatency \
-c:a aac -f mp4 -movflags frag_keyframe+empty_moov - | \
cargo run --bin moq-pub -- \
--host localhost:4443 \
--tls-disable-verify
Subscribe
cargo run --bin moq-sub -- \
--host localhost:4443 \
--tls-disable-verify | \
ffplay -
Option 2: moqtransport (Go)
go install github.com/mengelbart/moqtransport@latest
The Go implementation provides a clean API for building MOQ applications:
package main
import (
"github.com/mengelbart/moqtransport"
)
func main() {
// Create a new MOQ session
session, err := moqtransport.NewSession(...)
// Subscribe to a track
track, err := session.Subscribe("namespace", "track")
// Read objects
for {
obj, err := track.ReadObject()
// Process the media object...
}
}
Key Concepts to Understand
Tracks and Groups
- Track: A named stream of related objects (e.g., "video-hd")
- Group: A collection of objects that can be independently decoded (like a GOP in video)
- Object: The atomic unit of media data
Subscription Modes
- Latest Group: Start receiving from the most recent group (live edge)
- Absolute Range: Request specific groups by number
- Latest Object: Start from the most recent object
Delivery Preferences
- Stream per group: Each group gets its own QUIC stream
- Stream per object: Each object gets its own stream
- Stream per track: All objects from a track share one stream
- Datagram: Objects sent as unreliable datagrams
Next Steps
- Experiment with publishing and subscribing locally
- Try different codecs and configurations
- Set up a multi-hop relay topology
- Build a browser-based subscriber using WebTransport
- Join the IETF MOQ mailing list for the latest discussions