Snagr
Built to kill one specific chore: getting a track off YouTube and into Navidrome without downloading it, then manually moving the file into Navidrome's library folder. Paste a link, pick a format, and it lands directly in the library — or comes straight to your device instead.
Overview
The itch this scratches is very specific: Navidrome (part of the homelab) serves music from a folder it watches — but getting a track into that folder used to mean download it, find the file, drag it into the right place, wait for Navidrome to notice. Every time, for every song.
Snagr collapses that into one step. Paste a link, pick a format (audio and video listed separately), and choose the destination: a predefined server folder — Navidrome’s library — where it appears ready to stream within seconds, or straight to your own device if you just want the file. Either way, a live progress bar the whole time, no manual file-shuffling involved.
Highlights
- One click, straight into the library — the whole reason this exists: point the predefined destination at Navidrome’s music folder and a link becomes a streamable track with zero manual file handling.
- Real-time progress over WebSockets, not a spinner — FastAPI’s native WebSocket support streams progress straight to the browser.
- Format-aware muxing — video-only DASH formats get automatically muxed with audio via ffmpeg, so picking the best quality doesn’t leave you with a silent video.
- Nothing lingers — finished files are deleted the moment they’re either moved to their destination or streamed to the browser, a background sweeper cleans up anything abandoned, and a container restart wipes all in-memory job state.
- Built like it might actually be exposed to a network, because it might be: URLs are allowlisted to YouTube only, playlists/channels are rejected outright to stop unbounded scraping, yt-dlp is called through its Python API (never a shell string, so there’s no injection surface), filenames are sanitized before they ever touch the filesystem, and size limits are enforced twice — once as an estimate, once against actual bytes downloaded.
- Locked-down container: non-root user, read-only root filesystem, all
Linux capabilities dropped,
no-new-privilegesset.
Stack
FastAPI + Uvicorn for the async backend and WebSocket progress streaming,
yt-dlp for extraction, ffmpeg for muxing, vanilla HTML/CSS/JS on the front
end (no framework, no build step), dependencies managed with uv, deployed
as one of the services in the self-hosted stack.