Skip to main content

Getting started with MoQ Ingest

The @vindral/publisher SDK is a practical way of providing users and operators with a browser-based workflow for publishing live streams to Vindral Live over MoQ.

There are multiple ways to integrate MoQ ingest, depending on your use-case:

Hosted MoQ Publisher

The Vindral MoQ Publisher is a web page for publishing live streams from the browser. You will find browser capabilities, connection, and media statistics to make it easier to validate setups and diagnose stability issues.

You can find the latest version of the hosted publisher at publisher.vindral.com.

Installation

Install @vindral/publisher using npm:

npm install --save @vindral/publisher
Browser support

Google Chrome is recommended for the publisher SDK.

The publisher SDK relies on modern browser media APIs such as WebCodecs and WebTransport. In other browsers, API support may be partial, unavailable, or lower-performing, which can affect codec availability, hardware acceleration, and overall publishing performance.

Example usage

The Publisher constructor accepts the MoQ ingest url, the target channelId, and the authToken used for authorization. The example below uses the same publish URL as the official Publisher SDK reference. If Vindral has assigned a dedicated endpoint for your environment, use that instead.

import { Publisher } from "@vindral/publisher"

const stream = await navigator.mediaDevices.getUserMedia({
video: { width: 1280, height: 720 },
audio: { channelCount: 2, sampleRate: 48000 },
})

const publisher = new Publisher({
url: "https://moq.global.cdn.vindral.com:7001/voq/publish",
channelId: "your-channel-id",
authToken: "your-signed-token",
})

publisher.on("connection state", (state) => console.log("connection state:", state))
publisher.on("publisher state", (state) => console.log("publisher state:", state))
publisher.on("error", (error) => console.error(error))

publisher
.addTrack({
kind: "video",
track: stream.getVideoTracks()[0],
config: {
codec: "avc1.42E01E",
width: 1280,
height: 720,
bitrate: 2_000_000,
framerate: 30,
gopSize: 60,
},
})
.addTrack({
kind: "audio",
track: stream.getAudioTracks()[0],
config: {
codec: "opus",
sampleRate: 48_000,
numberOfChannels: 2,
bitrate: 128_000,
},
})

await publisher.publish()

The Publisher class exposes a simple lifecycle:

  • prepare() - starts encoding without connecting to the server
  • publish() - connects and starts publishing
  • unpublish() - stops the connection but keeps encoding active
  • close() - shuts down the publisher completely

Connection state, publisher state, and errors can be observed through publisher.on(...). Current encoding and connection metrics can be read using publisher.stats().

Authentication

If your ingest setup uses JWT-based authorization, sign the token on your own backend and provide it as authToken. Read more in Authorizing ingress.

API reference

For full details, see the Publisher SDK API reference.