Media over QUIC (MoQ) is a live media delivery protocol utilizing QUIC streams. See the MoQ working group for more information.
This repository provides a web library for MoQ. It uses browser APIs such as WebTransport and WebCodecs to support both contribution and distribution over MoQ.
Note: This library currently focuses on the client side. You’ll need a MoQ server or relay, such as moq-rs (for local usage).
This library offers two main approaches to playing MoQ streams in a browser:
- Web Component –
<video-moq>
with simple built-in controls. - Simple Player – A
Player
class that handles rendering and playback logic without built-in UI.
Install the library from npm:
npm install @moq-js/player
Or include via a <script>
tag (for the IIFE build):
<script src="https://cdn.jsdelivr.net/npm/@moq-js/player@latest/dist/moq-player.iife.js"></script>
<video-moq
src="https://example.com/my-moq-stream?namespace=demo"
fingerprint="https://example.com/fingerprint"
width="640"
muted
controls
></video-moq>
The built-in controls are basic. If you want more advanced controls or custom styling, see the Styling & Media Chrome section or our samples.
If you’d prefer to implement your own UI or integrate the player logic differently, use the class-based Player:
import { Player } from "moq-player";
async function initPlayer() {
const canvas = document.getElementById("my-canvas");
const player = await Player.create({
url: "https://example.com/my-moq-stream",
fingerprint: "https://example.com/fingerprint",
namespace: "demo",
canvas,
});
player.play();
// Implement your own play/pause buttons, volume sliders, etc.
}
Both the Web Component and the Class-Based Player emit a series of events to help track playback state:
play
pause
loadeddata
volumechange
unsubscribestared
unsubscribedone
subscribestared
subscribedone
waitingforkeyframe
timeupdate
You can listen to these events in the usual way. For example:
const videoMoq = document.querySelector("video-moq");
videoMoq.addEventListener("play", () => {
console.log("Playback started!");
});
See samples/event-handling
for complete examples.
When using the <video-moq>
element, you can style it in various ways:
- Media Chrome: Integrate
<video-moq>
inside a<media-controller>
and use<media-play-button>
,<media-time-range>
, and other controls. Seesamples/media-chrome
for an example.
<script type="module" src="https://cdn.jsdelivr.net/npm/media-chrome@4/+esm"></script>
<media-controller>
<video-moq slot="media" src="..." controls></video-moq>
<media-play-button></media-play-button>
<media-mute-button></media-mute-button>
<!-- more controls... -->
</media-controller>
- player.style: You can also use custom themes from player.style to style the player. See
samples/media-chrome
for a working example.
<script type="module" src="https://cdn.jsdelivr.net/npm/player.style/x-mas/+esm"></script>
<media-theme-x-mas>
<video-moq
src="https://localhost:4443?namespace=bbb"
fingerprint="https://localhost:4443/fingerprint"
width="640px"
slot="media"
></video-moq>
</media-theme-x-mas>
The samples/
directory demonstrates:
- Web Component Basic – A simple
<video-moq>
usage. - Web Component Advanced – Using the component as an ES module.
- Media Chrome – Integrating
<video-moq>
with player.style custom themes. - Simple Player – Using the class-based Player without built-in controls.
- Event Handling – Listening for playback and subscription events in detail.
- Install dependencies
npm install
- Run the dev server for local testing:
npm run dev
Open localhost:3000 in a browser to see the samples running.
Licensed under either:
- Apache License, Version 2.0, (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0)
- MIT license (LICENSE-MIT or http://opensource.org/licenses/MIT)
- Join our Discord for updates and discussion.
- File issues or suggestions via GitHub Issues.
- Pull requests are welcome!