Casting to a TV

A Cast output plays a canvas (the program, or a vertical canvas) on one TV in the room or on several at once: Chromecasts and Google TVs from every platform, an Apple TV from the Mac app. The app encodes the canvas once to low-latency HLS and serves it from its remote-control port; every TV fetches the same stream over your network. Expect about 2 s of delay.

What each platform can do

Chromecast / Google TV Apple TV (AirPlay) Stream URL (Safari, VLC)
macOS, Mac app yes yes yes
macOS, egui app yes listed, not castable: use the Mac app yes
Windows yes not listed (AirPlay needs a Mac) yes
Linux yes not listed (AirPlay needs a Mac) yes

AirPlay video from Windows and Linux is not possible: no public protocol sends it there, and Apple’s needs its pairing. So on those platforms the app does not look for Apple TVs, and the Cast section never lists one. To watch on an Apple TV from Windows or Linux, open the stream URL in a player on a device that can AirPlay, such as Safari on an iPhone.

Set up

  1. Add the output. Outputs ▸ Add ▸ Cast to a TV (under Streaming). Its editor has the canvas, the video bitrate and the audio bitrate; the size and rate the TV is sent are its Quality (below).
  2. Let the TV reach the app. The TV fetches the stream from the remote-control port, so Settings ▸ Remote control ▸ Listen on must not be This computer only. Remote control itself can stay off: while a Cast output runs, the port serves only the cast.
  3. Pick the TVs. The Cast section under the Streaming outputs searches the network when it first shows (Search looks again). Chromecasts and Apple TVs on the same network are listed; a TV that is both is listed once. This computer is never listed, even when a Mac’s AirPlay Receiver is on (it answers the search, but it is not a TV): when it is all that answered, the line says “No TV found, only this Mac”. The Cast output’s settings have a TVs list: tick every TV it should play on. A TV you ticked that the search does not find now stays in the list, greyed, as “Not found”; it is cast to when it is found.

Quality

Each Cast output has its own Quality, in the Cast section under the output picker: what size and frame rate the TV is sent, whatever the canvas. The line under it says what the cast will be (“Auto for Living Room (Chromecast): 1920×1080 at 30 fps”).

  • Auto (the default) sends the most the TV plays smoothly, from the model it reports on the network (the table below), and never more than the canvas: a 720p canvas casts at 720p, a 30 fps canvas at 30 fps. Its label says what it chose (“Auto (1080p60)”). With several TVs ticked, Auto sends what every one of them plays: the lower size and the lower rate of their limits (a 1080p30 TV and a 720p60 one get 720p30), and the line names the TV it chose for (“Auto for Kitchen (Google Nest Hub), the least of 2 TVs: 1280×720 at 30 fps”). Before a TV is ticked, and for a TV that reports no model, Auto is 1080p30.
  • 1080p60, 1080p30, 720p60, 720p30 send that size whatever the canvas (scaled to fit, with bars if the shapes differ; a vertical canvas is sent upright, 1080×1920). The frame rate is never above the canvas’s: a 1080p60 choice on a 30 fps canvas sends 30 fps, and the line says so. A rate below the canvas’s drops frames evenly.

The video bitrate stays the output’s (its editor). A change applies the next time the cast starts; the cast running keeps its size, and the line says so.

Latency

Each Cast output also has its own Latency, under its Quality: how far behind live the TV plays. Playing further behind lets the TV keep more of the stream in hand, so a short stall on the network does not stop the picture.

  • Lowest: 0.6 s behind live. The TV keeps almost nothing in hand and buffers on any hiccup; use it only on a wired network.
  • Balanced (the default): 1.2 s behind live.
  • Safe: 3 s behind live, for a TV on Wi-Fi.

Some TVs (a Google TV Streamer, for one) play exactly as far behind as the stream asks; an older Chromecast plays about 3 s behind whatever you pick. Changing it while the output casts starts the cast on each TV again (the picture stops for a moment); the line under it says so.

Device limits

What Auto sends, by the model the TV reports:

