cgo+ffmpeg+windows的简单使用


cgo+ffmpeg+windows的简单使用

最近想试试用go来直接调用ffmpeg是什么效果,但是第一步编译就花费了一点时间,这里记录一下这个过程。


环境配置

首先需要有c的编译环境,这个直接去安装一个64位的MinGW就可以了。

然后就是ffmpeg的编译环境配置,这个网上可以看到各个各样的说法,这里找了一个最简单明确的方法:

  1. 首先去ffmpeg官网下载一个dev版本的ffmpeg和一个share版本的ffmpeg。
  2. 将dev版本解压到某个路径下,例如这里解压到D:/ffmpeg/下面。这个路径下应该有D:/ffmpeg/libD:/ffmpeg/include
  3. 将share版本的bin文件夹解压到某个路径下,这里为了方便放在D:/ffmpeg/bin下面。

到这里其实就完成了配置,需要的其实就是ffmpeg的静态链接库动态链接库

  • D:/ffmpeg/include下面放的只是头文件。
  • D:/ffmpeg/lib就是静态链接库,但是里面没有代码,起的链接作用,可以帮助完成编译。
  • D:/ffmpeg/bin下面的dll文件则是动态链接库,是代码真正的所在,运行程序必需要有,但是编译时则不需要。

所以在编译代码时,需要指定includelib的位置,需要在go的代码中指定;在运行代码时,要在运行环境中能够找到相关的dll文件,则需要在windows环境变量中配置。


在cgo的代码的头部注释中加入:

1
2
3
4
5
6
/*
#cgo CFLAGS: -ID:/ffmpeg/include
#cgo LDFLAGS: -LD:/ffmpeg/lib/ -llibavformat -llibavcodec -llibavutil -llibavdevice -llibavfilter -llibswresample -llibswscale
*/
import "C"

其中的D:/ffmpeg/includeD:/ffmpeg/lib/就指定了头文件和静态链接库的位置。

然后需要在系统环境变量的path中加入:

1
D:/ffmpeg/bin

这样就完成了编译+运行的环境配置。


简单代码测试

这里使用goland来编译运行代码,如下图:

image

这里代码都放在了333这个目录。

其中main.go内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
package main
//
// 引用的C头文件需要在注释中声明,紧接着注释需要有import "C",且这一行和注释之间不能有空格
//
/*
#cgo CFLAGS: -ID:/ffmpeg/include
#cgo LDFLAGS: -LD:/ffmpeg/lib/ -llibavformat -llibavcodec -llibavutil -llibavdevice -llibavfilter -llibswresample -llibswscale
#include <stdlib.h>
#include "FTest.h"
*/
import "C"
import (
"fmt"
"os"
"time"
"unsafe"
)
func main() {
if len(os.Args) != 3 {
fmt.Printf("please use like this: \n$ %s <inputUrl> <outputUrl>\n", os.Args[0])
return
}
//使用C.CString创建的字符串需要手动释放。
inputUrl := "rtmp://xxx.cn/xxx/xxx"
outputUrl1 := "aaa"
outputUrl2 := "bbb"
go SnapShotGo(inputUrl, outputUrl1)
go SnapShotGo(inputUrl, outputUrl2)
time.Sleep(time.Second*60)
}
func SnapShotGo(inputUrl, outputUrl string) int {
//使用C.CString创建的字符串需要手动释放。
inputUrlC := C.CString(inputUrl)
outputUrlC := C.CString(outputUrl)
defer C.free(unsafe.Pointer(inputUrlC))
defer C.free(unsafe.Pointer(outputUrlC))
fmt.Println("1")
ret := C.SnapShotRun(inputUrlC, outputUrlC)
fmt.Println("ret = ", ret)
return 0
}

这是一个简单的测试程序,通过调用c的SnapShotRun函数来对rtmp直播流进行截图,并且同一时间运行了两个go程。

使用目录的方式进行编译运行:

image

成功运行代码:

image


但是这里有一个小问题,c代码中的打印在goland中不能实时显示,只有在结束程序的时候才会一瞬间全部打印出来,但是如果把编译得到可执行程序放到cmd执行就不会出现这个问题。


参考

golang直接调用ffmpeg预编译类库(windows)的配置方法

golang cgo 开发小结

golang cgo 使用总结

---------------------------------END---------------------------------