将 ffmpeg 执行结果写入 io 时冻结。管

Freeze when writing ffmpeg execution result to io.Pipe

提问人:alex 提问时间:11/8/2023 最后编辑:alex 更新时间:11/8/2023 访问量:65

问:

我正在编写一个包装器来使用.包装器旨在简化文件系统的工作,我想转换一个视频,将转换结果写入,在 goroutine 中读取它并传输它以预览新转换后的文件。为此,我使用 .但是我遇到了一个问题,当我开始测试时,执行只是挂起,我无法获得任何结果,但没有错误,一切都挂起。exec.Cmdio.Pipeio.PipeFFmpeg

CmdRunner 源代码

type CmdRunner struct {
    commander Commander
    StdIn io.ReadCloser
    StdoutWriter io.WriteCloser
    StdErrWriter io.Writer
}

func (c *CmdRunner) RunByPipe(ctx context.Context) error {
    //done := make(chan error)
    name, args := c.commander.Command()
    cmd := exec.CommandContext(ctx, name, args...)

    if c.StdIn != nil {
        fmt.Print("RunByPipe STDIN\n")
        cmd.Stdin = c.StdIn
    }

    if c.StdoutWriter != nil {
        fmt.Print("RunByPipe STDOUT\n")
        cmd.Stdout = c.StdoutWriter
    }

    stderr := bytes.Buffer{}
    cmd.Stderr = &stderr

    if err := cmd.Start(); err != nil {
        return err
    }

    if err := cmd.Wait(); err != nil {
        return err
    }

    if stderr.String() != "" {
        return fmt.Errorf("want empty stderr, but got %s", stderr.String())
    }

    return nil
}

单元测试代码

type TestCommander struct {
    name string
    args []string
}

func (c *TestCommander) SetCommand(name string, args []string) {
    c.name = name
    c.args = args
}

func (c *TestCommander) Command() (string, []string) {
    return c.name, c.args
}

func TestConvert(t *testing.T) {
    ctx := context.Background()
    filePath := "testdata/input_mp4.mp4"
    data, err := convertFile(filePath, ctx)
    outFile := "testdata/output_mp4.mp4"
    if err != nil {
        fmt.Print("ERR: ", err, "\n")
    }

    os.WriteFile(outFile, data, 0644)

}

func convertFile(filePath string, ctx context.Context) (bytes []byte, err error) {
    // Create a CmdRunner instance with your custom Commander.
    runner := &CmdRunner{}
    commander := &TestCommander{}
    args := []string{
        "-nostats",
        "-i", filePath,
        "-y",
        "-loglevel", "0",
        "-filter:v", "fps=30, crop=trunc(iw/2)*2:trunc(ih/2)*2",
        "-c:v", "libx264",
        "-c:a", "aac",
        "-pix_fmt", "yuv420p",
        "-movflags", "frag_keyframe+faststart",
        "-bufsize", "24M",
        "-maxrate", "12M",
        "-f", "mp4",
        "pipe:1",
    }

    commander.SetCommand("ffmpeg", args)
    runner.SetCommander(commander)
    outputPipeReader, outputPipeWriter := io.Pipe()
    runner.SetStdOutWriter(outputPipeWriter)

    wg := &sync.WaitGroup{}
    wg.Add(1)
    go func() {
        defer outputPipeReader.Close()
        defer wg.Done()

        // Read data from output pipe
        bytes, err = io.ReadAll(outputPipeReader)
        if err != nil {
            fmt.Print("\nReadAll err: ", err, "\n")
        }
    }()

    err = runner.RunByPipe(ctx)
    if err != nil {
        fmt.Print("\nRunByPipe err: ", err, "\n")
        return
    }

    wg.Wait()

    return
}

我找不到可能出了什么问题的线索。 PS:但是如果我删除然后问题就消失了,但是不会有数据,因为没有写入任何内容。为什么?if err := cmd.Wait(); err != nil { return err }io.Pipe

FFmpeg

评论


答: 暂无答案