将原始 []byte 视频传输到 ffmpeg - Go

Posted

技术标签:

【中文标题】将原始 []byte 视频传输到 ffmpeg - Go【英文标题】:Piping raw []byte video to ffmpeg - Go 【发布时间】:2018-09-22 20:32:20 【问题描述】:

我有一个直接来自 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 实现这一目标,但我找不到任何资源。

感谢您的帮助。

(编辑:我现在尝试将 []byte 数组通过管道传输到 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]流0,偏移0x5ded:部分文件

pipe:0:处理输入时发现无效数据

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

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

输出文件为空,未编码(检查 -ss / -t / -frames 参数是否使用)

【问题讨论】:

cmd.Stdin = bytes.NewReader(videoData),并将文件名替换为“pipe:0” 这是您的 previous question 的副本,更具体一点。 @icza 不,不是。在这个问题中,我特别询问如何将字节推送到 ffmpeg。这两个问题可能相关,但基础不同。 要知道你需要多少字节需要你解码视频,此时你可能不再需要 ffmpeg。但我希望 ffmpeg 在第一帧之后停止阅读。您可以使用io.TeeReader 来判断 ffmpeg 读取了多少。如果事实证明 ffmpeg 可以读取所有内容,io.LimitReader 可能会有所帮助。 @Peter 或者而不是 io.LimitReader 只是切片输入数据,例如bytes.NewReader(videoData[:limit])(但不要忘记检查切片长度以避免运行时恐慌)。 【参考方案1】:

我需要一帧视频并将其转换为 png。这是 有人会如何使用 ffmpeg。

有一个很受欢迎的 go 库,正是为您搜索的内容而设计的: https://github.com/bakape/thumbnailer

thumbnailDimensions := thumbnailer.DimsWidth: 320, Height: 130

thumbnailOptions := thumbnailer.OptionsJPEGQuality:100, MaxSourceDims:thumbnailer.Dims, ThumbDims:thumbnailDimensions, AcceptedMimeTypes: nil

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

imageBytes := thumbnail.Image.Data

他们在后台使用 ffmpeg,但为您删除了抽象。

【讨论】:

【参考方案2】:

请检查一下,我写这个是为了将示例 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

【讨论】:

以上是关于将原始 []byte 视频传输到 ffmpeg - Go的主要内容,如果未能解决你的问题,请参考以下文章

使用FFMPEG将视频文件连续传输到RTMP服务器

将 pi 的 opencv 视频传输到 ffmpeg 以进行 Youtube 流式传输

sh 通过ffmpeg将视频流式传输到youtube

sh 通过ffmpeg将视频流式传输到youtube

将音频和视频块从 python 中传输到 ffmpeg 的最佳方法

使用 node 和 ffmpeg 将编程创建的视频流式传输到 youtube