You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何基于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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 00:02:50