- AI 技能
- 媒体生成
- 视频
【免费下载链接】video-shotcraft
AI video skill for Claude Code & Codex — cinematic product videos with Remotion: 152 shot recipe cards, 209 motion previews, a production-ready template
导读
本文以 gallery/source/avatar-bracket-carousel.md 为核心,结合 demo 源码 与公共动效原语,完整拆解 video-shotcraft 中「AvatarBracketCarousel」这张 ui-entrance 动效卡的实现原理、全部参数标定与落地避坑点。读完你即可掌握「一句话填空 + 角色轮换」类镜头的可复刻方案:如何用单一距离量同步驱动缩放/透明度/模糊/位移,如何在 480×270 设计坐标系下标定切换节拍,以及如何在 Remotion 中把这一套参数原样落地渲染。
卡片定位:把一个位置的多重身份拍成一句话
该卡片的适用场景是「一个位置,多种角色」的能力枚举——团队、身份、预设、人格类产品的核心一句话镜头。它把「我们有设计师、客服、分析师、写手」这样一份清单,压缩进一个 92×92 的槽位里:句子不动,只有槽里的人换。四角对焦框不参与轮换,但把观众的眼睛钉死在方框内,于是四次更换被读作「同一个位置」,而不是「四张头像飘过」。
按 gallery/api/library.json 中该卡的登记信息,其规格为:
- 时长:约 5.2s(156f@30fps),源码常量 AVATAR_BRACKET_CAROUSEL_DURATION 即为 156;
- 能量:中——三次等距切换构成稳定节拍器,对焦框脉冲是唯一装饰性动作;
- 分类:ui-entrance,与源码目录 demos/ui-entrance/avatar-bracket-carousel/ 一致;workbench 侧有同源副本 workbench/demosrc/ui-entrance/avatar-bracket-carousel/AvatarBracketCarousel.tsx。
动效核心:一个连续位置量驱动四个属性
整张卡的动效骨架是「连续位置量 + 距离衰减」,而不是索引跳变。
位置量 pos 是三段 spring 的累加
let pos = 0; SWITCHES.forEach((s0) => { pos += seg(t, s0, s0 + 0.14, (k) => E.spring(k, 0.25)); });对应源码见 demos/ui-entrance/avatar-bracket-carousel/AvatarBracketCarousel.tsx,切换点为硬编码数组SWITCHES = [0.24, 0.46, 0.68](L24)。因为pos是连续量而非索引跳变,任意时刻都能算出每个头像离槽位有多远——这是后面一切衰减计算的输入。
距离量同时驱动四个属性
d = |k - pos|之后:
| 属性 | 公式 | 语义 |
|---|---|---|
| scale | max(0.5, 1 - d*0.38) | 入框放大、出框缩小 |
| opacity | max(0, 1 - d*0.62) | 出框淡化 |
| blur | min(3, d*2.4) | 出框模糊(景深暗示) |
| translateY | (k - pos) * STEP(STEP=76px) | 垂直位移 |
源码实现位于 L62-L83。四个属性同源于一个距离量,因此入框/出框的变化天然同步,不需要为每个属性单独排时间线。
队列的叠放与「锚点自居中」
队列是绝对定位在 slot 的 0×0 锚点上叠放的(left:-29px, top:-29px自居中,对应 58px 头像直径的一半),垂直位移全靠(k-pos)*STEP。框外的头像照样渲染,只是被 opacity 和 blur 藏掉——这保证了「随时可被轮换拉回来」,也暗示了队列的存在(出框头像仍露出一角)。
入场是叠在轮换之上的另一层
opacity: op * seg(t, 0.02 + k * 0.03, 0.12 + k * 0.03)见 L82。四张头像按 0.03 错峰在开场 0.15 内建立队列,之后这一项恒为 1,轮换全权接管。
角色标签独立一套但共享 pos
标签不位移,只换透明度:opacity = max(0, 1 - |k-pos|*2.2),见 L108-L125。衰减斜率 2.2 比头像的 0.62 陡得多——标签在约 0.45 格距离外就完全消失,永远不会出现两个标签同屏(两句文字同时半透明叠着最难读)。
对焦框呼吸
breath += Math.sin(seg(t, s0, s0 + 0.1) * Math.PI); // scale(1 + Math.min(1, breath) * 0.07)见 L36-L39 与 L97。正弦包络让脉冲在切换动作的正中达峰、走完归零;取min(1, breath)后乘 0.07 加到 scale 上,是「咬合了一下」的量,不喧宾夺主。
参数表:全部标定值与调节手感
以下参数均在 480×270 设计坐标系下标定(DesignStage等比放大时数值不动),来自原文档并对照源码常量逐一核实:
| 参数 | 典型值 | 调节手感 |
|---|---|---|
| 切换点 | 0.24 / 0.46 / 0.68,间隔 0.22(≈34f / 1.14s) | 间隔就是「读得完一个角色」的时长;<0.12 观众来不及看标签,>0.3 节拍器感散掉 |
| 切换行程 | 窗 0.14(≈22f),E.spring(k, 0.25) | 行程占间隔的 64% → 静置时间约 12f;阻尼 0.25 是明确一次回弹,调小会抖两下与相邻切换互相干扰 |
| 步距 | STEP=76px(框 92px、头像 58px) | 步距必须大于头像直径否则相邻两张会咬边;76/92 意味着出框的头像仍露出一角,队列的存在被暗示 |
| 缩放衰减 | 1 - d*0.38,下限 0.5 | 一格距离缩到 0.62;斜率调大出框更决绝,但下限 0.5 会更早触顶,队列变成「两档尺寸」 |
| 透明度衰减 | 1 - d*0.62 | 1.6 格距离外完全消失 → 画面里始终有约 3 张可见;斜率降到 0.3 会看到整列四张都在,取景框的「锁定」语义被削弱 |
| 模糊衰减 | d*2.4,上限 3px | 模糊是景深暗示,2.4 的斜率让邻位约 2.4px;>4px 邻位糊成色块,队列读不出是头像 |
| 标签衰减 | 1 - d*2.2 | 斜率必须显著大于头像的 0.62——标签是文字,两句同时半透明叠着最难读 |
| 框脉冲 | 窗 0.1,sin(·π)× 0.07 | 7% 是「咬合了一下」的量;>15% 框自己变成主角,抢过头像更换 |
其中STEP = 76与切换点数组在源码 L23-L24 直接可见。
已知坑:落地前必须确认的六件事
- 四张头像对三次切换:
pos最终停在 3,正好是末位。加第五张必须加第四次切换(且末次切换要在 0.86 之前结束才有静置时间),否则队列末尾永远进不了框。 - 切换点是硬编码数组,出现两处(
pos累加与breath累加,即源码 L30-L33 与 L36-L39)。改节拍必须同时改两处,漏改一处会出现「框脉冲和头像换位错开」。 - 入场 stagger 与首次切换的间隔只有 0.09(入场末 0.15 → 切换 0.24)。加头像数会推后入场结束点(
0.12+k*0.03),5 张以上就要把首次切换往后挪。 - 头像用 emoji + 中性灰阶底色圆(灰度分层仅用于区分队列项,见 AV 数组),强调色只在对焦框的四个 SVG 角标上。落地换成真实头像后仍应保持这个分工,头像本身别抢色。
- 对焦框 SVG 的四条 path 与 92×92 viewBox 是写死的坐标(
M4,26 L4,4 L26,4等,见 CORNERS)。改框尺寸要整套重标,只改容器宽高会让角标缩放失真。 - 句子用 flex + gap:22px 居中,槽宽固定 92px(
flex: 'none')所以句干不会因头像更换而重排——但换成中文句子时要确认槽两侧的字宽变化不会让槽偏离画面中心。
源码原语支撑:E.spring、seg、useT 与 DesignStage
动效卡并非自造一套时间轴,而是建立在 demos/_fixtures/Motion.tsx 的公共原语之上:
seg(t, t0, t1, ease)(L33-L34):把 t 在 [t0,t1] 内归一化后过缓动函数,越界钳位——所有动效的时间轴原语。上文所有seg(t, s0, s0+0.14, ...)都在用它。E.spring(t, bounce)(L24-L27):1 - exp(-6t) * cos(w * t * bounce * 2.2),bounce 默认 0.25,即参数表中的「明确一次回弹」。useT()(L43-L47):由useCurrentFrame驱动的全片归一化进度 t∈[0,1],末帧恰为 1,与样片渲染的 t 映射逐帧一致,保证确定性。DesignStage(L54-L81):480×270 设计坐标容器,按合成分辨率等比放大(默认 transform scale,raster='zoom'时用 CSS zoom,文字密集场景字形有可感差异时选 zoom)。
这些纯函数由 Remotion 的useCurrentFrame驱动,满足确定性渲染要求——同一帧在任何机器上渲染结果一致,这正是它适合做成可复用的 shot recipe 卡片的原因。
如何查看与运行这张卡
- 看成品:该卡的视频预览收录在 gallery 媒体库(
avatar-bracket-carousel的 poster 与 mp4),画廊目录登记于 gallery/api/library.json(category:ui-entrance,source 指向 gallery/source/avatar-bracket-carousel.md)。 - 看源码:主副本在 demos/ui-entrance/avatar-bracket-carousel/AvatarBracketCarousel.tsx,workbench 侧副本在 workbench/demosrc/ui-entrance/avatar-bracket-carousel/AvatarBracketCarousel.tsx,二者结构一致。
- 运行渲染:仓库采用 Remotion 技术栈,公共依赖见根目录 package.json;demo 渲染与 smoke 测试脚本可参考 lib/scripts/smoke-render-demos.py 与 demos/_fixtures/Motion.tsx 的确定性渲染约定。修改节拍类参数时,务必同时留意
pos累加与breath累加两处硬编码数组的一致性。
- AI 技能
- 媒体生成
- 视频
【免费下载链接】video-shotcraft
AI video skill for Claude Code & Codex — cinematic product videos with Remotion: 152 shot recipe cards, 209 motion previews, a production-ready template
相关推荐
es-toolkit 兼容版 forOwn 完全指南:对象自有属性迭代的实现原理与性能取舍
es toolkit 兼容版 forOwn 完全指南:对象自有属性迭代的实现原理与性能取舍 forOwn 是 es toolkit 兼容包( es toolki
AI 技能媒体生成视频Reactive Resume:可以自托管的免费开源简历生成器
Reactive Resume:可以自托管的免费开源简历生成器 投出去 20 份简历,18 份死在机器筛选那关,先别急着重写,检查一下文件有没有被读对。Reac
AI 技能媒体生成视频video-shotcraft 镜头卡 row-embed 全解析:让详情页数据行从空中"长进"页面的入行动效实战
video shotcraft 镜头卡 row embed 全解析:让详情页数据行从空中"长进"页面的入行动效实战 导读: row embed 是 video
AI 技能媒体生成视频
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考