用Go语言写一个365天祝福视频生成器,从零到一的全过程

为什么我要用Go写这个?上个月我妈生日,我翻了半天相册发现去年答应给她做的“每日祝福视频”才录了17天,那种愧疚感,你懂吧?我发誓要...

为什么我要用Go写这个?

上个月我妈生日,我翻了半天相册发现去年答应给她做的“每日祝福视频”才录了17天,那种愧疚感,你懂吧?我发誓要找个一劳永逸的办法——于是想到了写个程序,自动把一年的祝福视频片段拼起来。

选Go语言纯粹是因为它编译快、部署简单,而且我受不了Python打包时装依赖的破事,Go的ffmpeg绑定虽然不如Python的moviepy直观,但胜在稳定,跑一整天都不带崩的。

核心思路:把“一年”变成可计算的数据

一年有365天,每天对应一段祝福,这听上去像是个简单的循环,但真做起来全是坑:月份天数不一样、闰年怎么办、周末和节假日要不要特别处理?

我的方案是把“祝福内容”和“日期规则”解耦,先定义数据结构:

type DailyBlessing struct {
    DayOfYear int    // 第几天,1-365
    Date      string // 格式 "01-02"
    Message   string // 祝福内容
    VideoPath string // 生成的视频片段路径
}

然后分三步走:生成文案 → 渲染文字 → 视频合成

第一步:用Go生成365条不重样的祝福文案

别指望手写365条——那还不如自己录视频呢,我的技巧是模板+随机组合

var greetings = []string{
    "愿你今天笑容灿烂",
    "平凡日子也有光",
    "记得喝水,照顾好自己",
}
var closings = []string{
    "——来自远方的挂念",
    "——爱你的家人",
    "——那个总忘事的朋友",
}

然后用math/rand按日期做种子,保证同一天永远生成同样的“随机”组合,这样就算程序重启,只要日期不变,输出就不会变。

用Go语言写一个365天祝福视频生成器,从零到一的全过程

这里有个坑:Go的rand.Seed在1.20版本后不推荐用了,我查了文档,现在应该用rand.New(rand.NewSource(seed)),否则每次跑结果都不一样。

第二步:文字渲染成图片,要像真人写的

光有文字不够,视频需要画面,我用golang.org/x/image/font配合系统字体,把祝福文字画到一张1920x1080的JPEG上。

字体选择上,别用默认的宋体,太生硬,我推荐用思源黑体或楷体,至少看起来像人写的。

img := image.NewRGBA(image.Rect(0, 0, 1920, 1080))
// 画个渐变底色,免得全白太单调
drawGradient(img, dayOfYear) // dayOfYear决定颜色偏移
// 在中央写祝福语
drawText(img, message, fontFace, textColor)

说实话,调文字居中的代码我卡了半小时。font.MeasureString返回的是像素宽度,但字间距在中文里不稳定,最后我偷懒用了golang.org/x/image/measure包,才勉强对齐。

第三步:每天的视频片段拼接——ffmpeg调用

这里是我的主战场,Go标准库没有视频处理能力,我用os/exec调用系统ffmpeg,每生成一张图片,就转成3秒的视频片段:

cmd := exec.Command("ffmpeg", 
    "-loop", "1", 
    "-i", imgPath, 
    "-t", "3", 
    "-c:v", "libx264", 
    "-pix_fmt", "yuv420p", 
    fragmentPath)

注意-pix_fmt yuv420p必须加,不然生成的视频在手机上播放会花屏。

365个片段全拼起来,用concat协议最简单,我写了段脚本把文件列表写进一个txt,

ffmpeg -f concat -safe 0 -i list.txt -c copy final.mp4

手动跑过一次,生成的视频有18分钟长——刚好可以放一首歌的时间。

处理特殊情况:闰年、节假日、纪念日

写代码最容易忽略边缘情况,比如2024年是闰年,2月29日得算进去,我的数据里DayOfYear范围是1-366,但祝福内容按365天循环——额外那天我用了一条单独的分支:

if isLeapYear(year) && dayOfYear == 366 {
    message = "四年等一回,今天特别想你"
}

节假日我建了个表,春节”“七夕”等,查time.Now().Format("01-02"),如果匹配到就覆盖当天文案。这个表不用搞太全,先放5个最重要的节日就行。

