Sync curated YouTube documentary channels into a local library with yt-dlp
Find a file
xenarathon 35c3e61600 Initial public import: yt-docs-sync
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-15 22:30:00 -04:00
LICENSE Initial public import: yt-docs-sync 2026-06-15 22:30:00 -04:00
README.md Initial public import: yt-docs-sync 2026-06-15 22:30:00 -04:00
sync.sh Initial public import: yt-docs-sync 2026-06-15 22:30:00 -04:00

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 /work inside the box (the part after). The script reads and writes everything under /work. Change /path/to/your/YouTube Library to 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, installs ffmpeg, yt-dlp, and curl_cffi, then runs the sync.sh script. (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 as D:/Media/YouTube Library (forward slashes).
  • macOS/Linux: something like /Volumes/media/YouTube Library or /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 520s 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 13 + Documentary Features + DefunctTV (+ Jim Henson) + HALYX Story 91
Yesterworld/ Yesterworld Entertainment Seasons 16 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.