TV Reports itself as Auto
Chromecast Ultra Chromecast Ultra 1080p60
Chromecast with Google TV (4K and HD), Google TV Streamer Chromecast with Google TV, Google TV Streamer, Chromecast HD 1080p60
A TV with Chromecast built in (Android TV, Google TV, SHIELD) its model, with “TV” in it 1080p60
Chromecast, 1st to 3rd generation Chromecast 1080p30
Nest Hub, Nest Hub Max Google Nest Hub, Google Nest Hub Max 720p30
Google Home and Nest speakers, Cast groups Google Home, Google Nest Mini, Google Cast Group… 720p30
Apple TV 4K, Apple TV HD AppleTV5,3 and later 1080p60
Apple TV, 3rd generation AppleTV3,1, AppleTV3,2 1080p30
Apple TV, 2nd generation AppleTV2,1 720p30
HomePod, AirPort Express (sound only) AudioAccessory…, AirPort… 720p30
Anything else, or no model 1080p30

The three Chromecast generations report the same model; the third plays 1080p at 60 fps, the first two at 30, so Auto chooses 30. Pick 1080p60 for a third-generation Chromecast. A Nest Hub’s screen is 1024×600 (Max: 1280×800), so 720p is already more than it shows. A TV whose model the table does not know gets 1080p30, which every Cast and AirPlay TV plays; pick a fixed quality if it plays more.

Cast to a Chromecast

Pick it in the Cast section and press Cast. The output starts, the TV loads the stream and the line says “Casting to Living Room TV”. The TV is added to the output’s TVs list as a new row; TVs already there stay and are cast to as well. Pick another TV and press Cast while it casts, and that TV joins the same cast. Stop stops every TV’s player and the output. The cast also ends when the TV stops it, goes silent, or the Cast output is stopped from the Outputs list.

Cast to several TVs

  1. In the Cast output’s settings, tick each TV in its TVs list.
  2. Press Start there. The output starts once, and every ticked TV is given the same stream: one encoding, one stream URL, however many TVs. The Cast section’s line counts them (“Casting to 2 of 3 TVs”), and each TV’s own line in the list says how it is doing (“Casting to Kitchen”, “The cast to Den failed”).
  3. Stop stops every TV, then the output.

While it casts, ticking another TV gives it the stream too, and unticking one stops only that TV; the others keep playing and the encoding goes on. Unticking the last TV stops the cast. When one TV fails (it is off, it cannot reach this computer), the others keep playing; the cast ends only when every TV has stopped. A TV ticked while it casts gets the size the cast started with (the Quality line says the running cast keeps its size); Auto sizes for it the next time the cast starts.

Cast to an Apple TV (Mac app)

Pick the Apple TV and press Cast. The output starts and the line says “Choose Den in the AirPlay menu”: press the AirPlay button beside Stop and choose the Apple TV there (macOS lets only you pick the route). Once it plays, the line says “Playing on Den” and the dot turns green. Stop ends it.

macOS plays video on one AirPlay TV at a time, so a Cast output can have one Apple TV in its TVs list, beside as many Chromecasts as you like. While one Apple TV is ticked, the others are greyed with “macOS plays video on one Apple TV at a time: clear Den first”.

Watch without a TV

To check a cast before you have a TV, or with none:

  1. Start the Cast output (its Start button in the Outputs list, or Cast).
  2. In its editor, press Copy stream URL (or Open in player, which opens it with this computer’s handler for the link). Until the output runs the editor says “Start this Cast output to get its stream URL”.
  3. Open the URL in Safari on an iPhone, iPad or Mac on the same network (Safari plays HLS itself), or in VLC on any computer (Media ▸ Open Network Stream). Chrome and Edge do not play HLS without an extension.

Expect about 2 s of delay in Safari, a little more in VLC. Any number of players can watch at once, beside the TVs. A remote-control or MCP client sees the same URL: the OBS-compatible websocket’s GetOutputList gives a running Cast output’s outputCastUrl, and the MCP outputs resource its castUrl.

Privacy

The stream has no password (a TV cannot send one). It answers only while the Cast output runs, and anyone who can reach the remote-control port can watch it meanwhile, as anyone on the network can see an NDI source.

If no TV appears

The search asks the network who is a TV (mDNS), and the TVs answer two ways: straight back to the app, and to the mDNS group, which the app also listens to. A firewall on this computer can drop the answers, and it can also stop the TV from fetching the video from the remote-control port (4455 unless you changed it in Settings ▸ Remote control). When a search ends with nothing, the Cast section says so: “No TV answered. A firewall on this computer may be blocking the answers (UDP 5353 from the local network) or the video (TCP 4455).”

