如何基于ffmpeg-go为AWS S3的字节数组格式音视频图片加水印
使用ffmpeg-go为字节数组格式的图片/视频添加水印(无磁盘落地)
我尝试使用ffmpeg-go为存储在AWS S3上的图片和视频添加水印,文件以字节数组([]byte)形式存在,要求输入和输出均为字节数组,不落地到磁盘。但我写的代码未能成功运行:
buffFile := bytes.NewBuffer(file) out := &bytes.Buffer{} overlay := ffmpeg.Input("pipe:", ffmpeg.KwArgs{}).Filter("scale", ffmpeg.Args{"64:-1"}).WithInput(buffWatermark) err = ffmpeg.Filter( []*ffmpeg.Stream{ ffmpeg.Input("pipe:", ffmpeg.KwArgs{}).WithInput(buffFile), overlay, }, "overlay", ffmpeg.Args{"10:10"}, ffmpeg.KwArgs{"enable": "gte(t,1)"}). Output("pipe:", ffmpeg.KwArgs{}).WithOutput(out).OverWriteOutput().ErrorToStdOut().Run()
问题分析
原代码存在几个核心问题:
- 水印输入的关联逻辑错误,未明确指定输入格式导致ffmpeg无法识别字节流类型
- 多管道输入未区分类型,ffmpeg无法正确解析多个
pipe:输入的顺序和格式 - 输出未指定容器/编码参数,ffmpeg无法生成合法的字节流
- 视频的
enable时间参数对图片无效,未区分图片/视频场景
修正后的代码
1. 图片加水印(字节数组输入输出)
import ( "bytes" "github.com/u2takey/ffmpeg-go" ) func AddWatermarkToImage(mainImage []byte, watermark []byte) ([]byte, error) { mainBuff := bytes.NewBuffer(mainImage) watermarkBuff := bytes.NewBuffer(watermark) outBuff := &bytes.Buffer{} // 明确指定图片管道输入格式,避免ffmpeg自动识别失败 mainInput := ffmpeg.Input("pipe:", ffmpeg.KwArgs{"format": "image2pipe"}).WithInput(mainBuff) watermarkInput := ffmpeg.Input("pipe:", ffmpeg.KwArgs{"format": "image2pipe"}).Filter("scale", ffmpeg.Args{"64:-1"}).WithInput(watermarkBuff) // 图片无时间轴,无需enable参数 err := ffmpeg.Filter( []*ffmpeg.Stream{mainInput, watermarkInput}, "overlay", ffmpeg.Args{"10:10"}, // 水印左上角坐标:x=10,y=10 ). Output("pipe:", ffmpeg.KwArgs{"format": "image2pipe", "vcodec": "png"}). // 指定输出格式为PNG(可按需调整为jpeg等) WithOutput(outBuff). OverWriteOutput(). ErrorToStdOut(). Run() if err != nil { return nil, err } return outBuff.Bytes(), nil }
2. 视频加水印(字节数组输入输出)
func AddWatermarkToVideo(mainVideo []byte, watermark []byte) ([]byte, error) { mainBuff := bytes.NewBuffer(mainVideo) watermarkBuff := bytes.NewBuffer(watermark) outBuff := &bytes.Buffer{} mainInput := ffmpeg.Input("pipe:", ffmpeg.KwArgs{}).WithInput(mainBuff) watermarkInput := ffmpeg.Input("pipe:", ffmpeg.KwArgs{"format": "image2pipe"}).Filter("scale", ffmpeg.Args{"64:-1"}).WithInput(watermarkBuff) // 视频添加水印,控制从第1秒开始显示 err := ffmpeg.Filter( []*ffmpeg.Stream{mainInput, watermarkInput}, "overlay", ffmpeg.Args{"10:10"}, ffmpeg.KwArgs{"enable": "gte(t,1)"}, ). Output("pipe:", ffmpeg.KwArgs{"format": "matroska", "vcodec": "libx264", "acodec": "aac"}). // 使用matroska容器兼容主流编码 WithOutput(outBuff). OverWriteOutput(). ErrorToStdOut(). Run() if err != nil { return nil, err } return outBuff.Bytes(), nil }
关键注意事项
- 指定输入输出格式:管道输入必须通过
format参数明确类型,否则ffmpeg无法解析字节流 - 区分场景逻辑:图片无需时间轴参数,视频需指定合法的容器和编码格式
- 错误排查:若仍失败,可移除
ErrorToStdOut()查看原始ffmpeg错误日志,或添加LogLevel("debug")获取详细调试信息
内容的提问来源于stack exchange,提问作者Josivan
相关产品推荐
相关产品推荐

