Go to file
kingecg 0aaff1b28f ```
chore(project): 添加MIT许可证文件

向项目中添加完整的MIT许可证文本,明确版权归属和使用条款,
为goffmpeg项目提供法律保护和开源许可说明。
```
2026-03-20 21:55:00 +08:00
cmd/ffmpeg-cli Initial FFmpeg CGO bindings library structure 2026-03-20 21:02:47 +08:00
examples Remove simple-transcode example binary 2026-03-20 21:49:56 +08:00
pkg/ffmpeg Add .gitignore, enhance build script output, and implement codec context methods 2026-03-20 21:48:53 +08:00
.gitignore Add .gitignore, enhance build script output, and implement codec context methods 2026-03-20 21:48:53 +08:00
CLAUDE.md first 2026-03-20 20:45:13 +08:00
LICENSE ``` 2026-03-20 21:55:00 +08:00
README.md ``` 2026-03-20 21:53:09 +08:00
go.mod Initial FFmpeg CGO bindings library structure 2026-03-20 21:02:47 +08:00

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() - 编解码器 ID
  • Width() / 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() - 样本数

注意事项

  1. CGO 构建标签: 项目使用 //go:build cgo 约束,需要 CGO 支持才能构建
  2. FFmpeg 版本: 需要 FFmpeg 4.0+
  3. 线程安全: FFmpeg 的某些操作不是线程安全的,请参考 FFmpeg 文档
  4. 内存管理: 使用 Free() 方法释放资源,或使用 defer

许可证

MIT License