Connecting a laptop to your TV over HDMI for live TV
The cable is the easy part. What decides whether it looks right is which display Windows thinks is primary and what the app asks that display for.
An HDMI cable from a laptop to a television is the cheapest way to get this app onto a big screen, and it works. The cable is not the interesting part. What decides whether it looks right is what Windows tells the app about the display it has landed on.
Extend, not duplicate
Duplicate mode forces both panels to a shared resolution and refresh rate, which usually means your television gets driven at whatever your laptop panel can do. That is how a 4K television ends up showing a soft 1080p image with judder, and why a 3840 by 2160 panel can report itself as 1920 by 1080 while connected.
Extend instead. Drag the player window onto the television and press F. The laptop panel stays yours for everything else, and the television gets its own native mode.
3 keys reach fullscreen: F, Alt+Enter and F11. Escape leaves it, with one layer in front: if the stream information panel is open, the first Escape closes that and the second leaves fullscreen.
Why the picture changes when you move the window
Because the app asks the display it is actually on, not the display it started on.
HDR is decided per window against that window's monitor. Drag the player from a laptop panel to an HDR television and the app re-reads the colour space and can ask for a 10-bit surface; drag it back and it does not. This is deliberate. On a mixed desk, one panel should never inherit the other's state.
2 conditions have to hold before HDR is requested at all: the display has to report an HDR colour space, and the loaded player library has to be 3.0.21 or newer, probed at runtime rather than assumed. If either fails you get SDR, because SDR is the answer that cannot make anything worse.
Underneath that is a fallback ladder, tried in order:
1 R10G10B10A2 + Ignore preferred, 10-bit
2 R10G10B10A2 + Unspecified 10-bit, different alpha handling
3 B8G8R8A8 + Unspecified 8-bit, identical to the previous behaviour
The third rung matters more than it looks. It is byte-for-byte the old configuration, so a machine that cannot compose 10-bit behaves exactly as it did before rather than failing. And if the surface cannot be created at all, that logs and leaves the surface unloaded rather than throwing out of a layout callback, which would take the whole app down.
We got this wrong once on the way here. The first version asked for 10 bits everywhere, on the reasoning that it costs the same 4 bytes per pixel either way, so why not. It was reverted once the running app showed why: the translucent transport controls composited visibly lighter over the 10-bit surface and ghosted through the video. Same bytes per pixel, different picture. That is why the depth is chosen per monitor, and why the option builder is told which precision the surface actually came up at rather than which one was asked for.
Refresh rate, and the judder nobody attributes correctly
A 50 Hz broadcast on a 60 Hz display has to have frames repeated unevenly: 5 source frames stretched over 6 display refreshes, forever. The result is a small regular stutter on panning shots that is easy to blame on the stream. It is not the stream.
If your television supports it, set the display to match your content's rate, or turn on automatic refresh rate switching in Windows display settings. This is outside the app and the app cannot fix it, which is exactly why it is worth knowing: no amount of buffer tuning will change it. Fixing buffering and stuttering separates this from the failures that are ours to fix.
Audio
HDMI carries audio, and Windows will usually switch the default output to the television when you plug in. Usually.
If you have a receiver in the chain and want it to decode the bitstream itself, turn on audio passthrough. Know one thing first: it opens the output device in exclusive mode, which is why it is limited to the primary player, and which also means other applications lose that device while it is active. On a laptop you also use for calls, expect that surprise.
What was actually tested
Fullscreen and picture-in-picture were both exercised against real 4K sources in the same verification pass, resizing and migrating across windows while continuing to play, with 0 errors logged across the whole run. Moving a playing window between displays is a supported path, not a hopeful one.
If this becomes a habit rather than an occasional thing, a small dedicated machine beats reconnecting a laptop every evening: building a small home theatre PC covers what to buy, and starting the app with Windows makes it behave like an appliance.
What this article measured22 claims, each with the evidence behind it
| Claim | Evidence | Counted |
|---|---|---|
| The app decides HDR per window against the monitor that window is on, so moving the player from a laptop panel to a television changes what it asks for. | n = 1 | Aug 23, 2026 |
| The HDR switch is only emitted when the loaded player library is version 3.0.21 or newer, and the version is probed at runtime rather than assumed. | n = 1 | Aug 23, 2026 |
| The video surface tries three configurations in order and the last rung is byte-identical to the previous stock behaviour, so a machine that cannot compose 10-bit behaves exactly as it did before. | n = 3 | Aug 23, 2026 |
| Fullscreen and picture-in-picture were both verified against real 4K sources, resizing and migrating across windows while continuing to play, with zero errors logged. | n = 1 | Aug 23, 2026 |
| Audio passthrough opens the output device in exclusive mode, which is why it is limited to the primary player instance. | n = 1 | Aug 23, 2026 |
| Requesting 10 bits everywhere was tried on the reasoning that it costs the same 4 bytes per pixel, and reverted once the running app showed the translucent player chrome compositing lighter over it. | n = 1 | Aug 23, 2026 |
| Forcing HDR on a genuinely SDR panel makes the player output PQ, which looks washed out. The setting exists for displays that under-report rather than as a picture control. | n = 1 | Aug 23, 2026 |
| The stock video control builds its swapchain as 8-bit with no hook to change it, and the graphics layer refuses an HDR10 colour space on an 8-bit buffer, so the negotiation could only ever land on sRGB no matter what the stream carried. | n = 1 | Aug 23, 2026 |
| The replacement surface had to reproduce the old control's contract exactly, down to nudging the width by 2 pixels to provoke a rebuild, because the reparent, picture-in-picture and handover paths are built on those semantics. | n = 1 | Aug 23, 2026 |
| The model has exactly two surface precisions: 8-bit, documented as SDR only with HDR tone-mapped, and 10-bit, the precondition for an HDR colour space being accepted. | n = 2 | Sep 1, 2026 |
| The option builder is given the precision the surface actually came up at rather than the one requested, so a failed 10-bit allocation cannot leave a mismatched switch behind. | n = 1 | Sep 1, 2026 |
| The floating window is a real second window the video canvas is reparented into rather than an overlay, which is why it survives being dragged to another display. | n = 1 | Sep 1, 2026 |
| If the owning page is navigated away while the floating window is up, a plain restore would dock the video against a disconnected element and strand it in the shell's corner, so dismissal forces navigation back instead. | n = 1 | Sep 1, 2026 |
| On an SDR display an HDR stream keeps a fixed tone-mapping curve, because the modern alternative is not reachable in the player generation we ship at all. | n = 1 | Aug 23, 2026 |
| Passthrough opens the audio endpoint in exclusive mode, which is why it is limited to the primary player and why other applications lose that output while it is active. | n = 1 | Aug 23, 2026 |
| The console decodes audio to PCM regardless of setup, for two independent reasons: its player build ships no audio output module for passthrough, and the platform does not permit third-party bitstreaming. | n = 2 | Aug 23, 2026 |
| The HDR switch is emitted only when the loaded library is 3.0.21 or newer, probed at runtime, so a downgraded package loses HDR rather than failing to start the player. | n = 1 | Aug 23, 2026 |
| On live TV the transport keys act only while the player owns fullscreen, so pressing them on the browsing page does list navigation instead. | n = 1 | Sep 1, 2026 |
| Six aspect modes ship including forced 16:9, 4:3 and 2.39:1, which is the lever for a television that insists on its own scaling. | n = 6 | Sep 1, 2026 |
| Zoom is clamped between 0.5 and 2.0 on load, so a hand-edited settings file cannot leave the picture unrecoverably framed. | n = 1 | Sep 1, 2026 |
| Deinterlacing attaches on the next stream open rather than to a stream already playing, so changing it means re-tuning the channel. | n = 1 | Sep 1, 2026 |
| Three keys reach fullscreen and Escape leaves it, but Escape closes the stream information panel first if that is open. | n = 1 | Aug 31, 2026 |