|
|
||
|---|---|---|
| LICENSE | ||
| README.md | ||
| sync.sh | ||
yt-docs-sync
Download a curated set of YouTube documentary channels into one tidy folder so they can live in
a media server (Plex / ErsatzTV / Jellyfin) as their own library — without your *arr apps ever
touching them.
It currently pulls the "main docs" from three creators (Noclip, Defunctland, Yesterworld), capped at 1080p, named by the video's own title.
It's safe to re-run — it keeps a per-creator archive of what it has already grabbed, so a second run only fetches new uploads and never re-downloads or overwrites anything. It also skips anything that errors instead of stopping, and paces its requests politely so YouTube doesn't bot-wall it.
New to all this? No problem. The Quick start below is three copy-paste steps, and every step has a click-to-expand explainer telling you what the command does and why.
Quick start
This tool downloads into a folder you choose. The first run is a big bulk download; every run after that just tops up with new videos.
First time using a terminal? Start here
A "terminal" is a window where you type commands instead of clicking buttons.
- Windows: install Docker Desktop, then open PowerShell (search for it in the Start menu).
- macOS: install Docker Desktop, then open Terminal (in Applications → Utilities).
- Linux: you likely already have a terminal and may already have Docker.
To run a command, copy it, paste it into the terminal window, and press Enter. That's it.
"Docker" is just a tool that runs this program in a tidy box, so you don't have to install
yt-dlp, ffmpeg, or Python yourself.
1. Get the code
git clone https://github.com/you/yt-docs-sync.git
cd yt-docs-sync
What did that do?
git clone downloads a copy of this project to your computer. cd yt-docs-sync ("change
directory") moves you into the folder it created. Replace the URL with wherever you got this from
(e.g. your own Forgejo/GitHub address).
2. Run it
This starts the download in the background, inside a throwaway Docker box. Change
/path/to/your/YouTube Library to the folder where you want the videos to land.
docker run -d --name yt-docs-dl --restart no \
-v '/path/to/your/YouTube Library:/work' \
python:3.12-slim bash -c \
'apt-get update -qq && apt-get install -y -qq ffmpeg >/dev/null 2>&1 \
&& pip install -q --no-cache-dir "yt-dlp[default]" curl_cffi >/dev/null 2>&1 \
&& bash /work/_sync/sync.sh >>/work/_sync/download.log 2>&1'
What does this command do, piece by piece?
docker run -d— start the program in its own tidy box, in the background (-d, "detached", so your terminal is free again right away).--name yt-docs-dl— gives the box a friendly name so you can check on it later.--restart no— when it finishes, leave it stopped (this is a one-shot job, not a service).-v '/path/to/your/YouTube Library:/work'— connects a folder on your computer (the part before the:) to the folder/workinside the box (the part after). The script reads and writes everything under/work. Change/path/to/your/YouTube Libraryto where you want the videos saved. See Personalize it to your setup for how to find that path.python:3.12-slim bash -c '…'— the box starts from a bare Python image, installsffmpeg,yt-dlp, andcurl_cffi, then runs thesync.shscript. (Those tools are installed fresh inside the box each run, so nothing is added to your computer.)>>/work/_sync/download.log 2>&1— saves all the output to a log file inside your folder so you can read it afterward.
The very first run downloads ~300 videos and can take many hours. Because it keeps an archive of what it has fetched, you can stop and re-run the exact same command any time — it picks up where it left off and never re-downloads.
Heads up: the script (
sync.sh) must already be in a_sync/subfolder of your chosen library folder — see Personalize it to your setup.
3. Watch the progress
docker logs -f yt-docs-dl
How do I tell when it's finished?
docker logs -f yt-docs-dl shows the live output (press Ctrl+C to stop watching — the download
keeps going). You'll see one block per creator, and a final === SYNC COMPLETE … === line when
everything is done. You can also open _sync/download.log inside your library folder to read the
same output later.
Personalize it to your setup
A couple of things are specific to your machine and your taste. Here's what to change and how.
Your library path — the folder where the videos should be saved. In the docker run command,
replace /path/to/your/YouTube Library with that path.
How do I find / pick my library path?
Pick (or make) an empty folder you want the documentaries to live in, then use its full path:
- Windows:
D:\Media\YouTube Library→ write it asD:/Media/YouTube Library(forward slashes). - macOS/Linux: something like
/Volumes/media/YouTube Libraryor/srv/media/YouTube Library. - A NAS/server: the path as that machine sees it, e.g.
/srv/mergerfs/media/Storage/Media/YouTube Library.
Tip: open the folder in your file manager and copy it from the address bar.
Put sync.sh where the box can find it — the command runs bash /work/_sync/sync.sh, so the
script has to live in a _sync/ subfolder of your library path.
How do I do that?
Inside your library folder, make a folder called _sync and copy sync.sh (from this repo) into
it. So if your library is /srv/media/YouTube Library, the script ends up at
/srv/media/YouTube Library/_sync/sync.sh. The script creates the rest (Noclip/,
Defunctland/, Yesterworld/, and its archive files) the first time it runs.
Which channels/playlists you want — the list of creators and playlists is hardcoded in
sync.sh. Edit it to add, remove, or swap sources.
How do I change the channels or playlists?
Open sync.sh in a text editor. Each creator is one dl … call:
dl Noclip archive-noclip.txt \
"https://www.youtube.com/playlist?list=PL-THgg8QnvU5Y2hRXYo76fwl3083V8Bm8"
- The first word (
Noclip) is the subfolder the videos go into. - The second word (
archive-noclip.txt) is the file that remembers what's already downloaded — give each creator its own. - Each playlist or channel URL after that gets downloaded. Add more URLs (one per line, each
ending in
\except the last) or paste in a whole-channel URL.
To add a brand-new creator, copy a whole dl … block and change the folder name, archive name, and
URLs. To remove one, delete its block.
File ownership (NAS / Linux servers) — the last line of sync.sh does chown -R 1000:100 so
your media server can read the files.
When and how do I change the ownership numbers?
On a single personal computer you can usually ignore this. On a NAS or Linux server, the downloaded
files should be owned by the user/group your media server runs as. Find your numbers by running
id in a terminal (it prints uid=… and gid=…), then edit the chown -R 1000:100 "$ROOT" line
in sync.sh to match. If the wrong numbers are there it fails harmlessly (the || true keeps it
from stopping the run).
What the script tells yt-dlp to do
These are the download settings baked into sync.sh (in the COMMON list). You don't need to set
them — this table just explains what each one does if you want to tweak it.
| Flag | What it does |
|---|---|
-f "bv*[height<=1080]+ba/b[height<=1080]" |
Caps video at 1080p and grabs the best audio to match. |
--merge-output-format mkv |
Saves the final file as .mkv (chosen because AV1 video + Opus audio merge into mkv cleanly, but break in mp4). |
-o "<Creator>/%(title)s.%(ext)s" |
Names each file by its video title, inside the creator's folder — so a media server shows a readable title. |
--download-archive <file> |
Remembers what's been downloaded, making re-runs incremental (only new videos). This is what makes it safe to re-run. |
--embed-metadata --embed-chapters |
Stores title/description and chapter markers inside the file. |
--embed-subs --sub-langs "en.*" |
Embeds any English subtitles into the file. |
--sleep-interval 5 --max-sleep-interval 20 |
Waits a random 5–20s between videos so YouTube doesn't flag the activity. |
--ignore-errors --no-overwrites --no-progress --newline |
Skips videos that fail (instead of stopping), never overwrites existing files, and prints clean, log-friendly output. |
What is curl_cffi, and why is it installed?
curl_cffi lets yt-dlp impersonate a real browser's network fingerprint. Over hundreds of
back-to-back requests, this is what keeps YouTube from throwing up "Sign in to confirm you're not a
bot." It's installed automatically in the command above — nothing for you to configure.
How it works
sync.sh runs yt-dlp once per creator. For each one it downloads the listed playlists at a 1080p
cap, names files by video title, embeds metadata/chapters/English subs, and records every fetched
video in a per-creator --download-archive file under _sync/. The result is one clean folder per
creator:
YouTube Library/
├── _sync/
│ ├── sync.sh
│ ├── archive-noclip.txt
│ ├── archive-defunctland.txt
│ ├── archive-yesterworld.txt
│ └── download.log
├── Noclip/
├── Defunctland/
└── Yesterworld/
Because each video's title becomes its filename and metadata is embedded, the folders drop straight into a media server as a normal library. Re-running the same command only adds newly uploaded videos.
Sources (curated to "main docs" only)
| Folder | Creator | Playlists kept | ~Videos |
|---|---|---|---|
Noclip/ |
Noclip | "Just The Big Docs" | 99 |
Defunctland/ |
Defunctland | Seasons 1–3 + Documentary Features + DefunctTV (+ Jim Henson) + HALYX Story | 91 |
Yesterworld/ |
Yesterworld Entertainment | Seasons 1–6 | 110 |
Excluded on purpose: podcasts, minisodes, commentary, promos, music, VR, listicles, "most popular" (overlap), and topical re-grouping playlists (they duplicate the season sets).
Run it automatically (this setup's homelab use)
In the F.A.S.C. homelab this is deployed as a small DockHand stack that loops sync.sh on a
schedule and triggers a Plex + ErsatzTV rescan afterward, so new uploads land on the
Documentary channel (ch66) hands-off. After download, the files flow through the Tdarr AV1
pipeline like the rest of the library. See compose/yt-docs-sync.yaml in the docker workspace.
That part is specific to this homelab; the Quick start above is all you need to run it anywhere.
Attribution
Downloads are performed with yt-dlp. The documentaries themselves belong to their creators — Noclip, Defunctland, and Yesterworld Entertainment. Please support them directly, and keep your downloads for personal/offline use.
License
GNU GPL v3 (or later) — see LICENSE. Copyleft, so derivatives stay free software.