TV Hack
Log 05 / 06

TV Browser+

Browsing the web with a TV remote is miserable. This makes any website usable from the sofa, and it hit the hardest wall of the project.

By prutxviBuilt with Claude~5 min read
Typing into Google on the TV from the phone. The phone is in full-screen mode, so its address bar (and the room link) isn't visible.

What it is

TV Browser+ is a module for TizenBrew, an open-source tool for Samsung TVs that injects scripts into web pages (it's also what powers ad-free YouTube on the TV). Our module is injected into every page you open and adds:

FeatureHow it works
Remote cursorArrows move a cursor that speeds up when held. OK clicks, CH▲▼ scroll, Back goes back. Red toggles the cursor, Green opens the start page.
Jump modePress Yellow and the arrows hop between links and buttons with a red highlight, starting at the link nearest the cursor. OK opens.
Phone padScan the start page's QR: a touchpad (drag to move, tap to click, two fingers to scroll), a URL bar and a keyboard.
Text sizeA− / 100% / A+ on the phone, remembered per site.
Direct linkThe phone talks to the TV over Wi-Fi with WebRTC, with a cloud fallback. The phone shows "Direct · N ms" or "Internet · N ms".

The cursor is a 30 px white ring with a red centre, on its own GPU layer and redrawn at most once per frame, so it stays smooth even on heavy pages.

The wall

The plan was to reuse the fast path from the phone remote: the phone talks to the TV's own server, about 10 ms away. It didn't work, and the reason is a browser security rule.

Almost every website is served over https. The TV's own server is plain http, on the TV itself. Browsers block a secure page from talking to an insecure local address (mixed content). Our injected script lives inside that secure page, so it can't reach http://127.0.0.1:8090. The launcher can, because it's a local app, not a website.

Version 1.2 fell back to the cloud relay: the start page makes its own room, and the phone and the page meet there. It works everywhere, but it's back to ~80 ms.

The way around it: WebRTC

WebRTC is how video calls connect two devices directly. It's allowed from secure pages, and once connected, the data goes straight across the Wi-Fi. The cloud is only needed for the introduction.

Start page ── makes its own room ──▶ QR = https://<relay>/r/<room>

Phone ◀══ wss ══▶ cloud room ◀══ wss ══▶ page script     introduction + fallback, ~80 ms
Phone ◀════ WebRTC data channels, over Wi-Fi ════▶ page  direct

Honest status: in a two-tab test on one Mac the direct link measured 1 ms. On the real TV with a real phone, the screenshot in log 04 shows the meter at "Direct · 7–10 ms", but I haven't run a proper measurement yet, so I'm not claiming a number.

Shipping a TizenBrew module

TizenBrew loads modules from GitHub through the jsDelivr CDN. Two things there cost real time:

VersionWhat changed
1.0.1First version that opens: inject per page
1.2Pair through the cloud relay (the mixed-content wall)
1.3GPU-layer cursor, one redraw per frame, phone batches moves every 20 ms
1.4Per-site text size
1.5Jump mode
1.6WebRTC direct link and the live delay meter

What still doesn't work

It's open source and installable from TizenBrew's module manager: github.com/prutxvi/tv-browser-plus.