youtube-dl

youtube-dl is a general purpose tool, a bit like the wget or curl for streaming videos. It is written in Python and, as such, is quite portable, but to to further simplify (and sandbox) its dependencies, etc., it can also be containerised.

Sometime in late 2021, changes at YouTube's end resulted in download speeds dropping from link-constrained to approx. 60 kbps. Between this (rather significant) constraint, and the addition of several new features, I have switched to using a fork, and 'drop-in' replacement of youtube-dl, YT-DLP.

Containerisation

To run youtube-dl (or its fork, yt-dlp) within a containerised environment, you can use the following Dockerfile:

Dockerfile
FROM debian:10
 
RUN apt-get update && apt-get -y dist-upgrade
RUN apt-get install -y curl python3 && ln -sf /usr/bin/python3 /usr/bin/python
RUN apt-get install -y --no-install-recommends ffmpeg
RUN curl -L https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp -o /usr/local/bin/youtube-dl && chmod a+rx /usr/local/bin/youtube-dl
 
 
WORKDIR /data
 
ENTRYPOINT [ "/usr/local/bin/youtube-dl" ]

To rebuild / update this container, issue the following commands:

docker image rm youtube-dl:latest
docker build -t youtube-dl:latest .

The following shell scripts invoke youtube-dl / yt-dlp in a more-or-less transparent way, saving the downloaded file(s) in the current working directory:

youtube-dl
#!/bin/bash
 
if [ -z "${OUTPUT_TEMPLATE}" ]; then
  OUTPUT_TEMPLATE='%(upload_date)s - %(title)s (YT-%(id)s).%(ext)s'
fi
 
docker run --rm --mount type=bind,source="$(pwd)",target=/data youtube-dl "$@" --ignore-errors --format 'bestvideo[ext=mp4]+bestaudio[ext=m4a]/best[ext=mp4]/best' --output "${OUTPUT_TEMPLATE}"
youtube-dl-single
#!/bin/bash
 
youtube-dl $1 --no-playlist

More specialised Use Cases

Downloading subtitles

 docker run --rm --mount type=bind,source="$(pwd)",target=/data youtube-dl --write-auto-sub --sub-lang en --sub-format srv1 https://www.youtube.com/watch?v=t0Qp3McD3j0

Using browser cookies directly

YT-DLP can also access a browser's cookies directly using the --cookies-from-browser ${BROWSER_TYPE} flag; supported browser types include chrome and firefox