# Vindral Live Documentation
> Documentation for Vindral Live, an ultra-low latency live streaming platform by RealSprint.
This file is the full source-first export of the Vindral Live documentation, with authored Markdown and Mermaid diagrams preserved for AI-friendly ingestion.
For the navigable index, see [llms.txt](https://docs.vindral.com/llms.txt).
Welcome to the official Vindral Live documentation.
Try our interactive demos at [demo.vindral.com](https://demo.vindral.com/), find information about features at [vindral.com](https://www.vindral.com/), or read on for guides that explain how to manage, send, and consume Vindral Live streams.
For details about Vindral Composer, visit its [dedicated documentation page](https://composer-docs.vindral.com/).
## Getting started
- [Examples](https://realsprint.github.io/vindral-examples/): Test examples of player and sender applications and look at the code for a good entry point into the Vindral Live ecosystem.
- [Demo player](https://demo.vindral.com/): Test the demo player to see what an example of how channel switching works.
- [Demo channels](https://docs.vindral.com/playout/using-the-demo-channels.md): Use the 24/7 demo channels for testing your application and for faster development process.
- [Embeddable player](https://docs.vindral.com/playout/embeddable-player.md): Use the embeddable player without having previous knowledge of code or video.
- [Broadcast from OBS](https://docs.vindral.com/broadcast/broadcast-software/streaming-from-obs.md): Learn how to broadcast from a popular, free, and highly customizable video software.
- [Broadcast from browser](https://docs.vindral.com/broadcast/moq-ingest/getting-started.md#hosted-moq-publisher): Use the hosted Vindral Publisher to broadcast from the browser over MoQ without installing additional software.
## Deployment Options
Vindral Live's family of components can be used on-prem, in-cloud or hybrid, stand-alone or together as a platform.
Whichever way Vindral Live is integrated, it enables Media over QUIC (MoQ) and many other protocols for your streaming needs.
- [Vindral LiveEngine](https://docs.vindral.com/integrate/self-managed.md): The self-managed live CDN platform, built for low-latency streaming at scale. It supports MoQ, LLHLS, RTMP, SRT, and more, and can be white-labeled, OEM licensed, and deployed in your own infrastructure.
- [Vindral LiveCloud](https://docs.vindral.com/integrate/fully-managed.md): The global live CDN service, powered by Vindral LiveEngine, with user Portal, SLAs and multi-provider redundancy.
- [Vindral LivePackager](https://docs.vindral.com/broadcast/broadcast-software/livepackager.md): The muscles of LiveEngine can be run on-prem or in-cloud, offering real-time transcode, scale, multi-input/output, multi-protocol, with or without hardware offload.
## Build custom experiences
- [Custom web player](https://docs.vindral.com/playout/websdk/getting-started.md): Learn how to use the Web SDK to create a custom player interface on your own websites and applications.
- [Custom browser publisher](https://docs.vindral.com/broadcast/moq-ingest/getting-started.md): Learn how to use the Publisher SDK to integrate browser-based publishing over MoQ on your own website.
- [API integration](https://docs.vindral.com/manage/management-api.md): Learn how to use the API to manage channels, retrieve telemetry, and more.
- [Timed metadata](https://docs.vindral.com/manage/timed-metadata.md): Learn how to use timed metadata to build synchronized user experiences.
## Monitor and debug
- [Quality of Service player](https://docs.vindral.com/playout/qos-client.md): Learn how to use the QoS Client to monitor, verify, and debug channels.
- [Troubleshooting](https://docs.vindral.com/troubleshooting.md): Find solutions to common issues.
## API Reference
- [Web SDK API Reference](https://docs.vindral.com/web-sdk/api/): Delve into the functions, properties and interfaces of the Web SDK.
- [Publisher SDK API Reference](https://docs.vindral.com/web-sdk/api/publisher/): Explore the Publisher SDK API to publish live streams from the browser over MoQ.
- [AppleSDK API Reference](https://docs.vindral.com/applesdk/): Read about the classes, protocols and structures of the AppleSDK.
- [Management API Reference](https://docs.vindral.com/management-api/): Learn how to use the API to manage channels, retrieve telemetry, and more.
## Composer
- [Composer Documentation](https://composer-docs.vindral.com/): Learn how to use Composer for dynamic video composition, color correction, chroma-keying, visual effects, and live streaming.
- [Live casino workhorse](https://www.vindral.com/composer): Learn why Composer is the ultimate workhorse for authentic live casino experiences at 24/7 large-scale operations.
## General
### System overview
The Vindral Live ecosystem consists of a variety of modular components and services, each designed to meet specific needs. Together, they form [Vindral LiveEngine](https://docs.vindral.com/integrate/self-managed.md) — a high-performance, low-latency platform optimized for large-scale deployments. With Vindral LiveEngine, you can build a fully self-managed live CDN service that supports a wide range of protocols including MoQ, LLHLS, RTMP, SRT, and more. The system is highly customizable, offering white-labeling options, OEM licensing, and deployment flexibility on your own infrastructure.
For those seeking a fully managed solution, [Vindral LiveCloud](https://docs.vindral.com/integrate/fully-managed.md) provides a global, cloud-based live CDN service. Built on top of Vindral LiveEngine, LiveCloud offers all the features of Vindral LiveEngine, with the added convenience of managed services, robust SLAs, and a redundant, multi-provider infrastructure to ensure maximum uptime and reliability.
Unlike many streaming solutions, Vindral Live offers **configurable latency** that can be optimized for your specific use case, providing superior stability at low latency settings, while also keeping viewers in sync. [Learn more about Latency Control](https://docs.vindral.com/playout/latency-control.md).
Keep reading to learn more about how Vindral Live works and how easy it is to get started.
## Concepts
Some concepts need to be clarified within the live streaming area. Here, we explain some terms and the components related to them.
### Ingress
When broadcasting, the video/audio feed usually goes through a certain path from the source into the delivery network.
```mermaid
flowchart LR;
subgraph Ingress
direction LR
C(Ingress Server)
subgraph "Source, customer premises"
A(Camera)-->B(Encoder)
end
B-->C
end
E(Edge)-->F(Viewer);
C-->E;
```
This process is called *Ingress*.
The graph above exemplifies how it may work, as different setups use different protocols.
Our ingress servers can handle different types of content over various transport protocols.
The most common ways to ingress streams are:
- RTMP(s) - de facto standard for video ingress over the internet
- SRT - Secure Reliable Transport
- MoQ - recommended browser ingest transport via the Publisher SDK
- MPEG-TS - useful for on-prem installations
- HD-SDI - useful for on-prem installations
[Visit the protocol page](https://docs.vindral.com/broadcast/supported-protocols.md) to read more about supported ways of ingesting streams into Vindral Live.
### Transcoding
Most streams sent over the internet use multiple qualities to cater to different viewer conditions. Often, a single stream is sent to our service and turned into multiple qualities, a.k.a. an ABR Ladder.
```mermaid
flowchart LR;
subgraph Transcoding
direction LR
B(Transcoder / Packager)
end
A(Ingress)--1080p-->B;
B--ABR Ladder-->C(Edge)
C--1080p-->D(Viewer A);
C--720p-->E(Viewer B);
C--360p-->F(Viewer C);
```
This process is called *Transcoding*.
Our transcoding components are built for robust 24/7 streaming and support many different codecs and settings. They are built for dense and environmentally friendly operations through hardware offloading.
These are used internally within Vindral Live and can be used on-prem as well. [Let us know](https://vindral.com/contact/) if you are interested in learning more.
### Egress
After the stream has reached the Vindral Live ingress server, it will be transcoded and transmuxed as needed. After the transcoding step, the stream will find its path to the viewers.
This process is called *Egress*.
```mermaid
flowchart LR;
subgraph Egress
direction LR
A(Origin Edge region X)-->B(Edge region Y);
B-->C(Viewer region Y)
end
E(Ingress region X)-->A
```
The internal process of spreading data from the origin to edge servers closest to viewers is called *fanout*.
```mermaid
flowchart LR;
subgraph Fanout
direction LR
A(Origin Edge region X)-->B(Edge region Y);
end
B-->C(Viewer region Y)
E(Ingress region X)-->A
```
Our edge egress servers are highly optimized and can handle loads of viewers globally. We have tuned internal communication specifically to achieve low latency while maintaining stability.
The egress nodes have built-in support for serving live thumbnails, allowing you to create live lobbies, channel previews, monitoring boards, and more.
The last step, where the streams are sent from our closest edge servers to the viewers, is called *last-mile*.
```mermaid
flowchart LR;
subgraph Last-mile
direction LR
A(Edge region X)-->B(Viewer region X);
end
C(Origin)-->A
```
#### Players and SDKs
There are plenty of ways to consume Vindral Live streams:
- The [Vindral Web SDK](https://docs.vindral.com/playout/websdk/getting-started.md) - an extensive javascript (with Typescript typings) library, which includes a ready-to-use Player GUI, standalone Google Cast Sender, standalone API client, and more
- [Google Cast receiver](https://docs.vindral.com/playout/websdk/google-cast.md) - one of a few live streaming services with full support for Google Cast receivers (Chromecast, Android TV). Frame-synced metadata events can be sent to companion app/website
- [CDN-hosted player](https://docs.vindral.com/playout/embeddable-player.md) - can be used standalone for fullscreen monitoring or embedded on a website using iframe
- [Native](https://docs.vindral.com/playout/native.md) - the easiest way to consume Vindral in a native app is to wrap the CDN-hosted player within a WebView, which will get you up and running in a few lines of code
- [Live thumbnails](https://docs.vindral.com/playout/fetching-live-thumbnails.md) - great for monitoring and for serving a lobby of different channels
- Any [(LL-)HLS](https://docs.vindral.com/playout/ll-hls.md) (Low latency HLS or regular) compatible player
#### Formats and protocols
- *MoQ* – the default protocol of Vindral Live - a modern low-latency transport protocol, used for all internal communication as well as for egress to viewers. Has a clever fallback mechanism to WebSockets for browsers that do not support WebTransport, with the same features and in most cases the same performance
- *HLS* – used for playback of recordings and live HLS (LL-HLS) in cases where it’s needed, such as Apple Airplay
- *JPEG* – live thumbnails are served as JPEG images
### Customer Portal
The entry point for Vindral is called [Vindral Portal](https://docs.vindral.com/manage/portal.md). Channels, channel groups, auth secrets and settings are managed from here. You'll find analytics for all your channels to view in the browser or to download as CSV files.
### API
Vindral is actively maintained, and improving our APIs is always a top priority for the team. Use the [Management API](https://docs.vindral.com/manage/management-api.md) for integrating Vindral into your own services.
## Channel vs. Stream
The relation between a channel and a stream is not obvious. Let us use water as a reference for explaining:
> A stream is any body of running water that occupies a channel.
> Streams may be permanent or intermittent — occurring only part of the time.
> The channel is always there even if no water runs in it.
A channel can be part of a Channel Group, a logical grouping of channels. Channel groups allow for sharing authorization across channels and enable fast channel switching between them.
```mermaid
flowchart LR;
subgraph Channel Group 1
direction LR
C(Channel 1)
D(Channel 2)
end
A(Source 1)-- Stream 1 ---C;
B(Source 2)-- Stream 2 ---D;
C-->E(Viewers Channel 1);
D-->F(Viewers Channel 2);
```
## On-prem
### Encoding and packaging
[Vindral LivePackager](https://docs.vindral.com/broadcast/broadcast-software/livepackager.md) is a high-performant on-prem encoder that can be used for ingesting streams into Vindral Live and other services. It is a software-based solution that can run on basically any hardware, supports GPU/ASIC offload and is designed to be used in a 24/7 environment. It support muxing, transcoding, and ABR ladder generation. It is a great solution for customers who want to run their own encoder on-prem.
### Video Compositing
For customers requiring a high-end on-prem encoder with support for real-time video compositing, camera switching, chroma key, color correction, live graphics etc, we recommend [Vindral Composer](https://www.vindral.com/composer).
For verticals such as iGaming and other event-driven use cases, Composer is a turn-key solution that provides more features, higher density, lower complexity, and a more cost-efficient solution.
Composer is licensed separately from Vindral Live.
For more information, please visit [vindral.com/composer](https://www.vindral.com/composer) and the [Composer Documentation](https://composer-docs.vindral.com/).
### Third-party solutions
Most on-prem solutions are compatible with Vindral Live. A few examples are:
- [LiveU](https://docs.vindral.com/broadcast/broadcast-hardware/streaming-from-liveu.md) - hardware encoder
- [Blackmagic](https://docs.vindral.com/broadcast/broadcast-hardware/streaming-from-blackmagic.md) - hardware encoder
- [Intinor](https://docs.vindral.com/broadcast/broadcast-hardware/streaming-from-intinor.md) - hardware encoder
- [Elemental](https://docs.vindral.com/broadcast/broadcast-hardware/streaming-from-elemental.md) - hardware encoder
## Technical Deep-Dive
For more information about the protocols, components, and the internal flow within Vindral Live, please [contact us](https://vindral.com/contact/).
---
## Manage
### Advanced Authorization
Guides for advanced authorization, JWT signing, and connecting authenticated players and ingest clients.
## Pages
- [Advanced authorization](https://docs.vindral.com/manage/auth/intro.md): While the default channel access restriction is enough for most users, there might be times when it makes sense to keep a closer watch on who gets access to which channel.
- [Generate and sign JWT's](https://docs.vindral.com/manage/auth/generate-jwt.md): Generate JWTs for channel, channel group, and ingest authorization with TypeScript examples.
- [Connecting using JWT](https://docs.vindral.com/manage/auth/connecting-jwt.md): Pass signed JWT authentication tokens to embedded players, the Web SDK, and RTMP ingest workflows.
---
### Advanced authorization
While the [default channel access](https://docs.vindral.com/manage/channel-access.md) restriction is enough for most users, there might be times when it makes sense to keep a closer watch on who gets access to which channel.
Reasons may include content being non-free, pay-per-view, legal, or geographical restrictions.
JSON Web Tokens (JWT) enable specific access permissions if a more detailed authorization is needed. JWTs can be signed using your *auth secret*, giving access for either [viewing](https://docs.vindral.com/manage/auth/generate-jwt.md#single-channel-auth) a stream or [ingesting](https://docs.vindral.com/manage/auth/generate-jwt.md#authorizing-ingress) a stream, for a limited time, together with the *public key*. Using JWT, it is possible to grant access to a set of channels (a Channel Group) or a specific channel.
> **Caution**
>
> The secret provided for your organization in Vindral Live Portal should never be available to users and only be hosted securely on your own server.
## Configuring auth level
While the default channel access restriction is always active, the additional layer can be toggled on channels and defaults to being `disabled`.
> **Info**
>
> Subscribing to a group will require auth as long as one of its included channels requires auth.
> **Note**
>
> If a channel *without* auth requirements exists in a group where one of the other channels has an auth requirement, it will only require auth when requested together with the group id.
>
> **Example:**
>
> "channel\_1" - requires auth
> "channel\_2" - no auth
> "channel\_3" - no auth
>
> "channel\_group\_a" - channels 1,2,3
> "channel\_group\_b" - channels 2,3
>
> - `channel_group_a` will require auth, as it includes a channel with auth
> - `channel_group_b` will *not* require auth
> - `channel_1` will require auth
> - `channel_2` will *not* require auth when requested on its own `player.vindral.com/?core.channelId=channel_2`
> - `channel_2` will require auth when requested with a group that includes an authed channel `player.vindral.com/?core.channelId=channel_2&core.channelGroupId=channel_group_a`
## JSON Web Token
Vindral Live uses JWTs as a method of authorizing access.
### JSON Web Token format
All JWTs must:
- Contain `version: 2`
- Contain either a `channelId` or `channelGroupId` to define which channel or group you want to grant access to.
- Contain an object named `scope` to define what services you want to grant access to.
Every key in the `scope` object is optional, and omitting a key (e.g. `playout`), means that that scope is **not** granted.
We suggest keeping the scope of your tokens as narrow as possible, to avoid granting users unnecessary access.
`exp` and `nbf` are both optional, but will be validated if included. We recommend that you always use `exp`, as the only way to revoke a token without it is to reset your organization's authentication secret - invalidating all tokens signed with that secret.
An example of the entire format can be found below.
```typescript
{
version: "2",
channelId: "yourchannelid",
channelGroupId: "yourchannelgroupid",
excludedChannels: ["notincludedid"], // Used together with channelGroup to exclude certain channels
scope: {
playout: true, // Allow user to view the live stream
ingest: true, // Allow user to broadcast to the channel
clipping: { // Allow user to view clips between given dates
from: "2024-01-01T00:00:00Z",
to: "2024-01-02T00:00:00Z",
},
},
nbf: 1704063600, // Not before (optional)
exp: 1704150000, // Expiration timestamp (optional)
}
```
#### Legacy tokens
> **Warning**
>
> Tokens without version or tokens with `version: 1` are deprecated. Please consider migrating to the new version to better allow specifying the scope of your tokens.
### Player link builder
If you want to share a link that is valid for a specific time period you can use the player link builder in Vindral Live Portal.
Go to channel details in the portal and navigate to the "Playout" tab. There you can find the "Player link builder" section, in this section you can generate a link with the token and settings for the player.
If you want the link to only work between certain times you can activate authentication and set the "From" and "To" fields to the desired time.
When you have set the desired settings you can copy the link by clicking on it.

### Further reading
More Web SDK examples are available here: [Web SDK documentation](https://docs.vindral.com/web-sdk/api/).
For examples of libraries and more general information regarding JWT, [visit the official JWT information site](https://jwt.io/).
---
### Generate and sign JWT's
### Single channel auth
Example of signing a token using [jsonwebtoken](https://www.npmjs.com/package/jsonwebtoken) in TypeScript for single channel use.
```typescript
import { sign } from "jsonwebtoken"
const expiresAfterSeconds = 60 * 60 * 2
// Get real secret from customer panel interface
const secret = "75442486-0878-440c-9db1-a7006c25a39f"
const authenticationToken = sign(
{
version: 2,
channelId: "yourchannelid",
scope: {
playout: true
},
exp: Math.round(Date.now() / 1000 + expiresAfterSeconds),
},
secret
)
```
### Channel group auth
Signing a token for a channel group is helpful as you may reuse the token for any channel belonging to that group. Here is an example of using [jsonwebtoken](https://www.npmjs.com/package/jsonwebtoken) in TypeScript for giving access to a channel group:
```typescript
import { sign } from "jsonwebtoken"
const expiresAfterSeconds = 60 * 60 * 2
// Get real secret from customer panel interface
const secret = "75442486-0878-440c-9db1-a7006c25a39f"
const authenticationToken = sign(
{
version: 2,
channelGroupId: "yourchannelgroupid",
scope: {
playout: true,
},
exp: Math.round(Date.now() / 1000 + expiresAfterSeconds),
},
secret
)
```
The signed token can be used for any channel authorization within that group.
### Excluding channels within a group
Excluding channels from a group can be a great way of denying access during maintenance or temporary disruptions. Here is an example of using [jsonwebtoken](https://www.npmjs.com/package/jsonwebtoken) in TypeScript for giving access to a channel group but excluding a specific channel within that group:
```typescript
import { sign } from "jsonwebtoken"
const expiresAfterSeconds = 60 * 60 * 2
// Get real secret from customer panel interface
const secret = "75442486-0878-440c-9db1-a7006c25a39f"
const authenticationToken = sign(
{
version: 2,
channelGroupId: "yourchannelgroupid",
excludeChannelIds: "notincludedid",
scope: {
playout: true,
},
exp: Math.round(Date.now() / 1000 + expiresAfterSeconds),
},
secret
)
```
With the above code, the following will not work, as the channel id was excluded according to the claims:
```typescript
const vindral = new Vindral({
authenticationToken: "your_signed_token",
url: "https://lb.cdn.vindral.com",
channelId: "notincludedid", // this channel id was excluded above
})
```
### Authorizing ingress
Adding additional authorization to ingress is useful when providing a secure way of handling multiple broadcasters in custom integration.
Note that you need the correct `scope` part in the claims for allowing ingest of a stream. Also, `channelId` is used instead of the private `streamKey` that is used normally (for ingress without JWT).
Here is an example of signing a token using [jsonwebtoken](https://www.npmjs.com/package/jsonwebtoken) in TypeScript for use with ingress such as RTMP, SRT, or browser-based [MoQ ingest](https://docs.vindral.com/broadcast/moq-ingest/getting-started.md) with the Publisher SDK.
```typescript
import { sign } from "jsonwebtoken"
const expiresAfterSeconds = 60 * 60 * 20
// Get real secret from customer panel interface
const secret = "75442486-0878-440c-9db1-a7006c25a39f"
const authenticationToken = sign(
{
version: 2,
channelId: "yourchannelid",
scope: {
ingest: true,
},
exp: Math.round(Date.now() / 1000 + expiresAfterSeconds),
},
secret
)
```
### Authorizing clipping
Here is an example of signing a token using [jsonwebtoken](https://www.npmjs.com/package/jsonwebtoken) in TypeScript to allow generating clips between two dates.
```typescript
import { sign } from "jsonwebtoken"
const expiresAfterSeconds = 60 * 60 * 20
// Get real secret from customer panel interface
const secret = "75442486-0878-440c-9db1-a7006c25a39f"
const authenticationToken = sign(
{
version: 2,
channelId: "yourchannelid",
scope: {
clipping: {
from: "2024-01-01T00:00:00Z",
to: "2024-01-02T00:00:00Z"
}
},
exp: Math.round(Date.now() / 1000 + expiresAfterSeconds),
},
secret
)
```
---
### Connecting using JWT
## Embedded player
Provide the auth token via query param.
```html
```
## Web SDK
Provide the auth token via options.
```typescript
const vindral = new Vindral({
authenticationToken: "your_signed_token",
url: "https://lb.cdn.vindral.com",
channelId: "your_channel_id",
minBufferTime: 1000, // configures the target buffer time in milliseconds
});
```
A token with only a `channelGroupId` claim will also work as long as the requested channel is part of that group.
## RTMP
Instead of using the `streamKey` for publishing, use the `channelId`, and [a token with ingest permission](https://docs.vindral.com/manage/auth/generate-jwt.md#authorizing-ingress) and pass along the token as `&authToken=`
Examples are provided where you can replace the `` and `` for your specific channel values.
### Example - FFmpeg
`docker run --rm -it jrottenberg/ffmpeg -re -f lavfi -i testsrc="1280x720:rate=25" -f lavfi -i "sine=f=1000:sample_rate=48000, aformat=channel_layouts=stereo" -af "volume=0\:enable=gt(mod(t\, 1)\, 0.1)" -acodec aac -b:a 64k -vcodec libx264 -preset veryfast -tune zerolatency -profile:v baseline -pix_fmt yuv420p -g 25 -f flv "rtmp://rtmp.global.cdn.vindral.com/publish/?authToken="`
### Example - OBS Studio
#### Custom service

#### Vindral service

## SRT
Replace the normal `streamKey` placed in the `streamId` using `r=`, with the `channelId` such as: `r=`.
Add the [token with ingest permission](https://docs.vindral.com/manage/auth/generate-jwt.md#authorizing-ingress) using the key `jwt` so the full `streamId` results in `#!::r=,jwt=,m=publish`
Examples are provided where you can replace the `` and `` for your specific channel values.
### Example - FFmpeg
FFmpeg example using docker image, where you can replace the `` and `` for your specific channel values.
`docker run --rm -it jrottenberg/ffmpeg:8-alpine -re -f lavfi -i testsrc="1280x720:rate=25" -f lavfi -i "sine=f=1000:sample_rate=48000, aformat=channel_layouts=stereo" -af "volume=0\:enable=gt(mod(t\, 1)\, 0.1)" -acodec aac -b:a 64k -vcodec libx264 -preset veryfast -tune zerolatency -profile:v baseline -pix_fmt yuv420p -g 25 -f mpegts 'srt://srt.global.cdn.vindral.com:3333?streamid=#!::r=,jwt=,m=publish'`
### Example - OBS Studio
#### Custom service

## Requesting live thumbnails
Provide the auth token via `auth.token` query param.
`https://lb.cdn.vindral.com/api/thumbnail?channelId=&auth.token=`
A token with only a `channelGroupId` claim will also work as long as the requested channel is part of that group.
## Browser-based ingest
For new browser-based ingest integrations, use [MoQ ingest with the Publisher SDK](https://docs.vindral.com/broadcast/moq-ingest/getting-started.md).
---
### Manage
Learn how to manage your streams and integrate your services via API.
## Pages
- [Advanced Authorization](https://docs.vindral.com/manage/advanced-authorization.md): Guides for advanced authorization, JWT signing, and connecting authenticated players and ingest clients.
- [Live Portal](https://docs.vindral.com/manage/portal.md): The entry point for users of Vindral Live is Vindral Live Portal. LiveCloud customers can visit portal.cdn.vindral.com. Within the Portal, you manage and view information about your channels, channel groups, users, usage, and authentication settings.
- [Channel Access](https://docs.vindral.com/manage/channel-access.md): Understand Vindral channel credentials, stream keys, auth secrets, JWTs, and when to use each access layer.
- [Management API](https://docs.vindral.com/manage/management-api.md): Use the Management API to manage channels, channel groups, ingest settings, analytics, and organization data.
- [Timed metadata](https://docs.vindral.com/manage/timed-metadata.md): Vindral Live supports sending timed metadata, sometimes called cue points or out-of-band data.
- [Webhooks](https://docs.vindral.com/manage/webhooks.md): Webhooks allow your system to receive information about events within your organization as they occur and respond in a way that you define.
- [Hyperlocal](https://docs.vindral.com/manage/hyperlocal.md): The hyperlocal edge is an add on service on top of your Vindral Live account and comes with an additional cost. You can add one or more hyperlocal edges to your account and they can be spread across multiple local networks globally.
- [Digital Rights Management (DRM)](https://docs.vindral.com/manage/drm.md): Digital Rights Management (DRM) is a set of technologies and policies designed to protect copyrighted digital content from unauthorized access, distribution, and piracy. In the context of live video streaming, DRM ensures that only authorized users can view content while preventing activities such as illegal recording, redistribution, or tampering.
- [Two-factor Authentication (2FA)](https://docs.vindral.com/manage/2fa.md): Two-factor authentication (2FA) adds an extra layer of security to your Vindral Live Portal account. It ensures that only authorized users can access the portal by requiring two forms of verification: something you know (like a password) and something you have (like an authentication app or device).
---
### Live Portal
The entry point for users of Vindral Live is Vindral Live Portal. LiveCloud customers can visit [portal.cdn.vindral.com](https://portal.cdn.vindral.com). Within the Portal, you manage and view information about your channels, channel groups, users, usage, and authentication settings.
The access for the customer portal is divided into different roles: Administrator, Channel manager, and User. The different roles provide different levels of access and functionality.
## Dashboard
The Dashboard page gives an excellent overview with near real-time updates of the current state of all your channels, viewers, and geographic info.

## Analytics
Besides the current state, it is often helpful to be able to track performance over time as well. The Analytics page is a comprehensive built-in tool that lets you gain valuable insights about your channels and viewers.
You can filter for date, channel, region, and country. The resulting data is divided into several sections:
- Overview - viewers over time, sessions, average bit rate, and more
- Sessions & Viewer Time - amount of watched minutes and average session length
- Traffic - total ingress/egress and graphs over time, including a comparison to the previous period
- Geography - a heat map of sessions and a table of country sessions
- Devices - OS, browser, and device distribution
- Stability - information about the ingest stability, video keyframe interval and packet arrival delta.

We will continue to add new features and metrics to the Analytics Page.
---
### Channel Access
For managing access to channels, Vindral Live has the following layers:
- `stream key` - used for ingesting live streams and private Channel API endpoints
- `public key` / `channel id` - used for viewing live streams and public Channel API endpoints
- `auth secret` - used for signing auth token
- `jwt` / `auth token` - used for authorizing
- `channel group id` - used alongside the channel id for viewing live streams or independently for accessing public Channel API endpoints
This information can be found in the [Vindral Portal](https://portal.cdn.vindral.com/).
> **Caution**
>
> Think **twice** before sharing your *stream key* or *auth secret* token with anyone! With the *stream key*, they will be able to ingest content into your channel.
## Ingress authorization
The standard ingress authorization is via the `stream key`.
It is a GUID made up of organization, channel name, and a GUID. In most cases, this is enough level of authorization.
Example for RTMP ingress: `rtmps://rtmp.eu-west.cdn.vindral.com/publish/company_channel1_sk_ad00bcc5-6078-4319-b964-a04cf067af85`
## Access authorization
The standard access authorization is done via the `public key`, also called `channel id`.
It is a GUID made up of organization, channel name, and a GUID. No one will be able to guess the GUID. In most cases, this is enough protection as it is unlikely that anyone without access to the stream will be able to guess the GUID.
Example for an embedded player: `https://player.vindral.com/?core.channelId=company_channel1_ci_d0871b2a-dd19-4cb1-95ec-b944450ff200`
## Advanced authorization
If a more detailed authorization is needed, JSON Web Tokens (JWT) enable specific access permissions. JWTs can be signed using your *auth secret*, giving access for either viewing a stream or ingesting a stream, for a limited time, together with the *public key*. Using JWT, it is possible to grant access to a set of channels (a Channel Group) or a specific channel.
[Read more about advanced authorization](https://docs.vindral.com/manage/auth/intro.md).
## Geographical access limitation
In the Portal, you may limit access to a channel by denying (or allowing) specific countries, a handy feature if you have content that needs to be restricted due to, e.g., legal reasons.
By default, all channels are open to all countries.
[See the Management API channel update section](https://docs.vindral.com/manage/management-api.md) for information on programmatically setting geographical limitations.
## Channel group
A Channel Group is a logical grouping of channels that allows for shared authorization and fast channel switching. This is particularly useful for scenarios where users need to quickly switch between multiple streams without re-authenticating.
---
### Management API
The Management API allows you to integrate Vindral into your systems. With the API you can you can mange your channels and channel groups. You can also get lots of information such as:
- Transcoding profiles
- User profile
- Ingest information for a channel
- Status for all channels, including live status, current viewers, current ingress bitrate and current egress bitrate.
- Analytics data such as amount of viewers and sessions, total egress and ingress bytes, viewer device information and much more.
[Read the API reference](https://docs.vindral.com/management-api) for in-depth information on what you can do with the API or test it with swagger [here](https://api.cdn.vindral.com/api-docs).
## API Keys
To access the API you need an account in the Vindral Portal and then create an API Key. The API Key used for authentication is tied to a user and shares the permissions of that user which is configured in the Vindral Portal. In addition to the user level permissions each API key has a scope of either read-only or read-write.
### Create an API Key
1. Log in to the Vindral Portal.
2. Go to `Your profile`.
3. Click on the `API Keys` tab.
4. Click on the `New` button.
5. Enter a name for the API Key and optional notes.
6. Select the scope of the API Key.
7. Click on the `Create` button.
8. Copy the API Key and store it in a safe place, it will not be shown again.
### Permissions
Your user can have one of three roles in the Vindral Portal: Administrator, Channel Manager or User. The role determines what permissions you have in the Vindral Portal and what permissions your API Key will have. You can see what role you have in organizations on you user profile page. If your user is a member of multiple organizations the API keys will have the permissions to all organizations.

The tables below specify the set of permissions associated with each role. For API Keys with read-only scope Create/Update/Delete is always forbidden.
#### Administrator
| Entity | Read | Create | Update | Delete |
| ------------- |------------- |------------- |------------- |------------- |
| **Channel** | Yes | Yes | Yes | Yes |
| **Channel Group** | Yes | Yes | Yes | Yes |
| **Transcoding Profiles** | Yes | No | No | No |
| **Profile** | Yes | - | - | - |
| **Ingest** | Yes | - | - | - |
| **Status** | Yes | - | - | - |
| **Analytics** | Yes | - | - | - |
#### Channel Manager
| Entity | Read | Create | Update | Delete |
| ------------- |------------- |------------- |------------- |------------- |
| **Channel** | Yes | Yes | Yes | Yes |
| **Channel Group** | Yes | Yes | Yes | Yes |
| **Transcoding Profiles** | Yes | No | No | No |
| **Profile** | Yes | - | - | - |
| **Ingest** | Yes | - | - | - |
| **Status** | Yes | - | - | - |
| **Analytics** | Yes | - | - | - |
#### User
| Entity | Read | Create | Update | Delete |
| ------------- |------------- |------------- |------------- |------------- |
| **Channel** | Yes | No | No | No |
| **Channel Group** | Yes | No | No | No |
| **Transcoding Profiles** | Yes | No | No | No |
| **Profile** | Yes | - | - | - |
| **Ingest** | Yes | - | - | - |
| **Status** | Yes | - | - | - |
| **Analytics** | Yes | - | - | - |
---
### Timed metadata
Vindral Live supports sending timed metadata, sometimes called cue points or out-of-band data.
The data is sent as raw text and can be anything from JSON data to *Unix timestamps*. When received by the CDN, it is tagged with a timestamp and emitted client-side when the corresponding frame is shown on the screen (or audio is played, for audio-only streams). Use timed metadata to build frame-synchronized experiences within web pages, mobile applications, and second-screen setups.
When activated on your account, you will receive an API endpoint for your metadata ingestion.
## How to send timed metadata
Metadata is by default tagged with the timestamp of the frame being handled when received. This means that depending on ingest RTT, metadata request RTT, and potential jitter, the metadata may be a few frames off. If you experience a high diff, you should consider [tagging the metadata explicitly with a timestamp](#setting-timestamp-explicitly).
Metadata is sent using HTTP POST:
`https://metadata.global.cdn.vindral.com/api/timed-metadata/`.
### CURL example
A simple example of metadata ingestion using curl. Replace `` with the channel stream key found in the Portal:
```bash
curl -XPOST https://metadata.global.cdn.vindral.com/api/timed-metadata/ -d "my raw message" -vvv
```
### Javascript fetch example
A simple example of metadata ingestion using javascript fetch. Replace `` with the channel stream key found in the Portal:
```javascript
const data = { meaningOfLife: "42" };
fetch("https://metadata.global.cdn.vindral.com/api/timed-metadata/", {
method: "POST",
body: JSON.stringify(data),
})
.then(data => {
console.log("Success: ", data);
})
.catch((error) => {
console.log("Error: ", error);
});
```
### Setting timestamp explicitly
Vindral Live passes through the origin stream's timestamp. If you are in control of the flow and want to mark a metadata with a specific timestamp, you may do so by adding `?timestamp=`. If the timestamp is set to a lower value than what the viewer is playing, it is triggered immediately. Format of timestamp is in milliseconds (integer).
Example using curl with a specific timestamp:
```shell
curl -XPOST https://metadata.global.cdn.vindral.com/api/timed-metadata/?timestamp= -d "my raw message" -vvv
```
Note that all timed-metadata will trigger after a maximum of 5 seconds, even if sent with a further away future timestamp. Due to the ultra-low latency nature of Vindral Live, more extended event timeouts usually do not make sense. If you need to achieve longer timeouts or deactivate timeout entirely, reach out, and we will set it up for you.
## Use cases
Timed metadata fits any case where the user interface should be synchronized with what is shown in the stream.
For instance, you would not want your blackjack card to appear in the GUI before it is shown in the stream. Or vice versa.
Syncing the interface to the stream is key to a better experience for the viewer.
## Alternative method
Since Vindral Live supports using a fixed buffer length for all viewers, the latency is known beforehand. This means it is also possible to offset your metadata events by that known number.
Depending on your infrastructure, this method might be more straightforward and only requires using your fixed buffer (1500 ms by default) or reading the value from the Vindral instance `vindralInstance.playbackLatency`.
```javascript
// pseudo javascript code
myServiceSocket.onMessage(message => {
setTimeout(() => {
handleMyMessage(message)
}, 1500) // or vindralInstance.playbackLatency
})
```
While not being frame accurate, it should be pretty much in sync and, in worst cases, around `+-200ms`. Good enough for most use cases.
## Server wallclock time
If you depend on client devices being in sync, using an external backend source is often necessary.
Vindral Live has a built-in feature that emits the server wallclock time every second and can be used to sync viewer experiences outside of the video.
While not frame-accurate as [explicitly setting timestamp](#setting-timestamp-explicitly), it is easy to sync the user interface against external data sources.
See the [wallclock section](https://docs.vindral.com/playout/websdk/timed-metadata.md#server-wallclock-time) for an example on how to listen.
## Listening to metadata events
On the [Web SDK timed metadata documentation](https://docs.vindral.com/playout/websdk/timed-metadata.md) page, you will find examples of how to listen to the metadata event in the Web SDK.
---
### Webhooks
Webhooks allow your system to receive information about events within your organization as they occur and respond in a way that you define.
Vindral Live uses HTTP POST to send webhook events to your system as a JSON payload. The payload contains information about the event, such as the event type and the data associated with the event.
## Enable Webhooks
You can enable and configure your webhooks in the Vindral Portal. Navigate to the following URL to access the webhooks settings: [Vindral Portal](https://portal.cdn.vindral.com/settings/webhooks)
Here, you can add a new webhook by providing a callback URL where the webhook events will be sent.
## Channel events
Channel events are specific occurrences related to a channel within your organization. Currently, we support the following events:
- `channel.ingest.started`
- `channel.ingest.stopped`
When such an event occurs, a HTTP POST payload is sent to the webhook's configured URL endpoint.
### Delivery headers
HTTP POST payloads that are delivered to your webhook's configured URL endpoint will contain a signature header `x-signature`.
This is the HMAC hex digest of the request body, and is generated using the SHA-256 hash function and the secret as the HMAC key.
#### Verifying x-signature
To verify the `x-signature` in Node.js, you can use the `crypto` module's `createHmac` method.
Here's an example:
```typescript
const crypto = require('crypto')
// Get real secret from Vindral Portal
const secret = "1e265b0d-0ba2-4672-960c-cbfb9a02e003"
function verifySignature(req) {
const signature = req.headers['x-signature']
const calculatedSignature = crypto
.createHmac("sha256", secret)
.update(JSON.stringify(req.body))
.digest("hex")
return crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(calculatedSignature))
}
```
### Event payload
Here's an example of a channel event payload:
```json
{
"id": "75db6597-579c-4e0b-8183-6ea9a45c0e6e",
"version": 1,
"event": "channel.ingest.started",
"timestamp": "2023-12-01T07:42:54.063Z",
"data": {
"channelId": "vindral_demo1_ci_099ee1fa-80f3-455e-aa23-3d184e93e04f",
"sessionId": "e2f0dcfb-9931-4a33-9354-f5d00e89b3ba"
}
}
```
- `id` - A unique identifier for the event.
- `version` - The version of the event payload structure.
- `event` - The type of event that occurred. This can be either `channel.ingest.started` or `channel.ingest.stopped`, indicating the start and stop of the ingest process respectively.
- `timestamp` - The time when the event occurred, in ISO 8601 format.
- `data` - An object containing additional data about the event.
- `channelId` - Identifier of the channel related to the event.
- `sessionId` - Each ingest session will have its own `sessionId`, which allows you to correlate a `channel.ingest.started` event with the corresponding `channel.ingest.stopped` event.
## Handling Webhook Failures
If a webhook delivery fails, we will retry the delivery up to three times. If all retries fail, no further delivery attempts will be made. The resent event will have the same id as the original event. This allows you to identify and ignore duplicate events, preventing the same event from being processed multiple times
---
### Hyperlocal
The hyperlocal edge is an add on service on top of your Vindral Live account and comes with an additional cost. You can add one or more hyperlocal edges to your account and they can be spread across multiple local networks globally.
Hyperlocal Edge is a solution designed to optimize network performance during events or similar situations. It provides edge egress on a local network for your channels, thereby helping to avoid saturating the public network. This ensures smooth streaming and reduces latency, enhancing the user experience.
To set up a Hyperlocal Edge, you need to contact us so we can provide you with the necessary software. Once you have the software, you can install it on the server in your local network and configure it to work with your Vindral account.
## Getting Started
1. **Contact Vindral Support**: Reach out to our support team, via "Contact support" in Portal or [contact form](https://vindral.com/contact), to request access. Based on info about your local network environment, our team will prepare and provide you with the necessary software and instructions.
2. **Install Software**: Follow the provided instructions to install the Hyperlocal Edge software on your local server(s). Everything needed for installation will be included. Runs in Docker with modest hardware requirements.
3. **Configure**: The hyperlocal edge(s) are configured in the Portal for you organization, see [Configure](#configure) below.
4. **Verify**: Once configured, verify the setup to ensure it is functioning correctly and optimizing your network performance as expected.
**The Vindral support team is available to assist you during this process.**
## Configure
You can see your hyperlocal edge setup in the [Vindral Portal](https://portal.cdn.vindral.com/settings/hyperlocal). Simply navigate to your organization settings and find the **Hyperlocal** tab.

### Hyperlocal Edge
Input your Domain Name and external IP address for your Hyperlocal Edges in the provided fields.

If desired, you can also utilize an IP CIDR range, as illustrated below:

### Hyperlocal Api Key
The API key is used in the configuration of each hyperlocal edge to enable secure communication with the Vindral API.
## Verify Hyperlocal Edge
To verify that your Hyperlocal Edge is working correctly, you can start a live stream on the organization that has the Hyperlocal Edge configured. You can then open the Vindral QoS player and check the **Edge URL** field in the **Connection** section. If the Hyperlocal Edge is working correctly, the URL should match the one configured in the Vindral Portal.

## Browser Considerations
### Chrome Local Network Access Restrictions
Starting with Chrome 142, Chrome prompts users before a web page can connect to devices on the local network. Chrome 147 extends this to WebSocket and WebTransport connections. When a Vindral player embedded in your web app connects to a Hyperlocal Edge on the local network, end users may see a permission prompt before playback can start.
For end users, clicking **Allow** on the prompt is sufficient and is remembered per site.
For managed deployments where the prompt should be suppressed, IT administrators can pre-grant the permission using Chrome's [`LocalNetworkAccessAllowedForUrls`](https://chromeenterprise.google/policies/local-network-access-allowed-for-urls/) enterprise policy. The policy takes the origin of the **web page hosting the player** (for example `https://app.example.com`), not the local IP of the Hyperlocal Edge.
We also recommend including `https://*.vindral.com` in the allowlist so that Vindral-hosted troubleshooting tools (such as the QoS player) can reach your Hyperlocal Edge without triggering the prompt.
Other Chromium-based browsers (Microsoft Edge, Brave, Opera, Arc, and others) inherit the same restriction and the same policy. Firefox and Safari do not currently enforce Local Network Access checks.
---
### Digital Rights Management (DRM)
Digital Rights Management (DRM) is a set of technologies and policies designed to protect copyrighted digital content from unauthorized access, distribution, and piracy. In the context of live video streaming, DRM ensures that only authorized users can view content while preventing activities such as illegal recording, redistribution, or tampering.
DRM systems work by encrypting video content and enforcing playback restrictions through license management. These licenses define how, where, and when content can be accessed, taking into account factors like user authentication, geographic restrictions, and device compatibility. Vindral Live supports Google Widevine, Apple FairPlay, and Microsoft PlayReady, ensuring DRM compatibility across almost all devices, including desktops, mobile phones, smart TVs, and streaming devices.
To facilitate DRM license management, Vindral Live provides DRM support through [EZDRM](https://www.ezdrm.com/) or [Irdeto](https://irdeto.com/), two leading DRM service providers that offer cloud-based solutions for handling license distribution and content protection.
## Device support
Vindral Live supports CBCS, a widely used encryption mode for DRM-protected content. CBCS is required for Apple FairPlay DRM and is also compatible with Google Widevine and Microsoft PlayReady on many platforms. This ensures secure playback across a broad range of devices, including iOS devices, macOS, Apple TV, Android, Windows, and Smart TVs.
While CENC is not natively supported by Vindral, it may be possible to enable it in certain scenarios depending on the specific DRM provider and playback environment.
**Note:** For iOS version 16 and below, DRM support is only possible via HLS. See [LL-HLS](https://docs.vindral.com/playout/ll-hls.md#drm) for more information.
## Enabling DRM
Please contact us and we will help you get started.
### Apple FairPlay
To use Apple FairPlay DRM, customers must obtain a FairPlay Streaming (FPS) deployment package from Apple. This process includes applying for a server certificate, which is required to encrypt and deliver FairPlay-protected content. Apple issues this certificate only to approved content owners or distributors. Customers need to complete Apple’s application process and agree to the necessary licensing terms before integrating FairPlay DRM into their streaming workflow.
See instructions [here](https://developer.apple.com/streaming/fps/)
### Client integration
Integrating DRM into a client application depends on the chosen DRM service provider. Vindral Live supports DRM through Irdeto and EZDRM, each requiring different approaches for license acquisition and playback.
#### Irdeto
Irdeto requires an authorization token to be included as an authorization header in every license server request. Below are minimal examples of how to add it to your Vindral Live integration.
##### Core SDK
```javascript
...
const instance = new Vindral({
...
drm: {
headers: {
"Authorization: Bearer" : "Authorization token goes here",
},
}
})
...
```
[Full documentation for using the Core SDK](https://docs.vindral.com/playout/websdk/getting-started.md#core-sdk)
##### Vindral Player
```html
```
[Full documentation for using the Vindral Player](https://docs.vindral.com/playout/websdk/vindral-player.md)
#### EZDRM
EZDRM requires a user ID to be passed as a query parameter in every license server request. Below are minimal examples of how to add it to your Vindral Live integration.
##### Core SDK
```javascript
...
const instance = new Vindral({
...
drm: {
...
queryParams: {
"user_id": "User ID goes here",
}
}
})
...
```
[Full documentation for using the Core SDK](https://docs.vindral.com/playout/websdk/getting-started.md#core-sdk)
##### Vindral Player
```html
```
[Full documentation for using the Vindral Player](https://docs.vindral.com/playout/websdk/vindral-player.md)
## Advanced Configuration
### DRM Robustness Settings
Robustness levels can be configured for both Widevine and PlayReady DRM systems. By default, Vindral always tries to use the highest available robustness level on the device. However, if you need to override this behavior and force the use of a lower robustness level (for instance, to ensure compatibility with specific devices or environments), you can configure these settings explicitly.
#### Core SDK
```javascript
const instance = new Vindral({
...
drm: {
...
playready: {
videoRobustness: ["150"],
audioRobustness: ["150"],
},
widevine: {
videoRobustness: ["SW_SECURE_CRYPTO"],
audioRobustness: ["SW_SECURE_CRYPTO"],
},
}
})
```
#### Player SDK
```html
```
---
### Two-factor Authentication (2FA)
Two-factor authentication (2FA) adds an extra layer of security to your Vindral Live Portal account. It ensures that only authorized users can access the portal by requiring two forms of verification: something you know (like a password) and something you have (like an authentication app or device).
## Enabling 2FA
To enable 2FA, log in to the Vindral Live Portal and navigate to your account profile under [Password & Authentication](https://portal.cdn.vindral.com/profile/password). Here, you can enable, configure, or disable 2FA for your account.

In the [Password & Authentication](https://portal.cdn.vindral.com/profile/password) section, locate the option to enable two-factor authentication. Follow the on-screen instructions to set up your preferred authentication method, such as an authentication app.

Once 2FA is enabled, you will need to enter a verification code each time you log in to the Vindral Live Portal.

## Actions Requiring 2FA
Certain actions within the Vindral Live Portal require 2FA verification for added security. These include:
- Disabling 2FA
- Configuring 2FA
- Changing your password
- Resetting your password using a reset token
---
## Broadcast
### Broadcast Software
Many software applications are easy to use and have full RTMP or SRT support. These are commonly used among our customers.
## Pages
- [LivePackager](https://docs.vindral.com/broadcast/broadcast-software/livepackager.md): This software is used by Vindral LiveEngine as our internal component for ingress, encoding, transcoding, and packaging. It is a powerful tool for ingesting and packaging live streams, and it can be used in conjunction with Vindral LiveEngine or as a standalone component.
- [Composer](https://docs.vindral.com/broadcast/broadcast-software/composer.md): Vindral Composer is a real-time video compositing software for event-driven video compositing, color correction, chroma-key, visual effects, and live streaming. Designed to guarantee authentic live casino experiences at 24/7 large-scale operations, Composer runs any number of video sources, visual effects, compositions/layers, and outputs, with lossless processing without frame drops.
- [Streaming from OBS](https://docs.vindral.com/broadcast/broadcast-software/streaming-from-obs.md): OBS (Open Broadcaster Software) is free and open-source software for video recording and live streaming. Getting started is easy, and in this guide, we will show how to configure OBS for ingesting RTMP into Vindral.
- [Streaming from FFmpeg](https://docs.vindral.com/broadcast/broadcast-software/streaming-from-ffmpeg.md): FFmpeg is a powerful open-source multimedia framework that can decode, encode, transcode, mux, demux, stream, filter, and play almost anything that humans and machines have created.
- [Streaming from Wirecast](https://docs.vindral.com/broadcast/broadcast-software/streaming-from-wirecast.md): Wirecast is a popular application used for live broadcasting. It is a proprietary and paid product available as a free trial.
---
### LivePackager
This software is used by Vindral LiveEngine as our internal component for ingress, encoding, transcoding, and packaging. It is a powerful tool for ingesting and packaging live streams, and it can be used in conjunction with Vindral LiveEngine or as a standalone component.
- Deploy on-prem or in-cloud, with or without hardware offload (GPUs, ASICs).
- Receives live streams and packages them for delivery.
- Built-in monitoring and API for control.
- Supports multiple codecs & protocols, including Media over QUIC (MoQ), SRT, AV1, opus, and RTMP.
- A strong software alternative to Elemental encoders and other hardware encoders.
- Can act as a media gateway/proxy.
## Operation
When using LiveCloud or a full installation of LiveEngine, the packager is automatically launched during stream ingestion and verification. This process is fully automated and requires no user intervention.
For standalone cases, the packager can be run via Docker, with configuration options available for SDI, MPEG-TS, NDI, and other input types. Configuration can be managed through configuration files, the API, or a graphical user interface (GUI).
For more information on how to set up your encoder, requirements, or if you'd like to give LivePackager a try, please [contact us](https://vindral.com/contact/).
## API and monitoring
The LivePackager includes a built-in API and monitoring system. This allows you to control the packager, monitor its performance, and receive real-time metrics about the streams being processed.
Use Grafana to set up alerts on specific events, such as stream failures or performance issues, to ensure that your live streams are always running smoothly.
The API can be used to start and stop streams, configure settings, and retrieve information about the current state of the packager.
## Internals
### Protocol flow example
Below is an example of how the LivePackager can be used to receive streams from different sources and package them for delivery to Vindral LiveEngine, CDN, or other third-party services.
```mermaid
---
title: Vindral LivePackager protocol flow example
---
flowchart TD
S_SDI(Source)
S_MPEGTS(Source)
S_RTP(Source)
S_NDI(Source)
S_RTSP(Source)
S_ST2110(Source)
S_FILE(Source)
S_RTMP(Source)
S_SRT(Source)
S_MOQ(Source)
Packager("Vindral LivePackager")
S_SDI--SDI---->Packager
S_MPEGTS--MPEGTS---->Packager
S_RTP--RTP---->Packager
S_NDI--NDI---->Packager
S_RTSP--RTSP---->Packager
S_ST2110--ST2110---->Packager
S_FILE--File---->Packager
S_RTMP--RTMP---->Packager
S_SRT--SRT---->Packager
S_MOQ--MoQ---->Packager
Packager--MoQ--->VLE("Vindral Live")
Packager--HLS--->ThirdPartyHLS("CDN")
Packager--RTMP--->ThirdPartyRTMP("Youtube / Facebook / Twitch / etc")
Packager--MPEGTS--->ThirdPartyMPEGTS("Local network")
```
### SRT-RTMP gateway
Below is an example of how the LivePackager can be used to receive an SRT stream and proxy it to multiple RTMP endpoints.
```mermaid
---
title: Vindral LivePackager SRT-RTMP gateway example
---
flowchart LR
S_SRT(Source)
Packager("Vindral LivePackager")
S_SRT--SRT---->Packager
Packager--RTMP--->Sink1("Youtube")
Packager--RTMP--->Sink2("Facebook")
Packager--RTMP--->Sink3("Twitch")
```
### SDI source, encode + CC via MPEG-TS
Below is an example of how LivePackager can be used to handle an SDI video source alongside a separate MPEG-TS source for closed captions.
In this workflow:
- The SDI source is transcoded and packaged for delivery to Vindral LiveEngine.
- An HLS stream is generated for recording to an S3 bucket.
- The closed captions from the MPEG-TS source are integrated into the MoQ output, along with an adaptive bitrate ladder.
- The packaged stream is simultaneously delivered to a third-party RTMP service (e.g., YouTube).
- Local playback is supported via MoQ, using a player such as the Live Player.
```mermaid
---
title: Vindral LivePackager internal media flow example
---
flowchart LR
S_SDI(Source)
S_MPEGTS("Closed Captions")
subgraph LivePackager
direction LR
SS(Source)
TT(Transcode)
PP(Package)
SI(Sink)
SS-->TT
TT-->PP
SS-->PP
PP-->SI
end
S_SDI--SDI---->SS
S_MPEGTS--MPEGTS---->SS
SI--MoQ--->VLE("Vindral Live")
SI--HLS--->Recording("Recording S3 bucket")
SI--RTMP--->ThirdPartyRTMP("Youtube")
SI--MoQ--->LocalNetwork("Local Vindral MoQ playback")
```
### Multi-source, multi-audio, ABR via MPEG-TS
Below is an example of how LivePackager can be used to handle multiple MPEG-TS video sources at different bitrates, along with multiple MPEG-TS audio sources in various languages or with audio description tracks.
In this setup:
- No transcoding is required — LivePackager simply packages the incoming streams.
- An HLS stream is created for recording to an S3 bucket.
- Multiple audio tracks are preserved and included in the MoQ output, alongside the already-encoded adaptive bitrate ladder.
- The packaged streams are also delivered to a third-party RTMP service (e.g., YouTube).
- Local playback is enabled via MoQ, using a player such as the Live Player.
```mermaid
---
title: Vindral LivePackager internal media flow without transcode example
---
flowchart LR
S_MPEGTS_1080(Source 1080p @5Mbps)
S_MPEGTS_720(Source 720p @2Mbps)
S_MPEGTS_540(Source 540p @1Mbps)
S_MPEGTS_360(Source 360p @400Kbps)
S_MPEGTS_AUDIO_1(Source English AAC @96Kbps)
S_MPEGTS_AUDIO_2(Source Spanish AAC @96Kbps)
S_MPEGTS_AUDIO_3(Source Desc AAC @96Kbps)
subgraph LivePackager
direction LR
SS(Source)
PP(Package)
SI(Sink)
SS-->PP
PP-->SI
end
S_MPEGTS_1080--MPEGTS---->SS
S_MPEGTS_720--MPEGTS---->SS
S_MPEGTS_540--MPEGTS---->SS
S_MPEGTS_360--MPEGTS---->SS
S_MPEGTS_AUDIO_1--MPEGTS---->SS
S_MPEGTS_AUDIO_2--MPEGTS---->SS
S_MPEGTS_AUDIO_3--MPEGTS---->SS
SI--"MoQ (ABR + multi-audio)"--->VLE("Vindral Live")
SI--(HLS (1080p + English AAC))--->Recording("Recording S3 bucket")
SI--"RTMP (1080p + English AAC)"--->ThirdPartyRTMP("Youtube")
SI--"MoQ (ABR + multi-audio)"--->LocalNetwork("Local Vindral MoQ playback")
```
## Performance
The entire component is built using high-performance Rust code, with a focus on low latency, high throughput, and 24/7 stability.
Utilize the hardware offload support (GPUs and ASICs) to increase channel quality and achieve predictable performance.
### NVIDIA GPUs
Offloading encoding tasks to NVIDIA GPUs is the most common setup for LivePackager installations. Our system supports:
- Automatic load balancing and real-time metrics
- Deinterlacing, scaling, and support for 4K and 8K video
- AV1 encoding on 8th-generation GPUs and newer
- AV1 decoding on 7th-generation GPUs and newer
### Netint ASICs
Netint delivers reliable ASIC solutions for offloading video encoding. Our integration with Netint offers:
- Automatic balancing and real-time performance metrics
- Scaling capabilities and 4K/8K support
- AV1 encoding support starting with the Quadra generation and newer
- Up to 64x 1080p30 simultaneous streams per ASIC (Quadra T2A)
### Intel GPUs and iGPUs
Although less common than NVIDIA and Netint setups, Intel GPUs provide impressive performance and are fully supported:
- 4K and 8K support
- AV1 encoding support on Gen 12+ / ARC A-series
- AV1 decoding support starting from Gen 11+ / ARC series and newer
### AMD GPUs and iGPUs
While AMD offloading is less frequently used compared to NVIDIA, Netint, and Intel, it is supported:
- AV1 encoding support for the Alveo MA35D platform
- 8K support for the Alveo MA35D platform
## Next steps
If you'd like to know more about LivePackager, please [contact us](https://vindral.com/contact/).
---
### Composer
Vindral Composer is a real-time video compositing software for event-driven video compositing, color correction, chroma-key, visual effects, and live streaming. Designed to guarantee authentic live casino experiences at 24/7 large-scale operations, Composer runs any number of video sources, visual effects, compositions/layers, and outputs, with lossless processing without frame drops.
Read more about its features at [vindral.com/composer](https://www.vindral.com/composer).
## Getting started
Composer is compatible with Vindral Live. Set RTMP URL (including the *stream key*) to your designated Vindral Live ingress. Study our [general guidelines](https://docs.vindral.com/broadcast/broadcast-guidelines.md#general-recommendations) to avoid streaming pitfalls.
For more information about how to use it, please read the [Vindral Composer documentation](https://composer-docs.vindral.com/) or [contact us](https://vindral.com/contact/) for more information.
---
### Streaming from OBS
OBS ([Open Broadcaster Software](https://obsproject.com/)) is free and open-source software for video recording and live streaming. Getting started is easy, and in this guide, we will show how to configure OBS for ingesting RTMP into Vindral.
## Configuring OBS
Note that the below configuration is only an example. Depending on the hardware, it is possible to configure OBS in many ways.
### Stream Settings
Select Vindral in the Service dropdown or use a custom RTMP output with your designated Vindral Live ingest server and your private Stream Key.
[](https://docs.vindral.com/img/guides/broadcast-software/obs-stream.png)
*stream settings*
### Output settings
There will be different Output settings depending on the encoder chosen.
#### x264
x264 is a very capable software encoder. We recommend using x264 if you have no GPU/Asics accelerated encoders such as NVENC, QuickSync, or NetInt.
Set Output Mode to `Advanced`
- Encoder - `x264`
- Rate Control - `CBR`
- Bitrate - `2000`
- Use Custom Buffer Size - `not set / unchecked`
- Keyframe Interval - `1`, set to 1 or 2 seconds (for faster channel switching, lower value is preferred)
- CPU Usage Preset - `veryfast`
- Profile - `baseline`
- Tune - `zerolatency`
- x264 options - `bframes=0`
[](https://docs.vindral.com/img/guides/broadcast-software/obs-output.png)
*x264 ouput options*
#### nvenc
Nvidia NVENC is a hardware-accelerated encoder.
Set Output Mode to `Advanced`
- Encoder - `nvenc`
- Rate Control - `CBR`
- Bitrate - `2000`
- Keyframe Interval - `1`, set to 1 or 2 seconds (for faster channel switching, a lower value is preferred)
- Preset - `Performance`, depending on load, you might be able to use `Quality`
- Profile - `baseline`
- Look-ahead - `not set / unchecked`
- Psycho Visual Tuning - `not set / unchecked`
- GPU - `0` (or the index of the GPU of your choice)
- Max B-frames - `0`
[](https://docs.vindral.com/img/guides/broadcast-software/obs-output-nvenc.png)
*nvenc ouput options*
#### Quicksync H264
Many Intel CPUs have a built-in GPU (iGPU) with a hardware-accelerated encoder chip.
Set Output Mode to `Advanced`
- Encoder - `Quicksync H264`
- Rate Control - `CBR`
- Bitrate - `2000`
- Target Usage - `balanced`
- Profile - `baseline`
- Keyframe Interval - `1`, set to 1 or 2 seconds (for faster channel switching, a lower value is preferred)
- Latency - `low`
- B Frames - `0`
[](https://docs.vindral.com/img/guides/broadcast-software/obs-output-quicksync.png)
*quicksync ouput options*
#### Audio output
Audio settings will not impact latency and stability as much as video settings. Configure a sensible audio bitrate, usually around 96-160 depending on the content.
[](https://docs.vindral.com/img/guides/broadcast-software/obs-output-audio.png)
*audio ouput options*
### Video settings
We recommend using 30 FPS or less for most live streams. Configure the resolution as needed.
[](https://docs.vindral.com/img/guides/broadcast-software/obs-video.png)
*video settings*
### Streaming
When streaming, verify that the status light is green. If it is any other color, something is wrong. Potential causes for this include a jittery connection and encoding performance drops.
If the ingest status is unstable, all viewers could get a bad experience.
[](https://docs.vindral.com/img/guides/broadcast-software/obs-streaming.png)
*streaming settings*
---
### Streaming from FFmpeg
FFmpeg is a powerful open-source multimedia framework that can decode, encode, transcode, mux, demux, stream, filter, and play almost anything that humans and machines have created.
It does not have a graphical user interface like OBS or Wirecast. However, it is extremely powerful and flexible, making it a popular choice for advanced users and developers.
## FFmpeg examples
To stream to Vindral Live using FFmpeg and RTMP, you can use the following command (make sure to replace `` with your actual stream key):
```bash
ffmpeg -re -f lavfi -i "testsrc=size=1280x720:rate=25" -f lavfi -i "sine=frequency=440:sample_rate=48000, aformat=channel_layouts=stereo" -vcodec libx264 -preset veryfast -tune zerolatency -profile:v baseline -pix_fmt yuv420p -g 25 -acodec aac -b:a 64k -f flv rtmps://rtmp.global.cdn.vindral.com/publish/
```
This command generates a test video and audio stream using FFmpeg's built-in `testsrc` and `sine` filters, encodes the video with H.264 and the audio with AAC, and streams it to the specified RTMP URL.
**Test easily by using docker:**
```bash
docker run --rm -it jrottenberg/ffmpeg -re -f lavfi -i "testsrc=size=1280x720:rate=25" -f lavfi -i "sine=frequency=440:sample_rate=48000, aformat=channel_layouts=stereo" -vcodec libx264 -preset veryfast -tune zerolatency -profile:v baseline -pix_fmt yuv420p -g 25 -acodec aac -b:a 64k -f flv rtmps://rtmp.global.cdn.vindral.com/publish/
```
**Docker example using SRT:**
```bash
docker run --rm -it jrottenberg/ffmpeg:4.4-centos -re -f lavfi -i "testsrc=size=1280x720:rate=25" -f lavfi -i "sine=frequency=440:sample_rate=48000, aformat=channel_layouts=stereo" -vcodec libx264 -preset veryfast -tune zerolatency -profile:v baseline -pix_fmt yuv420p -g 25 -acodec aac -b:a 64k -f mpegts 'srt://srt.global.cdn.vindral.com:3333?streamid=#!::r=,m=publish'
```
---
### Streaming from Wirecast
[Wirecast](https://www.telestream.net/wirecast/) is a popular application used for live broadcasting. It is a proprietary and paid product available as a free trial.
## Configuring Wirecast
Like [OBS](https://docs.vindral.com/broadcast/broadcast-software/streaming-from-obs.md), Wirecast offers many configuration options.
The following is a common example configuration:
- Encoder - `x264`, `nvenc` or `Quicksync H264`
- Rate Control - `CBR`
- Bitrate - `2000`
- No buffer
- Keyframe Interval - `1`, set to 1 or 2 seconds (for faster channel switching, lower value is preferred)
- CPU Usage Preset - `veryfast`
- Profile - `baseline`
- Tune - `zerolatency`
- B-frames - `0` / `disabled`
---
### Broadcast Hardware
Most hardware encoders have RTMP(s) support and should work out of the box. More advanced on-prem setups using, e.g., HD-SDI or MPEG-TS is also possible.
## Pages
- [Streaming from Blackmagic devices](https://docs.vindral.com/broadcast/broadcast-hardware/streaming-from-blackmagic.md): While Blackmagic has many different products and solutions for video distribution, one of the more interesting to mention is the ATEM Mini Pro.
- [Streaming from Elemental](https://docs.vindral.com/broadcast/broadcast-hardware/streaming-from-elemental.md): Elemental is widely used within the broadcasting industry. It can ingest to Vindral Live via the standard RTMP output but also, e.g., SDI, MPEG-TS, and UDP-multicast for on-prem setups.
- [Streaming from Intinor devices](https://docs.vindral.com/broadcast/broadcast-hardware/streaming-from-intinor.md): With more than 15 years in the industry, Intinor offers solutions for remote productions, remote commentary, news gathering, sports, and more. Intinor develops products for high-quality point-to-point video and audio broadcast over the internet. They are easy to use, robust, and have a low total cost of ownership.
- [Streaming from LiveU devices](https://docs.vindral.com/broadcast/broadcast-hardware/streaming-from-liveu.md): With high quality, reliable, and cost-effective end-to-end solutions LiveU has offers for all types of live productions.
---
### Vindral WebRTC Ingest (Deprecated)
Deprecated documentation for WebRTC ingest. For new browser-based ingest, use MoQ ingest with the Publisher SDK.
## Pages
- [Getting started with WebRTC Ingest](https://docs.vindral.com/broadcast/webrtc-ingest/getting-started.md): WebRTC ingest is deprecated for new browser-based integrations. Use MoQ ingest with the Publisher SDK for new browser publishing workflows.
- [Embeddable WebRTC Sender](https://docs.vindral.com/broadcast/webrtc-ingest/embeddable-sender.md): WebRTC ingest is deprecated for new browser-based integrations. Use MoQ ingest with the Publisher SDK for new browser publishing workflows.
- [WebRTC Ingest Authentication](https://docs.vindral.com/broadcast/webrtc-ingest/webrtc-auth.md): Generate and refresh JWT authentication tokens for WebRTC Ingest publishers.
- [API Reference](https://docs.vindral.com/broadcast/webrtc-ingest/webrtcingest-api-reference.md): For in-depth information on how to configure and use the WebRTC Ingest SDK, read the API reference.
---
### Getting started with WebRTC Ingest
> **Warning: Deprecated**
>
> WebRTC ingest is deprecated for new browser-based integrations. Use [MoQ ingest](https://docs.vindral.com/broadcast/moq-ingest/getting-started.md) with the [Publisher SDK](https://docs.vindral.com/web-sdk/api/publisher/) for new browser publishing workflows.
>
> The WebRTC ingest workflow below remains available for existing integrations.
There are multiple ways to integrate WebRTC ingest for existing deployments:
- [WebRTC Ingest QoS](#webrtc-ingest-qos) - The Vindral WebRTC Quality of Service Ingest is hosted at [webrtc-ingest-qos.vindral.com](https://webrtc-ingest-qos.vindral.com/) and can be used for validating and testing existing setups.
- [WebRTC Ingest Embed](https://docs.vindral.com/broadcast/webrtc-ingest/embeddable-sender.md) - The Vindral WebRTC Ingest Embed is hosted at `https://webrtc-ingest-embed.vindral.com` and can be used by itself or embedded using iframe on your website.
- Custom integration using the SDK - Follow the steps below and read the [WebRTC Ingest SDK API reference](https://docs.vindral.com/webrtc-ingest/api/).
## Embeddable sender
The WebRTC Ingest Embed can be standalone or embedded using iframe on your website without any coding effort for existing WebRTC integrations.
You can find the latest version of the WebRTC Embed Sender at [webrtc-ingest-embed.vindral.com](https://webrtc-ingest-embed.vindral.com/).
### Iframe example
Below is a simple example of how to embed a responsive WebRTC Ingest.
```html
```
Read more about [embedding WebRTC ingest](https://docs.vindral.com/broadcast/webrtc-ingest/embeddable-sender.md).
## WebRTC Ingest QoS
The Vindral WebRTC Ingest QoS Client, Quality of Service client, is a web page for sending live streams from the browser in existing WebRTC workflows. You will find connection and media statistics to make it easier to test stability issues, which can be hard to find in other software.
You can find the latest version of the WebRTC Ingest QoS Client at [webrtc-ingest-qos.vindral.com](https://webrtc-ingest-qos.vindral.com/).
## Installation
Install `@vindral/webrtc-ingest-sdk` only if you are maintaining an existing WebRTC ingest integration.
Use `npm`:
```bash
npm install --save @vindral/webrtc-ingest-sdk
```
or `yarn`:
```bash
yarn add @vindral/webrtc-ingest-sdk
```
### Example usage
Examples of how to use the WebRTC Ingest SDK can be found in [the examples repository](https://github.com/RealSprint/vindral-examples).
### API Reference
For more in-depth information about the SDK, read the [WebRTC Ingest SDK API reference](https://docs.vindral.com/webrtc-ingest/api/).
## Self-hosted WebRTC Ingest QoS/Embed
The WebRTC Ingest QoS and Embed clients are available as a separate package for customers that need to keep hosting the workflow on their own infrastructure.
[Contact us](https://vindral.com/contact/) for more information on self-hosting.
---
### Embeddable WebRTC Sender
> **Warning: Deprecated**
>
> WebRTC ingest is deprecated for new browser-based integrations. Use [MoQ ingest](https://docs.vindral.com/broadcast/moq-ingest/getting-started.md) with the [Publisher SDK](https://docs.vindral.com/web-sdk/api/publisher/) for new browser publishing workflows.
>
> This page remains available for existing WebRTC ingest deployments that still use the embeddable sender.
For existing WebRTC integrations, you can use our CDN-hosted [embed version](https://webrtc-ingest-embed.vindral.com) or our [QoS version](https://webrtc-ingest-qos.vindral.com).
`webrtc-ingest-embed.vindral.com` hosts the latest version of the embedded WebRTC ingest client.
### Example using iframe
```html
```
Set `core.streamKey` to your private stream key.
`allow="camera; microphone"` is needed to let the iframe ask for permission to use your camera and microphone.
Some common core option parameters are
- `core.streamKey` - (required) the private stream key, used for regular stream authorization when broadcasting.
- `core.width` - (default 1280) width and height properties can be used to request a certain resolution from the webcam.
- `core.height` - (default 720)
- `core.maxBitrate` - (default 2000000) used to set the maximum bitrate.
---
### WebRTC Ingest Authentication
Authentication for Vindral Live is done using the secret provided for you in [Vindral Portal](https://portal.cdn.vindral.com/) and using
that secret to sign a JWT with the allowed channel group or channel. An [optional expiration can also be set](https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.4).
The secret provided in the customer panel should never be available to users and only be hosted securely on your own server.
The token can then be supplied when creating the [`WebrtcIngest`](https://docs.vindral.com/webrtc-ingest/api/classes/WebrtcIngest) instance—passing the token as [`authenticationToken` in the constructor options](https://docs.vindral.com/webrtc-ingest/api/interfaces/WebrtcIngestConfig#authenticationtoken).
If the token is close to expiration, you can refresh the token by calling [`.updateAuthenticationToken(token)`](https://docs.vindral.com/webrtc-ingest/api/classes/WebrtcIngest#updateauthenticationtoken) with a newly signed token on the Vindral instance with an established connection.
Errors will be emitted upon expiration or rejection.
## Examples
### Typescript
#### Single channel use
Signs a token using `jsonwebtoken` that can be used for a single channel.
```typescript
import { sign } from "jsonwebtoken"
const expiresAfterSeconds = 60 * 60 * 2
// Get real secret from customer panel interface
const secret = "75442486-0878-440c-9db1-a7006c25a39f"
const authenticationToken = sign(
{
channelId,
scope: {
ingest: true,
},
exp: Math.round(Date.now() / 1000 + expiresAfterSeconds),
},
secret
)
```
#### Channel group
Signs a token using `jsonwebtoken` that can be used for all channels in the group.
```typescript
import { sign } from "jsonwebtoken"
const expiresAfterSeconds = 60 * 60 * 2
// Get real secret from customer panel interface
const secret = "75442486-0878-440c-9db1-a7006c25a39f"
const authenticationToken = sign(
{
channelGroupId,
scope: {
ingest: true,
},
exp: Math.round(Date.now() / 1000 + expiresAfterSeconds),
},
secret
)
```
## Further reading
For examples of libraries and more general information regarding JWT, [jwt.io](https://jwt.io/).
---
### Streaming from Blackmagic devices
While [Blackmagic](https://www.blackmagicdesign.com/) has many different products and solutions for video distribution, one of the more interesting to mention is the [ATEM Mini Pro](https://www.blackmagicdesign.com/products/atemmini).
It is a low-cost entry-level product that can capture media and send it to the Vindral Live ingest.
## Streaming RTMP(s) from ATEM Mini Pro
Setting the RTMP output is more advanced than on most hardware encoders. You must open the `Streaming.xml` and add a new `` block. We recommend copying one of the existing service blocks.
Name it Vindral Live and set the server URL to your designated Vindral Live ingress. Save and reload the ATEM Software Control. You will be able to select the Vindral Live service now and enter your *stream key*.
Study our [general guidelines](../../broadcast-guidelines#general-recommendations) to avoid streaming pitfalls.
---
### Streaming from Elemental
Elemental is widely used within the broadcasting industry. It can ingest to Vindral Live via the standard RTMP output but also, e.g., SDI, MPEG-TS, and UDP-multicast for on-prem setups.
## RTMP
Create an `Output Group` with `Adobe RTMP`. Under `Output`, enter your designated Vindral Live RTMP URL in the `RTMP Endpoint` field. Enter the Stream Key in the `Stream Name` field.
Study our [general guidelines](../../broadcast-guidelines#general-recommendations) to avoid streaming pitfalls.
## On-prem
For more advanced on-prem setups, SDI, MPEG-TS, and UDP-multicast are fully supported by Vindral Live and muxing multiple sources to a single output, picking PIDs, languages, and much more.
[Let us know](https://vindral.com/contact/) the requirements, and we will help you with the configuration.
---
### Streaming from Intinor devices
With more than 15 years in the industry, [Intinor](https://intinor.com/) offers solutions for remote productions, remote commentary, news gathering, sports, and more. Intinor develops products for high-quality point-to-point video and audio broadcast over the internet. They are easy to use, robust, and have a low total cost of ownership.
All the [Direkt Router](https://intinor.com/products/direkt-router/) models and [Direkt Link](https://intinor.com/products/direkt-link/) models are compatible with Vindral. Set the RTMP endpoint (including the *stream key*) URL to your designated Vindral Live ingress. Study our [general guidelines](../../broadcast-guidelines#general-recommendations) to avoid streaming pitfalls.
---
### Streaming from LiveU devices
With high quality, reliable, and cost-effective end-to-end solutions [LiveU](https://www.liveu.tv/) has offers for all types of live productions.
LiveU is compatible with Vindral Live. Set the RTMP endpoint (including the *stream key*) URL to your designated Vindral Live ingress. Study our [general guidelines](../../broadcast-guidelines#general-recommendations) to avoid streaming pitfalls.
---
### API Reference
For in-depth information on how to configure and use the WebRTC Ingest SDK, [read the API reference](https://docs.vindral.com/webrtc-ingest/api/).
---
### Vindral MoQ Ingest
Ingest streams from the browser over MoQ using the hosted publisher or the @vindral/publisher SDK.
## Pages
- [Getting started with MoQ Ingest](https://docs.vindral.com/broadcast/moq-ingest/getting-started.md): 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.
## Additional Links
- [API Reference](https://docs.vindral.com/web-sdk/api/publisher/): In-depth documentation for the Publisher SDK API.
---
### 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](#hosted-moq-publisher) - The Vindral MoQ Publisher is hosted at [publisher.vindral.com](https://publisher.vindral.com/) and can be used for validating and testing setups.
- Custom integration using the SDK - [Follow the steps below](#installation) to build your own publisher and read the [Publisher SDK API reference](https://docs.vindral.com/web-sdk/api/publisher/).
## 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](https://publisher.vindral.com/).
## Installation
Install `@vindral/publisher` using `npm`:
```bash
npm install --save @vindral/publisher
```
> **Warning: 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`](https://docs.vindral.com/web-sdk/api/publisher/classes/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.
```typescript
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`](https://docs.vindral.com/web-sdk/api/publisher/classes/Publisher/) class exposes a simple lifecycle:
- [`prepare()`](https://docs.vindral.com/web-sdk/api/publisher/classes/Publisher/#prepare) - starts encoding without connecting to the server
- [`publish()`](https://docs.vindral.com/web-sdk/api/publisher/classes/Publisher/#publish) - connects and starts publishing
- [`unpublish()`](https://docs.vindral.com/web-sdk/api/publisher/classes/Publisher/#unpublish) - stops the connection but keeps encoding active
- [`close()`](https://docs.vindral.com/web-sdk/api/publisher/classes/Publisher/#close) - shuts down the publisher completely
Connection state, publisher state, and errors can be observed through [`publisher.on(...)`](https://docs.vindral.com/web-sdk/api/publisher/classes/Publisher/#on). Current encoding and connection metrics can be read using [`publisher.stats()`](https://docs.vindral.com/web-sdk/api/publisher/classes/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](https://docs.vindral.com/manage/auth/generate-jwt.md#authorizing-ingress).
## API reference
For full details, see the [Publisher SDK API reference](https://docs.vindral.com/web-sdk/api/publisher/).
---
### Broadcast
Learn how to broadcast streams via Vindral.
## Pages
- [Broadcast Software](https://docs.vindral.com/broadcast/software.md): Many software applications are easy to use and have full RTMP or SRT support. These are commonly used among our customers.
- [Broadcast Hardware](https://docs.vindral.com/broadcast/hardware.md): Most hardware encoders have RTMP(s) support and should work out of the box. More advanced on-prem setups using, e.g., HD-SDI or MPEG-TS is also possible.
- [Vindral WebRTC Ingest (Deprecated)](https://docs.vindral.com/broadcast/webrtc.md): Deprecated documentation for WebRTC ingest. For new browser-based ingest, use MoQ ingest with the Publisher SDK.
- [Vindral MoQ Ingest](https://docs.vindral.com/broadcast/moq-ingest.md): Ingest streams from the browser over MoQ using the hosted publisher or the @vindral/publisher SDK.
- [Broadcast Guidelines](https://docs.vindral.com/broadcast/broadcast-guidelines.md): Vindral Live supports multiple incoming transport protocols. However, RTMPS is the most widely used and supported - and therefore, the one we often recommend.
- [Supported Protocols](https://docs.vindral.com/broadcast/supported-protocols.md): These are the protocols supported by Vindral Live on the ingress side. The protocols are divided into two categories, those requiring local presence and those that can be used over public networks. The latter is often used for cloud-based solutions, while the former is more common in on-prem installations using LivePackager or other Encoder software or hardware.
- [Recording](https://docs.vindral.com/broadcast/recording.md): Vindral's recording feature is designed to provide you with the ability to record live streams and offer a practical solution if you wish to archive your broadcasts or make them available for on-demand viewing. The Recording feature allows for the recording of live streams on a per-channel basis. This means you can choose to record streams from all channels, a select few, or just one, depending on your needs.
- [Restreaming](https://docs.vindral.com/broadcast/restreaming.md): Restreaming is a powerful tool that enables you to broadcast your live stream simultaneously across multiple platforms such as YouTube, Twitch, and Facebook. This technique significantly expands your reach and maximizes your impact.
- [Transcoding](https://docs.vindral.com/broadcast/transcoding.md): Vindral offers a range of transcoding options to ensure that your content is delivered in the best possible quality to your viewers. Most streams sent over the internet use multiple qualities to cater to different viewer conditions. Often, a single stream is sent to our service and turned into multiple qualities, a.k.a. an ABR Ladder.
---
### Broadcast Guidelines
Vindral Live [supports multiple](https://docs.vindral.com/broadcast/supported-protocols.md) incoming transport protocols. However, RTMPS is the most widely used and supported - and therefore, the one we often recommend.
Most software and hardware encoders have a wide range of configuration options, but there are a couple of things that we generally recommend:
## General recommendations
- If your device supports it, use hardware acceleration - a performance drop on an origin encoder will lead to unwanted buffering for *all* connected clients.
- Verify that the host machine can run in a stable environment without other applications stealing CPU/IO power.
- Use constant bitrate as rate control - leads to a more stable experience for clients.
- Disable or limit buffers to achieve the lowest possible latency.
- Use a buffer only if needed for higher stability on unstable ingress connections.
- Keyframe Interval (GOP size) - should be around 1-2 seconds for fast connection time and channel switching.
- Profile - H.264 baseline for best possible compatibility and lowest latency.
- Tune for low-latency/live (no b-frames, high performance/stability).
- Your maximum upload bandwidth may be a limiting factor for deciding on encoder bitrate. Using more than half of the available bandwidth is not recommended as it may be exceeded because of the encoder and network jitter.
- While we recommend using RTMPS, some hardware encoders and software applications do not yet support RTMPS. RTMP is supported in Vindral using the same ingest URLs.
## Resolution, frame rate and bitrate
Vindral Live supports a wide range of resolutions and bitrates. We recommend using CBR (Constant Bitrate) for the best performance, especially for live streaming. The bitrate you choose will depend on the resolution and framerate of your video, as well as the codec you are using.
If you are uncertain about which resolution and bitrate to use, we recommend starting with **1080p30** at **4 Mbps**. This is a good balance between quality and bandwidth usage for most live streaming scenarios. If the player will be part of a user interface and not expected to be full screen or used on large screens, you can use a lower resolution and bitrate, such as **720p30** at **2 Mbps**. Some customers even go as low as 360p30 at **0.5 Mbps** for low-bandwidth or second-screen scenarios.
The following table provides some common resolutions and bitrate examples for 30 fps video. The bitrates are approximate and can vary based on the codec used, the content being streamed, and other factors.
| Resolution | Bitrate H.264 (Mbps) | Bitrate AV1 (Mbps) |
| ---------- | -------------------- | ------------------ |
| 2160p30 | 12 | 8 |
| 1440p30 | 8 | 4 |
| 1080p30 | 4 | 3 |
| 720p30 | 2 | 1.5 |
| 540p30 | 1 | 0.5 |
| 360p30 | 0.5 | 0.3 |
| 240p30 | 0.3 | 0.2 |
| 144p30 | 0.15 | 0.1 |
The table above serves as a helpful reference point, but actual bitrate requirements should be fine-tuned based on your specific **content type**, **use case**, and **network conditions**.
### 📺 Frame Rate
The most common frame rates for live streaming are **25 fps** and **30 fps**. However, some content may benefit from higher frame rates, such as **50 fps** or **60 fps**. The choice of frame rate can significantly impact the perceived quality of the stream. Some webinars and auction even use lower frame rates, such as **15 fps** or **10 fps**, to save bandwidth or make the content more crisp.
If you are uncertain about which frame rate to use, we recommend starting with **30 fps**.
> **Caution**
>
> Make sure your camera and encoder are set to the same frame rate, as mismatched frame rates can lead to choppy or stuttery video.
> **Note**
>
> While higher frame rates can enhance motion smoothness and improve the viewing experience, they also increase the computational load on both the encoder (server side) and decoder (client side). This added complexity often translates to higher infrastructure costs and may impact device compatibility or battery life on lower-end clients.
In most streaming scenarios, increasing the frame rate from **30fps to 60fps** (or **25fps to 50fps** in PAL regions) does **not require doubling the bitrate**. Thanks to efficient temporal compression in modern codecs, a **10–30% increase** is typically sufficient to maintain comparable or even better **perceived quality**, especially for content with smooth or predictable motion.
### 📦 Codec Efficiency
The **AV1** codec offers significantly better compression efficiency compared to **H.264**. For instance:
- **1080p30** streams with AV1 may achieve good quality at just **1–3 Mbps**, whereas **H.264** might require **2–6 Mbps** for similar results.
- At lower resolutions, AV1 performs even better. A **720p** AV1 stream can often deliver acceptable quality at **500 kbps** or less—something H.264 struggles to match at the same bitrate.
This makes AV1 especially valuable for delivering **low-latency or adaptive streams** in bandwidth-constrained environments.
### 🔊 Audio Considerations
For audio:
- **AAC** is commonly used with streaming, typically at **96 kbps**, though bitrates can range from **64 to 160 kbps** depending on quality goals.
- **Opus**, a more modern and flexible codec, can maintain high perceptual quality at **lower bitrates**—often between **48–64 kbps**—making it ideal for live streaming setups.
| Content type | Bitrate AAC (kbps) | Bitrate Opus (kbps) |
| ------------ | ------------------ | ------------------- |
| Voice | 96 | 64 |
| Mixed | 128 | 96 |
The table above serves as a helpful reference point, but actual bitrate requirements should be fine-tuned based on your specific content type, use case, and network conditions.
> **Note**
>
> Vindral Live supports audio only streams, for doing internet radio or similar.
> In those cases, make sure to only send the audio stream to Vindral Live, and not the video stream. This will save you bandwidth and make sure that the audio stream is not delayed or otherwise effected by the video stream.
## RTMP(s) or SRT
RTMP(s) and SRT are both widely used protocols for streaming video over the internet, but they have some key differences:
- **RTMP**: This is a traditional protocol and is widely supported across many streaming platforms and devices. It is easy to use and does not incur any additional latency. However, it is important to note that RTMP only supports a limited set of video- and audio codecs\[^1], and does not support multiple audio or video tracks.
- **SRT**: Secure Reliable Transport (SRT) is a newer protocol designed to overcome some of the limitations of RTMP. It offers high performance over unreliable networks, but can incur additional latency due to use of buffers. Unlike RTMP, SRT supports multiple audio and video tracks and is not limited to specific codecs.
In general, if your streaming setup does not need multiple audio or video tracks and is compatible with H.264 for video and AAC for audio, RTMP(s) is a straightforward and reliable choice. However, if you require more flexibility in terms of codecs, or if you are streaming over long distances or unstable networks, SRT might be the better option.
\[^1]: Being an old protocol, RTMP has not traditionally supported modern video codecs, but with the addition of the [Enhanced RTMP specification](https://github.com/veovera/enhanced-rtmp), AV1 is now supported and available to use when ingesting to Vindral.
## Software encoders
Many software applications are easy to use and have full support for RTMPS and other protocols. Our customers commonly use these:
- [OBS](https://docs.vindral.com/broadcast/broadcast-software/streaming-from-obs.md) - free
- [Vindral Composer](https://docs.vindral.com/broadcast/broadcast-software/composer.md) - proprietary
- [Vindral Live Packager](https://docs.vindral.com/broadcast/broadcast-software/livepackager.md) - proprietary
- [Wirecast](https://docs.vindral.com/broadcast/broadcast-software/streaming-from-wirecast.md) - proprietary
## Hardware encoders
Most hardware encoders have RTMP(s) support and should work out of the box.
Some of the more commonly used are:
- [LiveU](https://docs.vindral.com/broadcast/broadcast-hardware/streaming-from-liveu.md)
- [Blackmagic](https://docs.vindral.com/broadcast/broadcast-hardware/streaming-from-blackmagic.md)
- [Intinor](https://docs.vindral.com/broadcast/broadcast-hardware/streaming-from-intinor.md)
- [Elemental](https://docs.vindral.com/broadcast/broadcast-hardware/streaming-from-elemental.md)
## Custom encoder setups
[Let us know](https://vindral.com/contact/) if you have more advanced encoder requirements, such as:
- local monitoring dashboard with graphs and alerts
- error handling and automatic restarts
- robust 24/7 streaming
- multiple sources (MPEG-TS, SDI, RTMP) that should be combined into a single stream
- multiple outputs
- custom hardware
- dense transcoding, hardware offload using GPUs, iGPUs, or ASICs
- API control
We have solutions for advanced on-prem setups that have been in use for years with rock-solid performance.
---
### Supported Protocols
These are the protocols supported by Vindral Live on the ingress side. The protocols are divided into two categories, those requiring local presence and those that can be used over public networks. The latter is often used for cloud-based solutions, while the former is more common in on-prem installations using LivePackager or other Encoder software or hardware.
## Public network ingress
The following protocols are supported for ingesting content to Vindral Live via public internet:
- *RTMP* – de facto standard for video ingress over the internet
- *SRT* – gaining traction over RTMP due to better support for new codecs, multi-audio and metadata
- *WebRTC* (deprecated) – easy to use and embeddable on websites
- *MoQ* – is a next-generation transport protocol designed for ultra-low latency and high-quality media streaming, leveraging QUIC's capabilities to enhance real-time media delivery
```mermaid
---
title: Vindral Live public network ingress protocols
---
flowchart TB
S_RTMP(Source)
S_SRT(Source)
S_MOQ(Source)
S_WEBRTC(Source)
VLE("Vindral LiveEngine")
S_RTMP--RTMP--->VLE
S_SRT--SRT--->VLE
S_MOQ--MoQ--->VLE
S_WEBRTC--"WebRTC (deprecated)"--->VLE
```
## Local presence / on-prem encoder
Some protocols require specific hardware and/or local presence. [Vindral LivePackager](https://docs.vindral.com/broadcast/broadcast-software/livepackager.md) (or other on-prem encoders) will output MoQ, SRT, or RTMP to the ingress server. Contact us for more information on how to set up your encoder or if you'd like to give LivePackager a try.
- *RTMP* – de facto standard for video ingress over the internet
- *SRT* – gaining traction over RTMP due to better support for new codecs, multi-audio and metadata
- *MoQ* – next-generation transport protocol designed for ultra-low latency and high-quality media streaming, leveraging QUIC's capabilities to enhance real-time media delivery
- *(HD-)SDI* – still commonly used within broadcast
- *MPEG-TS* – still commonly used within broadcast and on private networks
- *RTP* – an alternative to MPEG-TS over UDP
- *RTSP* – commonly used by surveillance cameras
- *NDI* – useful for on-prem installations as a modern replacement for SDI
- *File* – Vindral LivePackager can read and loop file inputs and efficiently do ABR for synchronized playback
- *ST2110* – under development, contact for information
```mermaid
---
title: Vindral Live on-prem ingress protocols
---
flowchart TD
S_SDI(Source)
S_MPEGTS(Source)
S_RTP(Source)
S_NDI(Source)
S_RTSP(Source)
S_ST2110(Source)
S_FILE(Source)
S_RTMP(Source)
S_SRT(Source)
S_MOQ(Source)
Packager("Vindral LivePackager or other on-prem encoder")
S_SDI--SDI---->Packager
S_MPEGTS--MPEGTS---->Packager
S_RTP--RTP---->Packager
S_NDI--NDI---->Packager
S_RTSP--RTSP---->Packager
S_ST2110--ST2110---->Packager
S_FILE--File---->Packager
S_RTMP--RTMP---->Packager
S_SRT--SRT---->Packager
S_MOQ--MoQ---->Packager
Packager--MoQ--->VLE("Vindral LiveEngine")
```
## Additional information
The information below relates to specifically Vindral Live’s implementations of the protocols and may not be true for other vendors; for instance, many SRT providers still do not support proper authorization of streams and most MoQ implementations are still only in demo state and not made for production like Vindral Live MoQ is.
### MoQ (Media over QUIC)
MoQ is used internally within Vindral Live but is also supported as an ingest protocol, using the “Draft 7” spec.
For browser-based MoQ ingest, see [Getting started with MoQ Ingest](https://docs.vindral.com/broadcast/moq-ingest/getting-started.md).
### RTMP
Vindral's RTMP receiver has support for both unsecure (RTMP) and secure (RTMPS) variants, using the concept of "stream key" [and JWT](https://docs.vindral.com/manage/auth/connecting-jwt.md#rtmp) for authorizing streams. It has support for the new "Enhanced RTMP" with AV1 and HEVC capabilities.
### SRT
SRT uses the concept of "stream key" [and JWT](https://docs.vindral.com/manage/auth/connecting-jwt.md#srt) for authorizing streams. It supports being used with or without encryption and is easily configured in the Vindral Portal.
While more modern than RTMP, it does not really lower latency or add anything for most use real-time cases. Rather in many cases it adds latency and reduces stability.
### WebRTC
Vindral's WebRTC ingest flow remains available for existing integrations, but it is deprecated for new browser-based publishing. New integrations should use [MoQ ingest](https://docs.vindral.com/broadcast/moq-ingest/getting-started.md) with the [Publisher SDK](https://docs.vindral.com/web-sdk/api/publisher/) instead.
### SDI
Using LivePackager for instance, the Decklink SDI cards are supported. Multi-audio SDI is available and multiple SDI sources can be combined to a single stream where necessary.
### MPEG-TS
MPEG-TS over IP (both TCP/UDP/UDP Multicast) is available. Multiple sources or multiple PIDs inside a single source is supported and can be combined as necessary. Multi-audio, subtitles and other metadata are supported.
## Advanced setups
If need be, the Vindral LivePackager can be used for combining multiple sources of different types to a single stream, or proxy different protocols to for instance MoQ or SRT. It can also be used for adding advanced features like low-latency, ABR, and more.
Vindral Composer can in turn be used for adding overlays, AI, object-tracking, and more advanced features to the stream.
Please contact us for more information.
---
### Recording
Vindral's recording feature is designed to provide you with the ability to record live streams and offer a practical solution if you wish to archive your broadcasts or make them available for on-demand viewing. The Recording feature allows for the recording of live streams on a per-channel basis. This means you can choose to record streams from all channels, a select few, or just one, depending on your needs.
Please note that the Recording feature records the source material directly, not the transcoded qualities. This means the quality of the recording will be as high as the input stream, ensuring the best possible quality for your archived broadcasts.
## Enabling Recording
To enable the Recording feature, simply navigate to a channel, find the "Recording" tab, and toggle the switch. Once enabled, the system will automatically record the live streams for that channel.

## Setting the Recording Retention
In addition to enabling recording, you can specify the duration for which you want your recordings to be saved (retention). This is done by navigating to the recording tab, finding the "Retention" option, and entering the desired number of days you want to save the recording. The system will then automatically delete the recordings after the specified duration has passed.
## Start Streaming
Once everything is set up, you can begin broadcasting. In addition to your live stream, your recording will be saved and stored according to the retention duration you've set. This allows you to revisit or repurpose your broadcasts even after they've been live.
> **Note**
>
> If your channel is already broadcasting while you're modifying your recording settings, you will need to restart the broadcast for the new settings to take effect.
## Viewing
You can view the recordings of your channel under the "Recordings" tab. Here you will be presented with a player allowing you to watch your channel's recordings from a chosen time window. Enter your desired **from** and **to** date using the date pickers and any available recordings from that time window will be presented in the player.
You can also download an m3u8 playlist that uses your selected time window.

### Sessions
If you want to watch a recording from a specific session, navigate to the "Sessions" tab. Sessions that have an available recording will have a "Recording" button. Click this to be directed to the "Recordings" tab with the time window of your selected session pre-configured so you can watch it instantly.
# Clipping
View recorded material or create clips from your recordings to share with your audience. The [Clipping API](https://docs.vindral.com/management-api/#tag/Clipping) allows you to create clips from your recordings. To use the Clipping API, you will need an [API key](https://docs.vindral.com/manage/management-api/#api-keys).
### Example usage
To view recorded material between two timestamps use the following API call, with your own `API_KEY` and `CHANNEL_ID`, which will redirect you to an m3u8 playlist (see location header in response):
```bash
curl -vH "Authorization: Bearer " "https://api.cdn.vindral.com/v1/clipping//m3u8?from=2024-01-01T12:00:00Z&to=2024-01-01T12:05:00Z"
```
To create a clip from a recording between the same two timestamps, you can use ffmpeg to save the clip to an mp4 file:
```bash
ffmpeg -headers "Authorization: Bearer " -i "https://api.cdn.vindral.com/v1/clipping//m3u8?from=2024-01-01T12:00:00Z&to=2024-01-01T12:05:00Z" -c:v copy -c:a copy -f mp4 clip.mp4
```
---
### Restreaming
Restreaming is a powerful tool that enables you to broadcast your live stream simultaneously across multiple platforms such as YouTube, Twitch, and Facebook. This technique significantly expands your reach and maximizes your impact.
## Settings up restreaming
You can configure your restreaming settings in the [Vindral Portal](https://portal.cdn.vindral.com). The restreaming options are located in the Details section of the channel you wish to add restreams to, as illustrated below:

### Add RTMP Destinations
We allow you to add up to five RTMP destinations per channel. These destinations are the platforms where you want your stream to be broadcasted, such as YouTube, Twitch, or Facebook.
Here's how you can add a new restream. Enter the RTMP URL destination and choose if it should be enabled or not:

After you've added your restreams, they will be listed for the selected channel. Here, you can edit and delete your existing restreams:

Ensure to hit **Save** to preserve your configured settings.
### Connect Your Streaming Platforms
To connect a platform, you'll need to provide the RTMP URL for that platform. This URL should include the stream key, which is a unique identifier for your stream on that platform. This information can usually be found in the platform's live streaming settings.
- [YouTube](https://www.youtube.com/howyoutubeworks/product-features/live/#youtube-live)
- [Twitch](https://help.twitch.tv/s/twitch-ingest-recommendation?language=en_US)
- [Facebook](https://www.facebook.com/help/931327837299966/?helpref=hc_fnav)
> **Note**
>
> Each streaming platform may have its own specific setup process, so be sure to read their documentation and help guides for detailed instructions.
### Start Streaming
Once everything is set up, you can begin broadcasting. Your stream will be transmitted to all the RTMP destinations you added.
> **Note**
>
> If your channel is already broadcasting while you're modifying your restreaming settings, you will need to restart the broadcast for the new settings to take effect.
---
### Transcoding
Vindral offers a range of transcoding options to ensure that your content is delivered in the best possible quality to your viewers. Most streams sent over the internet use multiple qualities to cater to different viewer conditions. Often, a single stream is sent to our service and turned into multiple qualities, a.k.a. an ABR Ladder.
```mermaid
flowchart LR;
subgraph Transcoding
direction LR
B(Transcoder / Packager)
end
A(Ingress)--1080p-->B;
B--ABR Ladder-->C(Edge)
C--1080p-->D(Viewer A);
C--720p-->E(Viewer B);
C--360p-->F(Viewer C);
```
This process is called *Transcoding*.
Our transcoding components are built for robust live 24/7 streaming and support many different codecs and settings. These are used internally within Vindral Live and can be used on-prem as well. [Let us know](https://vindral.com/contact/) if you are interested in learning more.
## Why transcoding is important
If you are streaming to a global audience, you need to ensure that your content is delivered in the best possible quality to your viewers. If your source is a high-quality 4K stream, it is important to transcode the stream into multiple bitrates and resolutions to ensure that your viewers can watch your content without buffering. The Vindral Live player automatically selects the best quality based on the viewer's network conditions and device capabilities, this is called Adaptive Bitrate or ABR.
With our transcoding, we support new efficient formats such as AV1 that can save up to 30% of bandwidth compared to H.264. By reducing the bandwidth and keeping the quality high, you can reach more viewers with less resources.
All transcoding is done in real-time, and we ensure that your content is delivered in sync on all qualities and devices.
## Adaptive Bitrate (ABR)
Vindral Live supports Adaptive Bitrate (ABR) streaming, which allows us to deliver the best possible quality to your viewers based on their network conditions. ABR streaming is achieved by encoding your content at multiple bitrates and resolutions, and then delivering the best possible quality to your viewers based on their network conditions.
## Transcoding profiles
A transcoding profile is a set of rules that define how a stream is transcoded. Both the audio and video can be passthrough and/or transcoded into other formats. Some settings that can be included in a transcoding profile are:
- **Bitrate** - the amount of data that is transmitted per second.
- **Resolution** - the number of pixels in each dimension, e.g. 1920x1080. Or a scale factor, e.g. 50% for half the resolution of source.
- **Frame rate** - the number of frames per second.
- **Codec** - the format used to encode the video and audio data.
- **Thumbnail** - an image of the video source. How often the thumbnail is updated and in which qualities it is available.
- **Deinterlacing** - converting interlaced video into a non-interlaced form.
- **Frame rate conversion** - converting the frame rate of a video.
- **Passthrough** - no transcoding of the video or audio data to keep the original quality.
- **Crop** - removing parts of the video frame.
- **GOP Alignment** - aligning the Group of Pictures (GOP) based on the passthrough stream.
We provide one default transcoding profile, but we can create custom transcoding profiles to suit your specific needs.
### Example transcoding profile
As an example with an RTMP ingest with AV1 in 1080p at 4 Mbps. From the one incoming stream, we can create these outgoing streams:
- **1080p** (1920x1080) - 4 Mbps, AV1 (passthrough)
- **1080p** (1920x1080) - 4.5 Mbps, H.264
- **720p** (1280x720) - 2 Mbps, AV1
- **720p** (1280x720) - 2.5 Mbps, H.264
- **360p** (640x360) - 0.4 Mbps AV1
- **360p** (640x360) - 0.6 Mbps H.264
- **Audio** - 128 kbps, AAC passthrough
- **Audio** - 96 kbps, Opus
- **JPEG Thumbnail** (1280x720) - updated every 5 seconds
- **JPEG Thumbnail** (640x360) - updated every 5 seconds
The incoming stream can be passthrough without transcoding to avoid quality loss, and additionally, the stream is transcoded into multiple bitrates and resolutions to allow viewers with different network conditions to watch the stream without buffering. In this example we also create a H.264 stream for compatibility with older devices. Notice the higher bitrate for the H.264 streams to keep similar quality as the AV1 stream.
---
## Playout
### Web SDK
Learn how to use the Web SDK to build an available player experience.
## Pages
- [Getting Started with Web SDK](https://docs.vindral.com/playout/websdk/getting-started.md): Depending on the use case, there are multiple ways to integrate the Web SDK.
- [Configuration](https://docs.vindral.com/playout/websdk/configuration.md): Use these guides for the most common Web SDK configuration topics
- [Autoplay](https://docs.vindral.com/playout/websdk/autoplay.md): Some browsers allow autoplay with audio; some allow autoplay without audio, while some do not allow autoplay at all.
- [Authentication](https://docs.vindral.com/playout/websdk/web-auth.md): Generate and refresh JWT authentication tokens for Vindral Web SDK playback.
- [Timed metadata](https://docs.vindral.com/playout/websdk/timed-metadata.md): Vindral Live has support for sending timed metadata, also called cue points or out-of-band data.
- [Google Cast](https://docs.vindral.com/playout/websdk/google-cast.md): Vindral Web SDK supports Google Cast (a.k.a. Chromecast) devices, making it easy to build globally scalable, in-sync, second-screen experiences.
- [Fullscreen and Picture-in-Picture](https://docs.vindral.com/playout/websdk/fullscreen-pip.md): While Vindral Live player has support for running in fullscreen mode and Picture-in-Picture (PiP) mode, there are some caveats to be aware of.
- [Vindral Player](https://docs.vindral.com/playout/websdk/vindral-player.md): Vindral Player is our ready-to-go web component-based player for easy integration into your web applications. It is ideal for customizing controls or when the embed solution is not sufficient.
- [WebCodecs and Offscreen Renderer](https://docs.vindral.com/playout/websdk/webcodecs-offscreen-renderer.md): Vindral Web SDK supports low-level browser video decoding via the WebCodecs API and, when supported, off-main-thread rendering via an offscreen renderer backed by OffscreenCanvas. Together these can unlock a lower-latency, lower-overhead playback pipeline compared to the traditional MSE path, where drift management is harder to achieve. Whether hardware or software decoding is used is configurable — see Hardware acceleration and decoder latency.
- [API Reference](https://docs.vindral.com/playout/websdk/websdk-api-reference.md): Use the reference that matches your integration layer
---
### Getting Started with Web SDK
Depending on the use case, there are multiple ways to integrate the Web SDK.
The easiest way to get started is to use the iframe-based [Embed Player](#embed-player). It requires the least amount of code and will automatically be updated when new releases are available.
The two other alternatives are [Vindral Live Player](#vindral-player) and [Core SDK](#core-sdk) - these are the recommended options if the integration requires access to the APIs, such as timed metadata or other controls. The player is a web component-based player for easy integration and customization, while the Core SDK is the most stripped-down implementation for use cases where all UI components are customized.
If you are going for one of the SDK alternatives, follow the steps at [Installation](#installation) to get started.
## Vindral's Configurable Latency Advantage
**One of Vindral Live's key differentiators is our configurable latency system.** Unlike many other low-latency solutions in the market, Vindral allows you to fine-tune latency to match your specific requirements while maintaining superior stability.
**Why this matters:**
- **Stable Low Latency**: When you configure Vindral Live for low latency, you get more stable performance compared to protocols that enforce rigid low-latency settings. Our adaptive buffering algorithms, end-to-end jitter management, and robust CDN architecture work together to ensure smooth playback even under challenging network conditions.
- **Flexible Configuration**: Adjust `minBufferTime` from ultra-low latency (sub-second) to higher stability (several seconds) based on your use case
- **Reliability First**: Our adaptive approach ensures consistent playback quality across varying network conditions
This configurable approach means you're not locked into a one-size-fits-all latency setting - you get the best of both worlds: the ability to go as low as needed while maintaining the stability that fixed solutions can't match.
📖 **Learn more:** See our comprehensive [Latency Control](https://docs.vindral.com/playout/latency-control.md) guide for detailed configuration strategies and use case recommendations.
## Embed Player
This is the simplest way to integrate. It allows you to add a fully functional video player to your site in no time. It will also be automatically updated when improvements are released.
Add the following HTML snippet, set `core.channelId` to the *channel id* credential, and you're done.
```html
```
[See the player in action](https://player.vindral.com/?core.channelId=vindral_demo1_ci_099ee1fa-80f3-455e-aa23-3d184e93e04f) or [read more about the Embeddable Player here](https://docs.vindral.com/playout/embeddable-player.md).
## Installation
Install @vindral/web-sdk using `npm`:
```bash
npm install --save @vindral/web-sdk
```
Equivalent for `yarn`:
```bash
yarn add @vindral/web-sdk
```
### Core SDK
The Core SDK is the lowest level method to integrate that provides only a video view and audio playback - this allows for complete customization of the look of buffering indication and controls.
**Example**
The example assumes that there is an HTML page that loads this script that has at least a div with `id="root"`, `id="playback-state"` and a button with `id="activate-audio-button"`.
```javascript
import { Vindral } from "@vindral/web-sdk"
const root = document.querySelector("#root")
const button = document.querySelector("#activate-audio-button")
const playbackState = document.querySelector("#playback-state")
button.style.display = "none"
const instance = new Vindral({
url: "https://lb.cdn.vindral.com",
channelId: "vindral_demo1_ci_099ee1fa-80f3-455e-aa23-3d184e93e04f",
minBufferTime: 1000, // Vindral's configurable latency: adjust from 100ms (ultra-low) to 5000ms+ (high stability)
})
// Errors are emitted when they cannot be handled internally
// fatal errors mean that the client has been unloaded and will need to be re-initialized
instance.on("error", (error) => {
if (error.isFatal()) {
// A fatal error has occurred and the instance has been unloaded, read error.message to see what
// This can happen if the client has been unsuccessful to connect or authentication failed
// In this case a new Vindral instance needs to be created to restore the session
}
})
// This event is emitted when the playback state changes - can be used to show a buffer spinner while buffering
instance.on("playback state", (state) => (playbackState.textContent = state))
// This event is emitted when timed metadata events occur
instance.on("metadata", (metadata) => console.log("metadata: ", metadata.content))
// This event is emitted when Vindral detects that the browser requires a user-initiated click event to start the audio
instance.on("needs user input", () => (button.style.display = "block"))
// Will connect, start the stream and try to play
instance.play()
// Attaches the video view to the DOM
instance.attach(root)
// This activates audio on browsers that need user input before the audio can be played
button.addEventListener("click", () => {
button.style.display = "none"
instance.play()
})
```
> **Tip**
>
> If you are optimizing for the lowest possible latency or want to experiment with WebCodecs, decoder order, OffscreenCanvas rendering, or the media-element bridge for fullscreen/PiP, see [WebCodecs & Offscreen Renderer](https://docs.vindral.com/playout/websdk/webcodecs-offscreen-renderer.md).
### Vindral Player
Vindral Player is our ready-to-go web component-based player for easy integration into your web applications. It is ideal for customizing controls or when the embed solution is not sufficient.
**Example**
To be able to use the `` in your HTML you have to call `registerComponents`.
```javascript
import { registerComponents } from "@vindral/web-sdk/player"
registerComponents()
```
Or use `vindral-player-component.js`, which is a self-registering variant of the web components player intended to be used from a script tag.
> **Warning: Use a pinned version**
>
> The jsDelivr CDN (`https://cdn.jsdelivr.net`) is a third-party service and is not operated by Vindral. When using this script-tag distribution, pin an explicit package version instead of relying on the latest release so future updates do not change your integration unexpectedly.
```html
```
Channel id is the only required attribute when using ``.
```html
```
Easy to customize controls with CSS variables.
```css
```
### Player SDK
> **Deprecated**: The Player SDK is deprecated and has been replaced with the [Vindral Player](#vindral-player). It can still be used with `@vindral/web-sdk/legacy`.
**Example**
This example attaches a player to an element with the id `root`. The player will activate audio when needed and provide a minimalistic UI for controls such as fullscreen, channel switching, and language selection.
The example assumes that there is an HTML page that loads this script that has at least a div with `id="root"`.
```typescript
import { Player } from "@vindral/web-sdk/legacy"
const root = document.querySelector("#root")
const player = new Player({
url: "https://lb.cdn.vindral.com",
channelId: "vindral_demo1_ci_099ee1fa-80f3-455e-aa23-3d184e93e04f",
channelGroupId: "vindral_demo_pk_932730be-db0c-46a0-a592-cfce7bdc5a43",
minBufferTime: 1000, // Vindral's configurable latency: adjust from 100ms (ultra-low) to 5000ms+ (high stability)
})
// Will connect, start the stream and try to play
player.core.play()
// Attaches the player view to the DOM
player.attach(root)
```
---
### Configuration
Use these guides for the most common Web SDK configuration topics:
- [API reference](https://docs.vindral.com/web-sdk/api/) for the full option surface
- [Latency Control](https://docs.vindral.com/playout/latency-control.md) for buffer and stability tuning
- [WebCodecs & Offscreen Renderer](https://docs.vindral.com/playout/websdk/webcodecs-offscreen-renderer.md) for decoder selection, OffscreenCanvas rendering, and media-element bridging
- [Fullscreen and PiP](https://docs.vindral.com/playout/websdk/fullscreen-pip.md) for browser API caveats and integration details
- [Vindral Player](https://docs.vindral.com/playout/websdk/vindral-player.md) for the web component configuration surface
---
### Autoplay
Some browsers allow autoplay with audio; some allow autoplay without audio, while some do not allow autoplay at all.
Audio is, by default, blocked from automatically playing on most mobile devices and some desktop devices. There are, however, cases where an earlier interaction with the web page might be enough to allow auto-playing audio.
Video is generally only blocked if users have manually configured it so (not common) or by more advanced data-saver features on mobile devices (also not common).
Vindral Web SDK will try to autoplay. If it does not succeed, an event will be emitted.
```javascript
// This event is emitted when the Vindral instance detects that the browser requires a user-initiated click event to start the audio
instance.on("needs user input", () => (button.style.display = "block"))
```
As the event name implies, an actual user input (e.g., a real user click event) is needed to activate. Showing a unmute/play button is a reasonable course of action.
## Muted
In some cases, it might be desirable to start a stream muted. When instantiating Vindral, setting `muted: true` will ensure no unwanted audio is played.
## Video-only autoplay
As previously mentioned, the `"needs user input"` event can also be triggered for video-only, even if it is not very common.
## Setting Volume
Setting volume programmatically does not have consistent behavior between browsers. Therefore it is always recommended to set the volume via user input.
## Native
For native integration, autoplay can be achieved by setting the correct options on the WebView instance. Read more about [native integration for Android](https://docs.vindral.com/playout/native/native-android.md) and [native integration for iOS](https://docs.vindral.com/playout/native/native-ios.md).
## Further reading
[This autoplay guide](https://developer.mozilla.org/en-US/docs/Web/Media/Autoplay_guide#autoplay_availability) over at Mozilla is a good place to read more about the subject.
---
### Authentication
Authentication for Vindral Live is done using the secret provided for you in [Vindral Portal](https://portal.cdn.vindral.com/) and using
that secret to sign a JWT with the allowed channel group or channel. An [optional expiration can also be set](https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.4).
The secret provided in the Portal should never be available to users and only be hosted securely on your own server.
The token can then be supplied when creating the [`Vindral`](https://docs.vindral.com/web-sdk/api/web-sdk/classes/Vindral) instance—passing the token as [`authenticationToken` in the constructor options](https://docs.vindral.com/web-sdk/api/web-sdk/interfaces/Options#authenticationtoken).
If the token is close to expiration, you can refresh the token by calling [`.updateAuthToken(token)`](https://docs.vindral.com/web-sdk/api/web-sdk/classes/Vindral#updateauthenticationtoken) on the Vindral Live instance with an established connection.
Errors will be emitted upon expiration or rejection and can be expected to have `AUTHENTICATION_FAILED_CODE` or `AUTHENTICATION_EXPIRED_CODE` as exported by the `errors` module.
Note that reaching expiration on a token is a fatal error, and a new Vindral Live instance will have to be created with a new token. Therefore, it is recommended to have a mechanism to refresh the token before it expires using [`.updateAuthToken(token)`](https://docs.vindral.com/web-sdk/api/web-sdk/classes/Vindral#updateauthenticationtoken).
### Examples
#### Example signing a token using jsonwebtoken with Typescript for single channel use
```typescript
import { sign } from "jsonwebtoken";
function getAuthenticationToken() {
const expiresAfterSeconds = 3600;
// Get real secret from portal interface
const secret = "75442486-0878-440c-9db1-a7006c25a39f";
const authenticationToken = sign(
{
channelId,
scope: {
playout: true,
},
exp: Math.round(Date.now() / 1000 + expiresAfterSeconds),
},
secret
);
return authenticationToken;
}
```
#### Example signing a token using jsonwebtoken with Typescript for use with a channel group
```typescript
import { sign } from "jsonwebtoken";
function getAuthenticationToken() {
const expiresAfterSeconds = 3600;
// Get real secret from portal interface
const secret = "75442486-0878-440c-9db1-a7006c25a39f";
const authenticationToken = sign(
{
channelGroupId,
exp: Math.round(Date.now() / 1000 + expiresAfterSeconds),
},
secret
);
return authenticationToken;
}
```
#### Example using a token using typescript
```typescript
let vindral = new Vindral({
authenticationToken: getAuthenticationToken(),
url: "https://lb.cdn.vindral.com",
channelId: "your_channel_id",
minBufferTime: 1000, // Vindral's configurable latency: adjust from 100ms (ultra-low) to 5000ms+ (high stability)
});
vindral.on("error", (error) => {
switch (error.code()) {
case AUTHENTICATION_FAILED_CODE:
// Handle failed authentication
showNotAllowedError();
break;
case AUTHENTICATION_EXPIRED_CODE: {
// Handle expired authentication
// As this a fatal error, the instance is no longer usable and
// you will have to create a new instance of Vindral with a new token
break;
}
default:
break;
}
});
setInterval(() => {
vindral.updateAuthToken(getAuthenticationToken());
}, 1000 * 1800);
```
### Further reading
For examples of libraries and more general information regarding JWT, [see this site](https://jwt.io/).
---
### Timed metadata
Vindral Live has support for [sending timed metadata](https://docs.vindral.com/manage/timed-metadata.md), also called cue points or out-of-band data.
The data is sent as raw text and can be anything from JSON data to Unix timestamps. When received by the Vindral Live ingress, it is tagged with a timecode and emitted client-side when the corresponding frame is shown on the screen (or when audio is played for audio-only streams).
## Listening to timed metadata
### Example using Vindral
```typescript
import { Vindral } from "@vindral/web-sdk"
const instance = new Vindral({
url: "https://lb.cdn.vindral.com",
channelId: "vindral_demo1_ci_099ee1fa-80f3-455e-aa23-3d184e93e04f",
minBufferTime: 1000, // Vindral's configurable latency: adjust from 100ms (ultra-low) to 5000ms+ (high stability)
})
// metadata.content contains the raw string, metadata.timestamp contains timestamp in ms
instance.on("metadata", (metadata) => console.log(metadata))
```
### Example using Vindral Player
```typescript
import { Player } from "@vindral/web-sdk/legacy"
const root = document.querySelector("#root")
const player = new Player({
url: "https://lb.cdn.vindral.com",
channelId: "vindral_demo1_ci_099ee1fa-80f3-455e-aa23-3d184e93e04f",
minBufferTime: 1000, // Vindral's configurable latency: adjust from 100ms (ultra-low) to 5000ms+ (high stability)
})
player.core.play()
player.attach(root)
// metadata.content contains the raw string, metadata.timestamp contains timestamp in ms
player.core.on("metadata", (metadata) => console.log(metadata))
```
## Using playback latency for offsetting events
Since the [Vindral Live playback latency](https://docs.vindral.com/web-sdk/api/classes/Vindral#playbacklatency) is known, it can also be used to sync events. While it will not provide exact synchronization, it might be good enough for most use cases.
```javascript
// pseudo javascript code
myBackend.onMessage((message) => {
setTimeout(() => {
handleMyMessage(message)
}, vindralInstance.playbackLatency)
})
```
## Server wallclock time
Server wallclock time is emitted every second and can be used to synchronize users for a shared event.
> **Note**
>
> The format is Unix timestamp with milliseconds (Milliseconds since Unix Epoch).
> **Note**
>
> Server wallclock time may differ slightly between two viewers connected to different edge servers.
### Example listening to server wallclock time
Simple example using javascript:
```typescript
import { Vindral } from "@vindral/web-sdk"
const instance = new Vindral({
url: "https://lb.cdn.vindral.com",
channelId: "vindral_demo1_ci_099ee1fa-80f3-455e-aa23-3d184e93e04f",
minBufferTime: 1000, // Vindral's configurable latency: adjust from 100ms (ultra-low) to 5000ms+ (high stability)
})
// will log timestamp every second
instance.on("server wallclock time", (timestampMs) => console.log(timestampMs))
```
## Stream time
You may also use the [channelCurrentTime property](https://docs.vindral.com/web-sdk/api/web-sdk/classes/Vindral#channelcurrenttime) on the Vindral Live instance for synchronizing.
To use it, you need to be aware of your stream timestamps before ingress.
---
### Google Cast
Vindral Web SDK supports Google Cast (a.k.a. Chromecast) devices, making it easy to build globally scalable, in-sync, second-screen experiences.
There are several ways Vindral Cast can be initiated, the most straightforward being via our hosted [Embed Player](#example-using-embed-player) or the [Player SDK](#example-using-vindral-player-sdk). A [stand-alone version](#example-using-stand-alone-cast-sdk) of the Vindral Cast Sender is also available.
## Examples
### Example using embed player
[Embed player](https://docs.vindral.com/playout/embeddable-player.md) enables the Cast button by default. It will be visible if the browser has support.
```html
```
### Example using Vindral Player SDK
The bundled *Player* enables the Cast button by default. It will be visible if the browser has support.
```javascript
import { Player } from "@vindral/web-sdk/legacy"
const root = document.querySelector("#root")
const player = new Player({
url: "https://lb.cdn.vindral.com",
channelId: "vindral_demo1_ci_099ee1fa-80f3-455e-aa23-3d184e93e04f",
})
// listeners should be attached to both core and castSender
player.core.on("metadata", (meta) => console.log("metadata", meta))
player.core.on("server wallclock time", (wallclockTime) => console.log("server wallclock time", wallclockTime))
player.castSender.on("metadata", (meta) => console.log("metadata", meta))
player.castSender.on("server wallclock time", (wallclockTime) => console.log("server wallclock time", wallclockTime))
// Listeners for fail/resume/connected/disconnected are handled by Player.
// For a more custom setup, use the stand-alone version
// Will connect, start the stream and try to play
player.core.play()
// Attaches the player view to the DOM
player.attach(root)
// you'll see the button in the controls pane of the player if there's support
```
### Example using stand-alone Cast SDK
```javascript
import { CastSender } from "@vindral/web-sdk/cast-sender"
const castSender = new CastSender({
// Vindral options here
options: {
url: "https://lb.cdn.vindral.com",
channelId: "vindral_demo1_ci_099ee1fa-80f3-455e-aa23-3d184e93e04f",
},
})
castSender.on("connected", () => console.log("connected"))
castSender.on("resumed", () => console.log("resumed"))
castSender.on("disconnected", () => console.log("disconnected"))
castSender.on("failed", () => console.log("failed"))
castSender.on("metadata", (meta) => console.log("metadata", meta))
castSender.on("server wallclock time", (wallclockTime) => console.log("server wallclock time", wallclockTime))
castSender
.init()
.then(() => {
// either create the cast button, that will trigger the native/browser cast receiver picker dialogue
const castButton = document.createElement("google-cast-launcher")
document.body.appendChild(castButton)
// or call start manually, it will also open the dialogue
castSender.start()
})
.catch((err) => {
// not able to init cast
})
// when volume should be set
// castSender.volume = 0.5
// when active channel should be switched, just as with regular Vindral instance
// channelGroupId is needed for channelId to be switched (channels can only be switched within a group)
// castSender.channelId = "demo2"
// when sender/session should be closed
// castSender.unload()
```
### Example using Cast SDK together with Vindral Core
```javascript
import { Vindral } from "@vindral/web-sdk"
import { CastSender } from "@vindral/web-sdk/cast-sender"
const options = {
url: "https://lb.cdn.vindral.com",
channelId: "vindral_demo1_ci_099ee1fa-80f3-455e-aa23-3d184e93e04f",
}
let instance
const createVindralInstance = () => {
instance = new Vindral(options)
// setup, add listeners, connect
// ...
}
const stopVindralInstance = () => {
if (instance) {
instance.unload()
}
instance = undefined
}
const castSender = new CastSender(options)
castSender.on("connected", () => stopVindralInstance())
castSender.on("resumed", () => stopVindralInstance())
castSender.on("disconnected", () => createVindralInstance())
// create button or connect manually
```
### Example using JWT authentication
```javascript
import { CastSender } from "@vindral/web-sdk/cast-sender"
const castSender = new CastSender({
authenticationToken: "initial token",
url: "https://lb.cdn.vindral.com",
channelId: "vindral_demo1_ci_099ee1fa-80f3-455e-aa23-3d184e93e04f",
})
// ... set listeners and init
// whenever necessary, update authToken
setTimeout(() => {
castSender.updateAuthenticationToken("new token")
}, 60000)
```
## Custom Cast Receiver
It is possible to build a custom Cast Receiver as well. This is out of scope for this guide. [Read more about custom web receiver](https://developers.google.com/cast/docs/web_receiver) and [cast web sender](https://developers.google.com/cast/docs/web_sender).
## Browser support
For more information about which platforms Google Cast web sender is available on, [see this site](https://developers.google.com/cast/docs/web_sender).
As of writing:
> The Web Sender SDK is supported on Cast-supported web browsers on Mac, Windows, Linux, ChromeOS, and Android devices.
> Note: The iOS Chrome browser does not support Casting.
---
### Fullscreen and Picture-in-Picture
While Vindral Live player has support for running in fullscreen mode and Picture-in-Picture (PiP) mode, there are some caveats to be aware of.
The [Vindral Player](https://docs.vindral.com/web-sdk/api/player/interfaces/Player/) is a web component-based player with built-in buttons for fullscreen and picture-in-picture (PiP). When integrating the Vindral Web SDK, you'll need to handle the features yourself.
> **Info**
>
> If you are using WebCodecs or another canvas-rendered playback path, `streamToMediaElementEnabled: true` is required for Picture-in-Picture support and is the recommended way to retain media-element fullscreen/PiP behavior in non-MSE playback. See [WebCodecs & Offscreen Renderer](https://docs.vindral.com/playout/websdk/webcodecs-offscreen-renderer.md) for the decoder and rendering-path tradeoffs.
## Picture-in-Picture
[Vindral SDK provides a Picture-in-Picture helper](https://docs.vindral.com/web-sdk/api/web-sdk/classes/Vindral/#pictureinpicture) that you can use to query for support and toggle PiP mode programmatically. If you have requirements on look and feel of the PiP window, you can use the Picture-in-Picture API directly instead.
Read more about the [Picture-in-Picture API](https://developer.mozilla.org/en-US/docs/Web/API/Picture-in-Picture_API) and make sure to understand the limitations and requirements for using it.
If playback stays on a canvas without the media-element bridge, PiP is not available.
One such limitation is that some Android devices, for instance, require fullscreen to be active before PiP can be activated automatically through the Picture-in-Picture API (home screen button). This is not a limitation in Vindral Web SDK, but a limitation in the Picture-in-Picture API itself.
## Fullscreen
When integrating the Vindral Web SDK, you need to handle fullscreen mode yourself, you can use the Fullscreen API directly. Read more about the [Fullscreen API](https://developer.mozilla.org/en-US/docs/Web/API/Fullscreen_API) and make sure to understand the limitations and requirements for using it.
If you are building on the canvas-rendered playback path and want fullscreen/PiP behavior through a standard media element, enable `streamToMediaElementEnabled`.
## Native
Have a look at the [native examples](https://github.com/RealSprint/vindral-examples-webview) for information regarding how to toggle fullscreen and PiP on native iOS/Android.
---
### Vindral Player
Vindral Player is our ready-to-go web component-based player for easy integration into your web applications. It is ideal for customizing controls or when the embed solution is not sufficient.
[](https://docs.vindral.com/img/guides/player/player_example.png)
## Installation
Install `@vindral/web-sdk` using `npm`:
```bash
npm install --save @vindral/web-sdk
```
Equivalent for `yarn`:
```bash
yarn add @vindral/web-sdk
```
### Hosted via jsDelivr
> **Warning: Use a pinned version**
>
> The jsDelivr CDN (`https://cdn.jsdelivr.net`) is a third-party service and is not operated by Vindral. When using this script-tag distribution, pin an explicit package version instead of relying on the latest release so future updates do not change your integration unexpectedly.
```html
```
Example with JavaScript and HTML
To be able to use the `` in your HTML you have to call `registerComponents`.
JavaScript
```javascript
import { registerComponents } from "@vindral/web-sdk/player"
registerComponents()
```
HTML
```html
```
Or use `vindral-player-component.js`, which is a self-registering variant of the web components player intended to be used from a script tag. After loading the pinned script above, you can use it directly in your HTML.
HTML
```html
```
## Configuration
`Vindral Player` can easily be configured with HTML attributes and supports most of the same options as the core Web SDK in the [web-sdk](https://docs.vindral.com/web-sdk/api/web-sdk/classes/Vindral).
Some common core option attributes are:
- `channel-id` - (required) which channel to connect to.
- `channel-group-id` - when connecting to a channel group.
- `muted` - start muted.
- `authentication-token` - used when connecting to authed channels.
- `min-buffer-time` - **Vindral's configurable latency**: adjust from 100ms (ultra-low) to 5000ms+ (high stability). Default is 1500ms.
- `max-buffer-time` - set this to enable dynamic latency adjustment. By default, this will be disabled (set to same as min-buffer-time).
- `max-video-bit-rate` - constrain video bitrate.
- `max-size` - constrain video width and height.
For advanced playback-pipeline tuning, `vindral-player` also supports:
- `decoders="webcodecs,mse,wasm"` - prefer WebCodecs, then fall back to MSE and WASM
- `offscreen-canvas-enabled="false"` - explicitly disable worker-side OffscreenCanvas rendering; when omitted, WebCodecs enables it automatically when supported
- `stream-to-media-element-enabled="true"` - route canvas-rendered output through a media element for fullscreen/PiP support in non-MSE mode. Default is `false`.
- `webcodecs-hardware-acceleration="prefer-software"` - control whether WebCodecs should prefer hardware or software decoding
Example:
```html
```
See [WebCodecs & Offscreen Renderer](https://docs.vindral.com/playout/websdk/webcodecs-offscreen-renderer.md) for the rendering-path tradeoffs behind these attributes.
The following controls will also appear in some use cases based on support detection:
- `cast`
- `airplay`
- `pip`
- `fullscreen`
And can be enabled and disabled like this:
```html
```
These controls default to true except AirPlay.
[Read the full API reference for all the attributes](https://docs.vindral.com/web-sdk/api/player/interfaces/Player/#attributes)
## Controls and UI
Vindral Player includes all predefined controls for ease of use. It also comes with a responsive design that can automatically arrange controls and offers extensive customization options.
Demonstrating the responsive design for small players:
[](https://docs.vindral.com/img/guides/player/player_grid.png)
Channel switching with our built-in grid is available when providing a `channel-group-id`:
```html
```
[](https://docs.vindral.com/img/guides/player/player_grid.png)
### Styling With CSS
The `vindral-player` HTML element can be styled with CSS like any other HTML element. For example:
```css
vindral-player {
max-width: 100%;
max-height: 100%;
--vindral-fg-strong: pink;
aspect-ratio: 16 / 9;
}
```
#### CSS Variables
CSS variables are custom properties that allow you to define reusable values in your CSS. They can be used to customize the appearance of the `vindral-player` element.
To control the visibility of various player elements:
```css
vindral-player {
/* Hide all controls */
--vindral-ui-display: none;
--vindral-play-button-display: none;
--vindral-mute-button-display: none;
--vindral-airplay-button-display: none;
--vindral-pip-button-display: none;
--vindral-fullscreen-button-display: none;
--vindral-cast-button-display: none;
--vindral-grid-button-display: none;
--vindral-grid-item-offline-display: none;
--vindral-volume-range-display: none;
--vindral-rendition-menu-display: none;
--vindral-language-menu-display: none;
--vindral-play-overlay-display: none;
--vindral-buffering-overlay-display: none;
}
```
These CSS variables allow you to customize the appearance of the player.
```css
vindral-player {
--vindral-fg-strong: #000000;
--vindral-fg-subtle: #666666;
--vindral-fg-extra-subtle: #999999;
--vindral-bg-strong: #ffffff;
--vindral-bg-subtle: #f2f2f2;
--vindral-bg-extra-subtle: #e6e6e6;
--vindral-bg-component: #cccccc;
--vindral-bg-component-hover: #b3b3b3;
--vindral-bg-component-active: #999999;
--vindral-padding-1: 4px;
--vindral-padding-2: 8px;
--vindral-padding-3: 12px;
--vindral-padding-4: 16px;
--vindral-padding-5: 32px;
--vindral-control-padding: 4px;
--vindral-button-padding: 8px;
--vindral-ui-font: Arial, sans-serif;
}
```
## Vindral Controller
For more customization, the Player library provides a collection of components.
`` supports the same attributes as `` but doesn't come with predefined controls.
Example of building your own player:
```html
```
### Slots
Slots are like placeholders in custom elements where you can add your own content.
#### vindral-controller
- no slot(default slot): Places elements in the bottom
- slot="top-bar": Places elements in the top.
- slot="middle": Places elements in the middle.
- slot="overlay-interactive": Places element in the overlay area.
- slot="overlay": In contrast to the other slots "overlay" isn't shown/hidden on user interaction.
#### control-bar
- no slot(default slot): Places elements on the left side of the control bar.
- slot="right": Places elements on the right side of the control bar.
#### buttons
- slot="icon": Allows you to replace the default icon.
```html
Play
```
### Components
A list of available web components:
- vindral-player
- vindral-controller
- vindral-control-bar
- vindral-play-button
- vindral-mute-button
- vindral-buffering-overlay
- vindral-scroll-overlay
- vindral-play-overlay
- vindral-user-input-play-overlay
- vindral-fullscreen-button
- vindral-rendition-levels-menu
- vindral-channel-grid-button
- vindral-channel-grid
- vindral-pip-button
- vindral-airplay-button
- vindral-cast-button
- vindral-cast-overlay
- vindral-buffering-icon
- vindral-language-menu
- vindral-volume-range
## TypeScript
If you are using TypeScript, you can use the exported `VindralHTMLElementTagNameMap` to get typings as shown below:
```javascript
import { VindralHTMLElementTagNameMap, registerComponents } from "@vindral/web-sdk/player"
declare global {
interface HTMLElementTagNameMap extends VindralHTMLElementTagNameMap {}
}
registerComponents()
const player = document.createElement("vindral-player")
```
## React
React typings for our web components are exported in the `@vindral/web-sdk/react` package. To ensure TypeScript picks up the types, update your `tsconfig.json` file as follows:
```json
{
"compilerOptions": {
"types": ["@vindral/web-sdk/react"]
}
}
```
## Accessing the Core SDK
Both `vindral-player` and `vindral-controller` expose the [Vindral Live client instance](https://docs.vindral.com/web-sdk/api/web-sdk/classes/Vindral). You must wait for the `"vindral-instance-ready"` event before it becomes available.
```javascript
const player = document.createElement("vindral-player")
player.addEventListener("vindral-instance-ready", () => {
player.instance.on("error", (error) => {
console.error("error", error)
})
player.instance.on("playback state", (state) => {
console.log("playback state", state)
}
})
```
---
### WebCodecs and Offscreen Renderer
Vindral Web SDK supports low-level browser video decoding via the [WebCodecs API](https://developer.mozilla.org/en-US/docs/Web/API/WebCodecs_API) and, when supported, off-main-thread rendering via an offscreen renderer backed by [OffscreenCanvas](https://developer.mozilla.org/en-US/docs/Web/API/OffscreenCanvas). Together these can unlock a lower-latency, lower-overhead playback pipeline compared to the traditional `MSE` path, where drift management is harder to achieve. Whether hardware or software decoding is used is configurable — see [Hardware acceleration and decoder latency](#hardware-acceleration-and-decoder-latency).
The WebCodecs decoder is opt-in and can be enabled by setting the `decoders` option to include `webcodecs`. When the resolved decoder is `webcodecs`, the SDK will also automatically prefer OffscreenCanvas rendering unless `offscreenCanvasEnabled` is explicitly set to `false`.
## Decoder pipeline
The SDK selects a decoder based on the `decoders` option, which is an ordered priority list:
```javascript
import { Vindral } from "@vindral/web-sdk"
const instance = new Vindral({
url: "https://lb.cdn.vindral.com",
channelId: "...",
decoders: ["webcodecs", "mse", "wasm"], // default is ["mse", "wasm"]
})
```
| Decoder | Description |
|---|---|
| `webcodecs` | Uses the browser's [WebCodecs API](https://developer.mozilla.org/en-US/docs/Web/API/WebCodecs_API) for low-level decoding with configurable hardware or software acceleration. Lowest overhead and best latency control where supported. |
| `mse` | Uses [Media Source Extensions](https://developer.mozilla.org/en-US/docs/Web/API/Media_Source_Extensions_API) — the standard browser media pipeline. Widest compatibility. |
| `wasm` | Software decoder compiled to WebAssembly. Used as a fallback when neither WebCodecs nor MSE is available. |
The SDK will try each decoder in order and use the first one supported by the browser. Specifying `["webcodecs", "mse", "wasm"]` means WebCodecs is preferred, with automatic fallback to MSE and then WASM.
If DRM is active, the SDK will use `mse` regardless of decoder order.
## Rendering path and media-element bridge
The WebCodecs/offscreen path is controlled by `offscreenCanvasEnabled`, while `streamToMediaElementEnabled` controls whether canvas-rendered output is bridged back into a `