Skip to content

Instantly share code, notes, and snippets.

@nmasse-itix
Created June 11, 2025 09:42
Show Gist options
  • Save nmasse-itix/aeb5671f02ad3ba54885fa8f95ca3df8 to your computer and use it in GitHub Desktop.
Save nmasse-itix/aeb5671f02ad3ba54885fa8f95ca3df8 to your computer and use it in GitHub Desktop.
Download a Music Playlist from YouTube
#!/bin/bash
set -Eeuo pipefail
if [ $# -ne 1 ]; then
echo "Usage: $0 https://youtube.com/playlist?list=..."
exit 1
fi
PLAYLIST_URL="$1"
declare -a YTDLP_PARAMS=(
# Select the MP4 Audio format (m4a) to prevent re-encoding
-f m4a/bestaudio
# Extract audio track
-x
# Embed metadata and thumbnail
--embed-thumbnail
--embed-metadata
# The YouTube chain becomes the artist name
--parse-metadata "%(uploader|)s:%(artist)s"
# If the artist name is in the title extract only the song name
--parse-metadata "title:([^-–.,::]+ ?[-–.,::] )?(?P<title>.*)"
# Cleanup title
--replace-in-metadata "title" "( -)? ?[([](([Tt]he )?[Oo]fficial.*|OFFICIAL.*|([Cc]lip )?[Oo]fficiel.*|Remastered|[Vv]ideo)[)\]]" ""
--replace-in-metadata "title" " ?[-|] ?(Officiel|Warner Vault)$" ""
--replace-in-metadata "title" " ?[([]HD[)\]] ?" ""
# Remove common prefixes in artist name
--replace-in-metadata "artist" "^([Oo]fficial) ?" ""
# Cleanup artist
--replace-in-metadata "artist" " ?[(]?[Oo]fficial.*[)]?" ""
# Remove common suffixes in artist name
--replace-in-metadata "artist" "(officialVEVO|VEVO| ?- Topic|Music|TV| ?Channel)$" ""
# Add spaces in a CamelCase word (ie. CamelCase => Camel Case)
--replace-in-metadata "artist" "KoRn" "Korn" # Exception
--replace-in-metadata "artist" "P!NK" "Pink" # Exception
--replace-in-metadata "artist" "([a-z])([A-Z]+[a-z])" "\\1 \\2"
# Sanitize the title and artist name (remove path component separators)
--replace-in-metadata "title,artist" "[/\\\\]" "-"
# Output file name
--output "%(artist)s - %(title)s.%(ext)s"
# Throttling parameters
--sleep-requests 1
--min-sleep-interval 2
--max-sleep-interval 5
# Partial download
#--playlist-start 1
#--playlist-end 10
)
# Download the complete playlist
yt-dlp "${YTDLP_PARAMS[@]}" --yes-playlist "$PLAYLIST_URL"
PLAYLIST_FILE="playlist.m3u"
PLAYLIST_NAME="YouTube Playlist"
# M3U Header
cat > "$PLAYLIST_FILE" <<EOF
#EXTM3U
#EXTENC:UTF-8
#PLAYLIST:$PLAYLIST_NAME
EOF
# Generate M3U file content
for file in *.m4a; do
duration="$(mp4info "$file" |sed -r 's/^.* ([0-9]+).[0-9]+ secs.*/\1/;t;d')"
basename="$(basename "$file" .m4a)"
cat >> "$PLAYLIST_FILE" <<EOF
#EXTINF:$duration,$basename
$file
EOF
done
# Convert M3U to CRLF line ends to have a wider compatibility
todos "$PLAYLIST_FILE"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment