I am trying to write a bash script to download all the videos from a given public YouTube playlist. Here's what I have so far:
#!/bin/bash
# Default values
decode_video=true
output_format="avi"
audio_codec="libmp3lame"
audio_bitrate="192k"
audio_sample_rate="44100"
audio_channels="2"
video_codec="libxvid"
video_quality="3"
# Function to download and convert each video
download_and_convert() {
local video_url="$1"
local output_name="$2"
# Show download start message
echo "Downloading: $output_name.mp4..."
# Download the video
yt-dlp --progress -f "bv*+ba/b" --merge-output-format mp4 "$video_url" -o "$output_name.mp4"
# Show download end message
echo "Downloaded: $output_name.mp4"
# Check if video should be re-encoded
if $decode_video; then
# Debug: Output the values of the variables
echo "output_name: \"$output_name\""
echo "video_codec: $video_codec"
echo "video_quality: $video_quality"
echo "audio_codec: $audio_codec"
echo "audio_sample_rate: $audio_sample_rate"
echo "audio_bitrate: $audio_bitrate"
echo "audio_channels: $audio_channels"
# Re-encode video to MPEG-4 (Xvid) and convert audio to MP3
echo "Converting video to MPEG-4 (Xvid) and audio to MP3..."
# Ensure that the script runs the command directly without any prompt
ffmpeg -hide_banner -i "$output_name.mp4" -c:v libxvid -qscale:v 3 -c:a libmp3lame -ar 44100 -b:a 192k -ac 2 "$output_name.avi"
else
# Copy the video and only convert audio
echo "Copying video and converting audio to MP3..."
ffmpeg -i "$output_name.mp4" -c:v copy -c:a $audio_codec -ar $audio_sample_rate -b:a $audio_bitrate -ac $audio_channels "$output_name.$output_format"
fi
# Clean up the original MP4 file
#rm "$output_name.mp4"
echo "Converted: $output_name.$output_format"
}
# Parse command-line options
while [[ $# -gt 0 ]]; do
case $1 in
--no-decode-video)
decode_video=false
shift
;;
--decode-video)
decode_video=true
shift
;;
*)
playlist_url="$1"
shift
;;
esac
done
# Ensure playlist URL is provided
if [ -z "$playlist_url" ]; then
echo "Usage: $0 <playlist_url> [--no-decode-video]"
exit 1
fi
# Get total number of videos in the playlist
total_videos=$(yt-dlp -j --flat-playlist "$playlist_url" | jq -r '.id' | wc -l)
echo "Total videos in playlist: $total_videos"
# Download the playlist and process each video
current_video=1
yt-dlp -j --flat-playlist "$playlist_url" | jq -r '.id' | while read -r video_id; do
# Define output filename
output_name="video_$video_id"
# Show progress
echo "Processing video $current_video of $total_videos..."
# Download and convert the video
download_and_convert "https://www.youtube.com/watch?v=$video_id" "$output_name"
# Increment video counter
current_video=$((current_video + 1))
done
echo "All videos processed successfully!"
Now, downloading videos works, but the conversion with ffmpeg fails. It starts showing the regular ffmpeg output, just as if it was converting it properly, and then shows: Parse error, at least 3 arguments were expected, only 1 given in string 'GC1Y0'. What could that be? I read on a different thread that there's a problem when quoting file names.
echoin from of the various commands there and see what you are really running. Or just addset -xto the top of the script so you can get debugging output. Is everything as you expect?