WebVideo2NAS: A Chrome-to-NAS Stream Capture Pipeline
Self-hosted Chrome → NAS pipeline: capture HLS / DASH / MP4 streams from any site and download to your NAS. Single multi-arch Docker image (FastAPI + worker + ffmpeg) distributed via GHCR.
At a glance
- What is it?
- WebVideo2NAS pairs a Manifest V3 Chrome extension with a Dockerized FastAPI and ffmpeg backend to move HLS, DASH and MP4 streams onto your own NAS. The split between NAS-direct downloads and browser-side jobs is the interesting part, and the licence file is the part to check before you deploy it.
- Who is it for?
- Adopt WebVideo2NAS if you already run Docker on a NAS, you watch streams that your browser can play, and you want the files on your own storage rather than in a downloads folder. Do not adopt it if you need DRM-protected content, if you cannot run Redis and PostgreSQL alongside it, or if you have not yet checked the licence question: the repository metadata carries NOASSERTION while the README badge says MIT, and that gap is the first thing to resolve.
- Can I use it commercially?
- Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
- Is it still maintained?
- Yes. The repository last received commits 7 days ago.
- What is it written in?
- Mainly Python, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 15, 2026, and from our analysis. They are not legal advice.
DEEP OPEN-SOURCE ANALYSIS
The gap between a playing video and a file on your disk
Most people who want to keep a web video end up in the same place: the browser plays it, the download button does not exist, and the network tab shows a manifest URL that expires in a few minutes. WebVideo2NAS targets that gap directly. The README frames the workflow in four steps: detect M3U8, MPD, MP4 and MOV URLs in Chrome, send them to the NAS with one click, download through either NAS-direct or browser-side mode, and store the result on NAS storage. The intended user is someone who already owns a NAS, already runs Docker on it, and wants the video to land on that storage rather than in a desktop downloads folder. The README is explicit that this is not a universal ripper. Some sites use DRM, expiring URLs, anti-hotlinking or IP restrictions, and delivery logic can change at any time. That caveat is not boilerplate; it defines the shape of the tool. It works on streams your browser can already play, not on streams the site has deliberately locked down.
Detection in the extension and the disguised-manifest problem
The extension is Manifest V3 and watches for four URL types plus one harder case. Beyond plain M3U8, MPD, MP4 and MOV detection, the README describes deep manifest interception: fetch and XHR responses are inspected for content, which catches streams disguised as something else, with a .jpg-wrapped HLS stream given as the example. A second case is manifest-less JSON DASH, where the player exposes video and audio .m4s tracks only through its own JSON rather than through a manifest file. The extension pairs those complete tracks and keeps each quality selectable. Quality filters appear when mixed known resolutions are present, even with six or fewer detected items, which suggests the filter logic keys off resolution variety rather than a count threshold. For authenticated streams the extension forwards cookies and headers, and there is a trusted cross-site CDN allowlist with exact-host one-click add. That allowlist is the mechanism that keeps a page from silently redirecting a capture to an unrelated host; the README does not describe what happens when a legitimate CDN is not yet on the list, so treat that as something to observe in your own setup.
Two download paths, and why the browser-side one exists
The architecture splits into NAS-direct and browser-side modes, and the split is the design decision worth understanding. In NAS-direct mode the backend does the work: a multi-threaded segment downloader pulls the segments and ffmpeg merges them. That is the cheap path, because the NAS does the fetching and the browser only sends a URL. It fails when the stream is session-bound, meaning the manifest or segments are tied to the browser's cookies or IP address. For those cases the extension runs the HLS or DASH job in the browser and uploads segments to staging APIs on the backend, which then finalizes the job. The README describes live browser-side upload progress with separate CDN and NAS transfer rates, which tells you the segment data makes two hops: source to browser, browser to NAS. That is more bandwidth through the client machine, and it depends on the tab staying open. The trade-off is deliberate. NAS-direct is the default because it is cheaper; browser-side exists as the fallback for streams that would otherwise return 403.
The backend stack: FastAPI, Redis, PostgreSQL and a cleanup service
The backend is Python 3.11+ with FastAPI, ffmpeg, Redis and PostgreSQL, shipped as a single multi-arch container at ghcr.io/asdfghj1237890/webvideo2nas for linux/amd64 and linux/arm64. Redis holds the job queue; PostgreSQL holds persistent state. The README states that the Synology compose runs three workers by default for parallel processing, and that a periodic DB cleanup service handles per-status retention plus removal of orphan partial files. That cleanup service matters more than it looks. A downloader that writes partial segments and then dies leaves disk garbage, and on a NAS with finite storage that accumulates. Per-status retention means finished, failed and abandoned jobs can age out on different schedules. The REST API handles job management and progress tracking, and the health check is a bearer-token endpoint, so the API is not open by default. The compose file is the only artifact in the release zip, roughly 3 KB, which keeps the distribution surface small but also means configuration lives entirely in .env and the compose file.
Getting it running: compose file choice, two secrets, one curl
The README gives a concrete sequence. Download the release zip with wget from the latest release URL, unzip it to get ./docker/, and cd into it. Then pick a compose file: on Synology, rename docker-compose.synology.yml to docker-compose.yml; on Linux, macOS or Windows Docker, rename docker-compose_not_synology.yml instead. The Synology variant hard-codes paths under /volume1/ for the database, Redis, downloads and logs, so a NAS with a different volume layout needs the volumes section edited before the first start. Copy .env.example to .env and set two required values: API_KEY, generated with openssl rand -base64 32 and pasted into the Chrome extension settings, and DB_PASSWORD, generated with openssl rand -base64 24. Everything else ships with defaults, and the README says comments in .env.example cover rate limiting, CORS, worker tuning, IP allowlist, SSRF guard and image tag pinning. Then docker compose pull, docker compose up -d, and a health check against http://localhost:52052/api/health with the bearer token, which the README shows returning {"status":"healthy"}. The extension itself is unpacked, so Chrome needs developer mode enabled. The README notes the release zip contains only the compose file, so there is no bundled extension build to install from the archive.
Where it breaks, and when a different tool is the right call
The failure modes are stated plainly in the README rather than discovered later. DRM-protected content is out. Expiring URLs are out unless the capture happens before expiry. Anti-hotlinking and IP restrictions can defeat NAS-direct mode, which is exactly the case browser-side mode was built for, but that mode still fails if the site ties the session to something the extension cannot forward. Sites that change delivery logic will break detection until the extension is updated. The security note is equally direct: the README does not recommend exposing the service to the public internet and suggests LAN or VPN access, naming Tailscale as an example. That is the right posture for a service that holds an API key and writes files to your storage. Compared with yt-dlp, the difference is architectural rather than feature-level. yt-dlp is a command-line extractor with site-specific extractors maintained upstream, run wherever you invoke it. WebVideo2NAS has no per-site extractors; it reads what the browser already negotiated, which is why it catches a .jpg-wrapped manifest that a URL-pattern extractor would miss, and also why it cannot do anything the browser cannot play. If your target is a site yt-dlp already supports, yt-dlp is the smaller dependency. WebVideo2NAS is for the case where the browser plays it, the URL is awkward, and you want the file on the NAS without a shell session.
Licence status and the maintenance surface
The repository metadata reports the licence as NOASSERTION while the README carries an MIT badge linking to opensource.org. Those two signals disagree, and the discrepancy is worth resolving before you build anything on top of the project. If the badge is accurate, MIT permits commercial and private use with attribution; if the metadata is accurate, the terms are simply unclear from the repository listing. This is not legal advice, only an observation that the two sources conflict and the licence file itself is the thing to read. On maintenance, the release cadence is visible: v3.9.0 on 2026-09-09, v3.8.0 on 2026-08-25, v3.2.0 on 2026-07-19. The gap between v3.2.0 and v3.8.0 spans roughly five weeks with several releases skipped in the numbering, which is consistent with active development rather than a frozen project. Upgrade cost is low by design: the release zip contains only the compose file, the application image is pulled from GHCR, and the README mentions an image tag pin in .env, so you can hold a version until you choose to move. The real upgrade risk sits in the database and Redis volumes, since schema changes across minor versions are not described in the material available here.
Editorial conclusion
Adopt WebVideo2NAS if you already run Docker on a NAS, you watch streams that your browser can play, and you want the files on your own storage rather than in a downloads folder. Do not adopt it if you need DRM-protected content, if you cannot run Redis and PostgreSQL alongside it, or if you have not yet checked the licence question: the repository metadata carries NOASSERTION while the README badge says MIT, and that gap is the first thing to resolve. Verify next that your NAS host matches one of the two compose files, that the hard-coded /volume1 paths in the Synology variant match your volume layout, and that API_KEY is set before the stack is reachable from anything other than your LAN.
Community notes