性能优化:并发处理365个视频片段

刚开始是单循环,生成365张图片+365次ffmpeg调用,实测跑了23分钟,太慢了!

后来我开goroutine,用errgroup并行处理,同时跑8个进程,机器差点卡死,但时间缩短到4分钟,代码长这样:

g, ctx := errgroup.WithContext(context.Background())
g.SetLimit(8) // 最多8个并发
for i := 1; i <= 365; i++ {
    i := i // 闭包陷阱!
    g.Go(func() error {
        return generateFragment(i)
    })
}
if err := g.Wait(); err != nil {
    log.Fatal(err)
}

记得i := i那行,不然goroutine闭包捕获的变量会错乱——我犯过这个错,生成了365个一模一样的“第365天”祝福。

实际运行效果

我跑了一次完整流程,生成了blessings_2025.mp4,大小约800MB,画质还不错,但有个问题:所有片段都是图片,没有真人出镜,我妈看了说“像幻灯片”,不算成功。

后来我加了点过渡效果:片段之间用xfade滤镜,渐变时长0.5秒,代码在ffmpeg命令里变成:

ffmpeg -i 001.mp4 -i 002.mp4 -filter_complex "[0:v][1:v]xfade=transition=fade:duration=0.5:offset=2.5[v]" -map "[v]" output.mp4

不过这样只能连续拼接两个片段,全串起来需要链式处理,我偷懒了,直接用concat,过渡效果就没做,如果你的需求要平滑转场,得用更复杂的过滤图(filter graph),那玩意儿调试起来真要命。

一个更简单的替代方案?说实话

写着写着我发现自己有点“过度工程”了。如果你只是想要一个“一年祝福视频”,其实用手机录屏+剪映模板更方便,Go方案适合那种“每年自动生成,批量产出”的场景——比如公司给客户发定制贺卡视频。

但既然你问了Go怎么实现,我这个轮子也算能转。关键代码都在上面了,剩下就是你自己调字体、调颜色、调转场的事。

我最终版本大概写了600行Go代码,加上一些配置文件,说实话,折腾这事的乐趣比结果大,我妈最后看到视频还是感动的,虽然画面上只有彩色背景和文字,没有我的脸。

哦对了,还有个小坑:ffmpeg路径要在环境变量里配好,不然exec.Command找不到,在Windows上我直接写死了路径,在Linux服务器上用的usr/bin/ffmpeg——这根本不是Go的问题,是部署环境的问题。

最终的文件结构

bless-video/
├── main.go          // 入口
├── textgen.go       // 文案生成
├── render.go        // 图片渲染
├── video.go         // ffmpeg调用
├── holidays.json    // 节假日表
└── output/          // 生成结果

你可能会想,这值得吗?为了一个视频写600行代码,我的答案是:如果你有一次成功跑通,明年就不用再动手了——毕竟365天祝福这种事,不是一年就结束的吧。

现在这台服务器还挂了个定时任务,每年1月1日凌晨自动跑一次,生成整年的祝福视频存到网盘里,我爸妈到时候自己去看就行,技术改变生活,虽然改变的方式有点笨拙。

最后那个holidays.json我还在慢慢补充,等几年后它就能覆盖所有传统节日了,人生嘛,不就是在这样的循环里找到一点新意思。

本文来自作者[kyadmin]投稿,不代表be365立场,如若转载,请注明出处:http://hljbesthome.com/lvyou/2476.html

(1)

文章推荐

发表回复

本站作者才能评论

评论列表(4条)

  • kyadmin
    kyadmin 2026-08-24

    我是be365的签约作者“kyadmin”!

  • kyadmin
    kyadmin 2026-08-24

    希望本篇文章《用Go语言写一个365天祝福视频生成器,从零到一的全过程》能对你有所帮助!

  • kyadmin
    kyadmin 2026-08-24

    本站[be365]内容主要涵盖:be365,be365网站,be365网址,ball365体育,Be365排名

  • kyadmin
    kyadmin 2026-08-24

    本文概览:为什么我要用Go写这个?上个月我妈生日,我翻了半天相册发现去年答应给她做的“每日祝福视频”才录了17天,那种愧疚感,你懂吧?我发誓要...

    联系我们

    工作时间:周一至周五,9:30-18:30,节假日休息

    关注我们