Handle errors at download better

Related to #173
This commit is contained in:
Mattias Wadman
2024-03-13 17:28:49 +01:00
parent 95b1142af6
commit 8b5d2141e0
3 changed files with 62 additions and 10 deletions

View File

@ -25,7 +25,11 @@ func main() {
result, err := goutubedl.New(
context.Background(),
flag.Arg(0),
goutubedl.Options{Type: optType, DebugLog: log.Default(), StderrFn: func(cmd *exec.Cmd) io.Writer { return os.Stderr }},
goutubedl.Options{
Type: optType,
DebugLog: log.Default(),
StderrFn: func(cmd *exec.Cmd) io.Writer { return os.Stderr },
},
)
if err != nil {
log.Fatal(err)

View File

@ -623,15 +623,17 @@ func (result Result) DownloadWithOptions(
}
cmd.Dir = tempPath
var w io.WriteCloser
dr.reader, w = io.Pipe()
stderrWriter := io.Discard
var stdoutW io.WriteCloser
var stderrW io.WriteCloser
var stderrR io.Reader
dr.reader, stdoutW = io.Pipe()
stderrR, stderrW = io.Pipe()
optStderrWriter := io.Discard
if result.Options.StderrFn != nil {
stderrWriter = result.Options.StderrFn(cmd)
optStderrWriter = result.Options.StderrFn(cmd)
}
cmd.Stdout = w
cmd.Stderr = stderrWriter
cmd.Stdout = stdoutW
cmd.Stderr = io.MultiWriter(optStderrWriter, stderrW)
debugLog.Print("cmd", " ", cmd.Args)
if err := cmd.Start(); err != nil {
@ -641,12 +643,32 @@ func (result Result) DownloadWithOptions(
go func() {
_ = cmd.Wait()
w.Close()
stdoutW.Close()
stderrW.Close()
os.RemoveAll(tempPath)
close(dr.waitCh)
}()
return dr, nil
// blocks return until yt-dlp is downloading or has errored
ytErrCh := make(chan error)
go func() {
stderrLineScanner := bufio.NewScanner(stderrR)
for stderrLineScanner.Scan() {
const downloadPrefix = "[download]"
const errorPrefix = "ERROR: "
line := stderrLineScanner.Text()
if strings.HasPrefix(line, downloadPrefix) {
break
} else if strings.HasPrefix(line, errorPrefix) {
ytErrCh <- errors.New(line[len(errorPrefix):])
return
}
}
ytErrCh <- nil
_, _ = io.Copy(io.Discard, stderrR)
}()
return dr, <-ytErrCh
}
func (dr *DownloadResult) Read(p []byte) (n int, err error) {

View File

@ -552,3 +552,29 @@ func TestDownloadPlaylistEntry(t *testing.T) {
t.Error("not the same content between the playlist index entry and the direct link entry")
}
}
func TestFormatDownloadError(t *testing.T) {
defer leaktest.Check(t)()
ydl, ydlErr := goutubedl.New(
context.Background(),
"https://www.reddit.com/r/newsbabes/s/92rflI0EB0",
goutubedl.Options{},
)
if ydlErr != nil {
// reddit seems to not like github action hosts
if strings.Contains(ydlErr.Error(), "HTTPError 403: Blocked") {
t.Skip()
}
t.Error(ydlErr)
}
// no pre-muxed audio/video format available
_, ytDlErr := ydl.Download(context.Background(), "best")
expectedErr := "Requested format is not available"
if ydlErr != nil && !strings.Contains(ytDlErr.Error(), expectedErr) {
t.Errorf("expected error prefix %q got %q", expectedErr, ytDlErr.Error())
}
}