Skip to content

Repository files navigation

MediaDL



VersionSitesPowerShellLicense


Download videos and extract audio from YouTube, Facebook, Twitter/X, TikTok, Instagram, and 1800+ more.
Auto-detects media on any page. Floating download pills. Zero configuration.


3-tier failover · hidden background server · real-time progress · 7-layer Facebook extraction



🚀 Quick Install

✨ Features

🌍 Sites

🏗️ Architecture

🔧 Troubleshoot


🚀 Quick Install

One command. Everything configured. No manual setup.

irm https://raw.githubusercontent.com/SysAdminDoc/MediaDL/refs/heads/main/Install-MediaDL.ps1| iex

Run in an elevated PowerShell window. The installer downloads yt-dlp, ffmpeg, registers protocol handlers, deploys the background download server, creates a Scheduled Task for auto-start, and installs the userscript.


🌍 Supported Sites

MediaDL has optimized detection for these platforms, including Instagram Reels, Stories, and Highlights, plus generic <video> detection for any site yt-dlp supports:

PlatformVideoAudioPlatformVideoAudio
▶️YouTube🔵Vimeo
📘Facebook🔊SoundCloud
🐦Twitter / X🎸Bandcamp
🎵TikTok📺Dailymotion
📷Instagram🅱️Bilibili
🟣Twitch🏴Rumble / Odysee
🔴Reddit🍿Crunchyroll / Nebula

+ Kick, Floatplane, Streamable, Imgur, Arte, Tagesschau, and 1800+ more via yt-dlp


✨ Features

🌐 MediaDL Userscript

🔍 Auto-Detect

Scans every page for video and audio elements. Attaches floating download pills automatically — no clicking required.

TikTok uses server-rendered play URLs first for watermark-free MP4, with wmplay/download fallback when only a watermarked stream is exposed.

X Spaces discovers live .m3u8 audio from resource timing and embedded playback data.

Live YouTube and Twitch players expose a REC action that starts a server-backed recording from the current live edge.

🛡️ 3-Tier Failover

HTTP server → protocol handler → GM_download. If one method fails, the next activates seamlessly.

Video pills include a click-or-hold quality picker for Best, 720p, 1080p, and 4K. The server also applies editable per-host presets for format, quality, codec, and audio fallback.

Playlist and channel URLs are handled as collection downloads with one queue item, playlist-aware folders, the configured rate limit, and the download archive for resume-safe retries. API clients can force this behavior with channelMode: true in the /download body.

⚡ Background Server

Lightweight HTTP server on 127.0.0.1:9751. Concurrent downloads, progress tracking, queue management. Starts on login.

Queue requests and interrupted states persist in a SQLite WAL journal at %LOCALAPPDATA%\MediaDL\queue.db. The settings panel also exposes a bandwidth slider and per-site concurrency cap to keep busy hosts fair. Open http://127.0.0.1:9751/ui for the local queue viewer, where drag handles persist priority order and active downloads can be paused, resumed, or cancelled. Optional post-processing extracts MP3 audio, looks up MusicBrainz tags, and moves the result into the configured Music folder. The server can also show an opt-in native Windows toast after each download completes.

🔑 Zero-Config Auth

Server token negotiated automatically via X-MDL-Client header handshake. No manual setup.

📊 Progress Toasts

In-page progress bars with download speed and ETA. Appear at the bottom-right of the browser window.

🔄 SPA Compatible

MutationObserver + URL change detection handles single-page navigation on YouTube, Facebook, Twitter, and all modern SPAs.

🖥️ Download Handler

🧵 Async UI

Title and thumbnail fetched in background jobs. The progress popup renders instantly and never freezes.

🎯 Duplicate Prevention

Content identity lock (site + video ID + channel when available) prevents equivalent page/CDN URLs from being queued twice; a scoped URL hash remains the fallback for sites without stable IDs.

📈 Smooth Progress

Animated bar with eased interpolation. Reads only last 4KB via FileStream.Seek.

🔪 Cancel Kills All

Cancelling kills both the PowerShell wrapper and child yt-dlp.exe / ffmpeg.exe via CIM process lookup.

🖼️ Universal Thumbnails

YouTube via direct API. All other sites via yt-dlp --get-thumbnail. Both non-blocking.

✂️ Chapter Splitting

Enable chapter splitting in the server settings to emit one file per YouTube Chapters: section while preserving embedded chapter markers.

🎵 Music Post-Processing

Enable the opt-in post-processing switches to extract audio after a video completes, tag it through MusicBrainz, and move it to a collision-safe Music folder filename.

🎛️ Format Control

Configure host presets in the server settings JSON. The built-in examples request 1080p AV1 MP4 for YouTube, best MP4 for X/Twitter, and FLAC with an MP3 retry for SoundCloud.

Subtitle control can optionally download manual and automatic captions as SRT and mux them into an MKV output.

