yt-wsp.sh : add unique filename generation (#495)

Co-authored-by: genevera <genevera@noreply.users.github.com>
pull/501/head
genevera (she/her) 2 years ago committed by GitHub
parent 9764782bd9
commit 459753342d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -1,20 +1,10 @@
#!/usr/bin/env bash #!/usr/bin/env bash
# shellcheck disable=2086
# Small shell script to more easily automatically download and transcribe live stream VODs.
# This uses YT-DLP, ffmpeg and the CPP version of Whisper: https://github.com/ggerganov/whisper.cpp
# Use `./examples/yt-wsp.sh help` to print help info.
#
# Sample usage:
#
# git clone https://github.com/ggerganov/whisper.cpp
# cd whisper.cpp
# make
# ./examples/yt-wsp.sh https://www.youtube.com/watch?v=1234567890
#
# MIT License # MIT License
# Copyright (c) 2022 Daniils Petrovs # Copyright (c) 2022 Daniils Petrovs
# Copyright (c) 2023 Jennifer Capasso
# Permission is hereby granted, free of charge, to any person obtaining a copy # Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal # of this software and associated documentation files (the "Software"), to deal
@ -34,114 +24,181 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE. # SOFTWARE.
# Small shell script to more easily automatically download and transcribe live stream VODs.
# This uses YT-DLP, ffmpeg and the CPP version of Whisper: https://github.com/ggerganov/whisper.cpp
# Use `./examples/yt-wsp.sh help` to print help info.
#
# Sample usage:
#
# git clone https://github.com/ggerganov/whisper.cpp
# cd whisper.cpp
# make
# ./examples/yt-wsp.sh https://www.youtube.com/watch?v=1234567890
#
set -Eeuo pipefail set -Eeuo pipefail
# You can find how to download models in the OG repo: https://github.com/ggerganov/whisper.cpp/#usage # get script file location
MODEL_PATH="${MODEL_PATH:-models/ggml-base.en.bin}" # Set to a multilingual model if you want to translate from foreign lang to en SCRIPT_PATH="$(realpath -e ${BASH_SOURCE[0]})";
WHISPER_EXECUTABLE="${WHISPER_EXECUTABLE:-whisper}" # Where to find the whisper.cpp executable SCRIPT_DIR="${SCRIPT_PATH%/*}"
WHISPER_LANG="${WHISPER_LANG:-en}" # Set to desired lang to translate from
################################################################################
# Documentation on downloading models can be found in the whisper.cpp repo:
# https://github.com/ggerganov/whisper.cpp/#usage
#
# note: unless a multilingual model is specified, WHISPER_LANG will be ignored
# and the video will be transcribed as if the audio were in the English language
################################################################################
MODEL_PATH="${MODEL_PATH:-${SCRIPT_DIR}/../models/ggml-base.en.bin}"
################################################################################
# Where to find the whisper.cpp executable. default to the examples directory
# which holds this script in source control
################################################################################
WHISPER_EXECUTABLE="${WHISPER_EXECUTABLE:-${SCRIPT_DIR}/../main}";
# Set to desired language to be translated into english
WHISPER_LANG="${WHISPER_LANG:-en}";
# Default to 4 threads (this was most performant on my 2020 M1 MBP)
WHISPER_THREAD_COUNT="${WHISPER_THREAD_COUNT:-4}";
msg() { msg() {
echo >&2 -e "${1-}" echo >&2 -e "${1-}"
} }
################################################################################
# create a temporary directory to work in
# set the temp_dir and temp_filename variables
################################################################################
temp_dir="$(mktemp -d ${SCRIPT_DIR}/tmp.XXXXXX)";
temp_filename="${temp_dir}/yt-dlp-filename";
################################################################################
# for now we only take one argument
# TODO: a for loop
################################################################################
source_url="${1}"
title_name="";
cleanup() { cleanup() {
msg "Cleaning up..." local -r clean_me="${1}";
rm -rf "${temp_dir}" "vod-resampled.wav" "vod-resampled.wav.srt"
if [ -d "${clean_me}" ]; then
msg "Cleaning up...";
rm -rf "${clean_me}";
else
msg "'${clean_me}' does not appear to be a directory!";
exit 1;
fi;
} }
print_help() { print_help() {
echo "################################################################################"
echo "Usage: ./examples/yt-wsp.sh <video_url>" echo "Usage: ./examples/yt-wsp.sh <video_url>"
echo "See configurable env variables in the script" echo "# See configurable env variables in the script; there are many!"
echo "This will produce an MP4 muxed file called res.mp4 in the working directory" echo "# This script will produce an MP4 muxed file in the working directory; it will"
echo "Requirements: ffmpeg yt-dlp whisper" echo "# be named for the title and id of the video."
echo "Whisper needs to be built into the main binary with make, then you can rename it to something like 'whisper' and add it to your PATH for convenience." echo "# passing in https://youtu.be/VYJtb2YXae8 produces a file named";
echo "E.g. in the root of Whisper.cpp, run: 'make && cp ./main /usr/local/bin/whisper'" echo "# 'Why_we_all_need_subtitles_now-VYJtb2YXae8-res.mp4'"
echo "# Requirements: ffmpeg yt-dlp whisper.cpp"
echo "################################################################################"
} }
check_requirements() { check_requirements() {
if ! command -v ffmpeg &>/dev/null; then if ! command -v ffmpeg &>/dev/null; then
echo "ffmpeg is required (https://ffmpeg.org)." echo "ffmpeg is required: https://ffmpeg.org";
exit 1 exit 1
fi fi;
if ! command -v yt-dlp &>/dev/null; then if ! command -v yt-dlp &>/dev/null; then
echo "yt-dlp is required (https://github.com/yt-dlp/yt-dlp)." echo "yt-dlp is required: https://github.com/yt-dlp/yt-dlp";
exit 1 exit 1;
fi fi;
if ! command -v "$WHISPER_EXECUTABLE" &>/dev/null; then if ! command -v "${WHISPER_EXECUTABLE}" &>/dev/null; then
WHISPER_EXECUTABLE="./main" echo "The C++ implementation of Whisper is required: https://github.com/ggerganov/whisper.cpp"
if ! command -v "$WHISPER_EXECUTABLE" &>/dev/null; then echo "Sample usage:";
echo "Whisper is required (https://github.com/ggerganov/whisper.cpp):" echo "";
echo "Sample usage:" echo " git clone https://github.com/ggerganov/whisper.cpp";
echo "" echo " cd whisper.cpp";
echo " git clone https://github.com/ggerganov/whisper.cpp" echo " make";
echo " cd whisper.cpp" echo " ./examples/yt-wsp.sh https://www.youtube.com/watch?v=1234567890";
echo " make" echo "";
echo " ./examples/yt-wsp.sh https://www.youtube.com/watch?v=1234567890" exit 1;
echo "" fi;
exit 1
fi
fi
} }
if [[ $# -lt 1 ]]; then if [[ "${#}" -lt 1 ]]; then
print_help print_help;
exit 1 exit 1;
fi fi
if [[ "$1" == "help" ]]; then if [[ "${1##-*}" == "help" ]]; then
print_help print_help;
exit 0 exit 0;
fi fi
temp_dir="tmp" check_requirements;
source_url="$1"
check_requirements msg "Downloading VOD...";
msg "Downloading VOD..." ################################################################################
# Download the video, put the dynamic output filename into a variable.
# Optionally add --cookies-from-browser BROWSER[+KEYRING][:PROFILE][::CONTAINER] for members only VODs # Optionally add --cookies-from-browser BROWSER[+KEYRING][:PROFILE][::CONTAINER]
# for videos only available to logged-in users.
################################################################################
yt-dlp \ yt-dlp \
-f "bestvideo[ext=mp4]+bestaudio[ext=m4a]/best[ext=mp4]/best" \ -f "bestvideo[ext=mp4]+bestaudio[ext=m4a]/best[ext=mp4]/best" \
-o "${temp_dir}/%(title)s-%(id)s.vod.mp4" \
--print-to-file "%(filename)s" "${temp_filename}" \
--no-simulate \
--no-write-auto-subs \
--restrict-filenames \
--embed-thumbnail \ --embed-thumbnail \
--embed-chapters \ --embed-chapters \
--xattrs \ --xattrs \
"${source_url}" -o "${temp_dir}/vod.mp4" "${source_url}";
title_name="$(xargs basename -s .vod.mp4 < ${temp_filename})";
msg "Extracting audio and resampling..." msg "Extracting audio and resampling...";
ffmpeg -i "${temp_dir}/vod.mp4" \ ffmpeg -i "${temp_dir}/${title_name}.vod.mp4" \
-hide_banner \ -hide_banner \
-vn \
-loglevel error \ -loglevel error \
-ar 16000 \ -ar 16000 \
-ac 1 \ -ac 1 \
-c:a \ -c:a pcm_s16le \
pcm_s16le -y "vod-resampled.wav" -y \
"${temp_dir}/${title_name}.vod-resampled.wav";
msg "Transcribing to subtitle file..." msg "Transcribing to subtitle file...";
msg "Whisper specified at: ${WHISPER_EXECUTABLE}" msg "Whisper specified at: '${WHISPER_EXECUTABLE}'";
$WHISPER_EXECUTABLE \ "${WHISPER_EXECUTABLE}" \
-m "${MODEL_PATH}" \ -m "${MODEL_PATH}" \
-l "${WHISPER_LANG}" \ -l "${WHISPER_LANG}" \
-f "vod-resampled.wav" \ -f "${temp_dir}/${title_name}.vod-resampled.wav" \
-t 8 \ -t "${WHISPER_THREAD_COUNT}" \
-osrt \ -osrt \
--translate --translate;
msg "Embedding subtitle track..." msg "Embedding subtitle track...";
ffmpeg -i "${temp_dir}/vod.mp4" \ ffmpeg -i "${temp_dir}/${title_name}.vod.mp4" \
-hide_banner \ -hide_banner \
-loglevel error \ -loglevel error \
-i "vod-resampled.wav.srt" \ -i "${temp_dir}/${title_name}.vod-resampled.wav.srt" \
-c copy \ -c copy \
-c:s mov_text \ -c:s mov_text \
-y res.mp4 -y "${title_name}-res.mp4";
cleanup cleanup "${temp_dir}";
msg "Done! Your finished file is ready: res.mp4" msg "Done! Your finished file is ready: ${title_name}-res.mp4";

Loading…
Cancel
Save