I currently have this function, that pipes youtubedl command thru ffmpeg, and then pipes the output of ffmpeg to an HTTP client.
func pipeThruFfmpegToMp3(vi *VideoInfo, rw web.ResponseWriter) error {
var ffmpeg *exec.Cmd
ffmpeg = exec.Command("ffmpeg", "-i", "-","-acodec", "libmp3lame","-f", "mp3","-")
}
youtube := exec.Command("youtube-dl", "-f", "137", "video_url", "-o", "-")
var ytbuf, ffbuf bytes.Buffer
youtube.Stderr = &ytbuf
ffmpeg.Stderr = &ffbuf
audio, err := youtube.StdoutPipe()
if err != nil {
log.Printf("pipeThruFfmpegToMp3: %v\n", err)
return err
}
ffmpeg.Stdin = audio
ffmpeg.Stdout = rw
// Headers sent, no turning back now
rw.Header().Set("Content-Type", "audio/mpeg")
rw.Header().Set("Content-Disposition", fmt.Sprintf("attachment;filename=\"%s.mp3\"", vi.GetSlug()))
rw.Flush()
youtube.Start()
ffmpeg.Start()
ffmpeg.Wait()
youtube.Wait()
// check ytvbuf, ytbuf, ffbuf for stderr errors
if ffbuf.Len() != 0 {
log.Printf("pipeThruFfmpegToMp3: %v\n", ffbuf.String())
}
if ytbuf.Len() != 0 {
log.Printf("pipeThruYouTubeDLToMp3: %v\n", ytbuf.String())
}
return nil
}
The problem is, when youtubedl has a error, it sends a 0kb file, instead of returning the error and not sending the file.
So is there anyway I can fix this to have if youtubedl errores out to return instead of continuing sending?
I got this work by replacing the Start()
and Wait()
to a CombinedOutput()
var ffbuf bytes.Buffer
ffmpeg.Stderr = &ffbuf
audio, err := youtube.Output()
if err != nil {
log.Printf("pipeThruFfmpegToMp3: %v\n", err)
return err
}
ffmpeg.Stdin = bytes.NewReader(audio)
How about simply not discarding the error code returned by youtube-dl
?
Change
youtube.Wait()
to
err = youtube.Wait()
if err != nil {
log.Printf("youtube-dl failed: %v\n", err)
return err
}
See the documentation on Go's wait() API for more detail.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With