Skip to content
FrameworkStyle

Cast to AirPlay and Chromecast

Send playback to AirPlay and Google Cast devices, with availability detection and connection state.

Send playback to an Apple TV over AirPlay or a Chromecast over Google Cast while the browser stays in control.

Use a GoogleCast component with a CastButton, and add an AirPlayButton for Safari. The prebuilt skins already include both buttons; add GoogleCast next to a streaming media component to enable the configurable Cast route.

import { AirPlayButton, CastButton, Container, 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';

const { Player } = createPlayer({ features: videoFeatures });

export default function BasicUsage() {
  return (
    <Player>
      <Container className="media-container">
        <HlsJsVideo src="https://stream.mux.com/BV3YZtogl89mg9VcNBhhnHm02Y34zI1nlMuMQfAbl3dM.m3u8" autoPlay muted playsInline loop />
        <GoogleCast />
        <div className="media-remote-buttons">
          <AirPlayButton
            className="media-airplay-button"
            render={(props, state) => (
              <button {...props}>{state.state === 'connected' ? 'Stop AirPlay' : 'Start AirPlay'}</button>
            )}
          />
          <CastButton
            className="media-cast-button"
            render={(props, state) => (
              <button {...props}>{state.connection === 'connected' ? 'Stop casting' : 'Start casting'}</button>
            )}
          />
        </div>
      </Container>
    </Player>
  );
}

The demo pairs the streaming media component with GoogleCast in React or <google-cast> in HTML. Without that component, CastButton drives the browser’s native Remote Playback API instead, which does not provide Video.js receiver or load-request configuration.

How it works

The remote playback feature gives AirPlay and Google Cast one state shape:

  • remotePlaybackAvailability is 'available' when a remote device can be reached, 'unavailable' when the API exists but no device is reachable, and 'unsupported' when the browser has no remote playback route.
  • remotePlaybackState is 'disconnected', 'connecting', or 'connected'.
  • toggleRemotePlayback() opens the browser’s device picker, or disconnects an active session.

AirPlay uses WebKit’s presentation APIs. Google Cast uses a sender and receiver: the browser sends the receiver a media URL and then controls playback. Your UI reads the same Video.js state for either route.

While connected, playback actions — play, pause, seek, volume — proxy to the remote device, and player state keeps reflecting the remote session. Local playback is suspended.

The Google Cast SDK loads only when a GoogleCast component is present in a Chromium browser. Players without that component and browsers that cannot cast do not load it.

Availability and constraints

  • Remote playback is asynchronous and can fail mid-session when a device or network disappears. React to remotePlaybackState rather than assuming a request succeeds.
  • Google Cast works only in Chromium-based browsers; elsewhere its route reports 'unsupported'.
  • AirPlay works only in Safari; availability requires an AirPlay device reachable on the network.
  • The remote device fetches the source and tracks itself. Localhost, VPN-only, expired, or cross-origin URLs without the necessary CORS headers will fail on the receiver even if they play in the browser.
  • Set disableRemotePlayback on the media element to opt out entirely.

Common variations

Custom Cast receiver

By default, Video.js sends the current source to Google’s Default Media Receiver. Set receiver when you have your own receiver application:

<GoogleCast receiver="YOUR_APP_ID" />

Use src and contentType when the receiver should load a different source than the browser. streamType and customData let you describe that source and attach application-specific data. See the GoogleCast reference for the exact option types and HTML property mapping.

Read connection state

Use remotePlaybackAvailability to decide whether to offer a route and remotePlaybackState to show whether it is disconnected, connecting, or connected. CastButton and AirPlayButton already apply these states to their presentation; read them directly only when another part of your app needs them.

Troubleshooting

The cast button doesn’t render, or renders disabled

The Cast button hides when the route is unsupported. In Chromium with no Cast device reachable, it stays visible but disabled. The AirPlay button hides unless Safari reports an AirPlay device.

Casting starts but the device shows an error

The receiver cannot fetch the media. Confirm the source URL is reachable from the device and served with CORS headers, including caption tracks.

The UI freezes on “connecting”

The user dismissed the picker or the device disconnected. remotePlaybackState returns to 'disconnected'; drive your UI from that state.