feat(packages)!: support media components as markup (#1883)

This commit is contained in:
Wesley Luyten
2026-07-30 17:18:58 -07:00
committed by GitHub
parent a5e73393fe
commit 68e96079e5
52 changed files with 1392 additions and 357 deletions
+41 -44
View File
@@ -1,6 +1,6 @@
---
title: Google Cast
description: Cast playback to Chromecast devices with built-in Google Cast support, and configure the receiver and load request
description: Cast playback to Chromecast devices with the Google Cast component, and configure the receiver and load request
---
import FrameworkCase from '@/components/docs/FrameworkCase.astro';
@@ -8,11 +8,12 @@ import DocsLink from '@/components/docs/DocsLink.astro';
import DocsLinkCard from '@/components/docs/DocsLinkCard.astro';
import Aside from '@/components/Aside.astro';
Video.js streaming media elements (HLS and DASH) have Google Cast built in. Add a <DocsLink slug="reference/cast-button">CastButton</DocsLink> and users can move playback to a Chromecast device while the browser stays in control:
Add Google Cast to any Video.js streaming media element (HLS and DASH) by placing the Google Cast component next to it. Pair it with a <DocsLink slug="reference/cast-button">CastButton</DocsLink> and users can move playback to a Chromecast device while the browser stays in control:
<FrameworkCase frameworks={["react"]}>
```tsx title="App.tsx"
import { CastButton, createPlayer } from '@videojs/react';
import { GoogleCast } from '@videojs/react/media/google-cast';
import { HlsJsVideo } from '@videojs/react/media/hlsjs-video';
import { videoFeatures } from '@videojs/react/video';
@@ -29,6 +30,7 @@ export default function App() {
playsInline
loop
/>
<GoogleCast />
<CastButton />
</Player.Container>
</Player.Provider>
@@ -48,13 +50,20 @@ export default function App() {
playsinline
loop
></hlsjs-video>
<google-cast></google-cast>
<media-cast-button></media-cast-button>
</media-container>
</video-player>
```
Register the `<google-cast>` element by importing `@videojs/html/media/google-cast`.
</FrameworkCase>
The pre-built <DocsLink slug="concepts/skins">skins</DocsLink> include a Cast button already. It appears when a Chromecast device is on the network and stays hidden otherwise.
The component registers Google Cast with whichever media the player is using, so it works with any of the streaming media elements. The pre-built <DocsLink slug="concepts/skins">skins</DocsLink> include a Cast button already. It appears when a Chromecast device is on the network and stays hidden otherwise.
<Aside type="caution">
Casting needs this component. Without it, <DocsLink slug="reference/cast-button">CastButton</DocsLink> drives the browser's native Remote Playback API rather than a Cast session, so receivers and load requests don't apply.
</Aside>
<Aside type="note">
Cast only works in Chromium-based browsers (Chrome, Edge, and others built on Blink). On other browsers, `remotePlaybackAvailability` is `'unsupported'`.
@@ -81,9 +90,9 @@ While `connected`, the media element's `play`, `pause`, `currentTime`, `volume`,
### The lazy-loaded SDK
Video.js injects the Cast SDK (`cast_sender.js`) as a `<script>` tag the first time a Cast-capable media element loads in a Chromium browser. Browsers that can't cast never load the SDK.
Video.js injects the Cast SDK (`cast_sender.js`) as a `<script>` tag the first time a Google Cast component is added in a Chromium browser. Browsers that can't cast — and players without the component — never load the SDK.
Set `disableRemotePlayback` on the media element to opt out:
Set `disableRemotePlayback` on the media element to opt out of remote playback entirely:
<FrameworkCase frameworks={["react"]}>
```tsx
@@ -100,11 +109,11 @@ Set `disableRemotePlayback` on the media element to opt out:
## Configure Cast
<FrameworkCase frameworks={["react"]}>
Pass Cast options under the `googleCast` key of the media element's `config` prop.
Pass Cast options as props of the `GoogleCast` component.
</FrameworkCase>
<FrameworkCase frameworks={["html"]}>
Set Cast options under the `googleCast` key of the media element's `config` property. Set it from JavaScript — there is no HTML attribute for `config`.
Set Cast options as attributes on the `<google-cast>` element. Object-valued options (like `customData`) are properties only.
</FrameworkCase>
### Custom receiver application ID
@@ -113,17 +122,15 @@ By default, Video.js casts to Google's [Default Media Receiver](https://develope
<FrameworkCase frameworks={["react"]}>
```tsx
<HlsJsVideo
src="https://stream.mux.com/BV3YZtogl89mg9VcNBhhnHm02Y34zI1nlMuMQfAbl3dM.m3u8"
config={{ googleCast: { receiver: 'YOUR_APP_ID' } }} // [!code focus]
/>
<HlsJsVideo src="https://stream.mux.com/BV3YZtogl89mg9VcNBhhnHm02Y34zI1nlMuMQfAbl3dM.m3u8" />
<GoogleCast receiver="YOUR_APP_ID" /> // [!code focus]
```
</FrameworkCase>
<FrameworkCase frameworks={["html"]}>
```ts
const video = document.querySelector('hlsjs-video');
video.config = { googleCast: { receiver: 'YOUR_APP_ID' } }; // [!code focus]
```html
<hlsjs-video src="https://stream.mux.com/BV3YZtogl89mg9VcNBhhnHm02Y34zI1nlMuMQfAbl3dM.m3u8"></hlsjs-video>
<google-cast receiver="YOUR_APP_ID"></google-cast> <!-- [!code focus] -->
```
</FrameworkCase>
@@ -133,17 +140,15 @@ Send extra data (auth tokens, user IDs) to the receiver with each load request v
<FrameworkCase frameworks={["react"]}>
```tsx
<HlsJsVideo
src="https://stream.mux.com/BV3YZtogl89mg9VcNBhhnHm02Y34zI1nlMuMQfAbl3dM.m3u8"
config={{ googleCast: { customData: { token: 'abc123', userId: 'u_789' } } }} // [!code focus]
/>
<HlsJsVideo src="https://stream.mux.com/BV3YZtogl89mg9VcNBhhnHm02Y34zI1nlMuMQfAbl3dM.m3u8" />
<GoogleCast customData={{ token: 'abc123', userId: 'u_789' }} /> // [!code focus]
```
</FrameworkCase>
<FrameworkCase frameworks={["html"]}>
```ts
const video = document.querySelector('hlsjs-video');
video.config = { googleCast: { customData: { token: 'abc123', userId: 'u_789' } } }; // [!code focus]
const googleCast = document.querySelector('google-cast');
googleCast.customData = { token: 'abc123', userId: 'u_789' }; // [!code focus]
```
</FrameworkCase>
@@ -153,49 +158,41 @@ By default the receiver loads the same URL the browser plays. Set `src` (and opt
<FrameworkCase frameworks={["react"]}>
```tsx
<HlsJsVideo
src="https://stream.mux.com/BV3YZtogl89mg9VcNBhhnHm02Y34zI1nlMuMQfAbl3dM/highest.mp4"
config={{
googleCast: {
src: 'https://stream.mux.com/BV3YZtogl89mg9VcNBhhnHm02Y34zI1nlMuMQfAbl3dM.m3u8',
contentType: 'application/x-mpegURL',
},
}}
<HlsJsVideo src="https://stream.mux.com/BV3YZtogl89mg9VcNBhhnHm02Y34zI1nlMuMQfAbl3dM/highest.mp4" />
<GoogleCast
src="https://stream.mux.com/BV3YZtogl89mg9VcNBhhnHm02Y34zI1nlMuMQfAbl3dM.m3u8"
contentType="application/x-mpegURL"
/>
```
</FrameworkCase>
<FrameworkCase frameworks={["html"]}>
```ts
const video = document.querySelector('hlsjs-video');
video.config = {
googleCast: {
src: 'https://stream.mux.com/BV3YZtogl89mg9VcNBhhnHm02Y34zI1nlMuMQfAbl3dM.m3u8',
contentType: 'application/x-mpegURL',
},
};
```html
<hlsjs-video src="https://stream.mux.com/BV3YZtogl89mg9VcNBhhnHm02Y34zI1nlMuMQfAbl3dM/highest.mp4"></hlsjs-video>
<google-cast
src="https://stream.mux.com/BV3YZtogl89mg9VcNBhhnHm02Y34zI1nlMuMQfAbl3dM.m3u8"
content-type="application/x-mpegURL"
></google-cast>
```
</FrameworkCase>
### HLS on the receiver
When the source (or `config.googleCast.src`) is an HLS playlist, Video.js inspects the playlist, detects the segment format (TS or fMP4), and sets `hlsSegmentFormat` / `hlsVideoSegmentFormat` on the Cast load request. The default media receiver plays HLS natively; no extra configuration needed.
When the Cast source is an HLS playlist, Video.js inspects the playlist, detects the segment format (TS or fMP4), and sets `hlsSegmentFormat` / `hlsVideoSegmentFormat` on the Cast load request. The default media receiver plays HLS natively; no extra configuration needed.
Set `streamType` to tell the receiver whether the stream is `'on-demand'` or `'live'`. When unset, it falls back to the player's `streamType`:
<FrameworkCase frameworks={["react"]}>
```tsx
<HlsJsVideo
src="https://stream.mux.com/BV3YZtogl89mg9VcNBhhnHm02Y34zI1nlMuMQfAbl3dM.m3u8"
config={{ googleCast: { streamType: 'live' } }} // [!code focus]
/>
<HlsJsVideo src="https://stream.mux.com/BV3YZtogl89mg9VcNBhhnHm02Y34zI1nlMuMQfAbl3dM.m3u8" />
<GoogleCast streamType="live" /> // [!code focus]
```
</FrameworkCase>
<FrameworkCase frameworks={["html"]}>
```ts
const video = document.querySelector('hlsjs-video');
video.config = { googleCast: { streamType: 'live' } }; // [!code focus]
```html
<hlsjs-video src="https://stream.mux.com/BV3YZtogl89mg9VcNBhhnHm02Y34zI1nlMuMQfAbl3dM.m3u8"></hlsjs-video>
<google-cast stream-type="live"></google-cast> <!-- [!code focus] -->
```
</FrameworkCase>
+135
View File
@@ -0,0 +1,135 @@
---
title: Mux Data
description: Monitor playback quality and viewer experience by adding the Mux Data component to a player
---
import FrameworkCase from '@/components/docs/FrameworkCase.astro';
import DocsLink from '@/components/docs/DocsLink.astro';
import DocsLinkCard from '@/components/docs/DocsLinkCard.astro';
import Aside from '@/components/Aside.astro';
[Mux Data](https://www.mux.com/data) measures playback quality — startup time, rebuffering, playback failures, and watch time. Add the Mux Data component to a player and it monitors whichever media that player is playing:
<FrameworkCase frameworks={["react"]}>
```tsx title="App.tsx"
import { createPlayer } from '@videojs/react';
import { MuxData } from '@videojs/react/media/mux-data';
import { MuxVideo } from '@videojs/react/media/mux-video';
import { videoFeatures } from '@videojs/react/video';
const Player = createPlayer({ features: videoFeatures });
export default function App() {
return (
<Player.Provider>
<Player.Container>
<MuxVideo source={{ playbackId: 'BV3YZtogl89mg9VcNBhhnHm02Y34zI1nlMuMQfAbl3dM' }} playsInline />
<MuxData /> {/* [!code focus] */}
</Player.Container>
</Player.Provider>
);
}
```
</FrameworkCase>
<FrameworkCase frameworks={["html"]}>
```html title="index.html"
<video-player>
<media-container>
<mux-video src="https://stream.mux.com/BV3YZtogl89mg9VcNBhhnHm02Y34zI1nlMuMQfAbl3dM.m3u8" playsinline></mux-video>
<mux-data></mux-data> <!-- [!code focus] -->
</media-container>
</video-player>
```
Register the `<mux-data>` element by importing `@videojs/html/media/mux-data`.
</FrameworkCase>
That's the whole setup for Mux-hosted playback — no environment key required. The component renders nothing; place it inside the player, as a sibling of the media element.
<Aside type="note">
Mux Data is opt-in. No media element monitors playback on its own, Mux ones included, so nothing is measured and no beacons are sent until you add this component.
</Aside>
## Environment key
Mux Data needs to know which environment a view belongs to. For Mux-hosted playback it works that out on its own: the component reports the Mux playback ID as the view's `video_id`, and Mux attributes the view to the environment that owns that playback ID.
Set `envKey` when you monitor a source Mux doesn't host — a self-hosted HLS or DASH stream, for example. Find the key in the [Mux dashboard](https://dashboard.mux.com/settings/data):
<FrameworkCase frameworks={["react"]}>
```tsx
<HlsJsVideo src="https://example.com/stream.m3u8" />
<MuxData envKey="YOUR_ENV_KEY" /> {/* [!code focus] */}
```
</FrameworkCase>
<FrameworkCase frameworks={["html"]}>
```html
<hlsjs-video src="https://example.com/stream.m3u8"></hlsjs-video>
<mux-data env-key="YOUR_ENV_KEY"></mux-data> <!-- [!code focus] -->
```
</FrameworkCase>
An explicit key always wins, so set one to send Mux-hosted views to a specific environment.
## Any media element works
The component attaches to the media the player is using, not to a specific element type, so it monitors <DocsLink slug="reference/mux-video">MuxVideo</DocsLink>, <DocsLink slug="reference/hlsjs-video">HlsJsVideo</DocsLink>, <DocsLink slug="reference/dash-video">DashVideo</DocsLink>, and the rest alike. When the media exposes an [hls.js](https://github.com/video-dev/hls.js/) engine, the component hands that engine to the Mux Data SDK so it can report stream-level detail alongside the playback metrics.
The `video_id` it reports is the Mux playback ID for streams served from `stream.mux.com`, and the source URL otherwise. Each view also gets a generated `view_session_id`. Override either through `metadata`.
## Describe the view
Pass Mux Data [metadata](https://www.mux.com/docs/guides/make-your-data-actionable-with-metadata) to label views with your own titles, viewer IDs, and custom dimensions. It's an object, so it's a property rather than an attribute:
<FrameworkCase frameworks={["react"]}>
```tsx
<MuxData metadata={{ video_title: 'Big Buck Bunny', viewer_user_id: 'u_789' }} />
```
</FrameworkCase>
<FrameworkCase frameworks={["html"]}>
```ts
const muxData = document.querySelector('mux-data');
muxData.metadata = { video_title: 'Big Buck Bunny', viewer_user_id: 'u_789' }; // [!code focus]
```
</FrameworkCase>
## Options
<FrameworkCase frameworks={["react"]}>
| Prop | Type | Description |
|---|---|---|
| `envKey` | `string` | Mux Data environment key the beacons are sent to. Optional for Mux-hosted playback |
| `metadata` | `object` | Mux Data metadata for the view |
| `playerSoftwareName` | `string` | Player name reported to Mux Data |
| `playerSoftwareVersion` | `string` | Player version reported to Mux Data. Defaults to the Video.js version |
| `playerInitTime` | `number` | Epoch milliseconds the player was initialized. Defaults to when the component was created |
| `beaconCollectionDomain` | `string` | Custom domain the beacons are sent to |
| `disableCookies` | `boolean` | Stops the SDK from setting cookies |
| `debug` | `boolean` | Turns on SDK debug logging |
| `MuxDataSdk` | `object` | SDK used for monitoring. Set it to `undefined` to switch monitoring off |
</FrameworkCase>
<FrameworkCase frameworks={["html"]}>
| Attribute | Property | Description |
|---|---|---|
| `env-key` | `envKey` | Mux Data environment key the beacons are sent to. Optional for Mux-hosted playback |
| — | `metadata` | Mux Data metadata for the view |
| `player-software-name` | `playerSoftwareName` | Player name reported to Mux Data |
| `player-software-version` | `playerSoftwareVersion` | Player version reported to Mux Data. Defaults to the Video.js version |
| `player-init-time` | `playerInitTime` | Epoch milliseconds the player was initialized. Defaults to when the element was created |
| `beacon-collection-domain` | `beaconCollectionDomain` | Custom domain the beacons are sent to |
| `disable-cookies` | `disableCookies` | Stops the SDK from setting cookies |
| `debug` | `debug` | Turns on SDK debug logging |
| — | `MuxDataSdk` | SDK used for monitoring. Set it to `undefined` to switch monitoring off |
</FrameworkCase>
Changing `MuxDataSdk`, `beaconCollectionDomain`, `debug`, or `disableCookies` restarts monitoring, which ends the current view and starts a new one. The rest update the view in place.
## See also
<DocsLinkCard slug="reference/mux-video">MuxVideo element reference</DocsLinkCard>
<DocsLinkCard slug="reference/mux-audio">MuxAudio element reference</DocsLinkCard>
<DocsLinkCard slug="concepts/cast">Google Cast — the other media component you compose onto a player</DocsLinkCard>
@@ -6,6 +6,7 @@ description: Accessible Cast toggle button with state reflection and keyboard su
---
import ComponentReference from "@/components/docs/api-reference/ComponentReference.astro";
import DocsLink from "@/components/docs/DocsLink.astro";
import FrameworkCase from "@/components/docs/FrameworkCase.astro";
import StyleCase from "@/components/docs/StyleCase.astro";
import Demo from "@/components/docs/demos/Demo.astro";
@@ -41,6 +42,8 @@ Toggles a Google Cast session. Clicking the button while `disconnected` opens th
The button does nothing when `availability` is not `'available'` — for example, when no Chromecast is on the network, or on browsers that don't support Cast.
Cast sessions come from the <DocsLink slug="concepts/cast">Google Cast</DocsLink> component. Add it to the player next to your media element; without it the button drives the browser's native Remote Playback API instead, which offers no receiver or load-request configuration.
## Styling
Style based on cast state and availability:
@@ -9,6 +9,8 @@ import MediaReference from "@/components/docs/api-reference/MediaReference.astro
import FrameworkCase from "@/components/docs/FrameworkCase.astro";
import StyleCase from "@/components/docs/StyleCase.astro";
import Demo from "@/components/docs/demos/Demo.astro";
import DocsLink from "@/components/docs/DocsLink.astro";
import DocsLinkCard from "@/components/docs/DocsLinkCard.astro";
{/* React demos */}
import BasicUsageDemoReact from "@/components/docs/demos/mux-audio/react/css/BasicUsage";
@@ -23,6 +25,35 @@ import basicUsageHtmlTs from "@/components/docs/demos/mux-audio/html/css/BasicUs
Audio element for playing Mux-hosted HLS streams. Built on hls.js with Mux-specific optimizations.
## Analytics and casting
MuxAudio plays Mux streams. It doesn't monitor them or cast them — <DocsLink slug="concepts/mux-data">Mux Data</DocsLink> and <DocsLink slug="concepts/cast">Google Cast</DocsLink> are separate components 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:
<FrameworkCase frameworks={["react"]}>
```tsx
import { GoogleCast } from '@videojs/react/media/google-cast';
import { MuxAudio } from '@videojs/react/media/mux-audio';
import { MuxData } from '@videojs/react/media/mux-data';
<MuxAudio source={{ playbackId: 'BV3YZtogl89mg9VcNBhhnHm02Y34zI1nlMuMQfAbl3dM' }} />
<MuxData playerSoftwareName="mux-audio" />
<GoogleCast />
```
</FrameworkCase>
<FrameworkCase frameworks={["html"]}>
```html
<mux-audio src="https://stream.mux.com/BV3YZtogl89mg9VcNBhhnHm02Y34zI1nlMuMQfAbl3dM.m3u8"></mux-audio>
<mux-data player-software-name="mux-audio"></mux-data>
<google-cast></google-cast>
```
Register the elements by importing `@videojs/html/media/mux-data` and `@videojs/html/media/google-cast`.
</FrameworkCase>
<DocsLinkCard slug="concepts/mux-data">Mux Data — metadata, options, and configuration</DocsLinkCard>
<DocsLinkCard slug="concepts/cast">Google Cast — receivers, load requests, and session state</DocsLinkCard>
## Examples
### Basic Usage
@@ -9,6 +9,8 @@ import MediaReference from "@/components/docs/api-reference/MediaReference.astro
import FrameworkCase from "@/components/docs/FrameworkCase.astro";
import StyleCase from "@/components/docs/StyleCase.astro";
import Demo from "@/components/docs/demos/Demo.astro";
import DocsLink from "@/components/docs/DocsLink.astro";
import DocsLinkCard from "@/components/docs/DocsLinkCard.astro";
{/* React demos */}
import BasicUsageDemoReact from "@/components/docs/demos/mux-video/react/css/BasicUsage";
@@ -23,6 +25,35 @@ import basicUsageHtmlTs from "@/components/docs/demos/mux-video/html/css/BasicUs
Video element for playing Mux-hosted HLS streams. Built on hls.js with Mux-specific optimizations.
## Analytics and casting
MuxVideo plays Mux streams. It doesn't monitor them or cast them — <DocsLink slug="concepts/mux-data">Mux Data</DocsLink> and <DocsLink slug="concepts/cast">Google Cast</DocsLink> are separate components 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:
<FrameworkCase frameworks={["react"]}>
```tsx
import { GoogleCast } from '@videojs/react/media/google-cast';
import { MuxData } from '@videojs/react/media/mux-data';
import { MuxVideo } from '@videojs/react/media/mux-video';
<MuxVideo source={{ playbackId: 'BV3YZtogl89mg9VcNBhhnHm02Y34zI1nlMuMQfAbl3dM' }} playsInline />
<MuxData playerSoftwareName="mux-video" />
<GoogleCast />
```
</FrameworkCase>
<FrameworkCase frameworks={["html"]}>
```html
<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>
```
Register the elements by importing `@videojs/html/media/mux-data` and `@videojs/html/media/google-cast`.
</FrameworkCase>
<DocsLinkCard slug="concepts/mux-data">Mux Data — metadata, options, and configuration</DocsLinkCard>
<DocsLinkCard slug="concepts/cast">Google Cast — receivers, load requests, and session state</DocsLinkCard>
## Examples
### Basic Usage
+1
View File
@@ -42,6 +42,7 @@ export const sidebar: Sidebar = [
{ slug: 'concepts/ui-components' },
{ slug: 'concepts/accessibility' },
{ slug: 'concepts/cast', sidebarLabel: 'Google Cast' },
{ slug: 'concepts/mux-data' },
{ slug: 'concepts/security' },
],
},