Go 保存来自ffmpeg image2pipe的连续图像流

Go 保存来自ffmpeg image2pipe的连续图像流,go,ffmpeg,Go,Ffmpeg,我正在尝试将ffmpeg image2pipe中的序列/连续图像保存到go中。下面代码的问题是,由于io.Copy的阻塞性质,它只保存流中的第一个图像,因为它等待读卡器或写入器关闭 package main import ( "fmt" "io" "log" "os" "os/exec" "strconv" "time" ) //Trying to get png from stdout pipe func main() {

我正在尝试将ffmpeg image2pipe中的序列/连续图像保存到go中。下面代码的问题是,由于io.Copy的阻塞性质,它只保存流中的第一个图像,因为它等待读卡器或写入器关闭

package main

import (
    "fmt"
    "io"
    "log"
    "os"
    "os/exec"
    "strconv"
    "time"
)

//Trying to get png from stdout pipe

func main() {
    fmt.Println("Running the camera stream")
    ffmpegCmd := exec.Command("ffmpeg", "-loglevel", "quiet", "-y", "-rtsp_transport", "tcp", "-i", "rtsp://admin:123456@192.168.1.41:554/h264Preview_01_main", "-r", "1", "-f", "image2pipe", "pipe:1")

    ffmpegOut, err := ffmpegCmd.StdoutPipe()
    if err != nil {
        return
    }

    err = ffmpegCmd.Start()

    if err != nil {
        log.Fatal(err)
    }

    count := 0
    for {
        count++
        t := time.Now()
        fmt.Println("writing image" + strconv.Itoa(count))
        filepath := "image-" + strconv.Itoa(count) + "-" + t.Format("20060102150405.png")

        out, err := os.Create(filepath)
        if err != nil {
            log.Fatal(err)
        }
        defer out.Close()

        _, err = io.Copy(out, ffmpegOut)
        if err != nil {
            log.Fatalf("unable to copy to file: %s", err.Error())
        }
    }
    if err := ffmpegCmd.Wait(); err != nil {
        log.Fatal("Error while waiting:", err)
    }
}
我根据io.copy代码实现了自己的保存和复制功能

然后我将主函数中的for循环更新为下面的块,但仍然只得到序列中的第一个图像。由于
r.Read(buf[:])
是一个阻塞调用

for {
        count++
        t := time.Now()
        fmt.Println("writing image" + strconv.Itoa(count))
        filepath := "image-" + strconv.Itoa(count) + "-" + t.Format("20060102150405.png")

        out, err := os.Create(filepath)
        if err != nil {
            log.Fatal(err)
        }
        defer out.Close()

        err = copyAndSave(out, ffmpegOut)
        if err != nil {
            if err == io.EOF {
                break
            }
            log.Fatalf("unable to copy to file: %s", err.Error())
            break
        }
    }

我怀疑你的问题与阻止复制有关。如果ffmepg要输出多个文件,您如何知道一个文件何时停止,另一个文件何时启动?复制就是简单地复制它读取的所有内容,直到管道关闭,所以我怀疑您有一个包含多个图像的文件。我明白了,现在想想看,我怀疑ffmpeg正在将图像数据通过管道传输到stdout,中间有行断开。不太可能。图像是二进制数据,将包含多个换行符。我建议您了解ffmpeg如何在没有管道的情况下编写其输出。我猜它会将其写入多个文件,试图从管道处理此类输出可能是徒劳的。我怀疑您的问题与阻止复制有关。如果ffmepg要输出多个文件,您如何知道一个文件何时停止,另一个文件何时启动?复制就是简单地复制它读取的所有内容,直到管道关闭,所以我怀疑您有一个包含多个图像的文件。我明白了,现在想想看,我怀疑ffmpeg正在将图像数据通过管道传输到stdout,中间有行断开。不太可能。图像是二进制数据,将包含多个换行符。我建议您了解ffmpeg如何在没有管道的情况下编写其输出。我的猜测是,它会将其写入多个文件,而试图从管道处理此类输出可能是徒劳的。
for {
        count++
        t := time.Now()
        fmt.Println("writing image" + strconv.Itoa(count))
        filepath := "image-" + strconv.Itoa(count) + "-" + t.Format("20060102150405.png")

        out, err := os.Create(filepath)
        if err != nil {
            log.Fatal(err)
        }
        defer out.Close()

        err = copyAndSave(out, ffmpegOut)
        if err != nil {
            if err == io.EOF {
                break
            }
            log.Fatalf("unable to copy to file: %s", err.Error())
            break
        }
    }