VideoOut started as a five-minute annoyance fix. I was tired of web video players that fought me on speed controls, quality, and just generally behaving like a media player should, so I built a tiny Android app that would detect a video on a page and fire an Intent to open it in mpv instead. That was the whole v1: detect a video element, hand it off, done.
It stayed that simple for a while — a bottom sheet UI that popped up with the detected sources, a tap to send it to whatever external player was installed. Useful, narrow, Android-only.
The desktop problem
The itch came back once I was doing the same browsing on a Linux desktop and had no equivalent. Android Intents don't exist on desktop, obviously, so getting the same "found a video, hand it to mpv" behavior meant rethinking the whole delivery mechanism.
Firefox's Native Messaging API turned out to be the right tool: an extension can spawn a native host process and exchange JSON messages with it over stdin/stdout. So v2.0 became a Firefox extension that detects video sources in the page, same as before, but instead of firing an Android Intent, it messages a small Python host process running locally, which then shells out to whichever player is available — mpv, vlc, or a plain xdg-open as a fallback — depending on the platform.
- Content script scans the page for
<video>elements and common streaming sources. - Background script relays the selected URL to the native host via
runtime.sendNativeMessage. - The Python host resolves the best available player per OS and launches it, with a protocol URI fallback for setups without Native Messaging configured.
Where the real pain was: packaging, not code
The detection logic and the native host were the easy parts. What actually ate the time was getting the extension packaged correctly as an XPI and getting the manifest to pass Firefox's validation without silent rejections. A few of the sharper edges:
- Native messaging host manifests have to be registered in an exact location per OS, and a single wrong path silently breaks the connection with no useful error in the extension console.
- Firefox's manifest schema is stricter about permission scoping than it first appears — vague host permissions get rejected at review time even if they work fine unpacked in developer mode.
- Cross-platform meant testing the same native host logic against three different conventions for "where is the default media player," which is a surprisingly inconsistent question across Linux, macOS, and Windows.
The interesting engineering was in the protocol handoff. The time-consuming engineering was in the packaging.
Where it is now
VideoOut is at a point where it detects sources reliably across most sites I actually use, hands off cleanly to mpv on Linux, and falls back gracefully when the native host isn't installed. The Android version is still around as the app that started it, but the desktop path — extension plus native host — is where most of the current development happens.