Right-click menu
One MeTube entry on links, pages, selected text and the YouTube player. Three blocks (video, audio, subtitles), with the entries, the one-click choices and the layout you decide.
ChromeArcManifest V3No build step
MeTube Sender sends videos, shorts and playlists to your self-hosted MeTube from any page, then plays what MeTube downloaded in an overlay, right on top of YouTube.
Free and open source. A zip with its SHA-256 checksum on every release.
What it does
One MeTube entry on links, pages, selected text and the YouTube player. Three blocks (video, audio, subtitles), with the entries, the one-click choices and the layout you decide.
The toolbar button lists the videos, shorts and playlists linked from the current page, embedded players included, with their titles. Tick some or all, then send. Audio only is one toggle away.
On a video page, Alt+Shift+M opens the video from MeTube in an overlay: it resumes where you were, shows the download's progress if it's still running, and plays your subtitles.
YouTube links are cut down to v, list and t: no si, pp, feature or index. Short, mobile, live and embed links become the standard watch URL. Other sites pass through unchanged, since MeTube takes everything yt-dlp does.
The badge counts what was sent. A red ! means something failed: open the popup to read why. When the browser shows notifications, you get one too.
Menus, popup, settings, player, notifications and errors follow the browser's language, numbers and sizes included (1.2 GB, 1,2 Go). Adding a language is one JSON file.
Install
Download the latest metube-sender-<version>.zip and unzip it into a folder you'll keep. To run the unreleased code instead, clone the repository.
chrome://extensions.manifest.json.The player's shortcut is Alt+Shift+M (Option+Shift+M on a Mac). To change it, or if another extension already took it, open chrome://extensions/shortcuts and edit Play the current YouTube video from MeTube. The settings page shows the current shortcut and has a Change shortcut button.
Unzip the new release into the same folder, replacing its files (or pull the new code), then click the reload icon on the extension's card. Loading it from a different folder installs a second extension, without your settings.
Configure
When you click Save, the browser asks for permission to access your MeTube host: click Allow. Then Test connection calls /version and shows the MeTube and yt-dlp versions it finds.
https://metube.example.com. If MeTube runs under a path prefix (URL_PREFIX), include it: https://example.com/metube.Authorization: Basic … with every request, e.g. for Traefik basicAuth. Leave both empty if MeTube isn't behind auth.CUSTOM_DIRS=true, plus CREATE_CUSTOM_DIRS=true if the folder doesn't exist yet.fr, en). They must match the subtitleslangs MeTube downloads. The menu's subtitles block uses the same list.All settings, including the password, are stored in this browser's extension storage (chrome.storage.local). They are never sent anywhere except to your MeTube host.
Player on YouTube
On a youtube.com/watch?v=… page, press the shortcut or click Play in the popup. The overlay pauses YouTube's player, notes where you were, and looks the video up in MeTube's history by video ID. Then:
Plays the file. If you had watched more than 5 seconds on YouTube, it starts from there.
Shows the progress, refreshed every 2 seconds, and starts playing when the download finishes.
Adds it with your default options, then shows the progress.
Shows MeTube's error (private, age-restricted, removed…), with Try again.
Play/pause, seeking, volume, speed (0.5× to 2× in the ⋯ menu), subtitles, picture-in-picture and fullscreen are in the control bar. The overlay also closes when you navigate to another video.
The player is for watching a video once, while YouTube streaming is out of reach. Once watched, the file can go:
After deleting, the extension checks whether the file is really gone from the server and says so. MeTube only erases files when it's set up for it: see Server setup.
A <video> element can't send an Authorization header. The extension adds one with a declarativeNetRequest rule, rebuilt whenever you save the settings. The rule only applies to GET requests for media, started by the extension's own player, to your MeTube URL. Requests made by YouTube or any other site never get your credentials, so a web page can't use them to add or delete downloads. Every other request (/history, /add, subtitle files) is sent by the service worker.
MeTube server setup
Sending works with any MeTube. The player wants a little more: subtitles written next to the videos, HTTPS, and permission to erase files.
MeTube only writes subtitle files if yt-dlp is told to. Add this to MeTube's environment, with the same languages as in the extension's settings. yt-dlp then saves <video>.<lang>.vtt next to each video, and the player loads each one it finds. Only videos downloaded after this change have subtitles.
YTDL_OPTIONS={"writesubtitles": true, "writeautomaticsub": true, "subtitleslangs": ["fr","en"], "subtitlesformat": "vtt"}
MeTube's default (DELETE_FILE_ON_TRASHCAN=false) only removes the entry from its list and keeps the file. For the player's delete button to erase files, add the line below. true also works, but then MeTube's own trash button always erases files too. With the default, the player tells you the file was kept.
DELETE_FILE_ON_TRASHCAN=ask
YouTube is an HTTPS page, and browsers won't load http:// video inside it. MeTube must be reachable over https://, for example through Traefik with a certificate. localhost is the only exception.
The player expects MeTube's standard file URLs: {MeTube URL}/download/…, or /audio_download/… for audio. If you changed PUBLIC_HOST_URL to serve files from elsewhere, the player won't find them.
MeTube keeps one history entry per video URL. Downloading the audio or the subtitles of a video that's already downloaded replaces its entry (the video file stays on disk); the player then no longer finds the video and would download it again. For subtitles to watch with, prefer YTDL_OPTIONS; use the menu's subtitles block to get the files themselves.
The browser must be able to play the file. MP4 (H.264/AAC) and WebM play everywhere. If you get can't play this file, set the default video format to MP4 in the settings.
A MeTube service with everything the extension can use. Put it behind your HTTPS reverse proxy.
services:
metube:
image: ghcr.io/alexta69/metube
container_name: metube
restart: unless-stopped
ports:
- "8081:8081"
volumes:
- ./downloads:/downloads
environment:
# Optional "Folder" setting in the extension
- CUSTOM_DIRS=true
- CREATE_CUSTOM_DIRS=true
# Player: subtitles next to each video, same languages as the extension
- YTDL_OPTIONS={"writesubtitles":true,"writeautomaticsub":true,"subtitleslangs":["fr","en"],"subtitlesformat":"vtt"}
# Player: the delete button really erases the file
- DELETE_FILE_ON_TRASHCAN=ask
t= timestamps: current MeTube versions turn a t parameter into the start of a clip, so watch?v=…&t=90 downloads from 1:30 onward. To get the whole video, send a link without t.watch?v=…&list=…): the popup tags these In playlist. Whether MeTube downloads only that video or the whole playlist depends on its strict playlist mode (DEFAULT_OPTION_PLAYLIST_STRICT_MODE).WL), Liked videos (LL) and Liked music (LM).Troubleshooting
Check the username and password in the settings.
The URL is wrong, the server is down, or it's unreachable from this machine (VPN, DNS, TLS certificate).
The URL is missing MeTube's path prefix, or points to the wrong service.
MeTube refused the options; the reason comes from MeTube. Example: a folder was set but CUSTOM_DIRS is off.
Something other than MeTube answered, such as a login page from Authelia or Authentik, or a proxy error page. Basic auth is the only login method this extension supports.
Open the settings and click Save, then Allow. If no prompt appears, go to the extension's Details page → Site access and add your MeTube site.
Browser pages (chrome://, arc://, the Web Store) can't be read by extensions. Send page still works for normal web pages.
MeTube's own error is shown below it (private, age-restricted, removed…). Try again re-adds the video.
The download was deleted from disk but is still in MeTube's history. Download again re-adds it.
Serve MeTube over HTTPS (see Server setup).
The browser doesn't support the file's format. Set the default video format to MP4.
Check YTDL_OPTIONS (see Server setup), and that the languages match. Videos downloaded before the change have none.
MeTube removed the entry but not the file: run it with DELETE_FILE_ON_TRASHCAN=ask.
Check Right-click menu in the settings (block turned off, quality not selected, context unchecked). Subtitles need at least one Subtitle language.
Another extension may use it: set a different one (see Keyboard shortcut). It only works on youtube.com/watch?v=… pages.
Permissions and privacy
Every network call is made by the background service worker, never by the pages you visit. The player page is the only file YouTube pages can load from the extension.
contextMenusThe right-click menus, including the extension icon's.storageSaving settings, and remembering the last error for the popup.scripting + activeTabReading links from the current tab, and opening the player on it, only after you open the popup, use a menu item or press the shortcut.notificationsResult notifications, when the browser shows them.declarativeNetRequestWithHostAccessThe rule that adds your credentials to the player's video requests. Unlike declarativeNetRequest, it only acts on hosts you granted, and adds no install warning.https://*.youtube.com/*Scanning YouTube pages for links, and opening the player there.Development
No build step, no dependencies to install. The only library, Media Chrome for the player, is vendored (Manifest V3 doesn't allow loading code from the internet). Tests need Node 22+.
git clone https://github.com/CostardRouge/metube-extension.git
cd metube-extension
node --test # unit tests
scripts/build.sh # dist/metube-sender-<version>.zip
scripts/build.sh 1.2.0 # or with a given version
The CI workflow runs the tests and builds the zip on every pull request and push to main. The zip stays attached to the run for 14 days, to try a change before it's released.
git checkout main && git pull
git tag v1.1.0
git push origin v1.1.0
Releases are only created from a version tag on main. The Release workflow runs the tests, builds the zip with that version written into its manifest.json, and publishes a GitHub release with the zip, its SHA-256 checksum and notes from the merged pull requests.
manifest.json
background.js service worker entry: registers listeners, routes messages
sw/ menus, sending, feedback, player requests, the auth rule
lib/ settings, i18n, menu model, MeTube API client, history, YouTube URLs
content/overlay-host.js injected into YouTube on demand: the overlay iframe, pause, navigation
overlay/ the player page shown in that iframe
popup/ options/ ui/ toolbar popup, settings page, shared dark theme
_locales/ English (default) and French messages
vendor/media-chrome/ Media Chrome (MIT), unmodified ES modules
tests/ URL handling, history matching, menus, messages, the manifest, this site
docs/ this website (GitHub Pages)