Вопрос
Как мне передать 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()