Skip to content

Commit ba67045

Browse files
authored
Merge pull request #1810 from tonymet/subtitle-error-handling
improve subtitle lang, retry, debugging & error handling
2 parents 7d80fd6 + 4f20f7a commit ba67045

File tree

3 files changed

+63
-59
lines changed

3 files changed

+63
-59
lines changed
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
### PR [#1810](https://github.com/danielmiessler/Fabric/pull/1810) by [tonymet](https://github.com/tonymet): improve subtitle lang, retry, debugging & error handling
2+
3+
- Improve subtitle lang, retry, debugging & error handling

go.sum

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,6 @@ github.com/andybalholm/cascadia v1.3.3 h1:AG2YHrzJIm4BZ19iwJ/DAua6Btl3IwJX+VI4kk
2727
github.com/andybalholm/cascadia v1.3.3/go.mod h1:xNd9bqTn98Ln4DwST8/nG+H0yuB8Hmgu1YHNnWw0GeA=
2828
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFIImctFaOjnTIavg87rW78vTPkQqLI8=
2929
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4=
30-
github.com/anthropics/anthropic-sdk-go v1.12.0 h1:xPqlGnq7rWrTiHazIvCiumA0u7mGQnwDQtvA1M82h9U=
31-
github.com/anthropics/anthropic-sdk-go v1.12.0/go.mod h1:WTz31rIUHUHqai2UslPpw5CwXrQP3geYBioRV4WOLvE=
3230
github.com/anthropics/anthropic-sdk-go v1.13.0 h1:Bhbe8sRoDPtipttg8bQYrMCKe2b79+q6rFW1vOKEUKI=
3331
github.com/anthropics/anthropic-sdk-go v1.13.0/go.mod h1:WTz31rIUHUHqai2UslPpw5CwXrQP3geYBioRV4WOLvE=
3432
github.com/araddon/dateparse v0.0.0-20210429162001-6b43995a97de h1:FxWPpzIjnTlhPwqqXc4/vE0f7GvRjuAsbW+HOIe8KnA=

internal/tools/youtube/youtube.go

Lines changed: 60 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,13 @@
1010
package youtube
1111

