mirror of
https://github.com/zoriya/v10.git
synced 2026-08-16 02:45:09 +00:00
259 lines
8.4 KiB
Plaintext
259 lines
8.4 KiB
Plaintext
---
|
|
title: Google Cast
|
|
description: Cast playback to Chromecast devices with built-in Google Cast support, and configure the receiver and load request
|
|
---
|
|
|
|
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';
|
|
|
|
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:
|
|
|
|
<FrameworkCase frameworks={["react"]}>
|
|
```tsx title="App.tsx"
|
|
import { CastButton, createPlayer } from '@videojs/react';
|
|
import { HlsJsVideo } from '@videojs/react/media/hlsjs-video';
|
|
import { videoFeatures } from '@videojs/react/video';
|
|
|
|
const Player = createPlayer({ features: videoFeatures });
|
|
|
|
export default function App() {
|
|
return (
|
|
<Player.Provider>
|
|
<Player.Container>
|
|
<HlsJsVideo
|
|
src="https://stream.mux.com/BV3YZtogl89mg9VcNBhhnHm02Y34zI1nlMuMQfAbl3dM.m3u8"
|
|
autoPlay
|
|
muted
|
|
playsInline
|
|
loop
|
|
/>
|
|
<CastButton />
|
|
</Player.Container>
|
|
</Player.Provider>
|
|
);
|
|
}
|
|
```
|
|
</FrameworkCase>
|
|
|
|
<FrameworkCase frameworks={["html"]}>
|
|
```html title="index.html"
|
|
<video-player>
|
|
<media-container>
|
|
<hlsjs-video
|
|
src="https://stream.mux.com/BV3YZtogl89mg9VcNBhhnHm02Y34zI1nlMuMQfAbl3dM.m3u8"
|
|
autoplay
|
|
muted
|
|
playsinline
|
|
loop
|
|
></hlsjs-video>
|
|
<media-cast-button></media-cast-button>
|
|
</media-container>
|
|
</video-player>
|
|
```
|
|
</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.
|
|
|
|
<Aside type="note">
|
|
Cast only works in Chromium-based browsers (Chrome, Edge, and others built on Blink). On other browsers, `remotePlaybackAvailability` is `'unsupported'`.
|
|
</Aside>
|
|
|
|
## How Cast works
|
|
|
|
Cast uses a **sender / receiver** model:
|
|
|
|
- **Sender** — the browser tab. It sends the receiver a load request with the source URL and metadata, then issues playback commands (play, pause, seek, volume).
|
|
- **Receiver** — the Chromecast device running a receiver application: Google's default media receiver, or a custom one you configure.
|
|
|
|
### Session lifecycle
|
|
|
|
A Cast session moves through three states, exposed by the <DocsLink slug="reference/feature-remote-playback">Remote Playback</DocsLink> feature:
|
|
|
|
| State | Meaning |
|
|
|---|---|
|
|
| `'disconnected'` | No active session |
|
|
| `'connecting'` | Device picked; session starting |
|
|
| `'connected'` | Session active; receiver has the media |
|
|
|
|
While `connected`, the media element's `play`, `pause`, `currentTime`, `volume`, `muted`, and `playbackRate` all proxy to the Cast receiver. Local playback is suspended.
|
|
|
|
### 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.
|
|
|
|
Set `disableRemotePlayback` on the media element to opt out:
|
|
|
|
<FrameworkCase frameworks={["react"]}>
|
|
```tsx
|
|
<HlsJsVideo disableRemotePlayback />
|
|
```
|
|
</FrameworkCase>
|
|
|
|
<FrameworkCase frameworks={["html"]}>
|
|
```html
|
|
<hlsjs-video disableremoteplayback></hlsjs-video>
|
|
```
|
|
</FrameworkCase>
|
|
|
|
## Configure Cast
|
|
|
|
<FrameworkCase frameworks={["react"]}>
|
|
Pass Cast options under the `googleCast` key of the media element's `config` prop.
|
|
</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`.
|
|
</FrameworkCase>
|
|
|
|
### Custom receiver application ID
|
|
|
|
By default, Video.js casts to Google's [Default Media Receiver](https://developers.google.com/cast/docs/web_sender/integrate#default_media_web_receiver) (`CC1AD845`). To use your own receiver app, set `receiver`:
|
|
|
|
<FrameworkCase frameworks={["react"]}>
|
|
```tsx
|
|
<HlsJsVideo
|
|
src="https://stream.mux.com/BV3YZtogl89mg9VcNBhhnHm02Y34zI1nlMuMQfAbl3dM.m3u8"
|
|
config={{ 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]
|
|
```
|
|
</FrameworkCase>
|
|
|
|
### Custom data on load
|
|
|
|
Send extra data (auth tokens, user IDs) to the receiver with each load request via `customData`. The receiver app reads it from the load request's `customData` field:
|
|
|
|
<FrameworkCase frameworks={["react"]}>
|
|
```tsx
|
|
<HlsJsVideo
|
|
src="https://stream.mux.com/BV3YZtogl89mg9VcNBhhnHm02Y34zI1nlMuMQfAbl3dM.m3u8"
|
|
config={{ 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]
|
|
```
|
|
</FrameworkCase>
|
|
|
|
### Cast a different source
|
|
|
|
By default the receiver loads the same URL the browser plays. Set `src` (and optionally `contentType`) to send the receiver a different one — for example, cast an HLS stream while the browser plays an MP4:
|
|
|
|
<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',
|
|
},
|
|
}}
|
|
/>
|
|
```
|
|
</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',
|
|
},
|
|
};
|
|
```
|
|
</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.
|
|
|
|
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]
|
|
/>
|
|
```
|
|
</FrameworkCase>
|
|
|
|
<FrameworkCase frameworks={["html"]}>
|
|
```ts
|
|
const video = document.querySelector('hlsjs-video');
|
|
video.config = { googleCast: { streamType: 'live' } }; // [!code focus]
|
|
```
|
|
</FrameworkCase>
|
|
|
|
## Read Cast state
|
|
|
|
Cast session state lives in the <DocsLink slug="reference/feature-remote-playback">Remote Playback</DocsLink> feature slice. Subscribe with `selectRemotePlayback`:
|
|
|
|
<FrameworkCase frameworks={["react"]}>
|
|
```tsx
|
|
import { selectRemotePlayback, usePlayer } from '@videojs/react';
|
|
|
|
function CastStatus() {
|
|
const remotePlayback = usePlayer(selectRemotePlayback);
|
|
if (!remotePlayback) return null;
|
|
|
|
return <span>{remotePlayback.remotePlaybackState}</span>;
|
|
}
|
|
```
|
|
</FrameworkCase>
|
|
|
|
<FrameworkCase frameworks={["html"]}>
|
|
```ts
|
|
import { PlayerController, playerContext, selectRemotePlayback } from '@videojs/html';
|
|
|
|
class CastStatus extends HTMLElement {
|
|
readonly #remotePlayback = new PlayerController(this, playerContext, selectRemotePlayback);
|
|
}
|
|
```
|
|
</FrameworkCase>
|
|
|
|
## Browser availability
|
|
|
|
The Remote Playback feature reports availability as `'available'` (a device is on the network), `'unavailable'` (no device found), or `'unsupported'` (the browser can't cast). The `CastButton` reflects it as a `data-availability` attribute. Use it to hide the button where casting never works:
|
|
|
|
<FrameworkCase frameworks={["html"]}>
|
|
```css
|
|
media-cast-button[data-availability="unsupported"] {
|
|
display: none;
|
|
}
|
|
```
|
|
</FrameworkCase>
|
|
|
|
<FrameworkCase frameworks={["react"]}>
|
|
`CastButton` renders a `<button>` element. Give it a `className` to target:
|
|
|
|
```tsx
|
|
<CastButton className="cast-button" />
|
|
```
|
|
|
|
```css
|
|
.cast-button[data-availability="unsupported"] {
|
|
display: none;
|
|
}
|
|
```
|
|
</FrameworkCase>
|
|
|
|
## See also
|
|
|
|
<DocsLinkCard slug="reference/cast-button">CastButton component reference</DocsLinkCard>
|
|
<DocsLinkCard slug="reference/feature-remote-playback">Remote Playback feature reference</DocsLinkCard>
|