CarCast · field notes
On the CarPlay protocol · new in iOS 26

We put video on a CarPlay screen. Here's the shape of the problem.

For years the answer was "you can't." Then iOS 26 quietly changed the answer.

The premise

The screen you're not allowed to draw on

CarPlay looks like a video system. Maps glide, album art crossfades, apps scroll at sixty frames a second. So the first surprise is that third-party video on the head unit has never really been a thing — and not because of a licensing footnote. It's a posture baked into the protocol itself.

That's what shifted in iOS 26. The platform now carries a sanctioned path for video on the head unit — the plumbing is finally there. But "supported" and "obvious" are different things: the path only opens if you speak to it exactly right, and nothing tells you when you don't.

What it's called. The press calls it CarPlay video playback; Apple frames it as AirPlay video in the car — new in iOS 26, gated to when you're parked, and only if the carmaker turns it on. On the wire it has a blunter name: the capability the head unit advertises is literally videoPlayback. That string is the thread we pulled.

Under the surface, CarPlay isn't the screen-share you'd guess. It's a negotiated audio/video session in the AirPlay lineage, and in that session the phone — not your app, not the car — decides what is allowed to reach the display. Video isn't "missing." It's gated, and the gate is set during a handshake that happens once and is never reopened.

The instrument

You can't fix what you can't see

The only honest way through a closed protocol is to watch it as it actually behaves — against real phones and real head units, not a spec's idea of them. So we built the instrument first.

CarCast is a protocol inspector for CarPlay and AirPlay. It sits on the control channel and renders every message in plaintext, above the crypto, as it happens: session setup, the capability negotiation, the play commands, the heartbeats, the teardown. Not a capture you decode later — a live readout of the conversation between phone and car.

SETUP rtsp://████████████ # session opens streams[0].type = ██ # not what you'd expect enabledFeatures = [ ████████████ ] # ← the gate lives here POST /command insertPlayQueueItem Content-Location = ██████://localhost/███████

Real message shapes. The bytes that matter are blacked out — on purpose.

That readout is what turned "video is blocked" from a dead end into a map. Once you can see the negotiation, the interesting part isn't that video is refused. It's how, and under exactly what conditions it isn't.

The findings

Three things the wire told us

01

It isn't screen mirroring

Video-in-car doesn't arrive as a cast of the phone's display. It arrives the way a phone hands a movie to a living-room TV — a different mechanism entirely, grafted onto the CarPlay session. Naming that correctly was the whole unlock.

02

There is a single gate

Whether the dash will ever show a frame is decided in a handful of bytes during setup. Miss the negotiation and the phone doesn't fail loudly — it simply, politely, walks away. We found which handshake is load-bearing.

03

Every app drives differently

A long-form player, a protected title, a short-form feed — each steers the car its own way. Some proxy their media through the phone. Some carry a tiny courier protocol for keys. Some switch videos by tearing the whole session down and rebuilding it. One receiver has to speak all of it.

The handshake

How the car raises its hand: /info

Before any video, the phone asks the head unit exactly one opening question — GET /info — and the car answers with a binary plist describing everything it can do: audio formats, screen capture, protocol version, its volume model. It's the capability résumé the phone reads to decide what's even on the table.

A head unit that wants video doesn't flip a global switch. It opts in — by listing a videoPlayback capability among the features it advertises. Do that, and its /info answer grows a small cluster of keys the phone is specifically watching for:

GET /info playbackCapabilities = { ... } # "I can host a flung player" videoPlaybackInfo = { videoPlaybackAllowed = ██ # parked → yes, moving → no featuresEx = "████████████" # which control path to take } ██████████████ = { } # the buffered-video gate marker

The detail worth stealing: parked vs. moving is one boolean in this response. The same car says "yes, video" in the driveway and "audio only" at speed by flipping videoPlaybackAllowed — the safety policy lives in the capability answer, not somewhere downstream. And the elegant part: leave the capability out entirely and /info is byte-for-byte what it always was, so none of this disturbs plain audio or screen mirroring. Video is strictly additive, strictly opt-in — and miss the opt-in and, per finding 02, the phone just leaves.

One level deeper

How a "fling" actually flows

A few people asked for more than the shape, so here's the vocabulary — the verbs that move a video onto the dash — with the load-bearing values still held back. Once the session is up, playback is a small, chatty command language in both directions.

The phone drives

sender → head unit

  • insertPlayQueueItem — hand the car a URL and queue it
  • setRateplay / pause (rate 1 / 0)
  • setProperty — end-of-item behavior, scrub bounds, audio & subtitle track
  • playbackInfo (request) — "where are you right now?"
  • stop / flush — drop the item and tear the stream down

The car reports

head unit → sender

  • playbackStateloading → playing → stopped
  • readyToPlay0 until the first frames buffer, then 1
  • rate · position · duration — the transport clock
  • loadedTimeRangesChanged — how much is buffered ahead
playbackInfo playbackState = playing rate = 1 readyToPlay = 1 duration = { value = ████████ timescale = ████ } position = { value = ████████ ... }

The receiver answers every poll with its clock. That heartbeat is also how the phone knows the frame really landed.

And the pixels themselves don't arrive straight off the internet. The car asks for them back through the phone — an HLS-over-localhost proxy the phone stands up on the fly, serving a master playlist, then per-quality renditions, then byte-range slices of the media. The head unit does its own adaptive-bitrate picking; the phone is just the pipe — and, for protected titles, the key broker via that little courier protocol.

What we're not printing

The exact flags, the stream numbers, the values in that handshake, the message formats — those stay out of this post deliberately. This is the shape, not the recipe. If you're building anywhere near this, the specifics are exactly the conversation we'd like to have with you.

See the protocol, not the guesswork.

CarCast turns the CarPlay and AirPlay control plane into something you can actually read — and, when you need it, reshape. It's how we got here, and it's how you skip the months of squinting at hex.

info@vmlite.com

Topics CarPlay video playback AirPlay video in the car iOS 26 CarPlay videoPlayback CarPlay protocol AirPlay protocol URL fling playbackCapabilities CarPlay reverse engineering RTSP CarCast