Golang 使用 FFmpeg 转换视频文件
要在 Golang 中调用 FFmpeg,您需要使用 cgo(C 语言调用 Golang),并使用 FFmpeg 的 C API。
以下是一个简单的示例,它使用 FFmpeg 将一个视频文件转换为 GIF 文件:
- 安装 FFmpeg
首先,您需要安装 FFmpeg。在 Ubuntu 上,您可以使用以下命令安装:
sudo apt-get install ffmpeg
如果您使用其他操作系统,请参考 FFmpeg 官方文档进行安装。
- 创建一个 cgo 文件
在 Golang 项目中创建一个 cgo 文件(例如:ffmpeg.go),并在其中包含以下内容:
package main
/*
#cgo pkg-config: libavformat libavcodec libavutil
#include <libavformat/avformat.h>
#include <libavcodec/avcodec.h>
#include <libavutil/avutil.h>
#include <libswscale/swscale.h>
*/
import "C"
import (
"fmt"
"os"
)
func main() {
// 初始化 FFmpeg
C.av_register_all()
// 打开输入文件
inputFileName := C.CString('input.mp4')
defer C.free(unsafe.Pointer(inputFileName))
var inputFormatContext *C.AVFormatContext
if C.avformat_open_input(&inputFormatContext, inputFileName, nil, nil) != 0 {
fmt.Println("Could not open input file")
os.Exit(1)
}
// 查找流信息
if C.avformat_find_stream_info(inputFormatContext, nil) < 0 {
fmt.Println("Could not find stream information")
os.Exit(1)
}
// 查找视频流
var videoStreamIndex C.int = -1
for i := 0; i < int(inputFormatContext.nb_streams); i++ {
if inputFormatContext.streams[i].codec.codec_type == C.AVMEDIA_TYPE_VIDEO {
videoStreamIndex = C.int(i)
break
}
}
if videoStreamIndex == -1 {
fmt.Println("Could not find video stream")
os.Exit(1)
}
// 打开视频解码器
videoCodecContext := inputFormatContext.streams[videoStreamIndex].codec
videoCodec := C.avcodec_find_decoder(videoCodecContext.codec_id)
if videoCodec == nil {
fmt.Println("Could not find video decoder")
os.Exit(1)
}
if C.avcodec_open2(videoCodecContext, videoCodec, nil) < 0 {
fmt.Println("Could not open video decoder")
os.Exit(1)
}
// 分配帧和图像缓冲区
frame := C.av_frame_alloc()
if frame == nil {
fmt.Println("Could not allocate frame")
os.Exit(1)
}
defer C.av_frame_free(&frame)
buffer := C.av_malloc(C.avpicture_get_size(C.AV_PIX_FMT_RGB24, videoCodecContext.width, videoCodecContext.height))
defer C.av_free(unsafe.Pointer(buffer))
picture := (*C.AVPicture)(unsafe.Pointer(frame))
C.avpicture_fill(picture, (*C.uint8_t)(unsafe.Pointer(buffer)), C.AV_PIX_FMT_RGB24, videoCodecContext.width, videoCodecContext.height)
// 分配视频转换器
videoConverter := C.sws_getContext(
videoCodecContext.width, videoCodecContext.height, videoCodecContext.pix_fmt,
videoCodecContext.width, videoCodecContext.height, C.AV_PIX_FMT_RGB24,
C.SWS_BICUBIC, nil, nil, nil,
)
if videoConverter == nil {
fmt.Println("Could not allocate video converter")
os.Exit(1)
}
defer C.sws_freeContext(videoConverter)
// 读取帧并转换为 RGB
var packet C.AVPacket
for {
if C.av_read_frame(inputFormatContext, &packet) < 0 {
break
}
if packet.stream_index != videoStreamIndex {
C.av_packet_unref(&packet)
continue
}
if C.avcodec_send_packet(videoCodecContext, &packet) < 0 {
C.av_packet_unref(&packet)
continue
}
for {
if C.avcodec_receive_frame(videoCodecContext, frame) < 0 {
break
}
C.sws_scale(
videoConverter, (**C.uint8_t)(unsafe.Pointer(&frame.data)), frame.linesize,
0, videoCodecContext.height, (**C.uint8_t)(unsafe.Pointer(&picture.data)), picture.linesize,
)
// 在这里可以将 RGB 帧写入文件或进行其他处理
C.av_frame_unref(frame)
}
C.av_packet_unref(&packet)
}
// 清理
C.avcodec_close(videoCodecContext)
C.avformat_close_input(&inputFormatContext)
}
- 编译并运行
在 Golang 项目根目录下执行以下命令:
go build -o ffmpeg
./ffmpeg
上面的示例将读取名为“input.mp4”的视频文件,并将每一帧转换为 RGB 格式,您可以在此处添加代码来将 RGB 帧写入 GIF 文件或进行其他处理。
原文地址: https://www.cveoy.top/t/topic/nwah 著作权归作者所有。请勿转载和采集!