我正在try 使用youtube-dl和ffmpeg创建一个音乐流媒体服务.当用户发送一个带有视频URL的POST请求时,我的处理程序代码如下所示:


 router.POST("/submit", func(c *gin.Context) {
        body := Body{}
        if err := c.BindJSON(&body); err != nil {
            c.AbortWithError(http.StatusBadRequest, err)
            return
        }
        w := c.Writer
        header := w.Header()
        header.Set("Content-Type", "audio/mp3")
        w.WriteHeader(http.StatusOK)
        fetchMusic(c, body.Data)
    })
func fetchMusic(c *gin.Context, data string) {

    r, w := io.Pipe()
    defer r.Close()

    ydl := exec.Command("youtube-dl", data, "-o-")
    ffmpeg := exec.Command("ffmpeg", "-i", "/dev/stdin", "-vn", "-f", "mp3", "-")

    ydl.Stdout = w
    ydl.Stderr = os.Stderr

    ffmpeg.Stdin = r
    ffmpeg.Stdout = c.Writer
    ffmpeg.Stderr = os.Stderr
    fmt.Println("Starting-----------------------")
    go func() {
        if err := ydl.Run(); err != nil {
            panic(err)
        }
    }()
    
    if err := ffmpeg.Run(); err != nil {
        panic(err)
    }

    
    fmt.Println("Done-----------------------")
}

我用ffmpeg和youtube-dl创建了一个管道.在测试阶段,我发送了POST请求,但该请求没有完成.如果我看一下日志(log),我看不到"完成-".我认为,这一过程似乎停滞不前.你有什么 idea 吗?我的用法是真的吗?

推荐答案

这是非常接近的-我们也需要关闭*io.PipeWriter米.

否则,ffmpeg认为可能会有更多的数据通过.这将在节目中显示为EOF.

下面是我使用echocat组合起来的一个可运行的示例.您应该能够通过注释掉新的defer w.Close()来重现该问题:

package main

import (
    "fmt"
    "io"
    "os"
    "os/exec"
)

func main() {
    r, w := io.Pipe()
    defer r.Close()

    echo := exec.Command("echo", "hello")
    cat := exec.Command("cat")

    echo.Stdout = w
    echo.Stderr = os.Stderr

    cat.Stdin = r
    cat.Stdout = os.Stdout
    cat.Stderr = os.Stderr
    fmt.Println("Starting-----------------------")
    go func() {
        // -- I added this --
        defer w.Close()
        if err := echo.Run(); err != nil {
            panic(err)
        }
    }()

    if err := cat.Run(); err != nil {
        panic(err)
    }

    fmt.Println("Done-----------------------")
}

Go相关问答推荐

从Kafka到Clickhouse的实时消费数据

ChromeDriver不存在(高朗selenium)

未对GoFr中的所有请求进行跟踪

在整个SQL事务中将使用上下文作为默认设置吗?

golang regex基于关键字拆分字符串

日志(log)文件不在 golang 的日志(log)目录中

golang testscript .txtar 语法,用于 stderr 或 stdout 中包含的文本

Go 中的 YAML 自定义标签

动态 SQL 集 Golang

grpc-gateway:重定向与定义不匹配(原始文件)

在 Gorm 的 AfterFind() 钩子中获取智能 Select struct 的值

无法建立连接,因为目标机器主动拒绝它 Golang

Go 中 SDL Surface 的 OpenGL 纹理

函数调用中的类型参数panic

出于某种原因,Golang (Go) AES CBC 密文被填充了 16 个 0x00 字节

GORM GIN 更新查询导致 500 内部服务器错误

Go lang - 惯用的默认后备

什么是无效字符实体 &ccb

如何在 Gorm 中获得特定日期的最大值?

Golang 泛型同时具有接口和实现