1.5秒片尾设计:Timeline Visualizer如何在视频结尾缩放展示完整路线
【免费下载链接】google-timeline-visualizerVisualize your year in travel using your Google Location History (Timeline) data项目地址: https://gitcode.com/GitHub_Trending/go/google-timeline-visualizer
你看过那种播放完旅行轨迹后,镜头缓缓拉远、整条路线一帧铺满全屏的视频吗?这正是Timeline Visualizer的核心设计——它把 Google 位置历史(Timeline)数据转成旅行视频,并在最后 1.5 秒用一个精心调度的"片尾镜头",将整条路线缩放展示,给视频一个漂亮的收尾。本文带你从产品视角拆解这 1.5 秒背后的实现逻辑,即使你是新手也能看懂。
片尾为什么是 1.5 秒?
先说结论:片尾时长不是拍脑袋定的,而是一个写死在动画模块里的常量。
在 TimelineAnimation.kt 中可以看到两个关键数字:
OUTRO_SECONDS = 1.5f:整个片尾阶段共1.5 秒;OUTRO_TRANSITION_SECONDS = 1.0f:真正的镜头缩放转场只用其中1.0 秒。
为什么要"多留 0.5 秒"?这是一个很妙的细节:镜头在 1 秒内完成从局部路线到全局鸟瞰的缩放,随后 0.5 秒保持在全景画面停驻,让观众的视线有足够时间看清"整条路线长什么样",而不是刚拉到全景就黑屏结束。动效设计上这叫"动作 + 停留",是转场动画的经典节奏。
一帧之内发生了什么:进度如何切分
每一帧画面都由一个TimelineFrame描述,它有两个进度值(见 TimelineAnimation.kt):
| 进度值 | 含义 | 取值范围 |
|---|---|---|
journeyProgress | 主体行程进度 | 0 → 1,片尾期间恒为 1 |
outroProgress | 片尾转场进度 | 0 → 1,仅最后 1.5 秒内变化 |
切分逻辑在frameAtElapsedSeconds中(TimelineAnimation.kt):
- 前段(行程期):
journeyProgress随时间从 0 走到 1,outroProgress保持 0; - 最后 1.5 秒(片尾期):行程进度锁死在 1,
outroProgress用经过的片尾时间除以 1.0 秒转场时长算出缩放比例,超过 1.0 秒后停留在 1。
💡 也就是说:视频选 30 秒,实际"跟拍"只有 28.5 秒,剩下的 1.5 秒全部留给片尾镜头。
镜头缩放:从"跟拍视角"混插到"鸟瞰视角"
片尾的缩放本质上是两个镜头的混插,核心代码在 TimelinePainter.kt 的viewport方法中:
- 镜头 A(跟拍视角):一路跟随当前位置的局部地图视野;
- 镜头 B(鸟瞰视角):由
overviewViewport计算,能框住整条路线的全局视野(TimelinePainter.kt); - 混插:
blendViewport按easeOutCubic(outroProgress)的缓动曲线,把两个视野在缩放和位移上平滑过渡。
easeOutCubic(三次缓出)让镜头"先快后慢"地拉远——开头缩放感强烈、收尾柔和定格,观感非常自然。
除了镜头本身,片尾还在做两件事,让画面"讲完故事":
- 轨迹淡出:跟拍时的彩色轨迹和移动标记,透明度按
1 - easeOutCubic(outroProgress)逐渐归零(TimelinePainter.kt); - 完整路线淡入:与此同时,一条覆盖全程(0 → 总里程)的总览路线以
easeInOutCubic曲线渐显(TimelinePainter.kt)。
一进一出,画面完成了从"我在哪"到"我去了哪"的叙事切换。
片尾也影响视频推荐时长
你可能注意到,导出时应用会推荐视频时长——这 1.5 秒同样被算进公式里。DurationRecommendation.kt 会先根据路线的"移动工作量"和"缩放工作量"估算行程所需秒数,然后加上 1.5 秒片尾再向上取整到 5 秒的倍数。
也就是说:路线越复杂,行程段越长,但无论长短,片尾永远稳定保留 1.5 秒,保证每支视频都有完整的全景收尾。
导出时如何高效渲染片尾帧
真正导出 MP4 时(Mp4Exporter.kt):
videoFrameCounts按帧率把 1.5 秒换算成片尾帧数,与行程帧数分开统计(Mp4Exporter.kt);- 鸟瞰层是一次性预渲染好的位图:最大边长 1080 像素(
OVERVIEW_MAX_EDGE),整个片尾期只做透明度混合,不逐帧重绘地图(Mp4Exporter.kt); - 导出前的瓦片预下载也会把片尾帧和终态全景视野(
TimelineFrame(1f, 1f))一并纳入,保证片尾缩放时地图瓦片不缺失(Mp4Exporter.kt)。
小结
| 设计点 | 实现方式 |
|---|---|
| 片尾总时长 | 固定 1.5 秒(OUTRO_SECONDS) |
| 镜头缩放 | 1.0 秒内 easeOutCubic 混插跟拍 → 鸟瞰视野 |
| 收尾停驻 | 最后 0.5 秒定格全景,给观众阅读路线的时间 |
| 叙事切换 | 局部轨迹淡出 + 完整路线总览淡入 |
| 性能保障 | 鸟瞰层预渲染位图 + 片尾瓦片提前下载 |
这正是 Timeline Visualizer 让每支旅行视频"有始有终"的秘密:1.5 秒不长,却把整段旅程压缩成一张可以一眼看全的地图。如果你想了解完整路线数据如何解析、时间轴如何计算,可以进一步阅读 README.md 和 visualizer.py。
【免费下载链接】google-timeline-visualizerVisualize your year in travel using your Google Location History (Timeline) data项目地址: https://gitcode.com/GitHub_Trending/go/google-timeline-visualizer
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考