Skip to content

Player — Web Components

NPM:

Terminal window
npm install @livepeer-frameworks/player-wc
import "@livepeer-frameworks/player-wc/define";

CDN (no bundler):

<!-- unpkg -->
<script src="https://unpkg.com/@livepeer-frameworks/player-wc/fw-player.js"></script>
<!-- or jsdelivr -->
<script src="https://cdn.jsdelivr.net/npm/@livepeer-frameworks/player-wc/fw-player.js"></script>

Shadow DOM encapsulates all CSS — host page styles won’t break controls.

<fw-player content-type="live" content-id="<YOUR_PLAYBACK_ID>" autoplay muted></fw-player>

The element resolves through the official FrameWorks Gateway from the viewer’s browser, so Foghorn routes from that viewer’s IP. Set gateway-url only for a fully self-hosted control plane or local Gateway preview. For backend-generated playback URLs or custom players that do not use this element, use the dashboard playback DNS URL directly.

<fw-player
content-type="live"
content-id="<YOUR_PLAYBACK_ID>"
mist-url="https://edge-egress.eu.example.com"
autoplay
muted
></fw-player>
<fw-player content-type="dvr" content-id="pk_..."></fw-player>
<fw-player content-type="clip" content-id="pk_..."></fw-player>

Provide your own controls via the controls slot. Access the controller for programmatic control:

<fw-player id="player" content-type="live" content-id="pk_..." autoplay muted></fw-player>
<script>
const player = document.getElementById("player");
// Access the controller
player.controller.play();
player.controller.pause();
player.controller.seek(30000);
player.controller.setVolume(0.5);
// Listen for state changes
player.addEventListener("fw-state-change", (e) => {
console.log("State:", e.detail.state);
});
</script>

Provide custom controls via the controls slot and call the player element’s exposed controller:

<fw-player id="slot-player" content-id="pk_..." content-type="live">
<div slot="controls">
<button type="button" data-action="play">Play/Pause</button>
<button type="button" data-action="back">Back 10s</button>
<button type="button" data-action="forward">Forward 10s</button>
<button type="button" data-action="mute">Mute</button>
<button type="button" data-action="fullscreen">Fullscreen</button>
</div>
</fw-player>
<script>
const player = document.getElementById("slot-player");
player.addEventListener("click", (event) => {
const action = event.target?.dataset?.action;
if (action === "play") player.controller.togglePlay();
if (action === "back") player.controller.seekBy(-10000);
if (action === "forward") player.controller.seekBy(10000);
if (action === "mute") player.controller.toggleMute();
if (action === "fullscreen") player.controller.toggleFullscreen();
});
</script>

For bundled apps, import the package root to register the composable helper elements, then use them outside the player element with the for attribute:

import "@livepeer-frameworks/player-wc";
<fw-player id="my-player" content-id="pk_..." content-type="live"></fw-player>
<div class="external-controls">
<fw-play-button for="my-player"></fw-play-button>
<fw-volume-button for="my-player"></fw-volume-button>
<fw-time-display for="my-player"></fw-time-display>
<fw-live-badge for="my-player"></fw-live-badge>
<fw-fullscreen-button for="my-player"></fw-fullscreen-button>
</div>
ElementPurpose
<fw-play-button>Play/pause toggle
<fw-skip-button>Skip forward/back (direction="back" or "forward")
<fw-volume-button>Mute/unmute toggle
<fw-time-display>Current time / duration
<fw-live-badge>Live indicator + jump-to-live
<fw-fullscreen-button>Fullscreen toggle
AttributeTypeDefaultDescription
content-idstringPlayback ID
content-typestring"live"live, dvr, clip, or vod
gateway-urlstringOfficialGateway GraphQL endpoint override
mist-urlstringDirect MistServer URL
auth-tokenstringBearer token for Gateway GraphQL resolution
playback-tokenstringViewer JWT for playback access control
playback-token-transport"query" | "header""query"Sends the viewer JWT as ?jwt= or as Authorization: Bearer where player transports can set headers
thumbnail-urlstringPoster image before playback
autoplaybooleantrueAuto-start playback
mutedbooleanfalseStart muted
controlsbooleanfalseCompatibility no-op
no-controlsbooleanfalseHide the built-in controls
stock-controlsbooleanfalseUse browser-native video controls
native-controlsbooleanfalseAlias for stock-controls
animate-prerollbooleanfalseCycle thumbnail sprite tiles as a preroll animation before playback
themestring"default"Theme preset
localestring"en"Built-in UI locale
playback-modestring"auto"Controls/dev-panel mode label; current WC initial selection does not apply it
dev-modebooleanfalseShow dev panel
debugbooleanfalseDebug logging
fw-player {
--fw-accent: 200 80% 60%;
--fw-surface: 230 15% 12%;
--fw-radius: 8px;
}

Or use a preset:

<fw-player theme="tokyo-night" ...></fw-player>
<template>
<fw-player :content-id="contentId" content-type="live" autoplay muted />
</template>
<script setup>
import "@livepeer-frameworks/player-wc/define";
import { ref } from "vue";
const contentId = ref("pk_...");
</script>
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from "@angular/core";
import "@livepeer-frameworks/player-wc/define";
@NgModule({ schemas: [CUSTOM_ELEMENTS_SCHEMA] })
export class AppModule {}
<fw-player [attr.content-id]="contentId" content-type="live" autoplay muted></fw-player>