当前位置:首页 > 科技 > 正文

用Golang搞定365一周年蛋糕视频的自动生成,我试了试这个思路

  • 科技
  • 2026-07-23 05:24:01
  • 58
摘要: 你可能刷到过那种“365天每天一张照片,最后拼成一周年蛋糕视频”的内容,看着挺感动,但自己动手做的时候——光选照片、排顺序、加字...

你可能刷到过那种“365天每天一张照片,最后拼成一周年蛋糕视频”的内容,看着挺感动,但自己动手做的时候——光选照片、排顺序、加字幕、卡点音乐,就能折腾一整天,我以前也觉得这是视频剪辑师的活,直到我试着用 Golang 写了个小工具,才发现这事儿其实能自动化。

为什么是Golang,不是Python或剪映?

你可能会想:“剪映一键生成不就好了?” 但如果你有几十个、上百个这样的视频要处理(比如帮朋友、帮社群做),或者你想定制一些奇怪的效果,

  • 每张照片上自动加上当天的日期
  • 根据照片亮度自动调整转场时长
  • 把蛋糕“从无到有”的生长过程用代码控制

这时候手动剪辑就太痛苦了,我选Golang是因为它编译后是个单文件,丢到服务器或者别人的Windows电脑上,不用装依赖,双击就能跑,这一点在给不懂编程的朋友用时,特别重要。

核心思路:用FFmpeg做“脏活”

这里要坦白一下——Golang本身不会处理视频,它更像一个“指挥官”,我们用 os/exec 包去调 FFmpeg,这个命令行工具几乎能处理一切视频相关的操作。

// 伪代码,只是说明思路
func buildVideo(images []string, outputPath string) {
    // 1. 先把所有图片拼成一个视频(每张停留0.5秒)
    // 2. 在视频中间某个时间点插入“一周年蛋糕”的特效片段
    // 3. 加上背景音乐
    // 4. 输出最终文件
}

你可能会觉得:“那我直接写个Shell脚本不就行了?” 是,但当你需要处理复杂的逻辑时——比如根据照片的EXIF信息决定顺序,或者从数据库里读取用户数据生成个性化文字——Shell就有点力不从心了。

具体怎么做?我拆成3步

第一步:整理素材

你需要一个目录,里面放着365张照片,命名最好是 2024-01-01.jpg 这种格式,Golang里用 filepath.Walk 就能读出来。

files, _ := filepath.Glob("photos/*.jpg")
sort.Strings(files) // 按文件名排序

第二步:生成“蛋糕生长”效果

这是最核心的部分,我想让视频前半段显示“蛋糕一点点变高”,最后一下子变成完整的生日蛋糕,做法是:

  1. 准备一个蛋糕的PNG序列(或者直接用一张蛋糕图,用代码缩放)
  2. 每帧让蛋糕高度增加几个像素
  3. 用FFmpeg的 scaleoverlay 滤镜合到背景上

下面是我尝试的粗糙代码片段:

cmd := exec.Command("ffmpeg",
    "-i", "background.mp4",           // 背景视频
    "-i", "cake.png",                 // 蛋糕图片
    "-filter_complex", 
    "[1:v]scale=300:ih*0.01*t[inner];[0:v][inner]overlay=100:200",
    "-t", "30",
    "output.mp4")

这里 ih*0.01*t 的意思是:高度随时间线性增长,跑完之后视频里蛋糕确实在“长高”,但效果比较生硬,后来我改成用 逐帧生成PNG,再用FFmpeg合成,看起来更自然。

第三步:卡点和字幕

把365张照片按“月份”分组,每个月显示一个小标题,用FFmpeg的 drawtext 滤镜。

比如这段代码在每个月的第一张照片上叠加“第X个月”:

for i, img := range images {
    month := extractMonth(img)
    if i == 0 || month != lastMonth {
        // 在这个图片对应的帧上加文字
        drawtextCmd := fmt.Sprintf("drawtext=text='%d月':x=100:y=100:fontsize=48", month)
    }
}

我踩过的坑

坑1:视频长度不对
365张照片,如果每张显示0.5秒,应该是182.5秒,但FFmpeg默认会把最后一帧延长,导致总时长多出几秒,解决办法是显式指定 -frames:v

坑2:内存爆炸
如果一次性把所有图片加载到内存里(比如用 image.Decode),365张高清图能吃掉2-3GB内存,后来改为只读取文件名列表,把图片路径传给FFmpeg,让FFmpeg自己去读。

坑3:音乐版权
视频里用了某首流行歌,结果上传到平台后被静音,后来改用 Audius 上的CC0音乐,或者用 beep 库自己生成简单的旋律。

完整代码结构(仅供参考)

其实不需要特别复杂的架构,我最终的目录结构长这样:

.
├── main.go          // 主程序
├── photos/          // 放365张照片
├── cake.png         // 蛋糕素材
├── music.mp3        // 背景音乐
└── output/          // 输出目录

main.go 大概200行,核心逻辑就是:

  1. 扫描照片 → 按日期排序
  2. 生成视频 → 用FFmpeg拼图片,同时叠加蛋糕生长动画
  3. 加音乐 → 把音频混入视频
  4. 输出 → 得到 365_anniversary.mp4

你要我贴完整代码吗?其实不太建议直接复制,因为每个人的照片尺寸、音乐时长、蛋糕样式都不一样。我更建议你理解思路后,自己调参数。

这么做的价值在哪?

说实话,用Golang做这个事,不是为了炫技,而是因为:

  • 可重复使用:明年再做一个,改个路径就能跑
  • 可定制:想在视频里加“每张照片的天气数据”?加个API调用就行
  • 可批处理:帮10个朋友做,改个CSV文件就搞定

我后来把工具打包成一个exe,发给了几个不懂编程的朋友,他们双击运行,选择照片文件夹,等几分钟就拿到了视频。有个朋友说,她看到视频里蛋糕一点点长出来,最后变成完整的生日蛋糕时,眼眶红了。

那一刻我觉得,技术有时候确实能帮人省下时间,去更专注地感受生活。

你要是也想试试,从安装FFmpeg开始,然后写个10行Golang代码让一张图片变成视频,剩下的,慢慢加。

用Golang搞定365一周年蛋糕视频的自动生成,我试了试这个思路