- 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
本篇技术指南以 video-shotcraft 仓库中的avatar-bracket-carousel镜头卡(references/shots/ui-entrance/avatar-bracket-carousel.md)为骨架,拆解"一句承诺加四次证明"的对焦框头像轮换动效:从连续位置量pos的 spring 累加、距离驱动的缩放/透明度/模糊/位移四属性同步,到参数表的每个数值手感与六条已知坑。读完你不仅能完整还原这张 5.2 秒镜头,还能在真实产品落地时独立调整节拍、步距与衰减斜率而不破坏其"锁定同一位置"的语义。
卡片定位:把"一个位置,多种角色"拍成一句话镜头
这张卡的核心意图很清晰:把能力枚举从"清单"变成"承诺加证明"。文档原文说:
"我们有设计师、客服、分析师、写手"列成四行就是一张清单。塞进一句话的一个槽位里,它变成一个承诺加四次证明:句子不动,只有槽里的人在换。
也就是说,文案骨架是 "Your ___ teammates" 这类填空排版——句子本身不参与任何动画,只有槽位里的头像在轮换。四角对焦框(bracket)是这个手法的关键:它不参与轮换,但它把观众的眼睛钉死在那 92×92 的方框里,所以四次更换才被读作"同一个位置"而不是"四张头像飘过"。对焦框的"锁定"语义正是全片的叙事支点。
卡片的元信息(卡片 front-matter)完整如下,作为后续所有参数标定的基准:
| 元信息字段 | 值 |
|---|---|
| 一句话 | "Your ___ teammates" 填空排版,四角对焦框钉在句中不动,头像队列在框内垂直 spring 轮换三次,入框放大清晰、出框按距离缩小淡化模糊,角色标签同步更换,切换瞬间对焦框呼吸 7% |
| 适用 | "一个位置,多种角色"的能力枚举;团队/身份/预设/人格类产品的核心一句话镜头 |
| 时长 | 约 5.2s(156f @ 30fps) |
| 能量 | 中(三次等距切换构成稳定节拍器,对焦框脉冲是唯一装饰性动作) |
这张卡在仓库中有三处落点,可以相互印证:
- 定稿卡片文档:references/shots/ui-entrance/avatar-bracket-carousel.md,Gallery 数据源 gallery/source/avatar-bracket-carousel.md 与之内容一致;
- 原生 Remotion 参考实现:demos/ui-entrance/avatar-bracket-carousel/AvatarBracketCarousel.tsx(workbench 内的 workbench/demosrc/ui-entrance/avatar-bracket-carousel/AvatarBracketCarousel.tsx 是同一实现的副本);
- 共享动效原语:demos/_fixtures/Motion.tsx,提供
E缓动表、seg分段进度、useT归一化时间与DesignStage设计坐标容器。
动效核心:连续位置量pos与"距离驱动一切"
整个动效只有两个内部状态,其余全部由它们推导,没有任何逐帧手排的时间轴。
1. 位置量pos:三段 spring 的累加,而不是索引跳变
let pos = 0; SWITCHES.forEach((s0) => { pos += seg(t, s0, s0 + 0.14, (k) => E.spring(k, 0.25)); });其中SWITCHES = [0.24, 0.46, 0.68],seg把归一化时间t在[s0, s0+0.14]窗口内归一化后过缓动函数并钳位(demos/_fixtures/Motion.tsx 中定义:ease(Math.min(1, Math.max(0, (t - t0) / (t1 - t0)))))。E.spring(k, 0.25)是仓库缓动表内置的阻尼弹簧:
spring: (t: number, bounce = 0.25) => { const w = 8 + 8 * (1 - bounce); return 1 - Math.exp(-6 * t) * Math.cos(w * t * bounce * 2.2); },关键点在于:pos是连续量而非离散索引。它从 0 起步,经过三次各 0.14 的 spring 行程依次推进到 1、2、3,因此任意时刻都能算出每个头像距离槽位有多远——这就是后面所有属性同步的基础。
2. 距离驱动一切:四个属性同源于一个d
对第k张头像,先求距离d = |k - pos|,然后四个属性一次算齐:
const d = Math.abs(k - pos); const sc = Math.max(0.5, 1 - d * 0.38); const op = Math.max(0, 1 - d * 0.62);渲染时:
transform: `translateY(${(k - pos) * STEP}px) scale(${sc})`, opacity: op * seg(t, 0.02 + k * 0.03, 0.12 + k * 0.03), filter: `blur(${Math.min(3, d * 2.4)}px)`,对应文档公式:
scale = max(0.5, 1 - d*0.38)opacity = max(0, 1 - d*0.62)blur = min(3, d*2.4)translateY = (k - pos) * 76
因为入框/出框的缩放、透明、模糊、位移全部由一个距离量导出,四者的变化天然同步,不需要单独为每个属性排时间轴。这是本卡最值得抄走的设计:用连续标量驱动多元属性,比给每个属性各画一段关键帧更稳健、更好调。
3. 队列叠放:0×0 锚点上的绝对定位
四张头像全部绝对定位在槽位中心缩成的 0×0 锚点上叠放(left: '50%', top: '50%', width: 0, height: 0),每张再以left: -29, top: -29自居中(头像 58px 直径),垂直位移全靠(k - pos) * STEP。框外的头像照样在渲染,只是被 opacity 与 blur 藏掉——这意味着"出框"不是销毁元素,而是同一队列在连续位置上的不同投影,轮换过程里帧与帧之间不会有任何跳变。
4. 入场层:叠在轮换之上的独立一层
入场是另一段与距离无关的透明度渐变,按索引错峰建立队列:
opacity: op * seg(t, 0.02 + k * 0.03, 0.12 + k * 0.03),四张按 0.03 的时间偏移在开场约 0.15 内依次淡入到位;此后这一项恒为 1,轮换逻辑全权接管。把"建立队列"与"轮换"分成两个独立时间层,是这张卡在时间轴组织上的第二个可复用手法。
5. 角色标签:共享pos,但衰减更陡
标签(Designer / Support / Analyst / Writer)固定在对焦框下方(translate(-50%, 64px)),位置完全不动,只随对焦位置换透明度:
opacity: Math.max(0, 1 - Math.abs(k - pos) * 2.2),衰减斜率 2.2 比头像的 0.62 陡得多——标签在 0.45 格距离外就完全消失,永远不会出现两个标签同屏半透明叠着的状态。这是文字与图像的本质差异:文字是"读"的,两句同时半透明最难读,所以标签必须用近乎硬切的衰减。
6. 对焦框呼吸:正弦包络在切换正中达峰
let breath = 0; SWITCHES.forEach((s0) => { breath += Math.sin(seg(t, s0, s0 + 0.1) * Math.PI); }); // 渲染时 transform: `scale(${1 + Math.min(1, breath) * 0.07})`,sin(seg(·) * π)的波形天然是"从 0 升到峰再回到 0"的完整包络,取min(1, breath)防止三次脉冲叠加超过 1,乘 0.07 加到 scale 上。效果是每次切换动作的正中,对焦框"咬合"一下(放大 7% 再归零),作为唯一的装饰性动作与头像换位精确对齐。呼吸走完归零,因此画面静置期对焦框尺寸完全稳定,不抢"槽位不动"的主体语义。
参数表:每个数值的调节手感
文档给出了完整的参数表,这是本卡实战调参的第一手依据,逐项说明如下(所有数值均在 480×270 设计坐标系下标定,见 demos/README.md):
| 参数 | 典型值 | 调节手感 |
|---|---|---|
| 切换点 | 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% 框自己变成主角,抢过头像更换 |
把这张表和源码 AvatarBracketCarousel.tsx 对着看,几个数值的换算关系一目了然:
- 时长核对:156f @ 30fps = 5.2s;切换间隔 0.22 × 156 ≈ 34f ≈ 1.14s;行程 0.14 × 156 ≈ 22f,占间隔 0.22 的约 64%,剩余静置约 12f;
- 步距几何:头像直径 58px,步距 76px > 58px 所以相邻不咬边;76/92 ≈ 0.83,意味着出框头像在对焦框内仍露出一角,用"露角"暗示队列继续存在,而不是彻底消失;
- 衰减协同:0.62 的透明度斜率让 1.6 格外的头像完全消失,与 0.38 的缩放斜率、2.4 的模糊斜率叠加后,画面任意时刻稳定可见约 3 张头像——这正是"取景框锁定"与"队列存在感"的平衡点。
已知坑:这张卡最容易翻车的地方
文档明确列了六条已知坑,直接决定了你改卡时不能动哪些地方:
- 四张头像对应三次切换:
pos最终停在 3,正好是末位。加第五张必须加第四次切换,且末次切换要在 0.86 之前结束才有静置时间,否则队列末尾永远进不了框。 - 切换点数组出现两处:
SWITCHES硬编码数组同时用于pos累加与breath累加。改节拍必须同步改两处,漏改一处会出现"框脉冲和头像换位错开"(源码中两处SWITCHES.forEach是同一数组引用,天然同步,但如果你复制后各自改写就要小心)。 - 入场 stagger 与首次切换的间隔只有 0.09:入场末(约 0.15)到首次切换(0.24)之间很紧。加头像数会推后入场结束点(公式
0.12 + k*0.03),5 张以上就要把首次切换往后挪。 - 色彩分工:头像是 emoji + 中性灰阶底色圆(
#4a4d59→#828796灰度分层仅用于区分队列项),强调色#3b82f6只用在对焦框的四个 SVG 角标上。落地换成真实头像后仍应保持这个分工——头像本身别抢色,否则对焦框的锁定语义会被稀释。 - 对焦框 SVG 坐标写死:四条角 path(
M4,26 L4,4 L26,4等)与 92×92 viewBox 是写死的。改框尺寸要整套重标,只改容器宽高会让角标缩放失真。 - 中文句子适配:原句 "Your ___ teammates" 用 flex + gap:22px 居中,槽宽固定 92px,句干不因头像更换而重排;但换成中文句子时要确认槽两侧的字宽变化不会让槽偏离画面中心。
如何在 Remotion 工程中运行这张卡
按 demos/README.md 的说明,Motion 系 demo(2026-08 并入的 48 张卡)的用法与普通 demo 一致:copy 需要的 .tsx 进你的 Remotion 项目,注册成 Composition 即可跑。两个差异点:
- 共享依赖是
_fixtures/Motion.tsx(不是Fixtures.tsx)——E缓动表 /seg/lerp/ 确定性rand/useT/DesignStage都在其中。copy demo 时一并带上并改 import 路径; - 画面用
<DesignStage>的 480×270 设计坐标作画、等比放大到合成分辨率,卡片参数表的数值都在此坐标系下标定,改合成分辨率不需要动参数。DesignStage的raster="zoom"模式适合文字密集场景(布局期放大,小字号字形按目标尺寸光栅化更清晰)。
每个组件同时export const <卡名大写蛇形>_DURATION(30fps 帧数),注册 Composition 时直接用。本卡导出的是AVATAR_BRACKET_CAROUSEL_DURATION = 156:
import { AvatarBracketCarousel, AVATAR_BRACKET_CAROUSEL_DURATION } from './avatar-bracket-carousel/AvatarBracketCarousel'; import { Composition } from 'remotion'; <Composition id="AvatarBracketCarousel" component={AvatarBracketCarousel} durationInFrames={AVATAR_BRACKET_CAROUSEL_DURATION} fps={30} width={1920} height={1080} />动画全部由归一化时间t(useT(),末帧恰为 1)驱动计算,无真随机,逐帧确定性渲染;该批 demo 都经过与原样片 mp4 的全帧 SSIM 比对验收。渲染环境注意点:无头 Linux 上remotion still/render在低核机器会报--concurrency上限(传--concurrency=1即可),详见 README.md 的 Headless/CI 说明。
落地到真实产品:换素材、换句子、保持语义
把这张卡从 demo 变成产品镜头时,文档给出的原则可以总结为三步:
- 头像层:emoji + 灰阶圆替换为真实头像图,但保持中性处理(可统一加同色系底圆、不引入第二强调色),队列的"角色集合"仍靠灰阶/位置区分;
- 强调色:
ACCENT = '#3b82f6'只在四角对焦框上,替换成产品品牌色即可全局换肤; - 文案层:保持"固定槽位 + 两侧句干不动"的排版策略,槽宽按新文案宽度重新标定(并对齐对焦框 SVG 的 92×92 坐标),确认居中不偏移。
最终镜头就是一个稳定的节拍器:句子不动、槽位不动、对焦框只在切换瞬间呼吸 7%,四次头像轮换把"同一个位置"的承诺反复证明。这种"连续标量驱动多元属性"的动效架构,也可以平移到其他需要"同一位置换内容"的产品镜头里复用。
- 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
相关推荐
video-shotcraft 动效卡详解:AvatarBracketCarousel 对焦框头像轮换的填空排版实现
video shotcraft 动效卡详解:AvatarBracketCarousel 对焦框头像轮换的填空排版实现 导读 本文以 gallery/source
AI 技能媒体生成视频video-shotcraft 镜头卡拆解:PillSlotCycle 句中词槽轮换的实现原理与调参实战
video shotcraft 镜头卡拆解:PillSlotCycle 句中词槽轮换的实现原理与调参实战 本篇技术指南围绕 video shotcraft ht
AI 技能媒体生成视频video-shotcraft 镜头卡实战:crash-zoom-punch 急推镜头的动效设计、参数调校与 Remotion 源码拆解
video shotcraft 镜头卡实战:crash zoom punch 急推镜头的动效设计、参数调校与 Remotion 源码拆解 导读 :crash z
AI 技能媒体生成视频
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考