Add yt-dlp "Download Video" Chromium extension

Download the current page's video with yt-dlp via Alt+Shift+D or a click
on the toolbar icon. A native-messaging host runs the download, shows live
progress on the Quickshell OSD, and posts a clickable "Download complete"
toast that opens the file in mpv.

- Extension: pinned key for a stable id, green download-video icon,
  keyboard command + toolbar action (reads the active tab URL).
- Native host (omarchy-chromium-ytdlp-host): verifies the URL with
  yt-dlp --simulate (else "No video found"), streams progress to the OSD
  (time-throttled to ~4/s), saves to ~/Videos, opens mpv on click.
- Installer (omarchy-install-chromium-ytdlp) writes the native-messaging
  manifest into installed Chromium/Chrome/Brave/Edge profiles; wired into
  browser install and chromium refresh, with a migration for existing users.
- omarchy-osd: add -d/--duration so the OSD can persist during a download.
- Add yt-dlp to base packages, load the extension via --load-extension,
  and document the Alt+Shift+D binding.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
David Heinemeier Hansson
2026-06-04 11:15:28 +02:00
co-authored by Claude Opus 4.8
parent 1d6467c91c
commit e5290b0a12
15 changed files with 328 additions and 4 deletions
@@ -0,0 +1,41 @@
function sendUrl(url) {
if (!url || !/^https?:/i.test(url)) return;
// The native messaging host runs yt-dlp and owns all the desktop
// notifications, so we just hand off the URL and ignore the reply.
chrome.runtime.sendNativeMessage('com.omarchy.ytdlp', { url }, () => {
void chrome.runtime.lastError;
});
}
function triggerDownload(tab) {
if (!tab) return;
// The activeTab permission exposes tab.url whenever the user invokes the
// extension — both via the toolbar click and the keyboard shortcut.
if (tab.url) {
sendUrl(tab.url);
return;
}
// Fallback: read the URL straight from the page.
if (tab.id === undefined) return;
chrome.scripting
.executeScript({ target: { tabId: tab.id }, func: () => location.href })
.then((results) => sendUrl(results && results[0] && results[0].result))
.catch(() => {});
}
// Keyboard shortcut (Alt+Shift+D).
chrome.commands.onCommand.addListener((command) => {
if (command === 'download-video') {
chrome.tabs.query({ active: true, currentWindow: true }, (tabs) => {
triggerDownload(tabs[0]);
});
}
});
// Clicking the extension's toolbar icon.
chrome.action.onClicked.addListener((tab) => {
triggerDownload(tab);
});
@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" shape-rendering="geometricPrecision" text-rendering="geometricPrecision" image-rendering="optimizeQuality" fill-rule="evenodd" clip-rule="evenodd" viewBox="0 0 512 468.553"><path fill-rule="nonzero" d="M97.632 0h316.736c26.861 0 51.272 10.989 68.953 28.673C501.017 46.363 512 70.787 512 97.632v273.293c0 26.841-10.995 51.255-28.682 68.945-17.691 17.691-42.112 28.683-68.95 28.683H97.632c-26.845 0-51.269-10.986-68.959-28.676C10.989 422.193 0 397.785 0 370.925V97.632c0-26.867 10.983-51.281 28.667-68.965C46.351 10.983 70.765 0 97.632 0zm140.509 314.599l-3.333-105.58 36.408-1.151 3.276 103.999 42.188-43.498 26.112 25.404-87.819 90.577-85.765-88.532 26.125-25.404 42.808 44.188v-.003zM28.619 122.962H88.37l36.214-92.199c.286-.726.62-1.441.999-2.144H97.632c-18.963 0-36.218 7.77-48.731 20.282-12.512 12.513-20.282 29.768-20.282 48.731v25.33zm122.084-94.343l-37.057 94.343h108.69l36.129-91.983c.315-.798.687-1.587 1.116-2.36H150.703zm133.744 0l-37.054 94.343h105.793l36.215-92.199c.286-.726.62-1.441.998-2.144H284.447zm131.067.009l-37.051 94.334h104.918v-25.33c0-18.947-7.776-36.205-20.295-48.724-12.258-12.261-29.068-19.974-47.572-20.28zm67.867 122.947H28.619v219.35c0 18.956 7.776 36.204 20.289 48.717 12.519 12.518 29.777 20.292 48.724 20.292h316.736c18.941 0 36.196-7.78 48.715-20.299 12.518-12.518 20.298-29.773 20.298-48.71v-219.35z"/></svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

@@ -0,0 +1,23 @@
{
"manifest_version": 3,
"name": "Download Video",
"version": "1.0",
"description": "Download the current page's video, this extension is installed by Omarchy",
"key": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4fww2jejSazrS0dpOBYyx8IfWRkRmek213PnIOaqzAuLK1jE1T+rR+SqBaKnC9j311O6sGrQ+MZJHotJfZyXoKBvSlfiay2z3NU0+Qv1Xa2VaRDuFoHzpfc4OcPvN1B/dGutLCxcLjvSBWEomGVSV1RpK+fgcOeJPFOjKLVrajedv9RnV3JE/Mz3VqBIpkzCUBtsM2eEpZZYWOWuyyk+h6RlbGkHXwudzizf7uJ7bA6RzZKF92wqnbgKDvGji0TwolzAJKALFTul44JzYNiU3Cy7FJXv/aXAKXwAf1VOXXMKie6udXv/M0E1vZAIWHv1sGhkxZZFxZ3C33svlXfg7wIDAQAB",
"permissions": ["activeTab", "scripting", "nativeMessaging"],
"icons": {
"16": "icon.png",
"48": "icon.png",
"128": "icon.png"
},
"action": {
"default_title": "Download Video"
},
"commands": {
"download-video": {
"suggested_key": {"default": "Alt+Shift+D"},
"description": "Download Video"
}
},
"background": {"service_worker": "background.js"}
}
@@ -0,0 +1,9 @@
{
"name": "com.omarchy.ytdlp",
"description": "Omarchy yt-dlp download host",
"path": "__HOST_PATH__",
"type": "stdio",
"allowed_origins": [
"chrome-extension://dedjgknigfeelejglamclffonmophnfl/"
]
}