ReferenceMedia
PlayerJsVideo
Video component that plays any embed implementing the player.js protocol, such as Mux Player, Gumlet, FrameRate, Livid, Bunny Stream, and Streamable
player.js is a postMessage protocol for controlling embedded players, not a video host. Any embed that implements its receiver side plays through this one component: Mux Player’s iframe embed, Gumlet, FrameRate, Livid, Bunny Stream, Streamable, and others. Commands are posted to the embed directly, so no third-party script loads.
Import
Load a source
src takes the embed URL of any player.js receiver: an absolute http or https URL, with protocol-relative URLs (//host/…) read as https. Nothing inspects the URL to decide whether it speaks player.js; choosing this component is the opt-in. A src that isn’t an http(s) URL fails with MEDIA_ERR_SRC_NOT_SUPPORTED, and an embed that doesn’t implement the protocol never reports ready, so the element stays at readyState 0.
Feature detection
Embeds implement the spec to different degrees. Each one lists the methods and events it supports in its ready message, and every command is checked against that list:
- A missing getter leaves its value at the default, such as a
durationofNaN. Some embeds implement a getter but can’t answer it yet: Streamable reports no duration until playback starts. - A missing setter is a no-op; the value stays wherever the embed has it.
supports(type, name) reports whether the embed advertised a method or event. type is 'method' or 'event', and name is one player.js name or an array of names that must all be supported. It returns false until the embed reports ready.
onLoadedMetadata fires when the embed reports ready, so its handler is the first point where the answer is meaningful. event.currentTarget is the playback adapter:
Controls
Without controls, the element ignores pointer events, so a player skin above it receives every click. With controls, the embed’s own chrome takes pointer input.
player.js itself can’t hide an embed’s chrome, but for the services it recognizes, the element does it through the embed URL, as far as each service allows:
Other services get their URL untouched; pass whatever they offer under source.engine.playerJs.
URL parameters
For the recognized services, autoplay, muted (either muted or defaultMuted), loop, and preload are written onto the embed URL in the service’s own spelling, and turned off explicitly where the service defaults to on: Gumlet and Streamable loop, and Bunny Stream autoplays. Livid and Mux Player also take preload as the element’s own value. The embed reads its URL once, so changing these later reaches the embed over the protocol (autoplay, muted, loop) or not until the next source (controls, preload); rebuilding the frame for them would restart the video.
Every other parameter a service documents works too, in either of two places. Written into src, a parameter is kept as written, even over one the element would derive. Under source.engine.playerJs, it overrides both. A parameter a service reads from the URL hash, like Livid’s start time #t=25, goes in src.
Behavior
autoplay,muted(seeded bydefaultMuted), andloopare also applied over the protocol once the embed reports ready, which is how they reach services the element doesn’t recognize. An embed withoutsetLoopis looped by replaying it onended.volume(0 to 1, sent as the spec’s 0 to 100),muted, and seeking throughcurrentTimeuse the spec’s methods.playbackRatereaches only embeds that advertisesetPlaybackRate, an extension to the spec that Gumlet implements.- player.js reports no buffering, so a started embed counts as playing.
- No text tracks:
textTracksstays empty. - The protocol has no fullscreen command, so the element’s own
requestFullscreen()fullscreens the iframe. posterandplaysInlineare stored but have no effect on the embed.preloadreaches Livid and Mux Player as is and Bunny Stream aspreload=falsewhen it’s"none", and no other service.- An embed
errorwith code 1 surfaces asMEDIA_ERR_SRC_NOT_SUPPORTED. Codes 2 and 3 mean a command wasn’t supported; they’re ignored, with a warning in development. Any other code is a fatal error carrying the embed’s message.
Examples
Basic Usage
API Reference
Props
Accepts these Video.js-specific props:
Engine options
source.engine.playerJs
player.js standardizes the messages an embed answers, not its URL, so there are no shared parameters. Every key under source.engine.playerJs is written onto the embed URL’s query as given, for whichever service serves it — anything in Gumlet’s, Bunny Stream’s, or Livid’s parameter lists, for example. Values are stringified (true becomes 'true'), an array repeats the parameter once per value, and null removes a parameter the URL would otherwise carry. These override both src and the parameters the element derives from its props. Changing them reloads the embed. Media Sources covers how engine options fit into a structured source.
referrerPolicy never reaches the URL; it sets the referrerpolicy of the iframe the component renders.
Prefer the autoplay, loop, muted, controls, and preload props over their URL spellings: the props also reach the embed over the protocol and keep the element’s state in step with it.
Refs
ref
Forwards to the rendered <iframe>,
an HTMLIFrameElement. The iframe cannot play or seek; use mediaRef for playback.
mediaRef
Receives the PlayerJsAdapter that
drives the embed, which exposes media methods and properties such
as play() and currentTime. It is set once the
adapter has attached to the iframe, so its target is already that iframe, and
it is cleared when the iframe unmounts.
Events
Handle standard media events with React event props such as onPlay and onTimeUpdate. The adapter dispatches them, not the iframe. For events without a React prop, call addEventListener on the adapter from mediaRef.