gpt4 book ai didi

Golang 和 ffmpeg 实时流输入/输出

转载 作者:IT王子 更新时间:2023-10-29 02:03:16 24 4
gpt4 key购买 nike

我是 Go 的新手!

我正在做一个简单的测试,即从 ffmpeg 读取输出并写入文件。

我知道我可以用不同的方式做到这一点,只需转换,但这是一个项目的开始,我想稍后操作读取的字节,更改它们,然后将它们发送到输出。输入将是 UDP,输出也将是 UDP,也就是说,我将获得 ffmpeg 输出,我将按我希望的方式处理字节,然后将这些字节作为输入扔到另一个 ffmpeg 进程中,输出是 UDP 作为好吧。

通过这个简单的测试,文件的结果没有在 VLC 中运行,我相信我在输出文件中正确写入字节,但输出文件总是比输入文件小 1MB。

我需要一些帮助来阐明编写我正在做的这个测试的最佳方法是什么,基于此我可以离开这个地方。我不知道它是否完全错误,但我的印象是它是错误的。

输入文件是 4K 视频,h264,我相信输出应该是一样的,因为在这个简单的测试中,我只是简单地读取 cmd 写入文件的内容。

按照代码进行分析:

package main

import (
"os/exec"
"os"
)

func verificaErro(e error) {
if e != nil {
panic(e)
}
}

func main() {
dir, _ := os.Getwd()

cmdName := "ffmpeg"
args := []string{
"-hide_banner",
"-re",
"-i",
dir + "\\teste-4k.mp4",
"-preset",
"superfast",
"-c:v",
"h264",
"-crf",
"0",
"-c",
"copy",
"-f", "rawvideo", "-",
}
cmd := exec.Command(cmdName, args...)

stdout, err := cmd.StdoutPipe()
verificaErro(err)
err2 := cmd.Start()
verificaErro(err2)

fileOutput := dir + "/out.raw"
var _, err3 = os.Stat(fileOutput)

if os.IsNotExist(err3) {
var file, err = os.Create(fileOutput)
verificaErro(err)
defer file.Close()
}

f, err4 := os.OpenFile(dir+"/out.raw", os.O_RDWR|os.O_APPEND, 0666)

verificaErro(err4)

bytes := make([]byte, 1024)
for {
_, err5 := stdout.Read(bytes)
if err5 != nil {
continue
}
if len(bytes) > 0 {
_, err6 := f.Write(bytes)
verificaErro(err6)
} else {
break
}
}

f.Close()
}

最佳答案

您必须检查 stdout.Read 的返回值。请注意,读取的字节数 (nr) 可能小于缓冲区大小,因此您需要重新分片缓冲区以获得有效内容。修改阅读循环如下:

chunk := make([]byte, 40*1024)
for {
nr, err5 := stdout.Read(chunk)
fmt.Printf("Read %d bytes\n", nr)

//do something with the data
//e.g. write to file
if nr > 0 {
validData := chunk[:nr]
nw, err6 := f.Write(validData)
fmt.Printf("Write %d bytes\n", nw)
verificaErro(err6)
}

if err5 != nil {
//Reach end of file (stream), exit from loop
if err5 == io.EOF {
break
}
fmt.Printf("Error = %v\n", err5)
continue
}
}

if err := cmd.Wait(); err != nil {
fmt.Printf("Wait command error: %v\n", err)
}

另一种解决方案是利用 io.Copy 将整个输出复制到 golang 缓冲区中。代码片段如下所示:

var buf bytes.Buffer

n, err := io.Copy(&buf, stdout)
verificaErro(err)
fmt.Printf("Copied %d bytes\n", n)

err = cmd.Wait()
fmt.Printf("Wait error %v\n", err)

//do something with the data
data := buf.Bytes()
f, err4 := os.OpenFile(dir+"/out.raw", os.O_RDWR|os.O_APPEND, 0666)
verificaErro(err4)
defer f.Close()
nw, err := f.Write(data)
f.Sync()
fmt.Printf("Write size %d bytes\n", nw)

关于Golang 和 ffmpeg 实时流输入/输出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43601846/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com