Hardware transcode is opt-in in the same settings panel: choose NVENC or QSV to re-encode completed video with FFmpeg while copying audio, subtitle, and data streams unchanged.

📂 Open on Complete

Click "Complete!" to open Explorer with the downloaded file pre-selected.

🪟 Win11 Native

DWM rounded corners via DwmSetWindowAttribute. Degrades gracefully on Windows 10.

🔄 Verified Dependency Updates

The background server checks yt-dlp and ffmpeg once per day, downloads only the expected GitHub release assets, and replaces them only after their SHA-256 release digests match. Missing digests or unexpected download origins fail closed and leave the installed tools untouched.

Completion toasts are opt-in and fail safely when WinRT toast registration is unavailable.

🛑 Crash-Proof

4-layer exception handling: closing flag, nuclear try/catch, control guards, and global Application.ThreadException.

🌍 Browser Variants

The extension/ directory contains unsigned MV3 packages for Chrome and Firefox, plus an Edge package with a native side-panel queue viewer. Run node extension/build.mjs after changing MediaDL.user.js to regenerate the shared content/background adapters. Firefox AMO submission/signing is intentionally not performed; load the unsigned package as a development extension.

MediaDL.mobile.user.js is the lightweight Kiwi Browser/Orion variant. It contains no Windows paths, local protocol, or PowerShell assumptions and downloads direct MP4/audio URLs; page-managed blobs and HLS playlists are reported as desktop-only limitations.


📸 Screenshots

Installer Wizard


Installer - Welcome

Installer - Config

Installer - Complete


🏗️ Architecture

 ┌─ Browser ───────────────────────┐ ┌─ Windows ──────────────────────────┐
│ │ │ │
│ MediaDL Userscript │ │ ┌─ Tier 1: Download Server ────┐ │
│ ├─ Auto-detect <video> │HTTP│ │ ytdl-server.ps1 │ │
│ ├─ Floating download pills │◀──▶│ │ 127.0.0.1:9751 │ │
│ ├─ Facebook 7-layer extraction │ │ │ ├─ Concurrent downloads (3x) │ │
│ ├─ In-page progress toasts │ │ │ ├─ Real-time progress │ │
│ └─ SPA navigation handling │ │ │ └─ Auto-start on login │ │
│ │ │ └─────────────────────────────── │
│ ┌──────────────┐ ytdl:// │ │
│ │ Click pill │────────▶│ ┌─ Tier 2: Protocol Handler ────┐ │
│ └──────────────┘ │ │ │ ytdl-handler.ps1 │ │
│ │ │ │ ├─ Progress popup │ │
│ ┌──────────────┐ GM_dl│ │ │ ├─ Thumbnail + title │ │
│ │ CDN direct │───────▶│ │ └─ Auto-retry (3x) │ │
│ └──────────────┘ │ │ └────────────────────────────── │
└─────────────────────────────────┘ └────────────────────────────────────┘
│
Scheduled Task: MediaDL-Server
(auto-start on login, hidden)
TierMethodHowProgressActivates When
1HTTP ServerGM_xmlhttpRequest to 127.0.0.1:9751✅ Real-time pollingServer is running (default)
2Protocol Handlerytdl:// URL triggers ytdl-handler.ps1✅ Popup windowServer is offline
3Browser DirectGM_download for CDN URLs❌ NoneBoth 1 & 2 fail, URL is direct CDN

🔬 Facebook 7-Layer Extraction


Facebook aggressively obfuscates video URLs. MediaDL defeats this with seven extraction layers tried in priority order:

#LayerTechnique
1XHR/Fetch InterceptHooks window.fetch and XMLHttpRequest at document-start to capture playable_url_quality_hd from GraphQL responses
2Performance Resource TimingScans performance.getEntriesByType('resource') for fbcdn.net video entries, sorted by transfer size
3React Fiber Tree WalkTraverses __reactFiber from the <video> element upward through memoizedProps searching for browser_native_hd_url
4Embedded JSON ScrapeSearches <script type="application/json"> blocks for HD video URL patterns
5DOM Permalink WalkClimbs the DOM tree from the video element to find a /videos/, /watch/, or /reel/ link
6Page URL CandidateKeeps the current Facebook video/reel/story URL as a fallback candidate
7MQTT / GraphQL WebSocketHooks page-context WebSocket frames and extracts HD URLs from text, JSON, Blob, and ArrayBuffer payloads

🔌 Server API Reference


The download server runs on 127.0.0.1:9751 (localhost only, not exposed to network).

