Skip to main content

GStreamer Plugin

The Moq GStreamer plugin provides moqsrc and moqsink elements for integrating Moq into GStreamer pipelines. This enables efficient media processing and streaming with full control over encoding, decoding, and transformations.
This plugin is currently under development but works well for most use cases. Contributions are welcome!

Overview

The GStreamer plugin provides two main elements:
  • moqsink: Publish media to Moq relays
  • moqsrc: Subscribe to Moq broadcasts

Repository

The plugin is maintained in a separate repository:

Moq GStreamer Plugin

View source code, installation instructions, and examples

Installation

1
Install GStreamer
2
Ensure GStreamer development libraries are installed:
3
Ubuntu/Debian
sudo apt-get install libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev
Fedora
sudo dnf install gstreamer1-devel gstreamer1-plugins-base-devel
macOS
brew install gstreamer gst-plugins-base
4
Clone the Repository
5
git clone https://github.com/moq-dev/gstreamer
cd gstreamer
6
Build the Plugin
7
cargo build --release
8
Install to GStreamer
9
Copy the built plugin to your GStreamer plugins directory:
10
cp target/release/libhang_gst.so ~/.local/share/gstreamer-1.0/plugins/
11
On macOS, the extension is .dylib instead of .so.
12
Verify Installation
13
Check that GStreamer recognizes the plugin:
14
gst-inspect-1.0 moqsink
gst-inspect-1.0 moqsrc

Publishing with moqsink

Basic Publishing Pipeline

Publish a test video pattern:
gst-launch-1.0 videotestsrc ! x264enc ! \
  isofmp4mux name=mux chunk-duration=1 fragment-duration=1 ! \
  moqsink url=https://cdn.moq.dev/anon broadcast=test

Publish from Webcam

Stream from a video device:
gst-launch-1.0 v4l2src device=/dev/video0 ! \
  videoconvert ! x264enc tune=zerolatency ! \
  isofmp4mux chunk-duration=1 fragment-duration=1 ! \
  moqsink url=https://relay.example.com/anon broadcast=webcam

Publish with Audio

Include audio in your stream:
gst-launch-1.0 \
  videotestsrc ! videoconvert ! x264enc ! mux.video \
  audiotestsrc ! audioconvert ! avenc_aac ! mux.audio \
  isofmp4mux name=mux chunk-duration=1 fragment-duration=1 ! \
  moqsink url=https://relay.example.com/anon broadcast=test

Publish a File

Stream a video file:
gst-launch-1.0 filesrc location=video.mp4 ! \
  qtdemux ! h264parse ! mux.video \
  isofmp4mux name=mux chunk-duration=1 fragment-duration=1 ! \
  moqsink url=https://relay.example.com/anon broadcast=video

Subscribing with moqsrc

Basic Playback Pipeline

Subscribe and play a Moq broadcast:
gst-launch-1.0 moqsrc url=https://cdn.moq.dev/anon broadcast=test ! \
  decodebin ! autovideosink

Save to File

Record a Moq broadcast to a file:
gst-launch-1.0 moqsrc url=https://relay.example.com/anon broadcast=stream ! \
  filesink location=output.mp4

Transcode and Republish

Subscribe, transcode, and republish:
gst-launch-1.0 \
  moqsrc url=https://relay.example.com/anon broadcast=source ! \
  decodebin ! videoconvert ! \
  x264enc bitrate=1000 ! \
  isofmp4mux chunk-duration=1 fragment-duration=1 ! \
  moqsink url=https://relay.example.com/anon broadcast=transcoded

moqsink Properties

Configure the moqsink element:
PropertyTypeDefaultDescription
urlstringrequiredRelay server URL
broadcaststringrequiredBroadcast name
jwtstring-Authentication token

Example with Properties

gst-launch-1.0 videotestsrc ! x264enc ! \
  isofmp4mux chunk-duration=1 fragment-duration=1 ! \
  moqsink url="https://relay.example.com/anon" \
          broadcast="my-stream" \
          jwt="<token>"

moqsrc Properties

Configure the moqsrc element:
PropertyTypeDefaultDescription
urlstringrequiredRelay server URL
broadcaststringrequiredBroadcast name
jwtstring-Authentication token

Advanced Pipelines

Multi-Bitrate Publishing

Publish multiple quality levels:
gst-launch-1.0 videotestsrc ! tee name=t \
  t. ! queue ! videoscale ! video/x-raw,width=1920,height=1080 ! \
      x264enc bitrate=5000 ! isofmp4mux ! \
      moqsink url=https://relay.example.com/anon broadcast=high \
  t. ! queue ! videoscale ! video/x-raw,width=1280,height=720 ! \
      x264enc bitrate=2500 ! isofmp4mux ! \
      moqsink url=https://relay.example.com/anon broadcast=medium

Screen Capture

Capture and stream your screen:
gst-launch-1.0 ximagesrc ! \
  videoconvert ! x264enc tune=zerolatency ! \
  isofmp4mux chunk-duration=1 fragment-duration=1 ! \
  moqsink url=https://relay.example.com/anon broadcast=screen

Low Latency Configuration

Optimize for minimal latency:
gst-launch-1.0 videotestsrc ! \
  x264enc tune=zerolatency bitrate=2000 \
          key-int-max=30 bframes=0 \
          byte-stream=true threads=0 ! \
  isofmp4mux chunk-duration=1 fragment-duration=1 \
             streamable=true fragment-mode=first-moov-then-finalise ! \
  moqsink url=https://relay.example.com/anon broadcast=lowlatency
Key parameters for low latency:
  • tune=zerolatency: Disables lookahead
  • key-int-max=30: Frequent keyframes (every 1 second at 30fps)
  • bframes=0: No B-frames
  • chunk-duration=1: 1-second fragments

Debugging

Enable Debug Output

Set GStreamer debug level:
GST_DEBUG=moqsink:5,moqsrc:5 gst-launch-1.0 ...

Inspect Pipeline

Visualize your pipeline:
GST_DEBUG_DUMP_DOT_DIR=. gst-launch-1.0 ...
dot -Tpng pipeline.dot -o pipeline.png

More Examples

Check the repository’s justfile for additional examples:
cd gstreamer
just --list

Troubleshooting

Plugin Not Found

  • Verify plugin is in GStreamer plugins directory
  • Run gst-inspect-1.0 moqsink to check installation
  • Set GST_PLUGIN_PATH if using custom location

Connection Errors

  • Check relay URL is accessible
  • Verify firewall allows UDP traffic
  • Ensure JWT token is valid if using authentication

Pipeline Errors

  • Verify all elements are installed (gst-inspect-1.0 <element>)
  • Check element capabilities match (use gst-inspect-1.0)
  • Enable debug output to identify bottlenecks

Next Steps

Deploy a Relay

Set up your own relay server

FFmpeg Integration

Alternative command-line publishing

Web Playback

Watch streams in the browser

OBS Plugin

Stream using OBS Studio

Build docs developers (and LLMs) love