Вопрос

Как мне передать HTTP-ответ, как в NodeJS.Вот фрагмент, который я использую в NodeJS:

request({
  url: audio_file_url,
}).pipe(ffmpeg_process.stdin);

Как я могу добиться такого же результата в Go?

Я пытаюсь передать аудиопоток из HTTP в процесс FFmpeg, чтобы он преобразовывал его "на лету" и возвращал преобразованный файл обратно клиенту.

Просто чтобы всем было понятно, вот мой исходный код на данный момент:

func encodeAudio(w http.ResponseWriter, req *http.Request) {
    path, err := exec.LookPath("youtube-dl")
    if err != nil {
        log.Fatal("LookPath: ", err)
    }
    path_ff, err_ff := exec.LookPath("ffmpeg")
    if err != nil {
        log.Fatal("LookPath: ", err_ff)
    }

    streamLink := exec.Command(path,"-f", "140", "-g", "https://www.youtube.com/watch?v=VIDEOID")

    var out bytes.Buffer
    streamLink.Stdout = &out
    cmdFF := exec.Command(path_ff, "-i", "pipe:0", "-acodec", "libmp3lame", "-f", "mp3", "-")
    resp, err := http.Get(out.String())
    if err != nil {
        log.Fatal(err)
    }
    // pr, pw := io.Pipe()
    defer resp.Body.Close()
    cmdFF.Stdin = resp.Body
    cmdFF.Stdout = w
    streamLink.Run()
    //get ffmpeg running in another goroutine to receive data
    errCh := make(chan error, 1)
    go func() {
        errCh <- cmdFF.Run()
    }()

    // close the pipeline to signal the end of the stream
    // pw.Close()
    // pr.Close()

    // check for an error from ffmpeg
    if err := <-errCh; err != nil {
        // ff error
    }
}

Ошибка: 2014/07/29 23:04:02 Получить :схема неподдерживаемого протокола ""

Это было полезно?

Решение

Вот возможный ответ, используя стандартную функцию HTTP-обработчика.У меня нет программ, чтобы проверить это напрямую, но он работает с некоторыми простыми командами Shell, стоящей в виде прокси.

func encodeAudio(w http.ResponseWriter, req *http.Request) {

    streamLink := exec.Command("youtube-dl", "-f", "140", "-g", "https://www.youtube.com/watch?v=VIDEOID")
    out, err := streamLink.Output()
    if err != nil {
        log.Fatal(err)
    }

    cmdFF := exec.Command("ffmpeg", "-i", "pipe:0", "-acodec", "libmp3lame", "-f", "mp3", "-")
    resp, err := http.Get(string(out))
    if err != nil {
        log.Fatal(err)
    }

    defer resp.Body.Close()
    cmdFF.Stdin = resp.Body

    cmdFF.Stdout = w
    if err := cmdFF.Run(); err != nil {
        log.Fatal(err)
    }
}
.

Другие советы

http.Request.Body является io.ReadCloser, чтобы вы могли направить это в exec.Cmd.Стандартный код:

func Handler(rw http.ResponseWriter, req *http.Request) {
    cmd := exec.Command("ffmpeg", other, args, ...)
    cmd.Stdin = req.Body
    go func() {
        defer req.Body.Close()

        if err := cmd.Run(); err != nil {
            // do something
        }
    }()
    //redirect the user and check for progress?
}

// редактировать Я неправильно понял вопрос, однако ответ по-прежнему остается в силе, http.Get версия:

http.Response.Body является io.ReadCloser точно так же , как http.Request.Body.

func EncodeUrl(url, fn string) error {
    resp, err := http.Get(url)
    if err != nil {
        return err
    }
    defer resp.Body.Close()
    cmd := exec.Command("ffmpeg", ......, fn)
    cmd.Stdin = resp.Body
    return cmd.Run()
}

//редактировать 2:

это следует работайте в соответствии с документацией martini, но опять же, я настоятельно рекомендую научиться использовать ServeMux или, по крайней мере, использовать Горилла.

m := martini.Classic()
m.Get("/stream/:ytid", func(params martini.Params, rw http.ResponseWriter,
                            req *http.Request) string {
    ytid := params["ytid"]
    stream_link := exec.Command("youtube-dl","-f", "140", "-g", "https://www.youtube.com/watch?v=" + ytid)
    var out bytes.Buffer
    stream_link.Stdout = &out
    errr := stream_link.Run()
    if err != nil {
        log.Fatal(err)
    }
    log.Println("Link", out.String())

    cmd_ff := exec.Command("ffmpeg", "-i", "pipe:0", "-acodec", "libmp3lame", "-f", "mp3", "-")
    resp, err := http.Get(url)
    if err != nil {
        log.Fatal(err)
    }
    cmd_ff.Stdin = resp.Body
    go func() {
        defer resp.Body.Close()
        if err := cmd_ff.Run(); err != nil {
            log.Fatal(err)
        }
    }()
    return "Youtube ID: " + ytid
})
m.Run()
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top