IT码农库

您当前所在位置:首页 > 脚本专栏 > Golang

Golang

Golang调用FFmpeg转换视频流的实现

[db:来源] 2023-02-24Golang6872
本文主要介绍了Golang调用FFmpeg转换视频流,文中通过示例代码介绍的非常具体,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

问题背景

问题背景是在,由于视频采集端使用的是H264编码采集的裸流,而网络流媒体大多是以FLV为主的直播方式入行的,为了实现实时直播,当前是打算直接使用FFmpeg将H264裸流实时转成FLV视频流。

为什么是使用FLV视频流呢,因为相对简朴,加上FLV Header后将每个NALU打包成Tag并入往大致就行了。但是这块怕有疏忽,最终还是想使用成熟的工具FFmpeg。

方法实现

1. 使用FFmpeg-go封装好的方法

FFmpeg-go

上面有详细的Demo,但是只有流转文件,也只有文件转流的方法,对于流转流还是需要自己动手处理一下。

import ffmpeg "github.com/u2takey/ffmpeg-go"
 
err := ffmpeg.Input("pipe:", ffmpeg.KwArgs{
        "format":     "rawvideo",
        "video_size": fmt.Sprintf("%dx%d", 480, 1064)}).WithInput(filein).
        Output("pipe:",
            ffmpeg.KwArgs{"c:v": "libx264", "f": "flv", "crf": "24"}).
        WithOutput(buf, errorbuf).
        Run()
if err != nil {
        panic(err)
}
bufs := make([]byte, 1024)
out, _ := os.OpenFile("res2.flv", os.O_CREATE|os.O_RDWR|os.O_APPEND, 0644)
for {
    n, err := buf.Read(bufs)
    if n == 0 || err == io.EOF {
        out.Close()
        break
    } else {
        //此处处理输出流,这边简朴地写到文件里
        out.Write(bufs)
    }
}

其中

filein   是输进的H264视频裸流   buf是输出的视频流
虽说代码是这么写,但是实际上是run不起来的,不清晰详细是什么原因,因此后续还是打算直接调用ffmpeg可执行程序。

2. 直接调用FFmpeg

首先需要在电脑上下载好ffmpeg并且添加到环境变量,保证执行Powshell或者cmd指令的ffmpeg时能够正常运行,接下来还是直接上代码。

cmd := exec.Command("ffmpeg", "-re", "-r", "30", "-i", "pipe:0", "-vcodec", "libx264", "-f", "flv", "pipe:1", "-y", "another.flv")
 
//获取输进流
stdin, err := cmd.StdinPipe()
if err != nil {
    fmt.Println("Error getting stdout pipe:", err)
    return
}
 
//要写东西入往的时候只需要
stdin.Write(bytes) 
 
//获取输出流
stdout, err := cmd.StdoutPipe()
if err != nil {
    fmt.Println("Error getting stdout pipe:", err)
    return
}
 
// Start the command
err = cmd.Start()
if err != nil {
    fmt.Println("Error starting command:", err)
    return
}

这边需要注重到的点是,假如不加上"-re"的话,需要等stdin.close()之后,整个ffmpeg才会运行,才能见到有输出流。

其次,这边加了 “-y” "another.flv",是用来入行对比的,这里ffmpeg将会把输出同时放在两个地方,一个写进到文件another.flv里(-y 是覆盖原有文件),另一个通过stdout传出来,我将stdout的数据流保存成out.flv后发现同another.flv对比发现并不相同。或许视频流和文件不应该这么处理。

总结

建议直接调用FFmpeg的可执行文件入行操作最好。

但是这样实时的流转流的方式实际上还是有挺大延迟的,假如要实时视频流P2P模式建议要么在采集端处理好要么在播放端处理好,中间层就不要过多操作影响实时性,假如是推流拉流的模式还是建议在中间层处理好。

存在问题
这边还是发现一些问题的,尤其是直接使用ffmpeg的时候

1. 直接读取文件和读取文件通过stdin传进byte获取到的结果是不一致的。

2. 直接output成文件和通过stdout获取byte再保存成文件得到的结果也是不一致的。

到此这篇关于Golang调用FFmpeg转换视频流的实现的文章就介绍到这了,更多相关Golang FFmpeg转换视频流内容请搜索以前的文章或继承浏览下面的相关文章希望大家以后多多支持!

大图广告(830*140)