Repository navigation
Expand file tree
/
Copy pathtranscript
More file actions
executable file
·164 lines (143 loc) · 5.22 KB
/
Copy pathtranscript
File metadata and controls
executable file
·164 lines (143 loc) · 5.22 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
#!/bin/bash
# transcript - Get YouTube video transcript for free
# Usage: transcript [--all] <url>
GET_ALL=0
LANG="en" # Default language
URL=""
# Parse arguments
while [[ $# -gt 0 ]]; do
case $1 in
--all)
GET_ALL=1
shift
;;
--lang)
LANG="$2"
shift
shift
;;
http://*|https://*)
URL="$1"
shift
;;
*)
echo "Unknown argument: $1"
shift
;;
esac
done
if [ -z "$URL" ]; then
echo "Usage: transcript [--all] <url>"
exit 1
fi
# Resolve script directory (handling symlinks)
SOURCE="${BASH_SOURCE[0]}"
while [ -h "$SOURCE" ]; do
DIR="$( cd -P "$( dirname "$SOURCE" )" >/dev/null 2>&1 && pwd )"
SOURCE="$(readlink "$SOURCE")"
[[ $SOURCE != /* ]] && SOURCE="$DIR/$SOURCE"
done
SCRIPT_DIR="$( cd -P "$( dirname "$SOURCE" )" >/dev/null 2>&1 && pwd )"
# Prefer local binary, then python module, then system command
if [ -f "$SCRIPT_DIR/yt-dlp" ]; then
YTDLP="$SCRIPT_DIR/yt-dlp"
IMPERSONATE=""
elif python3 -m yt_dlp --version &> /dev/null; then
YTDLP="python3 -m yt_dlp"
# Enable impersonation if using the python module (more likely to have curl_cffi)
IMPERSONATE="--impersonate Chrome"
elif command -v yt-dlp &> /dev/null; then
YTDLP="yt-dlp"
IMPERSONATE=""
else
echo "yt-dlp not found. Downloading latest standalone binary..." >&2
CURL_URL="https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp"
DOWNLOAD_PATH="$SCRIPT_DIR/yt-dlp"
if curl -L "$CURL_URL" -o "$DOWNLOAD_PATH"; then
chmod +x "$DOWNLOAD_PATH"
YTDLP="$DOWNLOAD_PATH"
IMPERSONATE=""
echo "yt-dlp downloaded successfully to $SCRIPT_DIR." >&2
else
echo "Error: Failed to download yt-dlp. Please install it manually."
exit 1
fi
fi
if ! command -v jq &> /dev/null; then
echo "Error: jq is not installed. Please install it first."
exit 1
fi
TEMP_DIR=$(mktemp -d)
trap 'rm -rf "$TEMP_DIR"' EXIT
TITLE=""
DESCRIPTION=""
if [ $GET_ALL -eq 1 ]; then
# echo "Fetching metadata..." >&2
TITLE=$($YTDLP $IMPERSONATE --get-title "$URL" 2>/dev/null)
DESCRIPTION=$($YTDLP $IMPERSONATE --get-description "$URL" 2>/dev/null)
fi
# Download auto-generated subtitles in VTT format
# Strategy: Try requested lang first, then try with cookies.
# Only fallback to other languages if the user didn't specify a strict custom language (default en).
# echo "Fetching transcript (Attempt 1: $LANG)..." >&2
$YTDLP $IMPERSONATE --write-auto-subs --sub-lang "$LANG" --skip-download \
--output "$TEMP_DIR/sub.%(ext)s" "$URL" > /dev/null 2>&1
# If download failed, try with cookies
if [ -z "$(find "$TEMP_DIR" -name "sub.*.vtt" | head -n 1)" ]; then
# echo "Attempt 2: $LANG with cookies..." >&2
$YTDLP $IMPERSONATE --write-auto-subs --sub-lang "$LANG" --skip-download \
--cookies-from-browser "chromium:/home/lewis/.config/chromium-chatbot" \
--output "$TEMP_DIR/sub.%(ext)s" "$URL" > /dev/null 2>&1
fi
# Fallbacks (Only if using default English, otherwise respect user choice)
if [ "$LANG" == "en" ]; then
# If STILL failed, fetch RU (high success rate for this specific video and others)
if [ -z "$(find "$TEMP_DIR" -name "sub.*.vtt" | head -n 1)" ]; then
# echo "Attempt 3: RU..." >&2
$YTDLP $IMPERSONATE --write-auto-subs --sub-lang ru --skip-download \
--output "$TEMP_DIR/sub.%(ext)s" "$URL" > /dev/null 2>&1
fi
# If STILL failed, fetch any available language
if [ -z "$(find "$TEMP_DIR" -name "sub.*.vtt" | head -n 1)" ]; then
# echo "Attempt 4: Any language..." >&2
$YTDLP $IMPERSONATE --write-auto-subs --sub-lang ".*" --skip-download \
--output "$TEMP_DIR/sub.%(ext)s" "$URL" > /dev/null 2>&1
fi
fi
# Find the downloaded subtitle file
SUB_FILE=$(find "$TEMP_DIR" -name "sub.*.vtt" | head -n 1)
if [ ! -f "$SUB_FILE" ]; then
# Try manual subtitles (standard attempt)
"$YTDLP" --write-subs --skip-download --output "$TEMP_DIR/sub.%(ext)s" "$URL" > /dev/null 2>&1
SUB_FILE=$(find "$TEMP_DIR" -name "sub.*.vtt" | head -n 1)
# Retry manual subtitles with cookies if needed
if [ ! -f "$SUB_FILE" ]; then
"$YTDLP" --write-subs --skip-download \
--cookies-from-browser "chromium:/home/lewis/.config/chromium-chatbot" \
--output "$TEMP_DIR/sub.%(ext)s" "$URL" > /dev/null 2>&1
SUB_FILE=$(find "$TEMP_DIR" -name "sub.*.vtt" | head -n 1)
fi
fi
if [ -f "$SUB_FILE" ]; then
# Process VTT to plain text as a single paragraph
TRANSCRIPT=$(sed -E \
-e '/^[0-9]{2}:[0-9]{2}:[0-9]{2}\.[0-9]{3} --> [0-9]{2}:[0-9]{2}:[0-9]{2}\.[0-9]{3}.*/d' \
-e 's/<[^>]*>//g' \
-e '/^(WEBVTT|Kind:|Language:)/d' \
-e '/^[[:space:]]*$/d' \
"$SUB_FILE" | uniq | tr '\n' ' ' | sed 's/ */ /g' | sed 's/^ //' | sed 's/ $//')
if [ $GET_ALL -eq 1 ]; then
# Output as JSON
jq -n \
--arg title "$TITLE" \
--arg description "$DESCRIPTION" \
--arg transcript "$TRANSCRIPT" \
'{title: $title, description: $description, transcript: $transcript}'
else
# Output as plain text
echo "$TRANSCRIPT"
fi
else
echo "Error: Could not retrieve transcript for $URL"
exit 1
fi