📄 文档管理系统

← 返回列表

用 pi + HyperFrames 做了一首王菲《主角》的歌词 MV

default 📅 创建:2026-06-12 22:16:37 🔄 更新:2026-06-12 14:16:37
👁️ 预览 & 复制到公众号 ✏️ 编辑

最近用 pi + HyperFrames 给王菲的《主角》做了一个歌词 MV,黑胶唱片 + 卡拉 OK 逐字高亮那种。效果还行,过程挺折腾的,把流程和踩的坑都记下来。

先说说视频号那边发的

标题只能 16 个字,我写的是:

主角 · 歌词MV

描述写了这么一段:

追完《主角》这部剧,我被秦腔深深震撼了——那高亢苍凉的唱腔里,藏着西北人骨子里的倔强与深情。以前总觉得传统戏曲离自己很远,但这部剧让我第一次听懂秦腔,爱上了这份扎根黄土地的声腔艺术。

本视频使用 pi coding agent + HyperFrames 渲染引擎制作,HTML/CSS/JS 纯代码驱动动画,黑胶唱片旋转 + 卡拉OK逐字高亮,全程无模板无剪辑软件。

标签打了 10 个:#主角 #王菲 #秦腔 #传统文化 #歌词MV #HyperFrames #AIGC #黑胶唱片 #音乐可视化 #国风

精选评论留了一条自己的:

秦腔一响,魂就回来了。这部剧让我知道,真正的艺术不在聚光灯下,而在那些吼了几百年的老腔里。

我为什么想搞这个

歌词 MV 这东西,以前要么用剪映手动对时间轴,要么用 After Effects 写表达式。都不是不行,但每次换一首歌就要重新做一遍,很烦。

pi + HyperFrames 的组合干这事有个天然优势:HTML/CSS/JS 一次性写好了,换歌只需要换 MP3、LRC、封面图三个素材,代码几乎不改。

加上最近追《主角》上头,秦腔那段真的听得我起鸡皮疙瘩——那种从黄土高原里长出来的声音,《主角》剧里听一次震撼一次。就想用技术手段做一个复古黑胶唱片风格的 MV 来表达一下。

项目背景

时长 5 分钟(300.288 秒),规格 1920×1080,素材就三样:

我用的工具链:

视觉设计的几个关键数字

画布 1920×1080,左侧是唱片区,右侧是歌词区。

黑胶唱片:600×600 的正圆,封面图 440×440 居中嵌在里头,外圈留 80px 的黑胶黑环。黑环上叠了纹路(repeating-radial-gradient)和高光(conic-gradient),用 mask 把封面区域挖空,只在外环显示。

唱臂:三段式 SVG——固定转轴 + 220px J 形弯折臂杆 + 唱头。转轴定位在 (436, 170),也就是唱片垂直居中正上方。初始角度 20°,落针到 40°(CSS animation 实现,1s ease-in-out)。

配色:深棕红渐变背景 #6D1A0F#4B100A,唱片纯黑,唱臂纯白渐变。

右侧歌词:980px 宽,当前行 54px 纯白字体 + 暖光晕,已过行 0.55 透明度,还没到的行 0.4 透明度。每一行的字拆成了 <span class="word">,方便逐字高亮。

进度条:底部居中 900px 宽,白色填充条 + 红色圆点指示头。

制作信息:0-19 秒先展示制作人员名单(演唱/作词/作曲/编曲/录音师/乐手等 19 行),跟歌词同一个 track 平移机制,19 秒后自动切到歌词。

整个流程是这样的

Step 1 — 摸素材底细

先看 MP3 多长(300.288s)、LRC 有几条(50+ 条,前 19 条是制作信息)、封面图多大(1254×1254,够用)。

Step 2 — 项目初始化

npx hyperframes init

生成项目骨架。这一步没啥好说的。

Step 3 — 把 LRC 数据嵌到 HTML 里

把 50+ 条 LRC 解析成 {t: ms, text: "..."} 数组,直接内嵌在 <script> 里。分成两组:CREDITS(t < 19000ms)和 LYRICS(t ≥ 19000ms)。

Step 4 — 布局搭建

先是左右两栏布局。左栏放唱片区(SVG 唱臂 + div 唱片),右栏放歌曲信息(歌名、歌手名、作词作曲)和歌词视口。底部是进度条。

这块纯 CSS Grid,没什么特别的。

Step 5 — 动画系统

这里花的时间最多。三个动画源:

  1. GSAP Timeline(paused 模式):驱动唱片匀速旋转。30 秒转一圈,repeat 9 次,覆盖 300 秒的总时长。
  2. CSS Animation:唱臂 20° → 40°。为什么用 CSS 不用 GSAP?因为 HyperFrames 的 snapshot 模式下,GSAP 的 seek 有时候不触发 onUpdate,CSS animation 不受影响。
  3. rAF 循环:兜底用的。syncLyric() 函数每帧跑一次,处理歌词索引切换、track 平移、卡拉 OK 逐字高亮、进度条更新。

Step 6 — 卡拉 OK 逐字高亮

每行歌词的文字拆成 <span class="word">。当前行正在唱的时候,用 local * K_SPEED * words.length 算高亮到哪个字了。

K_SPEED = 1.5 是调出来的——原速高亮感觉歌手唱得比字跑得快,加速 50% 才追上。

Step 7 — 唱臂重构(改了三次)

这个最有意思,来回改了三版:

Step 8 — 修边框和溢出

长行歌词比预想的宽,max-width: 900px 经常截断。改成 980px,letter-spacing 从 3px 缩到 2px,好很多。

Step 9 — 预览

npx hyperframes preview    # 浏览器里看
npx hyperframes snapshot   # 抽帧分析

一键预览,边看边改。

Step 10 — 渲染

npx hyperframes render --quality standard --crf 28 --output renders/mv-final.mp4 --fps 30

5 分钟的 1080p 视频,渲染时间取决于你电脑性能。我的机器跑了大概十几分钟。

踩的几个坑

问题 解决
GSAP timeline seek 在 snapshot 模式下不触发 onUpdate 加了独立的 rAF 循环兜底
唱臂 SVG 渐变描边在快照中看不到 改成纯白 #f5f5f7 实色描边
每行最后一个字不亮 Math.floorMath.ceil(我写 bug 了)
歌词 container 宽度不够,长行被截断 max-width: 900px980px,间距 3px → 2px
唱臂渲染成三个离散点 改成纯白实色 + 10px 粗描边
Mac 上 Homebrew 装的 ffmpeg 不在 PATH 里 ln -s 一下就好

一些感想

pi + HyperFrames 这组合做歌词 MV,最大的好处是代码即模板——这次写好了一首歌的 HTML,下回换素材就能复用。我做数据新闻、产品演示、GitHub 项目介绍都用的这一套,换的是数据,代码结构不用重来。

如果你也想搞一个,源码我已经整理好了。

福利

凡点亮小红心 + 评论区回复「主角视频」,私信发你完整源码

包括:
- index.html(完整实现,600+ 行 CSS + JS)
- LRC 歌词解析模板
- HyperFrames 项目配置
- 渲染命令和参数参考

你也可以自己换歌:把 MP3、LRC、封面图替换掉,改一下歌词数据和总时长,就能生成你自己的歌词 MV。


评论区等你。一起搞点有意思的。

💬 评论区

加载中...