1212
import (
13+
"bufio"
1314
"bytes"
1415
"context"
1516
"encoding/csv"
1617
"flag"
1718
"fmt"
19+
"io"
1820
"log"
1921
"os"
2022
"os/exec"
@@ -26,6 +28,8 @@ import (
2628

2729
"github.com/danielmiessler/fabric/internal/plugins"
2830
"github.com/kballard/go-shellquote"
31+
32+
debuglog "github.com/danielmiessler/fabric/internal/log"
2933
"google.golang.org/api/option"
3034
"google.golang.org/api/youtube/v3"
3135
)
@@ -143,6 +147,46 @@ func (o *YouTube) GrabTranscriptWithTimestampsWithArgs(videoId string, language
143147
return o.tryMethodYtDlpWithTimestamps(videoId, language, additionalArgs)
144148
}
145149

150+
func detectError(ytOutput io.Reader) error {
151+
scanner := bufio.NewScanner(ytOutput)
152+
for scanner.Scan() {
153+
curLine := scanner.Text()
154+
debuglog.Debug(debuglog.Trace, "%s\n", curLine)
155+
errorMessages := map[string]string{
156+
"429": "YouTube rate limit exceeded. Try again later or use different yt-dlp arguments like '--sleep-requests 1' to slow down requests.",
157+
"Too Many Requests": "YouTube rate limit exceeded. Try again later or use different yt-dlp arguments like '--sleep-requests 1' to slow down requests.",
158+
"Sign in to confirm you're not a bot": "YouTube requires authentication (bot detection). Use --yt-dlp-args='--cookies-from-browser BROWSER' where BROWSER is chrome, firefox, brave, etc.",
159+
"Use --cookies-from-browser": "YouTube requires authentication (bot detection). Use --yt-dlp-args='--cookies-from-browser BROWSER' where BROWSER is chrome, firefox, brave, etc.",
160+
}
161+
162+
for key, message := range errorMessages {
163+
if strings.Contains(curLine, key) {
164+
return fmt.Errorf("%s", message)
165+
}
166+
}
167+
}
168+
if err := scanner.Err(); err != nil {
169+
return fmt.Errorf("Error reading yt-dlp stderr")
170+
}
171+
return nil
172+
}
173+
174+
func noLangs(args []string) []string {
175+
var (
176+
i int
177+
v string
178+
)
179+
for i, v = range args {
180+
if strings.Contains(v, "--sub-langs") {
181+
break
182+
}
183+
}
184+
if i == 0 || i == len(args)-1 {
185+
return args
186+
}
187+
return append(args[0:i], args[i+2:]...)
188+
}
189+
146190
// tryMethodYtDlpInternal is a helper function to reduce duplication between
147191
// tryMethodYtDlp and tryMethodYtDlpWithTimestamps.
148192
func (o *YouTube) tryMethodYtDlpInternal(videoId string, language string, additionalArgs string, processVTTFileFunc func(filename string) (string, error)) (ret string, err error) {
@@ -168,20 +212,18 @@ func (o *YouTube) tryMethodYtDlpInternal(videoId string, language string, additi
168212
"--write-auto-subs",
169213
"--skip-download",
170214
"--sub-format", "vtt",
171-
"--quiet",
172-
"--no-warnings",
173215
"-o", outputPath,
174216
}
175217

176218
args := append([]string{}, baseArgs...)
177219

178220
// Add built-in language selection first
179221
if language != "" {
180-
langMatch := language
181-
if len(langMatch) > 2 {
182-
langMatch = langMatch[:2]
222+
langMatch := language[:2]
223+
langOpts := language + "," + langMatch + ".*"
224+
if langMatch != language {
225+
langOpts += "," + langMatch
183226
}
184-
langOpts := language + "," + langMatch + ".*," + langMatch
185227
args = append(args, "--sub-langs", langOpts)
186228
}
187229

@@ -196,65 +238,26 @@ func (o *YouTube) tryMethodYtDlpInternal(videoId string, language string, additi
196238

197239
args = append(args, videoURL)
198240

199-
cmd := exec.Command("yt-dlp", args...)
200-
201-
var stderr bytes.Buffer
202-
cmd.Stderr = &stderr
203-
204-
if err = cmd.Run(); err != nil {
205-
stderrStr := stderr.String()
206-
207-
// Check for specific YouTube errors
208-
if strings.Contains(stderrStr, "429") || strings.Contains(stderrStr, "Too Many Requests") {
209-
err = fmt.Errorf("YouTube rate limit exceeded. Try again later or use different yt-dlp arguments like '--sleep-requests 1' to slow down requests. Error: %v", err)
210-
return
211-
}
212-
213-
if strings.Contains(stderrStr, "Sign in to confirm you're not a bot") || strings.Contains(stderrStr, "Use --cookies-from-browser") {
214-
err = fmt.Errorf("YouTube requires authentication (bot detection). Use --yt-dlp-args='--cookies-from-browser BROWSER' where BROWSER is chrome, firefox, brave, etc. Error: %v", err)
215-
return
216-
}
217-
218-
if language != "" {
219-
// Fallback: try without specifying language (let yt-dlp choose best available)
220-
stderr.Reset()
221-
fallbackArgs := append([]string{}, baseArgs...)
222-
223-
// Add additional arguments if provided
224-
if additionalArgs != "" {
225-
additionalArgsList, parseErr := shellquote.Split(additionalArgs)
226-
if parseErr != nil {
227-
return "", fmt.Errorf("invalid yt-dlp arguments: %v", parseErr)
228-
}
229-
fallbackArgs = append(fallbackArgs, additionalArgsList...)
230-
}
231-
232-
// Don't specify language, let yt-dlp choose
233-
fallbackArgs = append(fallbackArgs, videoURL)
234-
cmd = exec.Command("yt-dlp", fallbackArgs...)
235-
cmd.Stderr = &stderr
236-
if err = cmd.Run(); err != nil {
237-
stderrStr2 := stderr.String()
238-
if strings.Contains(stderrStr2, "429") || strings.Contains(stderrStr2, "Too Many Requests") {
239-
err = fmt.Errorf("YouTube rate limit exceeded. Try again later or use different yt-dlp arguments like '--sleep-requests 1'. Error: %v", err)
240-
} else {
241-
err = fmt.Errorf("yt-dlp failed with language '%s' and fallback. Original error: %s. Fallback error: %s", language, stderrStr, stderrStr2)
242-
}
243-
return
244-
}
245-
} else {
246-
err = fmt.Errorf("yt-dlp failed: %v, stderr: %s", err, stderrStr)
247-
return
241+
for retry := 1; retry >= 0; retry-- {
242+
var ytOutput []byte
243+
cmd := exec.Command("yt-dlp", args...)
244+
debuglog.Debug(debuglog.Trace, "yt-dlp %+v\n", cmd.Args)
245+
ytOutput, err = cmd.CombinedOutput()
246+
ytReader := bytes.NewReader(ytOutput)
247+
if err = detectError(ytReader); err == nil {
248+
break
248249
}
250+
args = noLangs(args)
251+
}
252+
if err != nil {
253+
return
249254
}
250-
251255
// Find VTT files using cross-platform approach
252256
// Try to find files with the requested language first, but fall back to any VTT file
253257
vttFiles, err := o.findVTTFilesWithFallback(tempDir, language)
254258
if err != nil {
255259
return "", err
256260
}
257-
258261
return processVTTFileFunc(vttFiles[0])
259262
}
260263

0 commit comments

Comments
 (0)