青训营笔记 视频截图的处理

197 阅读3分钟

这是我参与「第五届青训营 」伴学笔记创作活动的第 16 天

今天分享的是关于go语言视频截图的技术,通过在各种搜索引擎中搜寻资料,在golang中对视频截图大致有三个个方向可以选择,第一个是调用外部工具ffmpeg,第二个是安装opencv环境调用gocvku进行视频抽帧,第三个是通过操控其他语言进行视频截图然后将结果返回。上述三种办法我都尝试过,分享一下我的踩坑经验。

首先是ffmpeg最开始是使用了ffmpeg的golang绑定包goav,将代码写好之后进行测试时会弹出缺少相关依赖包的错误,在VMware安装完ffmpeg之后问题还是没有解决,上网查了一下,需要将ffmpeg里的相关的包都安装到系统中然后改变环境变量

sudo apt-get -y install autoconf automake build-essential libass-dev libfreetype6-dev libsdl1.2-dev libtheora-dev libtool libva-dev libvdpau-dev libvorbis-dev libxcb1-dev libxcb-shm0-dev libxcb-xfixes0-dev pkg-config texi2html zlib1g-dev

sudo apt install -y libavdevice-dev libavfilter-dev libswscale-dev libavcodec-dev libavformat-dev libswresample-dev libavutil-dev

sudo apt-get install yasm

export FFMPEG_ROOT=$HOME/ffmpeg
export CGO_LDFLAGS="-L$FFMPEG_ROOT/lib/ -lavcodec -lavformat -lavutil -lswscale -lswresample -lavdevice -lavfilter"
export CGO_CFLAGS="-I$FFMPEG_ROOT/include"
export LD_LIBRARY_PATH=$HOME/ffmpeg/lib

不过对ffmpeg的了解并不多,所以不知道直接转换为jpg格式的方法,又写了一个工具函数,测试,成功。不过真的挺麻烦的。

第二个进行尝试的是gocv包,这是opencv的golang绑定库,但是使用前需要安装opencv环境,根据官网提示我在centos7和windows10的环境中双管齐下,安装opencv,第一个遇到的问题是cmake,windows中之前写过cgo所以不用下载,我就直接去安装centos的cmake了,一开始图方便直接使用yum安装,但是非常遗憾在编译opencv库的时候提示需要3.15以上版本的cmake才行,所以又在网上找了下资源下载了3.16.8版本的cmake,然后加入环境变量,重新开始编译opencv库,最后还是失败了,具体原因忘记了,反正查了半天都没有解决,stack Overflow上也找不到,最终不得已放弃安装,windows也是一样的。

然后我就开始尝试第三种方式,通过操纵python进行截图然后保存,在python中使用anaconda安装opencv还是非常简单方便地,减去了痛苦的编译过程,然后查了下golang操作python3的包,看了看觉得很复杂,直接放弃(毕竟放弃goav就是因为复杂),然后我就把写好的截图python程序进行了打包,生成exe文件,在golang中使用os/exec这个库就可以直接操作exe文件,然后在python中不能用input接收命令,因为input无法在子进程中执行,所以用system.arg就行了,执行结果挺顺利的,也没有任何报错。(这时我还不知道exec.Command这个函数有多少坑我没有踩)不过有两个个非常严重的问题,第一个是这个exe文件包含了opencv库有200多M,git限制了上传大小,传不上去。第二个问题是我在go test中测试这个函数的时候它的执行时间有十几秒,emmmm这是一个致命的问题。

所以直接放弃,最后还是用回了ffmpeg不过是直接调用命令去调用ffmpeg,一开始用的exec.Command这个函数执行命令,但是这个函数网上基本没有资料写了怎么操作windows的cmd,网上的方式试了个遍,全都失败了。(如果有大佬会的话可以教教吗5555)不得以最后用了cgo

//#include <stdlib.h>
//int startCmd(const char* cmd){
//   return system(cmd);
//}
import "C"

import (
   "errors"
   "strings"
   "unsafe"
)

var path = "C:\Users\violet\Desktop\bytedance\douyin-demo\public\"

func GetSnapshotCmd(videoname, imagename string) error {
   var build strings.Builder
   build.WriteString("ffmpeg -i ")
   build.WriteString(path)
   build.WriteString(videoname)
   build.WriteString(" -ss 0:0:1 -vframes 1 ")
   build.WriteString(path)
   build.WriteString(imagename)
   cmd := build.String()
   cCmd := C.CString(cmd)
   defer C.free(unsafe.Pointer(cCmd))
   status := C.startCmd(cCmd)
   if status != 0 {
      return errors.New("视频切截图失败")
   }
   return nil
}