YouTube Download Script

Freepoorman

Active Member
Joined
Mar 8, 2024
Messages
263
Reaction score
164
Credits
2,248
I created this script to download individual videos (MP4) and/or audio tracks (MP3), as well as playlists. The requirements are yt-dlp and ffmpeg (which ships with yt-dlp).

Bash:
#!/bin/bash

# Function to check if a command exists
command_exists() {
    command -v "$1" >/dev/null 2>&1
}

# Check for yt-dlp and ffmpeg installations
if ! command_exists yt-dlp; then
    echo "Error: yt-dlp is not installed. Please install it and try again."
    exit 1
fi

if ! command_exists ffmpeg; then
    echo "Error: ffmpeg is not installed. Please install it and try again."
    exit 1
fi

# Define output directory
OUTPUT_DIR="/home/<USER>/Downloads"

# Function to check if output directory exists and is writable
check_output_dir() {
    if [ ! -d "$OUTPUT_DIR" ]; then
        echo "Output directory does not exist. Creating directory..."
        mkdir -p "$OUTPUT_DIR"
        if [ $? -ne 0 ]; then
            echo "Failed to create output directory. Exiting."
            exit 1
        fi
    fi
    if [ ! -w "$OUTPUT_DIR" ]; then
        echo "Output directory is not writable. Exiting."
        exit 1
    fi
}

# Function to sanitize filenames by replacing invalid characters
sanitize_filename() {
    echo "$1" | sed 's/[\/:*?"<>|]/_/g'
}

# Function to download a single MP4 video at best quality up to 720p
download_single_mp4() {
    read -p "Enter the YouTube URL: " url
    sanitized_title=$(sanitize_filename "$(yt-dlp --get-title "$url")")
    yt-dlp -f "best[ext=mp4][height<=720]" \
        --output "$OUTPUT_DIR/$sanitized_title.%(ext)s" \
        --no-sponsorblock \
        --fixup detect_or_warn \
        --fragment-retries infinite \
        --retries infinite \
        --buffer-size 10M \
        --limit-rate 5M \
        --verbose "$url"
    check_exit_status $?
}

# Function to download a single MP3 audio in best quality with metadata
download_single_mp3() {
    read -p "Enter the YouTube URL: " url
    sanitized_title=$(sanitize_filename "$(yt-dlp --get-title "$url")")
    yt-dlp -x --audio-format mp3 --embed-metadata --add-metadata --embed-thumbnail \
        --output "$OUTPUT_DIR/$sanitized_title.%(ext)s" "$url"
    check_exit_status $?
}

# Function to download MP4 Playlist at best quality up to 720p
download_playlist_mp4() {
    read -p "Enter the YouTube playlist URL: " url
    download_playlist "$url" "mp4"
}

# Function to download MP3 Playlist in best quality with metadata
download_playlist_mp3() {
    read -p "Enter the YouTube playlist URL: " url
    download_playlist "$url" "mp3"
}

# Function to download a playlist
download_playlist() {
    local url=$1
    local format=$2
    local temp_error_file=$(mktemp)

    local playlist_title=$(yt-dlp --flat-playlist --get-title "$url" | head -n 1)
    local playlist_dir="$OUTPUT_DIR/$(sanitize_filename "$playlist_title")"

    mkdir -p "$playlist_dir"

    if [ "$format" == "mp4" ]; then
        yt-dlp --yes-playlist -f "best[ext=mp4][height<=720]" \
            --output "$playlist_dir/%(title)s.%(ext)s" \
            --no-sponsorblock \
            --fixup detect_or_warn \
            --fragment-retries infinite \
            --retries infinite \
            --buffer-size 10M \
            --limit-rate 5M \
            --verbose "$url" 2> "$temp_error_file"
    elif [ "$format" == "mp3" ]; then
        yt-dlp --yes-playlist -x --audio-format mp3 --embed-metadata --add-metadata --embed-thumbnail \
            --output "$playlist_dir/%(title)s.%(ext)s" "$url" 2> "$temp_error_file"
    fi

    if [ -s "$temp_error_file" ]; then
        echo "Some files in the playlist failed to download. Here are the errors:"
        cat "$temp_error_file"
        read -p "Press Enter to continue..."
    fi

    rm -f "$temp_error_file"
}