MethodEndpointAuthResponse
GET/healthServer status. Returns auth token when X-MDL-Client: MediaDL header is present
GET/uiLocal queue viewer with drag handles and download controls
GET/plugins🔐Loaded extractor plugin names, versions, and directory
POST/download🔐Start download. Body: {url, title, audioOnly, referer, format, quality, channelMode}. Returns {id}
GET/status/:id🔐{status, progress, speed, eta, filename}
GET/queue🔐Priority-ordered array of downloads with status and site
POST/queue/reorder🔐Persist priority order. Body: {ids: [...]}
POST/pause/:id🔐Suspend a download process tree
POST/resume/:id🔐Resume a paused download
DELETE/cancel/:id🔐Cancel and clean up a download
GET/shutdown🔐Gracefully stop the server

🔐 = Requires X-Auth-Token header (auto-negotiated by the userscript)

The same local control surface is available on the \\.\pipe\MediaDL named pipe to avoid TCP port collisions. Send one newline-delimited JSON request such as {"method":"GET","path":"/health","headers":{"X-MDL-Client":"MediaDL"}}; the response is {"status":200,"body":...}. Pipe requests support health, download, status, queue, pause, resume, cancel, and shutdown operations and use the same auth token.

🧩 Extractor Plugins


Drop a trusted .ps1 file in %LOCALAPPDATA%\MediaDL\plugins. It registers a handler with Register-MediaDLPlugin; CanHandle receives the original page URL and Extract returns an absolute media URL plus optional metadata. Plugins are loaded at server start, limited to 256 KiB each, and can be inspected through the authenticated /plugins endpoint.

Register-MediaDLPlugin-Name 'ExampleCdn'-Version '1.0'`-CanHandle { param($url) $url-match'^https://example\.com/video/' } `-Extract {
param($url,$context)
@{ url=$url-replace'/video/','/media/'; title=$context.title }
}

The server passes the resolved URL through the normal queue, duplicate, format, subtitle, post-processing, and notification paths. Plugin scripts are local code and therefore run with the server user's permissions.


📂 Project Files

FileDescription
Install-MediaDL.ps1PowerShell WPF installer wizard (dark-themed GUI)
MediaDL.user.jsUserscript — auto-detect on all websites
ytdl-server.ps1Hidden HTTP download server (127.0.0.1:9751)
ytdl-handler.ps1Protocol handler with async progress popup
ytdl-server-launcher.vbsWindowless server launcher
ytdl-launcher.vbsSilent handler launcher
config.jsonPaths, server port/token, preferences
%LOCALAPPDATA%\MediaDL\plugins\*.ps1Optional trusted extractor plugins

💻 Installation

Option 1 — Automatic Installer (recommended)

# Open PowerShell as Administrator, then run:
irm https://raw.githubusercontent.com/SysAdminDoc/MediaDL/refs/heads/main/Install-MediaDL.ps1| iex

The installer creates a MediaDL-Server Scheduled Task that auto-starts the background server on login. No console windows will appear.

Option 2 — Manual Installation

  1. Install Tampermonkey or Violentmonkey
  2. Install the userscript:
  3. Install yt-dlp and ffmpeg
  4. Set up protocol handlers manually (see below)
Protocol Handler Registry Entry
Windows Registry Editor Version 5.00
[HKEY_CLASSES_ROOT\ytdl]
@="URL:YTDL Protocol"
"URL Protocol"=""
[HKEY_CLASSES_ROOT\ytdl\shell\open\command]
@="wscript.exe \"C:\\Path\\To\\ytdl-launcher.vbs\" \"%1\""

📋 Requirements

🤖 Automatic (recommended)

The installer handles everything:

ComponentStatus
yt-dlpAuto-downloaded
ffmpegAuto-downloaded
Protocol handlerAuto-registered
Download serverAuto-deployed
Scheduled TaskAuto-created

🔧 Manual

If installing without the wizard:

ComponentLink
📌Userscript managerTampermonkey
📌yt-dlpGitHub
📌ffmpegffmpeg.org

🔧 Troubleshooting

IssueSolution
Download pills don't appearRefresh the page. Verify userscript is enabled with @match *://*/*
Server not runningCheck Task Scheduler for MediaDL-Server, or run ytdl-server-launcher.vbs manually
Facebook downloads failClick the video to trigger playback first (populates CDN URLs for extraction)
Download fails silentlyVerify yt-dlp and ffmpeg are installed and paths are correct in config.json
JIT debugging dialogUpdate to the latest handler (4-layer crash prevention)
Duplicate downloadsUpdate to the latest handler (content identity lock with URL fallback)

🗑️ Uninstalling

Run the installer again — it auto-removes the previous installation before reinstalling.

For full manual removal:

  1. Task Scheduler → Delete the MediaDL-Server task
  2. Delete%LOCALAPPDATA%\MediaDL
  3. Registry → Remove HKCU:\Software\Classes\ytdl
  4. Browser → Remove the userscript from Tampermonkey

🤝 Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

📄 License

This project is licensed under the MIT License — see the LICENSE file for details.



About

Universal media downloader (userscript + PowerShell backend) with auto-detection on 1800+ websites, floating download buttons, 3-tier failover architecture, and 6-layer Facebook extraction.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages