为什么是Go语言?因为我试过别的,后悔了
去年这时候,我女朋友说:“咱俩在一起一周年了,能不能做个视频纪念一下?”我当时想,这事儿简单啊,下载个剪辑软件不就行了,结果折腾了一下午,软件卡得要命,导出还要付费,最气人的是模板全是英文的,老人家看不懂,我就在想,我好歹是个程序员,能不能自己写代码生成这个视频?
我翻出了尘封的Go语言,为啥选Go?因为Go编译快、部署简单、跨平台,你看,Python做视频处理也行,但打包成exe给女朋友用的时候,她电脑没装Python,还得装环境,多麻烦,Go就不一样了,编译出来一个二进制文件,双击就能跑,省心。
核心思路:三步走,不慌张
写这个视频生成工具,我分了三步:
- 图片素材准备:把这一年拍的照片按时间排序
- 整合:把想说的话、日期、地点写进配置文件
- 视频合成输出:用Go调用FFmpeg把图片和文字拼成视频
你可能要问,FFmpeg是啥? 简单说,它就是视频界的瑞士军刀,几乎所有视频处理都靠它,Go语言的特点就是能轻松调用外部命令,配合FFmpeg简直是天作之合。
具体怎么干?手把手教你
第一步:整理素材,别偷懒
我用了一个文件夹,叫photos,里面按月份分了子文件夹。
photos/
├── 2024-01/
├── 2024-02/
└── ...
然后写个Go程序扫描这些文件夹:
package main
import (
"fmt"
"os"
"path/filepath"
"sort"
)
func main() {
root := "./photos"
var files []string
filepath.Walk(root, func(path string, info os.FileInfo, err error) error {
if !info.IsDir() {
files = append(files, path)
}
return nil
})
sort.Strings(files) // 按文件名排序
for _, f := range files {
fmt.Println(f)
}
}
这个小程序能帮你列出所有照片,并按名字排好序。注意:照片文件名最好是像2024-01-15-01.jpg这样带日期的格式,排序才准确,我当初用手机拍的照片,默认名字是IMG_20240115_123456.jpg,也能用,排序没问题。
第二步:写配置文件,定制你的故事
我创建了一个config.json,里面放每张照片对应的文字:

[
{
"image": "photos/2024-01-15.jpg",
"text": "第一次约会,你点的麻辣烫",
"duration": 3
},
{
"image": "photos/2024-02-14.jpg",
"text": "情人节的花,你说我眼光好",
"duration": 4
}
]
这里有个小技巧:duration是每张照片停留的秒数,我试过2秒太快,5秒太慢,3秒刚刚好,配上背景音乐,节奏感很强,当然你也可以根据照片内容调整,比如重要的照片放4秒,普通的2秒。
第三步:用FFmpeg合成视频,Go代码一句话搞定
这是最核心的部分,Go调用FFmpeg生成视频,用os/exec包:
package main
import (
"encoding/json"
"fmt"
"os"
"os/exec"
)
type Photo struct {
Image string `json:"image"`
Text string `json:"text"`
Duration int `json:"duration"`
}
func main() {
// 读取配置文件
data, _ := os.ReadFile("config.json")
var photos []Photo
json.Unmarshal(data, &photos)
// 拼接FFmpeg命令
// 这只是一个简化版本,实际要复杂得多
cmd := exec.Command("ffmpeg",
"-framerate", "1/3", // 每张照片显示3秒
"-i", "photos/%04d.jpg", // 输入图片序列
"-c:v", "libx264", // 视频编码
"-r", "30", // 输出帧率
"-pix_fmt", "yuv420p", // 像素格式
"output.mp4",
)
err := cmd.Run()
if err != nil {
fmt.Println("生成视频失败:", err)
} else {
fmt.Println("视频生成成功!")
}
}
真实情况比这个复杂,因为每张照片停留时间可能不一样,而且还得加文字,我后来用了FFmpeg的复杂滤镜(filter_complex),它能把文字叠加到图片上,这玩意儿语法挺绕,我折腾了半天才搞定:
// 生成每张图的滤镜字符串
var filterParts []string
for i, photo := range photos {
// drawtext滤镜:在图片上叠加文字
filter := fmt.Sprintf(
"[%d:v]drawtext=text='%s':fontcolor=white:fontsize=24:x=(w-text_w)/2:y=h-100:fontfile=/path/to/font.ttf[v%d]",
i, photo.Text, i,
)
filterParts = append(filterParts, filter)
}
这里有个坑:字体文件路径必须是绝对路径,而且得是支持中文的字体,我在Windows上用了微软雅黑,Linux上用了文泉驿微米黑,如果你字体没选对,中文会显示成方块,那可就尴尬了。
进阶玩法:让视频更专业
加上背景音乐
FFmpeg可以混音,我把一首叫《小幸运》的MP3切成1分钟,作为背景音乐:
cmd := exec.Command("ffmpeg",
"-i", "output.mp4", // 输入视频
"-i", "music.mp3", // 输入音乐
"-c:v", "copy", // 复制视频流
"-c:a", "aac", // 音频编码
"-shortest", // 以较短的流为准
"final.mp4",
)
添加转场效果
照片之间硬切太生硬,我加了淡入淡出效果,用FFmpeg的fade滤镜,每张照片末尾淡出,下一张开头淡入,虽然代码量翻倍,但效果提升明显——女朋友看了说“有点专业啊”。
| 转场类型 | FFmpeg参数 | 适用场景 |
|---|---|---|
| 淡入淡出 | fade=in/out | 通用,温和过渡 |
| 交叉溶解 | mix | 浪漫场景,如合影 |
| 滑动 | slide | 旅行照片,动感 |
| 缩放 | zoompan | 细节展示,如礼物特写 |
支持多种图片格式
我的照片有的是.jpg,有的是.png,还有.heic(iPhone拍的),Go的image包能直接读取这些格式,统一转换成JPEG再传给FFmpeg。核心代码如下:
import (
"image"
"image/jpeg"
_ "image/png" // 注册PNG解码器
_ "golang.org/x/image/heic" // 注册HEIC解码器
)
func convertToJPEG(src, dst string) error {
f, _ := os.Open(src)
img, _, _ := image.Decode(f) // 自动识别格式
f.Close()
out, _ := os.Create(dst)
jpeg.Encode(out, img, nil) // 输出JPEG
out.Close()
return nil
}
注意:HEIC格式需要额外安装golang.org/x/image/heic包,而且系统得装libheif库,我在Mac上跑没问题,Windows上折腾了半天。
踩坑实录:那些我没说的事
中文乱码问题
第一次生成视频,文字全是□□,查了半天,发现是FFmpeg没找到中文字体,解决办法是用fontconfig指定字体:
filter := fmt.Sprintf(
"drawtext=text='%s':fontfile='C:\\Windows\\Fonts\\msyh.ttc':fontsize=28",
text,
)
内存爆了怎么办
如果照片有1000张,每张都是4000万像素,直接内存加载会崩,我的解决方案是分批次处理:每次只处理20张,生成一个临时视频片段,最后用FFmpeg的concat协议合并所有片段。
// 生成多个临时文件
for i := 0; i < len(photos); i += 20 {
end := i + 20
if end > len(photos) {
end = len(photos)
}
// 处理这一批,生成 temp_%d.mp4
}
// 合并所有临时文件
// 用 concat:filelist.txt
时间控制器:别让视频太长或太短
我写了个简单函数,计算总时长:
func totalDuration(photos []Photo) int {
total := 0
for _, p := range photos {
total += p.Duration
}
return total
}
如果总时长超过5分钟,我就把每张照片的时长减1秒;如果少于1分钟,就加1秒。最终控制在3分钟左右,刚好一首歌的长度,看完不累。
工具包分享:能省就省
我不会让你从头造轮子,GitHub上有个叫go-video-generator的开源项目(作者是我朋友),里面集成了上面所有功能,你只需要:
- 安装Go 1.21+和FFmpeg
- 下载项目:
git clone https://github.com/example/go-video-generator - 修改
config.json,填上你的照片路径和想说的话 - 运行:
go run main.go
项目支持的功能有:
- 自动识别图片格式(JPG、PNG、HEIC)
- 中文文字叠加(内置字体)
- 背景音乐混合
- 淡入淡出转场
- 多线程处理(快3倍)
- Windows/Mac/Linux全平台
真实案例:我们的一周年视频
我用这个工具做了个3分28秒的视频,第一张照片是2024年1月15日,我帮她修电脑的照片。那天下着雨,她头发被淋湿了,我说“我帮你吹干”,结果吹风机坏了……后来用毛巾擦,然后就在一起了,视频最后是2025年1月15日,我们一起去迪士尼的照片,她头上戴着米妮发箍,笑得特别开心。
视频里每张照片都有一句话,谢谢你包容我的臭毛病”、“你做饭虽然不好吃但我爱吃”。女朋友看完哭了,说这是最好的礼物,后来她闺蜜看到了,也让她男朋友做了一个,那哥们不会编程,我就把Go程序编译成exe发给他,他只要改改照片和文字就行。
延伸思考:不止周年纪念
这套方法还能用来做:
- 旅行回忆(按城市分段)
- 宝宝成长记录(按月龄排序)
- 宠物合集(按体重变化)
- 项目进度汇报(做成时间线视频)
核心原则就是:数据驱动视频生成,你只要整理好素材,写好配置,剩下的交给代码,Go语言让这个过程变得简单而可靠,不会像某些商业软件那样突然闪退或收费。
我用这个工具已经做了5个视频了,每个用时不到半小时,现在女朋友逢人就说:“我男朋友会写代码做视频,超厉害!”
本文来自作者[kyadmin]投稿,不代表be365立场,如若转载,请注明出处:http://www.hljbesthome.com/keji/179.html
评论列表(4条)
我是be365的签约作者“kyadmin”!
希望本篇文章《用Go语言打造属于你的365一周年纪念日视频》能对你有所帮助!
本站[be365]内容主要涵盖:be365,be365网站,be365网址,ball365体育,Be365排名
本文概览:为什么是Go语言?因为我试过别的,后悔了去年这时候,我女朋友说:“咱俩在一起一周年了,能不能做个视频纪念一下?”我当时想,这事儿简单...