最近用 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,素材就三样:
王菲 - 主角.mp3(320kbps, 48kHz)王菲 - 主角.lrc(JSON Lines 格式,前 19 行是制作信息,后面是主歌词)主角.png(1254×1254 的封面图)我用的工具链:
画布 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 — 动画系统
这里花的时间最多。三个动画源:
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.floor → Math.ceil(我写 bug 了) |
| 歌词 container 宽度不够,长行被截断 | max-width: 900px → 980px,间距 3px → 2px |
| 唱臂渲染成三个离散点 | 改成纯白实色 + 10px 粗描边 |
| Mac 上 Homebrew 装的 ffmpeg 不在 PATH 里 | ln -s 一下就好 |
pi + HyperFrames 这组合做歌词 MV,最大的好处是代码即模板——这次写好了一首歌的 HTML,下回换素材就能复用。我做数据新闻、产品演示、GitHub 项目介绍都用的这一套,换的是数据,代码结构不用重来。
如果你也想搞一个,源码我已经整理好了。
凡点亮小红心 + 评论区回复「主角视频」,私信发你完整源码。
包括:
- index.html(完整实现,600+ 行 CSS + JS)
- LRC 歌词解析模板
- HyperFrames 项目配置
- 渲染命令和参数参考
你也可以自己换歌:把 MP3、LRC、封面图替换掉,改一下歌词数据和总时长,就能生成你自己的歌词 MV。
评论区等你。一起搞点有意思的。
💬 评论区