Home  >  Article  >  Backend Development  >  The command executed by Golang using Run() does not return

The command executed by Golang using Run() does not return

WBOY
WBOYforward
2024-02-06 10:12:03824browse

Golang 使用 Run() 执行的命令没有返回

Question content

I'm trying to create a music streaming service using youtube-dl and ffmpeg. When the user sends a POST request with the video URL, my handler code works like this:

 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-----------------------")
}

I created a pipeline using ffmpeg and youtube-dl. During the testing phase, I sent a POST request, but the request was not completed. If I look at the logs, I don't see "Complete----------------". I think the process seems to be stuck. Do you have any ideas? Is my usage correct?


Correct answer


This is pretty close - we also need to close *io.PipeWriter.

Otherwise ffmpeg thinks more data can be passed. This will appear in the program as EOF.

Here's a runnable example I put together, using echo and cat instead. You should be able to reproduce the issue by commenting out the new 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-----------------------")
}

The above is the detailed content of The command executed by Golang using Run() does not return. For more information, please follow other related articles on the PHP Chinese website!

Statement:
This article is reproduced at:stackoverflow.com. If there is any infringement, please contact admin@php.cn delete