Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to have program return when error on piped input

Tags:

go

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?

like image 210
nadermx Avatar asked Feb 19 '20 19:02

nadermx


2 Answers

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)
like image 151
nadermx Avatar answered Nov 15 '22 06:11

nadermx


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.

like image 3
aij Avatar answered Nov 15 '22 06:11

aij