Membrane MoQ Plugin

Hex.pmAPI Docs

Membrane plugin for Media over QUIC (MoQ) streams:

The MoQ session, catalog and wire handling are implemented natively on top of the moq Rust stack (moq-native, moq-mux, hang), bound via Rustler NIFs.

Published broadcasts advertise both the hang catalog and the IETF MSF catalog, so they interoperate with the moq CLI, moq-gst and the JS @moq/hang player as well as MSF-based consumers. Subscribing picks the catalog from the broadcast name's suffix (.msf → MSF, otherwise hang).

Publishing encapsulates frames in the :legacy or :loc wire container. Consuming selects each track's container from the catalog automatically.

It is a part of Membrane Multimedia Framework.

Installation

The package can be installed by adding membrane_moq_plugin to your list of dependencies in mix.exs:

def deps do
[
{:membrane_moq_plugin, "~> 0.1.0"}
]
end

Building requires a Rust toolchain (the NIF is compiled by rustler)

Usage

Both elements talk to a MoQ relay. For local development run one with anonymous auth, e.g. moq-relay (cargo install moq-relay). The examples assume https://localhost:4443 with a self-signed certificate.

Publishing an H.264 track:

child(:source, %Membrane.File.Source{location: "video.h264"})
|> child(:parser, %Membrane.H264.Parser{
output_stream_structure: :avc3,
generate_best_effort_timestamps: %{framerate: {30, 1}}
})
|> child(:realtimer, Membrane.Realtimer)
|> via_in(Pad.ref(:input, :video), options: [track: "video"])
|> child(:sink, %Membrane.MoQ.Sink{
url: "https://localhost:4443",
broadcast: "demo.hang",
disable_tls_verify?: true
})

Subscribing to it:

child(:source, %Membrane.MoQ.Source{
url: "https://localhost:4443",
broadcast: "demo.hang",
disable_tls_verify?: true
})
|> via_out(Pad.ref(:output, :video), options: [track: "video"])
|> child(:parser, %Membrane.H264.Parser{
generate_best_effort_timestamps: %{framerate: {30, 1}}
})

The examples/ directory has runnable scripts covering the common setups:

Testing

mix test runs the unit suite. Integration tests exercise a real relay and are opt-in:

mix test --include integration

Copyright 2026, Software Mansion

Software Mansion

Licensed under the Apache License, Version 2.0