A script that might be useful when downloading albums with yt-dlp

Downloading Albums

This is a script that might be useful when downloading music from YouTube Music.
I’m using it without any particular issues, but there might be some deficiencies, so please ask Claude to fix it if necessary.

.sh Version

Info
Tested on macOS, Ubuntu, and ArchLinux.
#!/bin/bash

# Settings
OUTPUT_DIR="$HOME/Music"
FORMAT="mp3"

# Check command line arguments
if [ $# -eq 0 ]; then
    echo "Please specify a URL"
    exit 1
fi

# Use argument as URL
URL="$1"

# Create output directory if it doesn't exist
mkdir -p "$OUTPUT_DIR"

# Execute yt-dlp command
yt-dlp "$URL" \
    --default-search "ytsearch" \
    --add-header "Accept-Language:ja-JP" \
    --add-metadata \
    --embed-metadata \
    -f "bestaudio[acodec^=opus]/best" \
    -x \
    --audio-format "$FORMAT" \
    --audio-quality 0 \
    --embed-thumbnail \
    --convert-thumbnails jpg \
    --ppa "ThumbnailsConvertor:-qmin 1 -q:v 1 -vf crop=\"'if(gt(ih,iw),iw,ih)':'if(gt(iw,ih),ih,iw)'\"" \
    -o "$OUTPUT_DIR/%(album)s/%(playlist_index)s - %(title)s.%(ext)s" \
    --parse-metadata "playlist_index:%(track_number)s" \
    --parse-metadata "%(upload_date).4s:%(meta_year)s" \
    --parse-metadata "%(upload_date).4s:%(meta_date)s" \
    --parse-metadata "%(artists.0)s:%(meta_album_artist)s" \
    --parse-metadata "n_entries:%(meta_totaltracks)s" \
    --no-warnings

exit_code=$?

if [ $exit_code -eq 0 ]; then
    echo "Download completed!"
    echo "Save location: $OUTPUT_DIR"
else
    echo "An error occurred. Exit code: $exit_code"
fi

exit $exit_code

Save this with an appropriate name (e.g., album-dl.sh), and make it executable with chmod.

Usage:

./album-dl.sh https://music.youtube.com/playlist?list=xxxxxxx..

This will create a folder with the album name in ~/Music and download the content into it.

.py Version

import os
import sys
import subprocess
from pathlib import Path

def main():
    # Settings
    output_dir = os.path.expanduser("~/Music")
    audio_format = "mp3"

    # Check command line arguments
    if len(sys.argv) < 2:
        print("Please specify a URL")
        sys.exit(1)

    # Use argument as URL
    url = sys.argv[1]

    # Create output directory if it doesn't exist
    os.makedirs(output_dir, exist_ok=True)

    # Build yt-dlp command
    cmd = [
        "yt-dlp", url,
        "--default-search", "ytsearch",
        "--add-header", "Accept-Language:ja-JP",
        "--add-metadata",
        "--embed-metadata",
        "-f", "bestaudio[acodec^=opus]/best",
        "-x",
        "--audio-format", audio_format,
        "--audio-quality", "0",
        "--embed-thumbnail",
        "--convert-thumbnails", "jpg",
        "--ppa", "ThumbnailsConvertor:-qmin 1 -q:v 1 -vf crop=\"'if(gt(ih,iw),iw,ih)':'if(gt(iw,ih),ih,iw)'\"",
        "-o", f"{output_dir}/%(album)s/%(playlist_index)s - %(title)s.%(ext)s",
        "--parse-metadata", "playlist_index:%(track_number)s",
        "--parse-metadata", "%(upload_date).4s:%(meta_year)s",
        "--parse-metadata", "%(upload_date).4s:%(meta_date)s",
        "--parse-metadata", "%(artists.0)s:%(meta_album_artist)s",
        "--parse-metadata", "n_entries:%(meta_totaltracks)s",
        "--no-warnings"
    ]

    # Run command as subprocess
    try:
        result = subprocess.run(cmd, check=True, text=True, stderr=subprocess.PIPE)
        print("Download completed!")
        print(f"Save location: {output_dir}")
        return 0
    except subprocess.CalledProcessError as e:
        print(f"An error occurred. Exit code: {e.returncode}")
        if e.stderr:
            print(f"Error details: {e.stderr}")
        return e.returncode

if __name__ == "__main__":
    sys.exit(main())

Save this with an appropriate name (e.g., album-dl.py).
Usage:

python album-dl.py https://music.youtube.com/playlist?list=xxxxxxx..

Common Requirements

Both versions require a Python environment, yt-dlp, ffmpeg, and mutagen.

Features

A distinctive feature is that it crops thumbnails to a 1:1 ratio to make them square when embedding album art.
Also, it manipulates various metadata fields.

Conclusion

Well, that’s about it…

It’s good to write scripts to avoid repetitive typing and manual work.
Enjoy your shell life.