Skip to content

Casting and AirPlay

Full story: the seven-part casting deep dive; the playback-angle summary is playback deep dive 4.

The phone must first answer “which device on this network is a Chromecast?” Casting protocols all solve LAN discovery via mDNS/DNS-SD ( multicast 224.0.0.251, the technology behind Bonjour). Chromecasts advertise under _googlecast._tcp.local with a TXT record carrying the friendly name shown in the picker. In this app discovery runs through bonsoir.

  • local_lib/flutter_cast — the only package still vendored in local_lib/, handling the Chromecast/DLNA protocol work.
  • lib/presentation/widgets/player/cast/ — sender-side UI and session handling, including cast_aware_navigation.dart (how navigation behaves while a cast session is live).
  • lib/presentation/widgets/player/airplay/airplay_controller.dart — AirPlay.

A cast receiver cannot send custom headers, and the KMS key request requires three of them. So the app runs a small HTTP server on the phone (the LAN proxy), and hands the TV URLs pointing at the phone instead of at the CDN. The proxy:

  1. rewrites the playlist so every segment and key URL routes through it (cast_playlist_rewriter.dart),
  2. signs key requests on the TV’s behalf using the same EncryptionHelper.playerHeader() headers,
  3. serves segments straight from the CDN or, for offline titles, from the download on disk.

AirPlay uses the same proxy for the same reason — see AirPlay and the proxy.

Sessions survive app restarts and reconnect to a running receiver — the recovery rules are in Session persistence and recovery. Who owns playback while a session is live (and what happens to the trailer on the content page) is defined in Playback ownership.