# Function to check exit status and handle errors
check_exit_status() {
    if [ $1 -ne 0 ]; then
        echo "An error occurred during the download. Please check the URL and try again."
        read -p "Press Enter to continue..."
    fi
}

# Function to display the main menu
show_menu() {
    echo "----------------------------------------"
    echo "          Download Menu"
    echo "----------------------------------------"
    echo "1. Download single MP4 (<=720p quality)"
    echo "2. Download single MP3 (best quality)"
    echo "3. Download MP4 Playlist (<=720p quality)"
    echo "4. Download MP3 Playlist (best quality)"
    echo "5. Exit"
    echo "----------------------------------------"
    read -p "Please select an option [1-5]: " choice
    case $choice in
        1) download_single_mp4 ;;
        2) download_single_mp3 ;;
        3) download_playlist_mp4 ;;
        4) download_playlist_mp3 ;;
        5) exit 0 ;;
        *) echo "Invalid option. Please select a number between 1 and 5." ;;
    esac
}

# Main script execution
check_output_dir
while true; do
    show_menu
done


Remember to download the dependencies and edit this line to the actual Downloads directory on your system:
Bash:
OUTPUT_DIR="/home/<USER>/Downloads"

Feel free to use, edit, and share as you wish.
 


Moving this to Command Line, where scripting threads are preferred.

Goodonyer.

Wizard
 
Kudos to Freepoorman for taking the time to come up with that script.

For those running Mint and don't wish to use the command line, there is a small program in the repository that does this. I'm not near my computer. So, I can't post the name of it (I need more memory for the computer between my ears). But it's pretty simple to use.
 
Kudos to Freepoorman for taking the time to come up with that script.

For those running Mint and don't wish to use the command line, there is a small program in the repository that does this. I'm not near my computer. So, I can't post the name of it (I need more memory for the computer between my ears). But it's pretty simple to use.


I think you might be referring to youtube-dl gui, it's available in the flatpak repository but doesn't work since it's been deprecated and youtube has updated it's encoding.. The other one you might be referring to is 4k video downloader, which is limited in it's free-tier but does everything great in the paid version.

My script uses yt-dlp which is a fork of youtube-dl, and it works ok and is 100% free.. If you really need the gui experience, you can do something like this:


Bash:
chmod +x /home/<USER>/Documents/custom-scripts/download-yt.sh
(with name and directory of the script on your machine)

Then use menulibre to create a launcher icon pretty easily.
 
Menulibre is really easy to use. Just need the command to run it and the working directory. Remember to check the box saying "Run in Terminal"
 

Attachments

  • yt-dl.png
    yt-dl.png
    34.4 KB · Views: 39
  • yt-dl2.png
    yt-dl2.png
    58.3 KB · Views: 40
After some research I saw there is yt-dlp-gui on github. It might be more user friendly but the installation might be a little more challenging..
 
I have this in my favorites but haven't had the time to test it.


It's in there for a potential article - which I'll be resuming shortly.
 
I have this in my favorites but haven't had the time to test it.


It's in there for a potential article - which I'll be resuming shortly.
I'm pretty sure youtube-dl is deprecated..? At least it was when I started working on this script
 
That's for yt-dlp. You gotta click the link. The 'blurb' lied to you. (They probably didn't update the meta tags.)
 
The frontend looks very nice. I'm curious how well the quality selection works..? That is the part I really struggled with, as the available formats differ for each video url and selecting specific quality would sometimes exclude compatible formats for parsing. That's the main reason I chose the flag "best[ext=mp4][height<=720]", it downloads mp4 without the need for parsing but rarely gets 720p (mostly 360p is achieved)... but at least I don't run into parsing issues...
 
I'm curious how well the quality selection works..?

I never got around to testing it. So, I only note that it was in my bookmarks. It looked interesting and like they'd done quality work. I figured I'd eventually test it but never got there. I had a bit of a burnout. For a while, I didn't even type much here - just logged in to do my mod duties. I'm feeling more motivated lately.

I don't want to derail the thread and it turns out it was a bit of a medical issue (a lesser known side effect of a med I was on). This has been corrected and the brain fog is steadily lifting.
 
Hey Freepoorman
Thanks for the cool script. Works great.
The Stacher program needs " --no-sandbox" when run as root. Cool app and works great.

Vektor
 


Members online


Top