This blog contains my shell script to download audio from YouTube videos. The programs you would need installed on your system for this script to work are:
It is also available on my GitHub.
#!/usr/bin/env bash
# =========================== #
# ========= GLOBALS ========= #
# =========================== #
# User defined flies and directories
g_url="$1"
g_audio_dir="${AUDIO_DIRECTORY:-"$HOME/music"}"
g_temp_dir="/tmp/ytdw"
# Control variables used between multiple functions
g_dir_or_audio_name="$2"
g_temp_file=""
g_is_playlist=0
# Colors
c_normal="\e[0m"
c_red="\e[1;31m"
c_green="\e[1;32m"
# Constants
g_user_agent="Mozilla/5.0 (X11; Linux x86_64; rv:125.0) Gecko/20100101 Firefox/125.0"
# =========================== #
# ======== FUNCTIONS ======== #
# =========================== #
# Checks for the program dependencies, which are: aria2c, yt-dlp and ffmpeg.
# And creates the temporary directory in $g_temp_dir
function f_check_dependencies {
if ! command -v aria2c &> /dev/null; then
echo -e "${c_red}Program 'aria2' not found!$c_normal"
exit 1
fi
if ! command -v yt-dlp &> /dev/null; then
echo -e "${c_red}Program 'yt-dlp' not found!$c_normal"
exit 1
fi
if ! command -v ffmpeg &> /dev/null; then
echo -e "${c_red}Program 'ffmpeg' not found!$c_normal"
exit 1
fi
if [ ! -d "$g_temp_dir" ]; then
mkdir -p "$g_temp_dir"
fi
}
# Downloads audio. Takes two parameters. First is the audio URL and seconds is
# the directory where the audio will be located. The "return" of this function
# is the return code of the yt-dlp program call.
function f_dw_audio {
local url="$1"
local dir="$2"
local name=""
if [ $g_is_playlist -eq 1 ] || [ -z "$g_dir_or_audio_name" ]; then
name="$dir/%(title)s.%(ext)s"
else
name="$dir/$g_dir_or_audio_name.%(ext)s"
fi
echo "Downloading video from URL '$url'"
if ! yt-dlp --quiet \
--no-warnings \
--progress \
--ignore-errors \
--no-mtime \
--downloader aria2c \
--downloader-args "\
--user-agent='$g_user_agent' \
--max-connection-per-server=16 \
--split=16 \
" \
--extract-audio \
--prefer-ffmpeg \
--audio-quality 0 \
--postprocessor-args "-q:a 0 -map a" \
-o "$name" \
"$url"; then
echo -e "${c_red}Failed to download audio from URL '$url'!$c_normal"
else
echo -e "${c_green}Audio from URL '$url' downloaded successfully!$c_normal"
fi
}
# Parses the command line parameter which can either be a playlist or a single
# audio from YT.
function f_parse_data_and_dw {
local dir="$g_audio_dir"
local start_time=0
local end_time=0
local runtime=0
start_time="$(date +%s)"
if [[ "$g_url" == *"playlist"* ]]; then
echo "Starting to download playlist at URL: $g_url"
g_is_playlist=1
if [ -n "$g_dir_or_audio_name" ]; then
dir="$g_audio_dir/$g_dir_or_audio_name"
else
dir="$g_audio_dir/$(date '+%H%M%S%d%m')-playlist"
fi
if [ ! -d "$dir" ]; then
mkdir -p "$dir"
fi
g_temp_file="${g_temp_dir}/$(date '+%H%M%S%d%m')-playlist.txt"
yt-dlp --quiet \
--no-warnings \
--flat-playlist \
--ignore-errors \
--print-to-file url \
"$g_temp_file" "$g_url"
readarray -t urls < "$g_temp_file"
for url in "${urls[@]}"; do
f_dw_audio "$url" "$dir"
echo
done
rm "$g_temp_file"
else
f_dw_audio "$g_url" "$dir"
fi
end_time="$(date +%s)"
runtime=$((end_time-start_time))
echo
echo "Total program runtime lasted for $runtime seconds!"
echo
exit 0
}
# =========================== #
# =========== MAIN ========== #
# =========================== #
function f_main {
f_check_dependencies
f_parse_data_and_dw
}
f_main