chore(project): 添加MIT许可证文件 向项目中添加完整的MIT许可证文本,明确版权归属和使用条款, 为goffmpeg项目提供法律保护和开源许可说明。 ``` |
||
|---|---|---|
| cmd/ffmpeg-cli | ||
| examples | ||
| pkg/ffmpeg | ||
| .gitignore | ||
| CLAUDE.md | ||
| LICENSE | ||
| README.md | ||
| go.mod | ||
README.md
goffmpeg
Go bindings for FFmpeg using CGO.
项目简介
本项目提供 Go 语言对 FFmpeg 动态库的 CGO 绑定,以 lib 库形式开放接口供其他应用调用。
系统依赖
FFmpeg 开发库
Ubuntu/Debian:
sudo apt install libavcodec-dev libavformat-dev libavutil-dev libavfilter-dev libswscale-dev libswresample-dev pkg-config
验证安装:
pkg-config --exists libavcodec libavformat libavutil
echo $? # 应输出 0
项目结构
goffmpeg/
├── pkg/ffmpeg/ # 核心库
│ ├── cgo.go # CGO 配置和头文件导入
│ ├── errors.go # 错误类型定义
│ ├── ffmpeg.go # FormatContext、Stream、CodecParameters
│ ├── codec.go # 编解码器封装
│ ├── frame.go # 帧数据封装
│ └── packet.go # 数据包封装
├── cmd/ffmpeg-cli/ # CLI 工具
├── examples/ # 示例代码
│ └── simple-transcode/ # 简单转码示例
└── README.md
构建
go build ./...
示例用法
简单转码 (流拷贝模式)
package main
import (
"fmt"
"log"
"os"
"git.kingecg.top/kingecg/goffmpeg/pkg/ffmpeg"
)
func main() {
inputURL := "input.mp4"
outputURL := "output.mp4"
// 打开输入文件
ic := ffmpeg.AllocFormatContext()
defer ic.Free()
if err := ic.OpenInput(inputURL); err != nil {
log.Fatalf("Failed to open input: %v", err)
}
defer ic.Close()
// 查找流信息
if err := ic.FindStreamInfo(); err != nil {
log.Fatalf("Failed to find stream info: %v", err)
}
// 打印输入格式信息
fmt.Printf("Input: %s\n", inputURL)
ic.DumpFormat(0, inputURL, false)
// 猜测输出格式
of := ffmpeg.GuessFormat("", outputURL)
if of == nil {
log.Fatal("Failed to guess output format")
}
// 创建输出上下文
ofc, err := ffmpeg.AllocOutputContext(outputURL, of)
if err != nil {
log.Fatalf("Failed to allocate output context: %v", err)
}
defer ofc.Free()
// 获取输入流
inputStreams := ic.Streams()
// 处理流
for i, is := range inputStreams {
cp := is.CodecParameters()
if cp == nil {
continue
}
// 只处理视频和音频
if cp.CodecType() != ffmpeg.CodecTypeVideo &&
cp.CodecType() != ffmpeg.CodecTypeAudio {
continue
}
// 添加输出流 (流拷贝模式)
os, err := ofc.AddStream(nil)
if err != nil {
continue
}
// 复制编解码参数
os.SetCodecParameters(cp)
os.SetTimeBase(is.TimeBase())
fmt.Printf("Stream %d: type=%d\n", i, cp.CodecType())
}
// 打开输出文件
if err := ofc.OpenOutput(outputURL); err != nil {
log.Fatalf("Failed to open output: %v", err)
}
// 写入头部
if err := ofc.WriteHeader(); err != nil {
log.Fatalf("Failed to write header: %v", err)
}
// 转封装循环
pkt := ffmpeg.AllocPacket()
defer pkt.Free()
for {
err := ic.ReadPacket(pkt)
if err != nil {
break
}
ofc.WritePacket(pkt)
pkt.Unref()
}
// 写入尾部
ofc.WriteTrailer()
fmt.Printf("Remuxing complete! Output saved to: %s\n", outputURL)
}
API 概览
FormatContext
AllocFormatContext()- 分配格式上下文OpenInput(url)- 打开输入FindStreamInfo()- 查找流信息Streams()- 获取所有流VideoStreams()- 获取视频流AudioStreams()- 获取音频流ReadPacket()/WritePacket()- 读写数据包
OutputFormatContext
AllocOutputContext(url, format)- 分配输出上下文AddStream(codec)- 添加流OpenOutput(url)- 打开输出文件WriteHeader()/WriteTrailer()- 写入头部/尾部
Stream
CodecParameters()- 获取编解码参数SetCodecParameters(cp)- 设置编解码参数TimeBase()/SetTimeBase(r)- 时间基
CodecParameters
CodecType()- 编解码器类型CodecID()- 编解码器 IDWidth()/Height()- 尺寸Format()- 格式SampleRate()- 采样率Channels()- 声道数
Context (编解码器上下文)
AllocContext()- 分配上下文SetCodec(codec)- 设置编解码器Open(codec)- 打开编解码器SendPacket()/ReceiveFrame()- 解码SendFrame()/ReceivePacket()- 编码
Packet
AllocPacket()- 分配数据包Data()/Size()- 数据和大小PTS()/DTS()- 时间戳StreamIndex()- 流索引
Frame
AllocFrame()- 分配帧Width()/Height()- 尺寸Format()- 格式NbSamples()- 样本数
注意事项
- CGO 构建标签: 项目使用
//go:build cgo约束,需要 CGO 支持才能构建 - FFmpeg 版本: 需要 FFmpeg 4.0+
- 线程安全: FFmpeg 的某些操作不是线程安全的,请参考 FFmpeg 文档
- 内存管理: 使用
Free()方法释放资源,或使用defer
许可证
MIT License