MuxVideo
Video element for Mux-hosted HLS streams
Video element for playing Mux-hosted HLS streams. Built on hls.js with Mux-specific optimizations.
Import
pnpm add @videojs/react @videojs/mux-videopnpm add @videojs/html @videojs/mux-videoimport { MuxVideo } from '@videojs/react/media/mux-video';import '@videojs/html/media/mux-video';Or load it from the CDN:
<script type="module" src="https://cdn.jsdelivr.net/npm/@videojs/cdn@10.0.0-beta.32/media/mux-video.js"></script>Load a source
The source param builds the URL for you from a playback ID, an optional custom domain, and playback params. Playback params are just camelCased Mux playback query params; for example, max_resolution becomes maxResolution.
<MuxVideo
source={{
playbackId: 'BV3YZtogl89mg9VcNBhhnHm02Y34zI1nlMuMQfAbl3dM',
customDomain: 'media.example.com',
playback: { maxResolution: '1080p' }
}}
/>If for some reason you need a bit more control, you can use the src param with a plain ’ol URL, too:
<MuxVideo
src="https://stream.mux.com/BV3YZtogl89mg9VcNBhhnHm02Y34zI1nlMuMQfAbl3dM.m3u8"
/>MuxVideo ignores the same source object when it is assigned again. A new object fires sourcechange even when its values are equal, although an equivalent playback source does not reload.
MuxVideo takes Mux content two ways: a stream URL through src, or a structured source object.
<mux-video src="https://stream.mux.com/BV3YZtogl89mg9VcNBhhnHm02Y34zI1nlMuMQfAbl3dM.m3u8"></mux-video>The source object builds the URL for you from a playback ID, an optional custom domain, and playback params. Playback params are just camelCased Mux playback query params; for example, max_resolution becomes maxResolution.
const video = document.querySelector('mux-video')!;
video.source = {
playbackId: 'BV3YZtogl89mg9VcNBhhnHm02Y34zI1nlMuMQfAbl3dM',
customDomain: 'media.example.com',
playback: { maxResolution: '1080p' },
};MuxVideo ignores the same source object when it is assigned again. A new object fires sourcechange even when its values are equal, although an equivalent playback source does not reload.
Posters and storyboards
MuxVideo derives a poster image and a storyboard from the playback ID. source.poster and source.storyboard configure the generated URLs.
When MuxVideo is inside a player, it supplies the poster for the skin to display. Set poster on the player when you want to use your own image instead.
A generated poster becomes available after MuxVideo mounts. Pass poster to the player when the image must appear in server-rendered HTML.
MuxVideo injects the derived storyboard <track> automatically and removes it when the media detects a live stream. Configure the derived URLs through the source object:
<MuxVideo
source={{
playbackId: 'BV3YZtogl89mg9VcNBhhnHm02Y34zI1nlMuMQfAbl3dM',
poster: { time: 2, width: 1280 },
storyboard: { format: 'webp' },
}}
/>const video = document.querySelector('mux-video')!;
video.source = {
playbackId: 'BV3YZtogl89mg9VcNBhhnHm02Y34zI1nlMuMQfAbl3dM',
poster: { time: 2, width: 1280 },
storyboard: { format: 'webp' },
};For declarative HTML, poster-time="2" reflects to source.poster.time after the src attribute is parsed.
The storyboard lives on a Mux domain, so MuxVideo has to be CORS-enabled for that cross-origin <track> to load at all. Thumbnail then fetches the sprite sheets its cues point at the same way:
<MuxVideo
source={{ playbackId: 'BV3YZtogl89mg9VcNBhhnHm02Y34zI1nlMuMQfAbl3dM' }}
crossOrigin="anonymous"
/><mux-video
src="https://stream.mux.com/BV3YZtogl89mg9VcNBhhnHm02Y34zI1nlMuMQfAbl3dM.m3u8"
crossorigin="anonymous"
></mux-video>Signed playback
For signed playback, put the playback token on source.playback.token. The token replaces every other playback param, so bake modifiers like resolution and time bounds into the token when you sign it.
Signed playback needs a separate token for each image URL. Put the thumbnail token (aud: 't') at source.poster.token and the storyboard token (aud: 's') at source.storyboard.token. If either token is missing or has the wrong audience, MuxVideo does not generate the corresponding URL.
<MuxVideo
source={{
playbackId: 'BV3YZtogl89mg9VcNBhhnHm02Y34zI1nlMuMQfAbl3dM',
playback: { token: playbackToken },
poster: { token: posterToken },
storyboard: { token: storyboardToken },
}}
/>const video = document.querySelector('mux-video')!;
video.source = {
playbackId: 'BV3YZtogl89mg9VcNBhhnHm02Y34zI1nlMuMQfAbl3dM',
playback: { token: playbackToken },
poster: { token: posterToken },
storyboard: { token: storyboardToken },
};Analytics and casting
MuxVideo plays Mux streams. It doesn’t monitor them or cast them — Mux Data and Google Cast are separate extensions you add to the player alongside it. Mux Data needs no environment key here, since Mux attributes the views to the environment that owns the playback ID:
Add @videojs/mux-data to the installation before using the telemetry component below:
pnpm add @videojs/mux-dataimport { createPlayer } from '@videojs/react';
import { GoogleCast } from '@videojs/react/extensions/google-cast';
import { MuxData } from '@videojs/react/extensions/mux-data';
import { MuxVideo } from '@videojs/react/media/mux-video';
import { videoFeatures } from '@videojs/react/video';
const { Player } = createPlayer({ features: videoFeatures });
export function MuxPlayer() {
return (
<Player>
<MuxVideo source={{ playbackId: 'BV3YZtogl89mg9VcNBhhnHm02Y34zI1nlMuMQfAbl3dM' }} playsInline />
<MuxData playerSoftwareName="mux-video" />
<GoogleCast />
</Player>
);
}<script type="module">
import '@videojs/html/video/player';
import '@videojs/html/media/mux-video';
import '@videojs/html/extensions/mux-data';
import '@videojs/html/extensions/google-cast';
</script>
<video-player>
<mux-video src="https://stream.mux.com/BV3YZtogl89mg9VcNBhhnHm02Y34zI1nlMuMQfAbl3dM.m3u8" playsinline></mux-video>
<mux-data player-software-name="mux-video"></mux-data>
<google-cast></google-cast>
</video-player>Examples
Basic Usage
import { MuxVideo } from '@videojs/react/media/mux-video';
export default function BasicUsage() {
return (
<MuxVideo
className="mux-video"
src="https://stream.mux.com/BV3YZtogl89mg9VcNBhhnHm02Y34zI1nlMuMQfAbl3dM.m3u8"
autoPlay
muted
playsInline
loop
crossOrigin="anonymous"
/>
);
}
.mux-video {
width: 100%;
aspect-ratio: 16 / 9;
}
<media-container class="media-container">
<mux-video src="https://stream.mux.com/BV3YZtogl89mg9VcNBhhnHm02Y34zI1nlMuMQfAbl3dM.m3u8" autoplay muted playsinline loop crossorigin="anonymous"></mux-video>
</media-container>
.media-container {
position: relative;
display: block;
width: 100%;
aspect-ratio: 16 / 9;
}
import '@videojs/html/ui/container';
import '@videojs/html/media/mux-video';
API Reference
Props
Accepts the standard React props for a native <video>, plus these Video.js-specific props:
| Prop | Type | Default | Details |
|---|---|---|---|
disableRemotePlayback | unknown | false | |
| |||
preload | MediaPreloadType | 'metadata' | |
| |||
source | { drm?: MuxDrmParams } | null | null | |
| |||
src | string | '' | |
| |||
streamType | MediaStreamType | "unknown" | |
| |||
Engine options
source.engine.hlsJs
Options passed under source.engine.hlsJs.
| Option | Type | Details |
|---|---|---|
abrBandWidthFactor | number | undefined | |
abrBandWidthUpFactor | number | undefined | |
abrController | typeof AbrController | undefined | |
abrEwmaDefaultEstimate | number | undefined | |
| ||
abrEwmaDefaultEstimateMax | number | undefined | |
abrEwmaFastLive | number | undefined | |
abrEwmaFastVoD | number | undefined | |
abrEwmaSlowLive | number | undefined | |
abrEwmaSlowVoD | number | undefined | |
abrMaxWithRealBitrate | boolean | undefined | |
appendErrorMaxRetry | number | undefined | |
assetPlayerId | string | undefined | |
audioPreference | AudioSelectionOption | undefined | |
audioStreamController | typeof AudioStreamController | undefined | |
audioTrackController | typeof AudioTrackController | undefined | |
autoStartLoad | boolean | undefined | |
backBufferLength | number | undefined | |
bufferController | typeof BufferController | undefined | |
capLevelController | typeof CapLevelController | undefined | |
capLevelOnFPSDrop | boolean | undefined | |
capLevelToPlayerSize | boolean | undefined | |
captionsTextTrack1Label | string | undefined | |
captionsTextTrack1LanguageCode | string | undefined | |
captionsTextTrack2Label | string | undefined | |
captionsTextTrack2LanguageCode | string | undefined | |
captionsTextTrack3Label | string | undefined | |
captionsTextTrack3LanguageCode | string | undefined | |
captionsTextTrack4Label | string | undefined | |
captionsTextTrack4LanguageCode | string | undefined | |
certLoadPolicy | LoadPolicy | undefined | |
cmcd | CMCDControllerConfig | undefined | |
cmcdController | typeof CMCDController | undefined | |
contentSteeringController | typeof ContentSteeringController | un... | |
| ||
cueHandler | CuesInterface | undefined | |
debug | boolean | ILogger | undefined | |
defaultAudioCodec | string | undefined | |
detectStallWithCurrentTimeMs | number | undefined | |
drmSystemOptions | DRMSystemOptions | undefined | |
drmSystems | DRMSystemsConfiguration | undefined | |
emeController | typeof EMEController | undefined | |
emeEnabled | boolean | undefined | |
enableCEA708Captions | boolean | undefined | |
enableDateRangeMetadataCues | boolean | undefined | |
enableEmsgKLVMetadata | boolean | undefined | |
enableEmsgMetadataCues | boolean | undefined | |
enableID3MetadataCues | boolean | undefined | |
enableIMSC1 | boolean | undefined | |
enableInterstitialPlayback | boolean | undefined | |
enableSoftwareAES | boolean | undefined | |
enableWebVTT | boolean | undefined | |
enableWorker | boolean | undefined | |
errorController | typeof ErrorController | undefined | |
fetchSetup | Request) | undefined | function | |
| ||
fLoader | FragmentLoaderConstructor | undefined | |
forceKeyFrameOnDiscontinuity | boolean | undefined | |
fpsController | typeof FPSController | undefined | |
fpsDroppedMonitoringPeriod | number | undefined | |
fpsDroppedMonitoringThreshold | number | undefined | |
fragLoadingMaxRetry | number | undefined | |
fragLoadingMaxRetryTimeout | number | undefined | |
fragLoadingRetryDelay | number | undefined | |
fragLoadingTimeOut | number | undefined | |
fragLoadPolicy | LoadPolicy | undefined | |
frontBufferFlushThreshold | number | undefined | |
highBufferWatchdogPeriod | number | undefined | |
ignoreDevicePixelRatio | boolean | undefined | |
ignorePlaylistParsingErrors | boolean | undefined | |
initialLiveManifestSize | number | undefined | |
interstitialAppendInPlace | boolean | undefined | |
interstitialAssetListLoadPolicy | LoadPolicy | undefined | |
interstitialLiveLookAhead | number | undefined | |
interstitialsController | typeof InterstitialsController | unde... | |
| ||
keyLoadPolicy | LoadPolicy | undefined | |
levelLoadingMaxRetry | number | undefined | |
levelLoadingMaxRetryTimeout | number | undefined | |
levelLoadingRetryDelay | number | undefined | |
levelLoadingTimeOut | number | undefined | |
licenseResponseCallback | undefined | function | |
| ||
licenseXhrSetup | Uint8Array | Promise<Uint8Array | void>) | undefined | function | |
| ||
liveBackBufferLength | number | null | undefined | |
liveDurationInfinity | boolean | undefined | |
liveMaxLatencyDuration | number | undefined | |
liveMaxLatencyDurationCount | number | undefined | |
liveSyncDuration | number | undefined | |
liveSyncDurationCount | number | undefined | |
liveSyncMode | 'edge' | 'buffered' | undefined | |
liveSyncOnStallIncrease | number | undefined | |
loader | object | |
| ||
lowLatencyMode | boolean | undefined | |
manifestLoadingMaxRetry | number | undefined | |
manifestLoadingMaxRetryTimeout | number | undefined | |
manifestLoadingRetryDelay | number | undefined | |
manifestLoadingTimeOut | number | undefined | |
manifestLoadPolicy | LoadPolicy | undefined | |
maxAudioFramesDrift | number | undefined | |
maxBufferHole | number | undefined | |
maxBufferLength | number | undefined | |
maxBufferSize | number | undefined | |
maxDevicePixelRatio | number | undefined | |
maxFragLookUpTolerance | number | undefined | |
maxLiveSyncPlaybackRate | number | undefined | |
maxLoadingDelay | number | undefined | |
maxMaxBufferLength | number | undefined | |
maxStarvationDelay | number | undefined | |
minAutoBitrate | number | undefined | |
nudgeMaxRetry | number | undefined | |
nudgeOffset | number | undefined | |
nudgeOnVideoHole | boolean | undefined | |
playlistLoadPolicy | LoadPolicy | undefined | |
pLoader | PlaylistLoaderConstructor | undefined | |
preferManagedMediaSource | boolean | undefined | |
preserveManualLevelOnError | boolean | undefined | |
primarySessionId | string | undefined | |
progressive | boolean | undefined | |
renderTextTracksNatively | boolean | undefined | |
requestMediaKeySystemAccessFunc | MediaKeyFunc | null | undefined | |
requireKeySystemAccessOnStart | boolean | undefined | |
startFragPrefetch | boolean | undefined | |
startLevel | number | undefined | |
startOnSegmentBoundary | boolean | undefined | |
startPosition | number | undefined | |
steeringManifestLoadPolicy | LoadPolicy | undefined | |
stretchShortVideoTrack | boolean | undefined | |
subtitlePreference | SubtitleSelectionOption | undefined | |
subtitleStreamController | typeof SubtitleStreamController | und... | |
| ||
subtitleTrackController | typeof SubtitleTrackController | unde... | |
| ||
testBandwidth | boolean | undefined | |
timelineController | typeof TimelineController | undefined | |
timelineOffset | number | undefined | |
useMediaCapabilities | boolean | undefined | |
videoPreference | VideoSelectionOption | undefined | |
widevineLicenseUrl | string | undefined | |
workerPath | string | null | undefined | |
xhrSetup | void) | undefined | function | |
| ||
source.engine.nativeHls
Options passed under source.engine.nativeHls.
| Option | Type | Details |
|---|---|---|
drmSystems | DrmSystemsConfig | undefined | |
| ||
Ref
Forwards its ref to the rendered <video>. The ref is an HTMLVideoElement and exposes its complete native property and method API.
Events
Handle standard media events with React event props such as onPlay and onTimeUpdate. For native events without a React prop, attach a listener through the ref with addEventListener.