Sleek, lightweight browser extension for opening direct video links (.mp4, .m3u8, .webm) from Firefox or Chromium in external media players (mpv/VLC).
Watching high-definition video streams directly inside a web browser on low-end hardware, such as a Raspberry Pi, often causes severe CPU bottlenecks, frame drops, and lag. This is due to heavy browser rendering engines and the lack of efficient hardware-accelerated video decoding in web browsers on ARM-based or low-spec devices.
CastFlow solves this by:
- Zero-overhead redirection: It catches video stream URLs, referrers, and session cookies directly from your web traffic.
- Hardware-accelerated playback: It forwards the stream to a native external player (
mpvorVLC) via a lightweight Native Messaging host. - Optimized performance: Media players render streams directly with native GPU acceleration, resulting in smooth, stutter-free playback and significantly lower CPU usage and temperatures on your Pi.
- Watches network requests and simple DOM video/source/link URLs.
- Stores recent video URLs per browser tab.
- Popup shows the captured URLs.
- Buttons launch
mpvor VLC through a Native Messaging host. - Native host accepts only
http(s)URLs and launches the player without a shell.
To maximize code reuse and avoid duplication, the source files for both Firefox and Chromium extensions are unified in the src/ directory.
src/: Contains the core logic (background.js,content.js,popup.js,popup.html,popup.css).extension-firefox/: Contains only Firefox-specific settings (manifest.jsonusing Manifest V2).extension-chromium/: Contains only Chromium-specific settings (manifest.jsonusing Manifest V3).build.sh: Copies files fromsrc/to both extension directories for local loading/testing.package.sh: Runsbuild.shand then archives the extensions into thedist/directory.
Edit src/background.js:
const ALLOWED_PAGE_HOSTS = ["example.com", "video.example.net"];Leave it empty while testing:
const ALLOWED_PAGE_HOSTS = [];Before loading or packaging, make sure to compile the shared files:
cd CastFlow
./build.shOn the Pi:
./install_native_host.sh firefoxThen open Firefox:
- Go to
about:debugging#/runtime/this-firefox. - Click
Load Temporary Add-on. - Select
extension-firefox/manifest.json. - Start a video on a target site.
- Open the extension popup and click
Open mpvorOpen VLC.
A pre-built, signed Firefox addon is committed and ready to install at:
dist/firefox-signed/247d4b86c0534abaa496-0.1.0.xpi
For permanent installation on regular Firefox Release, you can simply install this .xpi file. For temporary testing, use the Load Temporary Add-on flow.
Each browser extension is independent. Build separate archives with:
cd CastFlow
./package.shThis creates:
dist/open-video-in-player-firefox.zip
dist/open-video-in-player-firefox-unsigned.xpi
dist/open-video-in-player-chromium.zip
dist/open-video-native-host.zip
The Firefox and Chromium zips contain only extension files. The native host is intentionally separate because browsers do not allow an extension package to install or run local programs by itself.
Normal Firefox will not permanently install an unsigned local .xpi; it shows "This add-on could not be installed because it has not been verified."
For Firefox temporary testing, use Load Temporary Add-on against extension-firefox/manifest.json:
about:debugging#/runtime/this-firefox
For a permanent Firefox add-on, submit/sign open-video-in-player-firefox.zip through Mozilla's add-on signing flow. Choose unlisted/self-distributed signing if this extension is only for you. The signed .xpi can then be installed normally.
open-video-in-player-firefox-unsigned.xpi is only a convenience artifact for Developer Edition/Nightly or other Firefox builds where unsigned extensions are allowed. It will not install in regular Firefox Release.
- Create AMO API credentials:
https://addons.mozilla.org/en-US/developers/addon/api/key/
- Export them in your shell:
export WEB_EXT_API_KEY="..."
export WEB_EXT_API_SECRET="..."- Sign as unlisted/self-distributed:
./sign_firefox_self_distributed.shThe signed .xpi will appear in:
dist/firefox-signed/
Install that signed .xpi in regular Firefox.
For Chromium local use, running ./build.sh and then doing Load unpacked from extension-chromium is simplest. If you pack it into a .crx, keep the generated private key so the extension ID stays stable; the native host manifest must contain that exact Chromium extension ID.
Before loading or packaging, make sure to compile the shared files:
cd CastFlow
./build.shOn the Pi:
- Open
chrome://extensions. - Enable Developer mode.
- Click
Load unpacked. - Select
extension-chromium. - Copy the extension ID shown by Chromium.
Then run:
cd CastFlow
./install_native_host.sh chromium EXTENSION_ID_FROM_CHROMIUMRestart Chromium after installing the native host.
On macOS, this installs to:
~/Library/Application Support/Chromium/NativeMessagingHosts/com.local.open_video.json
For Google Chrome instead of Chromium:
./install_native_host.sh chrome EXTENSION_ID_FROM_CHROMEThe installer supports Linux, macOS, and Windows:
python3 install_native_host.py firefox
python3 install_native_host.py chromium EXTENSION_ID_FROM_CHROMIUM
python3 install_native_host.py chrome EXTENSION_ID_FROM_CHROMEConvenience wrappers:
./install_native_host.sh chromium EXTENSION_ID
install_native_host.bat chromium EXTENSION_IDIt writes manifests here:
Linux Firefox: ~/.mozilla/native-messaging-hosts/com.local.open_video.json
Linux Chromium: ~/.config/chromium/NativeMessagingHosts/com.local.open_video.json
Linux Chrome: ~/.config/google-chrome/NativeMessagingHosts/com.local.open_video.json
macOS Firefox: ~/Library/Application Support/Mozilla/NativeMessagingHosts/com.local.open_video.json
macOS Chromium: ~/Library/Application Support/Chromium/NativeMessagingHosts/com.local.open_video.json
macOS Chrome: ~/Library/Application Support/Google/Chrome/NativeMessagingHosts/com.local.open_video.json
Windows: native/generated/com.local.open_video.json plus HKCU registry entry
On Windows, Native Messaging hosts are discovered through Registry keys under:
HKCU\Software\Mozilla\NativeMessagingHosts\com.local.open_video
HKCU\Software\Chromium\NativeMessagingHosts\com.local.open_video
HKCU\Software\Google\Chrome\NativeMessagingHosts\com.local.open_video
- This does not handle DRM.
- This passes session cookies to the external player (for mpv) to support authenticated streams. It also passes the page URL as
Referer. blob:URLs cannot be opened directly; the extension tries to catch the real.m3u8/.mp4network request instead.- Some sites use URLs without file extensions but correct
Content-Type; the Chromium build has a small Debug section in the popup to show whether anything was caught.