将raw []字节视频管道输入ffmpeg - Go

时间:2018-04-12 15:43:38

标签: go ffmpeg

我直接从http主体以[]字节格式显示视频:

//Parsing video
videoData, err := ioutil.ReadAll(r.Body)
if err != nil {
    w.WriteHeader(UPLOAD_ERROR)
    w.Write([]byte("Error uploading the file"))
    return
}

我需要一段视频并将其转换为png。这是使用ffmpeg:

的人使用静态和编码文件的方式
        filename := "test.mp4"
        width := 640
        height := 360
        cmd := exec.Command("ffmpeg", "-i", filename, "-vframes", "1", "-s", fmt.Sprintf("%dx%d", width, height), "-f", "singlejpeg", "-")
        var buffer bytes.Buffer
        cmd.Stdout = &buffer
        if cmd.Run() != nil {
            panic("could not generate frame")
        }

如何使用原始视频实现相同目标?

来自reddit的用户告诉我,我可能会使用https://ffmpeg.org/ffmpeg-protocols.html#pipe实现此目的,但我无法找到任何资源。

感谢任何帮助,谢谢。

编辑:我现在试图将[]字节数组传递给ffmpeg,但是ffmpeg没有填充我的缓冲区:

width := 640
height := 360
log.Print("Size of the video: ", len(videoData))


cmd := exec.Command("ffmpeg", "-i", "pipe:0", "-vframes", "1", "-s", fmt.Sprintf("%dx%d", width, height), "-f", "singlejpeg", "-")
cmd.Stdin = bytes.NewReader(videoData)

var imageBuffer bytes.Buffer
cmd.Stdout = &imageBuffer
err := cmd.Run()

if err != nil {
    log.Panic("ERROR")
}

imageBytes := imageBuffer.Bytes()
log.Print("Size of the image: ", len(imageBytes))

但我得到以下错误:

  

[mov,mp4,m4a,3gp,3g2,mj2 @ 0x7ff05d002600] stream 0,offset 0x5ded:partial file

     

pipe:0:处理输入时找到无效数据

     

在没有写入任何数据的情况下完成流0:0。

     

frame = 0 fps = 0.0 q = 0.0   Lsize = 0kB时间= -577014:32:22.77比特率= -0.0kbits / s速度= N / A   视频:0kB音频:0kB字幕:0kB其他流:0kB全局标题:0kB   muxing开销:未知

     

输出文件为空,没有编码(如果使用,请检查-ss / -t / -frames参数)

2 个答案:

答案 0 :(得分:3)

  

我需要一段视频并将其转换为png。这是   怎么有人会用ffmpeg来做。

有一个流行的go库,它完全针对您搜索的内容: https://github.com/bakape/thumbnailer

thumbnailDimensions := thumbnailer.Dims{Width: 320, Height: 130}

thumbnailOptions := thumbnailer.Options{JPEGQuality:100, MaxSourceDims:thumbnailer.Dims{}, ThumbDims:thumbnailDimensions, AcceptedMimeTypes: nil}

sourceData, thumbnail, err := thumbnailer.ProcessBuffer(videoData, thumbnailOptions)

imageBytes := thumbnail.Image.Data

他们在引擎盖下使用ffmpeg,但为你删除了抽象。

答案 1 :(得分:0)

请检查一下,我写这个是为了将示例 mp3 文件降低到 128k 比特率,它应该适合你。请更改适合您的命令:

package main

import (
    "bytes"
    "io/ioutil"
    "log"
    "os"
    "os/exec"
)

func check(err error) {
    if err != nil {
        log.Fatalln(err)
    }
}

func main() {
    file, err := os.Open("test.mp3") // open file
    check(err)
    
    defer file.Close()
    buf, err := ioutil.ReadAll(file)
    check(err)

    cmd := exec.Command("ffmpeg", "-y", // Yes to all
        //"-hide_banner", "-loglevel", "panic", // Hide all logs
        "-i", "pipe:0", // take stdin as input
        "-map_metadata", "-1", // strip out all (mostly) metadata
        "-c:a", "libmp3lame", // use mp3 lame codec
        "-vsync", "2", // suppress "Frame rate very high for a muxer not efficiently supporting it"
        "-b:a", "128k", // Down sample audio birate to 128k
        "-f", "mp3", // using mp3 muxer (IMPORTANT, output data to pipe require manual muxer selecting)
        "pipe:1", // output to stdout
    )

    resultBuffer := bytes.NewBuffer(make([]byte, 5*1024*1024)) // pre allocate 5MiB buffer

    cmd.Stderr = os.Stderr // bind log stream to stderr
    cmd.Stdout = resultBuffer // stdout result will be written here

    stdin, err := cmd.StdinPipe() // Open stdin pipe
    check(err)

    err = cmd.Start() // Start a process on another goroutine
    check(err)

    _, err = stdin.Write(buf) // pump audio data to stdin pipe
    check(err)

    err = stdin.Close() // close the stdin, or ffmpeg will wait forever
    check(err)

    err = cmd.Wait() // wait until ffmpeg finish
    check(err)

    outputFile, err := os.Create("out.mp3") // create new file
    check(err)
    defer outputFile.Close()
    
    _, err = outputFile.Write(resultBuffer.Bytes()) // write result buffer to file
    check(err)
}

参考:https://gist.github.com/aperture147/ad0f5b965912537d03b0e851bb95bd38