golang FFmpeg全面绑定与多媒体处理插件库goav的使用
Golang FFmpeg全面绑定与多媒体处理插件库goav的使用
废弃通知
该仓库已不再维护。
goav简介
goav是一个针对FFmpeg的Golang绑定库,提供了对ffmpeg视频/音频处理库的全面绑定。
基本用法
import "github.com/giorgisio/goav/avformat"
func main() {
filename := "sample.mp4"
// 注册所有格式和编解码器
avformat.AvRegisterAll()
ctx := avformat.AvformatAllocContext()
// 打开视频文件
if avformat.AvformatOpenInput(&ctx, filename, nil, nil) != 0 {
log.Println("Error: Couldn't open file.")
return
}
// 获取流信息
if ctx.AvformatFindStreamInfo(nil) < 0 {
log.Println("Error: Couldn't find stream information.")
// 关闭输入文件并释放上下文
ctx.AvformatCloseInput()
return
}
//...
}
支持的库
avcodec
对应FFmpeg库: libavcodec [提供更广泛的编解码器实现]avformat
对应FFmpeg库: libavformat [实现流协议、容器格式和基本I/O访问]avutil
对应FFmpeg库: libavutil [包含哈希器、解压缩器和各种实用函数]avfilter
对应FFmpeg库: libavfilter [提供通过过滤器链改变解码后的音频和视频的方法]avdevice
对应FFmpeg库: libavdevice [提供访问捕获和播放设备的抽象]swresample
对应FFmpeg库: libswresample [实现音频混合和重采样例程]swscale
对应FFmpeg库: libswscale [实现颜色转换和缩放例程]
安装方法
首先安装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
然后安装goav库:
go get github.com/giorgisio/goav
更多示例
更多编码示例可在examples/目录中找到。
注意事项
- Go中的函数名称与库中的函数名称保持一致,便于搜索
- goav不提供任何形式的保证
贡献指南
- 分叉此仓库并创建您自己的功能分支
- 遵循标准的Go惯例
- 测试您的代码
- 创建拉取请求
待办事项
- 错误返回处理
- 垃圾回收
- 更多教程
- Go测试
- 可能的包重构
许可证
该库使用MIT许可证
更多关于golang FFmpeg全面绑定与多媒体处理插件库goav的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html
1 回复
更多关于golang FFmpeg全面绑定与多媒体处理插件库goav的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
GoAV: Golang的FFmpeg全面绑定与多媒体处理
GoAV是一个强大的Golang绑定库,它提供了对FFmpeg多媒体处理功能的全面访问。下面我将详细介绍GoAV的使用方法,并提供实用的代码示例。
GoAV简介
GoAV(goav)是FFmpeg的Golang绑定,允许开发者在Go程序中直接调用FFmpeg的功能进行音视频处理。它比直接调用FFmpeg命令行工具更灵活高效。
安装准备
首先需要安装FFmpeg开发库:
# Ubuntu/Debian
sudo apt-get install libavformat-dev libavcodec-dev libavutil-dev libavdevice-dev libavfilter-dev libswscale-dev libswresample-dev
# macOS
brew install ffmpeg
然后安装GoAV:
go get github.com/giorgisio/goav
基础使用示例
1. 获取视频文件信息
package main
import (
"fmt"
"github.com/giorgisio/goav/avformat"
)
func main() {
// 注册所有编解码器和格式
avformat.AvRegisterAll()
// 打开输入文件
ctx := avformat.AvformatAllocContext()
if avformat.AvformatOpenInput(&ctx, "input.mp4", nil, nil) != 0 {
fmt.Println("无法打开文件")
return
}
defer ctx.AvformatCloseInput()
// 获取流信息
if ctx.AvformatFindStreamInfo(nil) < 0 {
fmt.Println("无法获取流信息")
return
}
// 打印文件信息
fmt.Printf("格式: %s, 时长: %d秒\n", ctx.iformat().Name(), ctx.Duration()/avformat.AV_TIME_BASE)
// 遍历所有流
for i := 0; i < int(ctx.NbStreams()); i++ {
stream := ctx.Streams()[i]
codec := stream.CodecParameters()
fmt.Printf("流 #%d: 类型 %s, 编码 %s\n",
i,
avGetMediaTypeString(codec.AvCodecGetType()),
avcodec.AvcodecGetName(codec.AvCodecGetId()))
}
}
func avGetMediaTypeString(t avformat.AvMediaType) string {
switch t {
case avformat.AVMEDIA_TYPE_VIDEO:
return "视频"
case avformat.AVMEDIA_TYPE_AUDIO:
return "音频"
default:
return "其他"
}
}
2. 视频转码示例
package main
import (
"fmt"
"github.com/giorgisio/goav/avcodec"
"github.com/giorgisio/goav/avformat"
"github.com/giorgisio/goav/avutil"
"github.com/giorgisio/goav/swscale"
)
func main() {
// 初始化
avformat.AvRegisterAll()
avcodec.AvcodecRegisterAll()
// 打开输入文件
inputCtx := avformat.AvformatAllocContext()
if avformat.AvformatOpenInput(&inputCtx, "input.mp4", nil, nil) != 0 {
fmt.Println("无法打开输入文件")
return
}
defer inputCtx.AvformatCloseInput()
// 创建输出文件
outputCtx := avformat.AvformatAllocContext()
if avformat.AvformatAllocOutputContext2(&outputCtx, nil, "mp4", "output.mp4") < 0 {
fmt.Println("无法创建输出文件")
return
}
defer outputCtx.AvformatFreeContext()
// 查找视频流
videoStreamIndex := -1
for i := 0; i < int(inputCtx.NbStreams()); i++ {
stream := inputCtx.Streams()[i]
if stream.CodecParameters().AvCodecGetType() == avformat.AVMEDIA_TYPE_VIDEO {
videoStreamIndex = i
break
}
}
if videoStreamIndex == -1 {
fmt.Println("未找到视频流")
return
}
// 配置输出流
outStream := outputCtx.AvformatNewStream(nil)
if outStream == nil {
fmt.Println("无法创建输出流")
return
}
// 复制编解码器参数
if avcodec.AvcodecParametersCopy(outStream.CodecParameters(),
inputCtx.Streams()[videoStreamIndex].CodecParameters()) < 0 {
fmt.Println("无法复制编解码器参数")
return
}
// 打开输出文件
if outputCtx.AvioOpen("output.mp4", avformat.AVIO_FLAG_WRITE) < 0 {
fmt.Println("无法打开输出文件")
return
}
// 写入文件头
if outputCtx.AvformatWriteHeader(nil) < 0 {
fmt.Println("无法写入文件头")
return
}
// 转码处理
packet := avcodec.AvPacketAlloc()
for inputCtx.AvReadFrame(packet) >= 0 {
if packet.StreamIndex() == videoStreamIndex {
packet.SetStreamIndex(outStream.Index())
outputCtx.AvInterleavedWriteFrame(packet)
}
avcodec.AvPacketUnref(packet)
}
// 写入文件尾
outputCtx.AvWriteTrailer()
fmt.Println("转码完成")
}
3. 视频帧处理
package main
import (
"fmt"
"image/jpeg"
"os"
"github.com/giorgisio/goav/avcodec"
"github.com/giorgisio/goav/avformat"
"github.com/giorgisio/goav/avutil"
"github.com/giorgisio/goav/swscale"
)
func main() {
avformat.AvRegisterAll()
avcodec.AvcodecRegisterAll()
// 打开视频文件
ctx := avformat.AvformatAllocContext()
if avformat.AvformatOpenInput(&ctx, "input.mp4", nil, nil) != 0 {
fmt.Println("无法打开文件")
return
}
defer ctx.AvformatCloseInput()
// 查找视频流
videoStreamIndex := -1
var codecCtx *avcodec.Context
for i := 0; i < int(ctx.NbStreams()); i++ {
stream := ctx.Streams()[i]
if stream.CodecParameters().AvCodecGetType() == avformat.AVMEDIA_TYPE_VIDEO {
videoStreamIndex = i
// 获取解码器
codec := avcodec.AvcodecFindDecoder(stream.CodecParameters().AvCodecGetId())
if codec == nil {
fmt.Println("找不到解码器")
return
}
// 创建解码器上下文
codecCtx = avcodec.AvcodecAllocContext3(codec)
if avcodec.AvcodecParametersToContext(codecCtx, stream.CodecParameters()) < 0 {
fmt.Println("无法复制编解码器参数")
return
}
// 打开解码器
if avcodec.AvcodecOpen2(codecCtx, codec, nil) < 0 {
fmt.Println("无法打开解码器")
return
}
break
}
}
if videoStreamIndex == -1 {
fmt.Println("未找到视频流")
return
}
// 准备帧和包
frame := avutil.AvFrameAlloc()
rgbFrame := avutil.AvFrameAlloc()
packet := avcodec.AvPacketAlloc()
// 创建图像转换上下文
swsCtx := swscale.SwsGetContext(
codecCtx.Width(), codecCtx.Height(), codecCtx.PixFmt(),
codecCtx.Width(), codecCtx.Height(), avutil.AV_PIX_FMT_RGB24,
swscale.SWS_BILINEAR, nil, nil, nil)
// 分配RGB帧缓冲区
avutil.AvImageAlloc(
rgbFrame.Data(), rgbFrame.Linesize(),
codecCtx.Width(), codecCtx.Height(), avutil.AV_PIX_FMT_RGB24, 1)
// 读取并解码帧
frameCount := 0
for ctx.AvReadFrame(packet) >= 0 {
if packet.StreamIndex() == videoStreamIndex {
// 发送包到解码器
if avcodec.AvcodecSendPacket(codecCtx, packet) < 0 {
continue
}
// 接收解码后的帧
for avcodec.AvcodecReceiveFrame(codecCtx, frame) >= 0 {
// 转换帧格式为RGB
swscale.SwsScale(swsCtx, frame.Data(), frame.Linesize(),
0, codecCtx.Height(), rgbFrame.Data(), rgbFrame.Linesize())
// 保存为JPEG
saveAsJPEG(rgbFrame, codecCtx.Width(), codecCtx.Height(), fmt.Sprintf("frame%d.jpg", frameCount))
frameCount++
}
}
avcodec.AvPacketUnref(packet)
}
fmt.Printf("提取了%d帧\n", frameCount)
}
func saveAsJPEG(frame *avutil.Frame, width, height int, filename string) {
file, err := os.Create(filename)
if err != nil {
return
}
defer file.Close()
img := &image.RGBA{
Pix: frame.Data()[0],
Stride: frame.Linesize()[0],
Rect: image.Rect(0, 0, width, height),
}
jpeg.Encode(file, img, &jpeg.Options{Quality: 90})
}
高级功能
1. 视频滤镜处理
// 初始化滤镜图
filterGraph := avfilter.AvfilterGraphAlloc()
src := filterGraph.AvfilterGraphAllocFilter("buffer", "in")
sink := filterGraph.AvfilterGraphAllocFilter("buffersink", "out")
// 配置输入参数
args := fmt.Sprintf("video_size=%dx%d:pix_fmt=%d:time_base=%d/%d",
width, height, pixFmt, timeBaseNum, timeBaseDen)
filterGraph.AvfilterGraphParsePtr("scale=w=640:h=480", &inputs, &outputs, nil)
// 处理帧
avfilter.AvBuffersrcAddFrame(srcCtx, frame)
avfilter.AvBuffersinkGetFrame(sinkCtx, filteredFrame)
2. 音频处理
// 重采样
swrCtx := swresample.SwrAllocSetOpts(
int64(outLayout), outFormat, outRate,
int64(inLayout), inFormat, inRate,
0, nil)
swresample.SwrInit(swrCtx)
swresample.SwrConvert(swrCtx, outData, outCount, inData, inCount)
性能优化建议
- 使用硬件加速解码/编码
- 批量处理帧减少内存分配
- 合理设置缓冲区大小
- 多线程处理不同流
- 复用解码器/编码器上下文
总结
GoAV提供了对FFmpeg功能的全面访问,使得在Go中进行多媒体处理变得简单高效。通过上述示例,你可以实现视频信息获取、转码、帧处理等常见功能。对于更复杂的需求,可以进一步探索FFmpeg的滤镜系统、硬件加速等高级特性。
注意:实际使用时需要根据具体需求调整代码,并添加适当的错误处理。