Spaces:
Running
Running
genevera (she/her)
genevera
commited on
yt-wsp.sh : add unique filename generation (#495)
Browse filesCo-authored-by: genevera <[email protected]>
- examples/yt-wsp.sh +129 -72
examples/yt-wsp.sh
CHANGED
|
@@ -1,20 +1,10 @@
|
|
| 1 |
#!/usr/bin/env bash
|
| 2 |
-
|
| 3 |
-
# Small shell script to more easily automatically download and transcribe live stream VODs.
|
| 4 |
-
# This uses YT-DLP, ffmpeg and the CPP version of Whisper: https://github.com/ggerganov/whisper.cpp
|
| 5 |
-
# Use `./examples/yt-wsp.sh help` to print help info.
|
| 6 |
-
#
|
| 7 |
-
# Sample usage:
|
| 8 |
-
#
|
| 9 |
-
# git clone https://github.com/ggerganov/whisper.cpp
|
| 10 |
-
# cd whisper.cpp
|
| 11 |
-
# make
|
| 12 |
-
# ./examples/yt-wsp.sh https://www.youtube.com/watch?v=1234567890
|
| 13 |
-
#
|
| 14 |
|
| 15 |
# MIT License
|
| 16 |
|
| 17 |
# Copyright (c) 2022 Daniils Petrovs
|
|
|
|
| 18 |
|
| 19 |
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
| 20 |
# of this software and associated documentation files (the "Software"), to deal
|
|
@@ -34,114 +24,181 @@
|
|
| 34 |
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
| 35 |
# SOFTWARE.
|
| 36 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 37 |
set -Eeuo pipefail
|
| 38 |
|
| 39 |
-
#
|
| 40 |
-
|
| 41 |
-
|
| 42 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 43 |
|
| 44 |
msg() {
|
| 45 |
echo >&2 -e "${1-}"
|
| 46 |
}
|
| 47 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 48 |
cleanup() {
|
| 49 |
-
|
| 50 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 51 |
}
|
| 52 |
|
| 53 |
print_help() {
|
|
|
|
| 54 |
echo "Usage: ./examples/yt-wsp.sh <video_url>"
|
| 55 |
-
echo "See configurable env variables in the script"
|
| 56 |
-
echo "This will produce an MP4 muxed file
|
| 57 |
-
echo "
|
| 58 |
-
echo "
|
| 59 |
-
echo "
|
|
|
|
|
|
|
| 60 |
}
|
| 61 |
|
| 62 |
check_requirements() {
|
| 63 |
if ! command -v ffmpeg &>/dev/null; then
|
| 64 |
-
echo "ffmpeg is required
|
| 65 |
exit 1
|
| 66 |
-
fi
|
| 67 |
|
| 68 |
if ! command -v yt-dlp &>/dev/null; then
|
| 69 |
-
echo "yt-dlp is required
|
| 70 |
-
exit 1
|
| 71 |
-
fi
|
| 72 |
-
|
| 73 |
-
if ! command -v "$WHISPER_EXECUTABLE" &>/dev/null; then
|
| 74 |
-
|
| 75 |
-
|
| 76 |
-
|
| 77 |
-
|
| 78 |
-
|
| 79 |
-
|
| 80 |
-
|
| 81 |
-
|
| 82 |
-
|
| 83 |
-
|
| 84 |
-
|
| 85 |
-
fi
|
| 86 |
-
fi
|
| 87 |
}
|
| 88 |
|
| 89 |
-
if [[
|
| 90 |
-
print_help
|
| 91 |
-
exit 1
|
| 92 |
fi
|
| 93 |
|
| 94 |
-
if [[ "$1" == "help" ]]; then
|
| 95 |
-
print_help
|
| 96 |
-
exit 0
|
| 97 |
fi
|
| 98 |
|
| 99 |
-
|
| 100 |
-
source_url="$1"
|
| 101 |
|
| 102 |
-
|
| 103 |
|
| 104 |
-
|
| 105 |
-
|
| 106 |
-
# Optionally add --cookies-from-browser BROWSER[+KEYRING][:PROFILE][::CONTAINER]
|
|
|
|
|
|
|
| 107 |
yt-dlp \
|
| 108 |
-f "bestvideo[ext=mp4]+bestaudio[ext=m4a]/best[ext=mp4]/best" \
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 109 |
--embed-thumbnail \
|
| 110 |
--embed-chapters \
|
| 111 |
--xattrs \
|
| 112 |
-
"${source_url}"
|
|
|
|
|
|
|
| 113 |
|
| 114 |
-
msg "Extracting audio and resampling..."
|
| 115 |
|
| 116 |
-
ffmpeg -i "${temp_dir}
|
| 117 |
-hide_banner \
|
|
|
|
| 118 |
-loglevel error \
|
| 119 |
-ar 16000 \
|
| 120 |
-ac 1 \
|
| 121 |
-
-c:a \
|
| 122 |
-
|
|
|
|
| 123 |
|
| 124 |
-
msg "Transcribing to subtitle file..."
|
| 125 |
-
msg "Whisper specified at: ${WHISPER_EXECUTABLE}"
|
| 126 |
|
| 127 |
-
$WHISPER_EXECUTABLE \
|
| 128 |
-m "${MODEL_PATH}" \
|
| 129 |
-l "${WHISPER_LANG}" \
|
| 130 |
-
-f "vod-resampled.wav" \
|
| 131 |
-
-t
|
| 132 |
-osrt \
|
| 133 |
-
--translate
|
| 134 |
|
| 135 |
-
msg "Embedding subtitle track..."
|
| 136 |
|
| 137 |
-
ffmpeg -i "${temp_dir}
|
| 138 |
-hide_banner \
|
| 139 |
-loglevel error \
|
| 140 |
-
-i "vod-resampled.wav.srt" \
|
| 141 |
-c copy \
|
| 142 |
-c:s mov_text \
|
| 143 |
-
-y res.mp4
|
| 144 |
|
| 145 |
-
cleanup
|
| 146 |
|
| 147 |
-
msg "Done! Your finished file is ready: res.mp4"
|
|
|
|
| 1 |
#!/usr/bin/env bash
|
| 2 |
+
# shellcheck disable=2086
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3 |
|
| 4 |
# MIT License
|
| 5 |
|
| 6 |
# Copyright (c) 2022 Daniils Petrovs
|
| 7 |
+
# Copyright (c) 2023 Jennifer Capasso
|
| 8 |
|
| 9 |
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
| 10 |
# of this software and associated documentation files (the "Software"), to deal
|
|
|
|
| 24 |
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
| 25 |
# SOFTWARE.
|
| 26 |
|
| 27 |
+
# Small shell script to more easily automatically download and transcribe live stream VODs.
|
| 28 |
+
# This uses YT-DLP, ffmpeg and the CPP version of Whisper: https://github.com/ggerganov/whisper.cpp
|
| 29 |
+
# Use `./examples/yt-wsp.sh help` to print help info.
|
| 30 |
+
#
|
| 31 |
+
# Sample usage:
|
| 32 |
+
#
|
| 33 |
+
# git clone https://github.com/ggerganov/whisper.cpp
|
| 34 |
+
# cd whisper.cpp
|
| 35 |
+
# make
|
| 36 |
+
# ./examples/yt-wsp.sh https://www.youtube.com/watch?v=1234567890
|
| 37 |
+
#
|
| 38 |
+
|
| 39 |
set -Eeuo pipefail
|
| 40 |
|
| 41 |
+
# get script file location
|
| 42 |
+
SCRIPT_PATH="$(realpath -e ${BASH_SOURCE[0]})";
|
| 43 |
+
SCRIPT_DIR="${SCRIPT_PATH%/*}"
|
| 44 |
+
|
| 45 |
+
################################################################################
|
| 46 |
+
# Documentation on downloading models can be found in the whisper.cpp repo:
|
| 47 |
+
# https://github.com/ggerganov/whisper.cpp/#usage
|
| 48 |
+
#
|
| 49 |
+
# note: unless a multilingual model is specified, WHISPER_LANG will be ignored
|
| 50 |
+
# and the video will be transcribed as if the audio were in the English language
|
| 51 |
+
################################################################################
|
| 52 |
+
MODEL_PATH="${MODEL_PATH:-${SCRIPT_DIR}/../models/ggml-base.en.bin}"
|
| 53 |
+
|
| 54 |
+
################################################################################
|
| 55 |
+
# Where to find the whisper.cpp executable. default to the examples directory
|
| 56 |
+
# which holds this script in source control
|
| 57 |
+
################################################################################
|
| 58 |
+
WHISPER_EXECUTABLE="${WHISPER_EXECUTABLE:-${SCRIPT_DIR}/../main}";
|
| 59 |
+
|
| 60 |
+
# Set to desired language to be translated into english
|
| 61 |
+
WHISPER_LANG="${WHISPER_LANG:-en}";
|
| 62 |
+
|
| 63 |
+
# Default to 4 threads (this was most performant on my 2020 M1 MBP)
|
| 64 |
+
WHISPER_THREAD_COUNT="${WHISPER_THREAD_COUNT:-4}";
|
| 65 |
|
| 66 |
msg() {
|
| 67 |
echo >&2 -e "${1-}"
|
| 68 |
}
|
| 69 |
|
| 70 |
+
################################################################################
|
| 71 |
+
# create a temporary directory to work in
|
| 72 |
+
# set the temp_dir and temp_filename variables
|
| 73 |
+
################################################################################
|
| 74 |
+
temp_dir="$(mktemp -d ${SCRIPT_DIR}/tmp.XXXXXX)";
|
| 75 |
+
temp_filename="${temp_dir}/yt-dlp-filename";
|
| 76 |
+
|
| 77 |
+
################################################################################
|
| 78 |
+
# for now we only take one argument
|
| 79 |
+
# TODO: a for loop
|
| 80 |
+
################################################################################
|
| 81 |
+
source_url="${1}"
|
| 82 |
+
|
| 83 |
+
|
| 84 |
+
title_name="";
|
| 85 |
+
|
| 86 |
+
|
| 87 |
cleanup() {
|
| 88 |
+
local -r clean_me="${1}";
|
| 89 |
+
|
| 90 |
+
if [ -d "${clean_me}" ]; then
|
| 91 |
+
msg "Cleaning up...";
|
| 92 |
+
rm -rf "${clean_me}";
|
| 93 |
+
else
|
| 94 |
+
msg "'${clean_me}' does not appear to be a directory!";
|
| 95 |
+
exit 1;
|
| 96 |
+
fi;
|
| 97 |
}
|
| 98 |
|
| 99 |
print_help() {
|
| 100 |
+
echo "################################################################################"
|
| 101 |
echo "Usage: ./examples/yt-wsp.sh <video_url>"
|
| 102 |
+
echo "# See configurable env variables in the script; there are many!"
|
| 103 |
+
echo "# This script will produce an MP4 muxed file in the working directory; it will"
|
| 104 |
+
echo "# be named for the title and id of the video."
|
| 105 |
+
echo "# passing in https://youtu.be/VYJtb2YXae8 produces a file named";
|
| 106 |
+
echo "# 'Why_we_all_need_subtitles_now-VYJtb2YXae8-res.mp4'"
|
| 107 |
+
echo "# Requirements: ffmpeg yt-dlp whisper.cpp"
|
| 108 |
+
echo "################################################################################"
|
| 109 |
}
|
| 110 |
|
| 111 |
check_requirements() {
|
| 112 |
if ! command -v ffmpeg &>/dev/null; then
|
| 113 |
+
echo "ffmpeg is required: https://ffmpeg.org";
|
| 114 |
exit 1
|
| 115 |
+
fi;
|
| 116 |
|
| 117 |
if ! command -v yt-dlp &>/dev/null; then
|
| 118 |
+
echo "yt-dlp is required: https://github.com/yt-dlp/yt-dlp";
|
| 119 |
+
exit 1;
|
| 120 |
+
fi;
|
| 121 |
+
|
| 122 |
+
if ! command -v "${WHISPER_EXECUTABLE}" &>/dev/null; then
|
| 123 |
+
echo "The C++ implementation of Whisper is required: https://github.com/ggerganov/whisper.cpp"
|
| 124 |
+
echo "Sample usage:";
|
| 125 |
+
echo "";
|
| 126 |
+
echo " git clone https://github.com/ggerganov/whisper.cpp";
|
| 127 |
+
echo " cd whisper.cpp";
|
| 128 |
+
echo " make";
|
| 129 |
+
echo " ./examples/yt-wsp.sh https://www.youtube.com/watch?v=1234567890";
|
| 130 |
+
echo "";
|
| 131 |
+
exit 1;
|
| 132 |
+
fi;
|
| 133 |
+
|
|
|
|
|
|
|
| 134 |
}
|
| 135 |
|
| 136 |
+
if [[ "${#}" -lt 1 ]]; then
|
| 137 |
+
print_help;
|
| 138 |
+
exit 1;
|
| 139 |
fi
|
| 140 |
|
| 141 |
+
if [[ "${1##-*}" == "help" ]]; then
|
| 142 |
+
print_help;
|
| 143 |
+
exit 0;
|
| 144 |
fi
|
| 145 |
|
| 146 |
+
check_requirements;
|
|
|
|
| 147 |
|
| 148 |
+
msg "Downloading VOD...";
|
| 149 |
|
| 150 |
+
################################################################################
|
| 151 |
+
# Download the video, put the dynamic output filename into a variable.
|
| 152 |
+
# Optionally add --cookies-from-browser BROWSER[+KEYRING][:PROFILE][::CONTAINER]
|
| 153 |
+
# for videos only available to logged-in users.
|
| 154 |
+
################################################################################
|
| 155 |
yt-dlp \
|
| 156 |
-f "bestvideo[ext=mp4]+bestaudio[ext=m4a]/best[ext=mp4]/best" \
|
| 157 |
+
-o "${temp_dir}/%(title)s-%(id)s.vod.mp4" \
|
| 158 |
+
--print-to-file "%(filename)s" "${temp_filename}" \
|
| 159 |
+
--no-simulate \
|
| 160 |
+
--no-write-auto-subs \
|
| 161 |
+
--restrict-filenames \
|
| 162 |
--embed-thumbnail \
|
| 163 |
--embed-chapters \
|
| 164 |
--xattrs \
|
| 165 |
+
"${source_url}";
|
| 166 |
+
|
| 167 |
+
title_name="$(xargs basename -s .vod.mp4 < ${temp_filename})";
|
| 168 |
|
| 169 |
+
msg "Extracting audio and resampling...";
|
| 170 |
|
| 171 |
+
ffmpeg -i "${temp_dir}/${title_name}.vod.mp4" \
|
| 172 |
-hide_banner \
|
| 173 |
+
-vn \
|
| 174 |
-loglevel error \
|
| 175 |
-ar 16000 \
|
| 176 |
-ac 1 \
|
| 177 |
+
-c:a pcm_s16le \
|
| 178 |
+
-y \
|
| 179 |
+
"${temp_dir}/${title_name}.vod-resampled.wav";
|
| 180 |
|
| 181 |
+
msg "Transcribing to subtitle file...";
|
| 182 |
+
msg "Whisper specified at: '${WHISPER_EXECUTABLE}'";
|
| 183 |
|
| 184 |
+
"${WHISPER_EXECUTABLE}" \
|
| 185 |
-m "${MODEL_PATH}" \
|
| 186 |
-l "${WHISPER_LANG}" \
|
| 187 |
+
-f "${temp_dir}/${title_name}.vod-resampled.wav" \
|
| 188 |
+
-t "${WHISPER_THREAD_COUNT}" \
|
| 189 |
-osrt \
|
| 190 |
+
--translate;
|
| 191 |
|
| 192 |
+
msg "Embedding subtitle track...";
|
| 193 |
|
| 194 |
+
ffmpeg -i "${temp_dir}/${title_name}.vod.mp4" \
|
| 195 |
-hide_banner \
|
| 196 |
-loglevel error \
|
| 197 |
+
-i "${temp_dir}/${title_name}.vod-resampled.wav.srt" \
|
| 198 |
-c copy \
|
| 199 |
-c:s mov_text \
|
| 200 |
+
-y "${title_name}-res.mp4";
|
| 201 |
|
| 202 |
+
cleanup "${temp_dir}";
|
| 203 |
|
| 204 |
+
msg "Done! Your finished file is ready: ${title_name}-res.mp4";
|