The same firewall can let the TV find nothing to play: it is given the video’s address but cannot connect to it. When the TV has fetched nothing 8 seconds after it was given the video, the cast to that TV stops and its line says “The TV could not fetch the video: a firewall on this computer may block TCP 4455” (with several TVs, the others keep playing). (Ubuntu with ufw turned on blocks every incoming port it has not been told to allow, 4455 included.)

On Linux the app can do it for you. When ufw or firewalld is on, the Cast section shows Allow casting through the firewall… under those two lines, and Settings ▸ Remote control shows it next to Listen on. It asks for your password once (the system’s own prompt) and allows, from your local network only (the network of the connection your default route uses, worked out by the app), TCP 4455 (your remote-control port) and UDP 5353, then says what it did. Press Search again afterwards. Cancelling the prompt changes nothing.

To do it by hand instead, allow both for your local network only (replace 192.168.1.0/24 with your network, and 4455 with your port). ip -4 route show default names the interface your network is on, and ip -4 -o addr show dev <interface> its address and size (192.168.1.23/24 is the network 192.168.1.0/24):

  • ufw (Ubuntu):

    sudo ufw allow proto udp from 192.168.1.0/24 port 5353
    sudo ufw allow proto tcp from 192.168.1.0/24 to any port 4455
    
  • firewalld (Fedora, openSUSE):

    sudo firewall-cmd --permanent --add-service=mdns
    sudo firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="192.168.1.0/24" source-port port="5353" protocol="udp" accept'
    sudo firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="192.168.1.0/24" port port="4455" protocol="tcp" accept'
    sudo firewall-cmd --reload
    

On Windows the app can do it for you too. A Cast output’s settings show Allow casting through Windows Firewall…, and the Cast section shows it under the “could not fetch” and “No TV answered” lines. It asks for administrator permission once (the Windows prompt) and adds one inbound rule, “stream-concern casting”: TCP 4455 (your remote-control port) for stream-concern itself, on Private and Public networks. Pressing it again replaces that rule; it never adds a second one. Under the button the app says whether the rule is there, and when your network is set to Public: Windows applies a rule made for Private networks only (such as one you added by hand) to no Public network, and a wired connection is often Public. Declining the permission prompt changes nothing, and the app says so.

On macOS, allow stream-concern when the system asks whether it may accept incoming connections.

When it does not work

  • No TV found: the TV and this computer must be on the same network (a guest network often keeps devices apart), and the network must pass mDNS; see If no TV appears for this computer’s firewall.
  • “Couldn’t reach Office TV at 192.168.1.35. It may be off, asleep or on a new address; Search again to find it”: the app could not connect to the TV itself (its port 8009). Nothing on this computer is blocking it. Each cast first looks its TVs up again by name, and once more after a failed connection, so a TV that took a new address from your router is found there; this line means it did not answer at all. Wake or turn on the TV, then press Search and cast again.
  • “Casting needs Remote control’s Listen on set to an address the TV can reach”: see Set up, step 2.
  • The TV shows an error or spins: a firewall may block the remote-control port; allow the app through it.
  • The TV buffers (the picture stops and spins now and then while the cast goes on): set the Cast output’s Latency to Safe, so the TV keeps 3 s in hand; connect the TV (a Google TV Streamer has an Ethernet port) or this computer by cable rather than Wi-Fi; or pick a lower Quality and lower the output’s video bitrate in its editor (the bitrate is what the network carries). The log counts it: a cast: Living Room is buffering line each time a TV stalls after it played, and, when the cast ends, cast: the TVs rebuffered 3 times, 4.2 s in all.
  • The list is out of date (a TV turned on later): press Search again. It works at any time, also while a search or a cast runs, and starts the search over.
  • What did the search do? Each search logs it at INFO: cast search: querying with the network interfaces it asks on (the one your default route uses first; on Windows the query goes out of every local network adapter, so a WSL, Hyper-V or VPN adapter cannot swallow it), one cast search: heard … line per TV, and cast search: ended with how many answered. A query or receive that fails is a WARN line.
  • Why did the cast stop? The log says, on a cast ended: line: stopped in the app, stopped on the TV (with the TV’s reason, such as FINISHED), the TV’s error and its code, or that the TV never fetched the video. Each TV’s own end is a cast to Kitchen ended: line.
  • “None of this output’s TVs was found. Search again”: Start found none of the ticked TVs; check they are on, then press Search.
  • “Choose at least one TV for this output first”: tick a TV in the Cast output’s TVs list.