去年我孩子满一周岁的时候,我翻着手机里365天拍的照片和视频,突然想做个纪念视频,网上那些模板吧,数字滚动效果看着挺酷,但用起来总差点意思——要么是付费的,要么数字滚动卡得跟老式电风扇似的,我寻思着,自己是个程序员,干脆用Golang写一个得了。
什么是PR出生365天视频里的数字滚动
Premiere Pro(PR)里那种数字滚动,说白了就是让数字像老式计程表或者体育计时器那样,从0快速跳到365,这个效果在视频里特别抓眼球,尤其是配合宝宝从襁褓里到满地爬的画面,数字“唰”一下翻过去,那种时间流逝感一下子就出来了。
Golang能做什么
你可能觉得PR自己能做这个效果啊,没错,PR确实能做,但那是手动关键帧,调起来费劲,用Golang写个小工具,可以自动生成这个数字滚动的帧序列,然后导入PR里叠在视频上就行了,关键是——完全可控,想滚多快、从哪个数字开始、用啥字体,你说了算。
核心实现思路
我们先捋一下数字滚动到底要怎么做,其实原理特简单:生成一系列图片,每张图片上显示一个数字,然后把这些图片连起来播放,Golang里有个image包,加上golang.org/x/image/font和golang.org/x/image/freetype,就能画图写字了。

第一步:生成数字帧
我直接贴一段关键代码,你感受一下:
package main
import (
"image"
"image/color"
"image/png"
"log"
"math"
"os"
"strconv"
"golang.org/x/image/font"
"golang.org/x/image/font/basicfont"
"golang.org/x/image/math/fixed"
)
func generateNumberFrame(num int, width, height int) *image.RGBA {
img := image.NewRGBA(image.Rect(0, 0, width, height))
// 背景设为透明
for y := 0; y < height; y++ {
for x := 0; x < width; x++ {
img.Set(x, y, color.RGBA{0, 0, 0, 0})
}
}
// 画数字
text := strconv.Itoa(num)
// 这里简化了,实际要算居中位置
point := fixed.Point26_6{
X: fixed.Int26_6(50 * 64),
Y: fixed.Int26_6(100 * 64),
}
d := &font.Drawer{
Dst: img,
Src: image.NewUniform(color.RGBA{255, 255, 255, 255}),
Face: basicfont.Face7x13,
Dot: point,
}
d.DrawString(text)
return img
}
这段代码看着简单,但有个坑——basicfont.Face7x13这个字体太小了,放视频里根本看不清,你得换成自定义字体,比如下载一个粗体数字字体文件(.ttf),用freetype加载。
第二步:让数字动起来
数字滚动不能是生硬的一帧一个数字跳,真正的滚动效果,每个数字应该有一个垂直位移的动画,比如从0到1,中间经过0.1、0.2……一直到0.9,然后再跳到1,这个位移要配合正弦曲线或者线性插值。
我做了个表,对比不同滚动方式的视觉效果:
| 滚动方式 | 实现方法 | 视觉效果 | 适合场景 |
|---|---|---|---|
| 直接跳转 | 每帧显示整数 | 生硬,像翻页 | 不推荐 |
| 线性插值 | 数字带小数逐帧递增 | 顺滑但有点机械 | 简洁风视频 |
| 缓动插值 | 用ease-in-out曲线 | 最真实,像机械表 | 高级感纪念视频 |
我最后选了缓动插值,代码大概是:
// 用缓动函数计算当前帧应该显示的数字
func easeInOutQuad(t float64) float64 {
if t < 0.5 {
return 2 * t * t
}
return -1 + (4-2*t)*t
}
func getCurrentNumber(start, end float64, progress float64) float64 {
easedProgress := easeInOutQuad(progress)
return start + (end-start)*easedProgress
}
第三步:输出视频用的帧序列
咱们不直接生成视频文件——Golang做视频编码太费劲了,我的做法是生成一堆PNG图片,命名成frame_0001.png、frame_0002.png这种格式,然后导入PR,在时间轴上把所有图片拖进去,设置成每帧持续0.04秒(25帧/秒的话),再叠在视频轨道上。
实际踩过的坑
写这个工具的时候,我栽了好几个跟头:
坑1:字体模糊。 一开始用的字体太小,数字边缘锯齿严重,后来找了思源黑体的粗体版本,像素调到了72pt,才清楚。
坑2:背景不透明。 生成的PNG默认背景是黑色,叠在视频上像贴了块膏药,后来在image.NewRGBA的时候把alpha通道设成0,PR里选“屏幕”混合模式才解决。
坑3:数字位数不对齐。 1位数和3位数宽度不一样,滚动的时候数字会左右晃动,解决办法是固定三位数,000”到“365”,左边补零。
具体补零代码:
func padNumber(num int, totalDigits int) string {
return fmt.Sprintf("%0*d", totalDigits, num)
}
// 用的时候:padNumber(5, 3) -> "005"
最终效果和PR里怎么用
我写了个完整的命令行工具,支持指定起始数字、结束数字、总帧数、字体路径、输出目录,用起来就是:
go run main.go -start 0 -end 365 -frames 150 -font ./DIN-Bold.ttf -out ./frames
然后去PR里,导入这个文件夹,勾选“图像序列”,PR会自动把图片识别成一个视频片段,把这个片段放在时间轴上,调到视频轨道2,下面的轨道1放宝宝的日常视频,把轨道2的混合模式改成屏幕或者相加,数字就浮在视频上面了。
数字从0到365滚动的时候,配上宝宝从出生到周岁的片段,那种感觉——说实话,我老婆看完哭了,不是煽情,是真的觉得时间过得快,数字一跳一跳的,像心跳一样。
一些可以玩的花样
基础版本做出来之后,我还加了几个小功能:
- 多段滚动:0-100天”、“100-200天”、“200-365天”三段,匹配不同阶段照片
- 随机抖动:给数字加一个像素级别的随机位移,看起来更像老式计程表
- 粒子散落:数字滚动结束的时候,炸成粒子散开(这个用Golang+OpenGL做的,复杂了点)
如果你不想写代码,也可以去GitHub搜“golang number counter video”或者“digital flip clock generator”,有人已经封装好了轮子,但自己写一遍的好处是,你能精确控制每个像素,而且后面可以随时改。
所以啊,用Golang做数字滚动,本质上就是把动画拆成帧,用代码批量生成,这事搁以前得在AE里一帧一帧调,现在几行代码就搞定了,宝宝百天视频也好,周岁纪念也好,数字滚动那个效果,真的让视频多了点仪式感,我小孩现在两岁多了,偶尔翻出那个365滚动的视频,他自己看着屏幕里那个数字变来变去,也跟着比划,挺有意思的。
本文来自作者[kyadmin]投稿,不代表be365立场,如若转载,请注明出处:http://www.hljbesthome.com/nengyuan/1347.html
评论列表(4条)
我是be365的签约作者“kyadmin”!
希望本篇文章《用Golang给宝宝的PR出生365天视频做一个数字滚动效果,其实没那么难》能对你有所帮助!
本站[be365]内容主要涵盖:be365,be365网站,be365网址,ball365体育,Be365排名
本文概览:去年我孩子满一周岁的时候,我翻着手机里365天拍的照片和视频,突然想做个纪念视频,网上那些模板吧,数字滚动效果看着挺酷,但用起来总差点意...