Skip to content

Instantly share code, notes, and snippets.

@skybldev
Last active August 20, 2021 13:41
Show Gist options
  • Save skybldev/35203a1bc5b483e8f63a3fbbc89437d6 to your computer and use it in GitHub Desktop.
Save skybldev/35203a1bc5b483e8f63a3fbbc89437d6 to your computer and use it in GitHub Desktop.
A script I use to quickly download YouTube videos into my music folder as .ogg files.
#!/usr/bin/env bash
# ytdl-ogg - quickly download a youtube video from a URL and save to an ogg,
# with an optional custom filename.
#
# USAGE:
# ytdl-ogg <URL> <output filename>
#
# If a custom filename is given, it will save to that name under OUTDIR.
# Otherwise, it will save to youtube-dl's default format under OUTDIR.
#
# TODO:
# - Make this code not look like garbage
# The directory to output files by default, later sorting, as an example.
OUTDIR="$HOME/Music/auto"
UNCDIR="$OUTDIR/unconverted"
if ! [ -d $UNCDIR ]; then mkdir -p $UNCDIR; fi
ytdl_output="$UNCDIR/%(title)s-%(id)s.%(ext)s"
# Download the video's audio.
youtube-dl \
"$1" \
-f bestaudio \
--no-playlist \
-o "$ytdl_output"
# Use the same parameters but only get the filename.
filename=$(youtube-dl \
"$1" \
-f bestaudio \
-o "$ytdl_output" \
--get-filename
)
if [ "${filename#*.}" = "webm" ]; then
# If the container is .webm, that means that the format is opus. For some
# reason, ffprobe doesn't detect stream bitrate from an opus stream, but
# can still get it from the format.
# Take audio from downloaded file and save it to a .opus file.
ffmpeg \
-v error \
-i "$filename" \
-c:a copy \
"${filename%%.*}.opus"
# Strip the extension from the filename and add ".opus" to it.
filename="${filename%%.*}.opus"
# Find bitrate from the "format" section.
bitrate=$(ffprobe \
-v error \
-select_streams a:0 \
-show_entries format=bit_rate \
-of compact=p=0:nk=1 \
"$filename"
)
else
# If it isn't .webm, then it's .m4a with a DASH stream. ffprobe can determine
# the bitrate from the stream, so we tell it to do so here.
bitrate=$(ffprobe \
-v error \
-select_streams a:0 \
-show_entries stream=bit_rate \
-of compact=p=0:nk=1 \
"$filename"
)
fi
# Determine sample rate from stream section.
samplerate=$(ffprobe \
-v error \
-select_streams a:0 \
-show_entries stream=sample_rate \
-of compact=p=0:nk=1 \
"$filename"
)
echo "Bitrate: $bitrate"
echo "Sample Rate: $samplerate"
if [ "$2" ]; then
# If an output filename is provided, use that.
if [ "$(basename "$2")" = "$2" ]; then
# If the basename matches the original string, it's a filename, not a path.
# Save the file to the name under OUTDIR.
output_filename="$OUTDIR/$2"
else
# If the basename doesn't match the original string, it's under a path.
# Save the file to that full custom path instead.
output_filename="$2"
fi
else
# Otherwise, save to youtube-dl's format under OUTDIR.
file_basename=$(basename "$filename")
file_basename_noextension=${filename_basename%%.*}
output_filename="$OUTDIR/$file_basename_noextension.ogg"
fi
echo "Saving to: $output_filename"
# Finally, convert the file to .ogg with minimal loss.
ffmpeg \
-v error \
-i "$filename" \
-c:a libvorbis \
-ab $bitrate \
-ar $samplerate \
"$output_filename";
echo "Done."
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment