用Golang写一年365天带娃的视频,这事儿我认真琢磨过
- 汽车
- 2026-07-01 13:43:24
- 326
为什么突然想用Golang干这事儿?
说实话,最开始我也没想过用代码来管理带娃视频,直到有一天,手机提示“存储空间不足”,我才发现——好家伙,一年下来拍了三百多个视频,从娃第一次翻身到喊出“爸爸”,全挤在相册里,手动分类?那得熬几个通宵,于是我想:既然我是写Go的,不如让程序替我干活?
Golang的并发特性特别适合处理大量文件,而且编译出来的东西跑起来贼快,不像Python脚本还要装依赖,我当时的思路很简单:把视频按日期自动归档,顺便提取关键帧做成缩略图。
第一步:扫描全年视频文件
我先写了个函数,遍历指定目录下的所有视频,Go的filepath.Walk非常好用,但注意别把系统文件也扫进来,得过滤格式:
func scanVideos(root string) []string {
var videos []string
filepath.Walk(root, func(path string, info os.FileInfo, err error) error {
if err != nil { return nil}
if !info.IsDir() && strings.HasSuffix(strings.ToLower(info.Name()), ".mp4") {
videos = append(videos, path)
}
return nil
})
return videos
}
这一步看着简单,但有个坑:视频文件名最好带上日期,比如2023-01-15_第一次站起来.mp4,我家孩子他妈习惯用手机默认命名,全是IMG_20230115_xxxx.mp4,这就得从文件名里截取日期,你可以用正则:
re := regexp.MustCompile(`(\d{4})(\d{2})(\d{2})`)
match := re.FindStringSubmatch(filename)
// match[1]是年,match[2]是月,match[3]是日
第二步:按月份和事件类型打标签
一年365天,视频不是均匀分布的,娃刚学会爬那两周,每天拍十条;后几个月慢慢少了,我建了个简单的标签系统,用Golang的map搞定:
| 月份 | 视频数量 | 主要标签 |
|---|---|---|
| 1月 | 45 | 满月、黄疸消退 |
| 3月 | 62 | 抬头练习、第一次翻身 |
| 6月 | 38 | 添加辅食、出牙 |
| 9月 | 29 | 学爬、生病记录 |
| 12月 | 41 | 学走路、生日派对 |
标签怎么提取?我用了最笨的办法——关键词匹配,比如文件名包含“翻身”、“爬”、“走路”就自动打标签,Go的strings.Contains效率很高,配合sync.Map做并发标签写入,跑1000个视频只要几秒:
var tagMap sync.Map
for _, v := range videos {
if strings.Contains(strings.ToLower(v), "翻身") {
tagMap.Store(v, "大动作发育")
}
}
这方法不完美,有时候把“翻身农奴把歌唱”之类的奇怪文件名也会打上标签(还好我没存这种视频),后来我干脆加了个人工确认步骤:把自动标签结果写入JSON文件,用json.Decode读出来手动改。
第三步:生成时间线缩略图
光分类不够,视频太多,想快速找到“去年春天带娃去公园”那段,总不能一个个点开看,我借助ffmpeg(用Go的exec.Command调用)提取关键帧:
func extractThumbnail(videoPath, outputPath string) error {
cmd := exec.Command("ffmpeg", "-i", videoPath, "-ss", "00:00:05",
"-vframes", "1", outputPath)
return cmd.Run()
}
这里有个小技巧:别每帧都取,优化性能,我是在转码时顺便把缩略图命名成[原始文件名]_thumb.jpg,然后塞进一个与视频同名的文件夹里,这样打开目录时,缩略图网格一目了然,比相册自带的“时光轴”好用。
第四步:自动生成年度回顾视频
这是最花哨的功能——把一年视频剪辑成一个5分钟的集锦,用Golang拼接ffmpeg命令,读取之前生成的标签JSON,按月份抽取代表性片段:
- 先按标签权重排序:学走路类的权重设高,因为那是里程碑事件
- 每个月份至少选一条视频,避免某个月被跳过
- 用ffmpeg的
concat滤镜把片段连起来,加上片头片尾
片头我用Go的text/template生成文字:“2023年度带娃实录”,字体选思源黑体(免费),背景音乐从/music目录随机选一首,第一次跑出来的视频有34分钟,后来限制每个片段3~5秒,硬是压到了7分钟。
这事儿真不能全自动,有一次程序把娃嚎啕大哭的片段加到“快乐时光”标签下,生成出的视频简直像恐怖片,从那以后,我加了个人工审核步骤:输出一个待确认.tsv文件,里面列出每个片段的时间和标签,在电脑上快速过一遍。
说点实在的坑
这条路不是一帆风顺的,有几个问题我必须提一下:
- 时间戳偏移:手机视频的创建时间可能被修改过(比如微信传过来的),得用
ffprobe读元数据里的creation_time - 文件重复:老人用不同手机拍同一个场景,得用
md5校验去重,Go标准库就有crypto/md5,别用sha256慢死了 - 内存控制:处理4K视频时,一次性加载所有文件路径会占用不少内存,改用
filepath.Walk的回调方式,边扫描边处理
还有,别像我一样在笔记本上跑这个程序——风扇转得比飞机发动机还响,建议放到云服务器上,或者晚上睡觉前跑,用time.AfterFunc设置定时任务。
这事儿到底值不值?
说实话,如果你一年只拍十来个视频,手动整理更快,但像我家这样,从产房到周岁,手机里攒了300多G素材的,Go写的这个小工具真的能救命,整理完那一刻,你看着时间线从春天到冬天,从哭闹到会叫“妈妈”,那种感觉——不是用语言能描述的。
代码放在GitHub上,叫baby-year(别搜,我真的写了一个,但太丑了不好意思公开),各位自己动手折腾的时候,记得给程序留个退出开关,用signal.Notify监听Ctrl+C,别像我第一次一样,跑了一半想停只能拔电源。
