mirror of
https://github.com/ggerganov/whisper.cpp.git
synced 2025-01-30 09:49:18 +01:00
yt-wsp.sh : add unique filename generation (#495)
Co-authored-by: genevera <genevera@noreply.users.github.com>
This commit is contained in:
parent
9764782bd9
commit
459753342d
@ -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
|
||||||
|
echo "The C++ implementation of Whisper is required: https://github.com/ggerganov/whisper.cpp"
|
||||||
|
echo "Sample usage:";
|
||||||
|
echo "";
|
||||||
|
echo " git clone https://github.com/ggerganov/whisper.cpp";
|
||||||
|
echo " cd whisper.cpp";
|
||||||
|
echo " make";
|
||||||
|
echo " ./examples/yt-wsp.sh https://www.youtube.com/watch?v=1234567890";
|
||||||
|
echo "";
|
||||||
|
exit 1;
|
||||||
|
fi;
|
||||||
|
|
||||||
if ! command -v "$WHISPER_EXECUTABLE" &>/dev/null; then
|
|
||||||
WHISPER_EXECUTABLE="./main"
|
|
||||||
if ! command -v "$WHISPER_EXECUTABLE" &>/dev/null; then
|
|
||||||
echo "Whisper is required (https://github.com/ggerganov/whisper.cpp):"
|
|
||||||
echo "Sample usage:"
|
|
||||||
echo ""
|
|
||||||
echo " git clone https://github.com/ggerganov/whisper.cpp"
|
|
||||||
echo " cd whisper.cpp"
|
|
||||||
echo " make"
|
|
||||||
echo " ./examples/yt-wsp.sh https://www.youtube.com/watch?v=1234567890"
|
|
||||||
echo ""
|
|
||||||
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}";
|
||||||
|
|
||||||
msg "Extracting audio and resampling..."
|
title_name="$(xargs basename -s .vod.mp4 < ${temp_filename})";
|
||||||
|
|
||||||
ffmpeg -i "${temp_dir}/vod.mp4" \
|
msg "Extracting audio and resampling...";
|
||||||
|
|
||||||
|
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…
Reference in New Issue
Block a user