将原始 [] 字节视频管道到 Go



我有一个直接来自 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.0q=0.0 Lsize= 0kB 时间=-577014:32:22.77 比特率= -0.0kbits/s 速度=N/A 视频:0kB 音频:0kB 字幕:0kB 其他流:0kB 全局标头:0kB 头顶沐星:未知

输出文件为空,未编码任何内容(如果使用,请检查 -ss/-t/-frame 参数)

我需要视频

的单帧并将其转换为 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,但为您删除了抽象。

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

最新更新