Motion · Intro
Nét chữ rời ghép thành chữ
Nét đứt thành chữ — tiêu đề tách thành hơn chục đoạn nét rời không liền nhau, sáng lên không theo thứ tự; 70% đầu không đọc được, đoạn cuối vào vị trí thì ý nghĩa "bật" thành hình.
Nguồn: video-shotcraft (Vincent Wei) ↗ · Apache-2.0 · Composition Remotion (React/TSX) — có video preview, không có player trong trình duyệt
Khi nào dùng
Mở đầu tạo hồi hộp cho tên sản phẩm/con số lớn được tiết lộ; một phim dùng ≤1 lần; phân vai với type-assembly/draw-svg-trace: các thẻ đó là "xem chữ được lắp ráp/vẽ ra", thẻ này là "ý nghĩa trì hoãn tiết lộ"
Ý đồ
Án lệ tiêu đề phim Alien: tiêu đề không phải được vẽ ra, mà "hiện hình" — tách thành các đoạn nét rời rạc sáng lên không theo thứ tự, 70% thời gian đầu khán giả chỉ thấy các đoạn bí ẩn, đến vài đoạn cuối vào vị trí thì đột nhiên đọc ra đó là chữ gì. "Khoảnh khắc nhận ra" chính là cái móc câu, độ mạnh của móc câu phụ thuộc vào thời gian không đọc được kéo dài bao lâu và đoạn chìa khóa bị nén lại muộn tới đâu.
Thời lượng & năng lượng
- Thời lượng: 4–5s
- Năng lượng: Thấp lúc đầu, dâng lên lúc kết (kiểu hồi hộp, khung hình vào vị trí là điểm năng lượng)
Công thức cảnh quay (bản gốc tiếng Trung — timing, easing, bảng tham số, lỗi hay gặp)
意图
《异形》片头判例:标题不是被画出来的,是"显影"出来的——拆成离散 笔画段乱序点亮,观众前 70% 时间只看到神秘碎段,最后几段落位的瞬间 突然读出是什么字。"认出的那一刻"就是钩子,钩子的强度取决于 不可读期撑多久、钥匙段压多晚。
动作阶段
| 阶段 | 帧段参考 | 内容 | |------|------|------| | 1 暗场 | f0–10 | 空场静置 | | 2 乱序点亮 | ~f10–105 | 每段 6f(opacity 0→1 + 沿笔画方向 12px 滑入 out cubic),段间隔 6f 错峰 | | 3 落位脉冲 | 末段落位帧 | 整字 scale 1→1.06→1 脉冲 8f | | 4 定格 | 末 ≥30f | 真静止,可接 hold 满 1s(R1 品牌位) |
参数表
| 参数 | 典型值 | 调节手感 | |------|--------|----------| | 拆段粒度 | 4 字母 ~16 段(SVG line 粗方端帽,44px 级线宽) | 段太少悬念期短;太碎读作噪点 | | 乱序表 | 手工排:跨字母乱跳,"可读性钥匙段"(如 H 中横)压到最后 2–3 段 | 顺序点亮 = 没有悬念;钥匙段早出 = 提前泄底 | | 不可读期 | 总时长的 60–70% 处仍应读不出字 | QA 抽中段帧自问"能猜出来吗",能猜出就重排 | | 落位脉冲 | scale 1.06 / 8f | demo 自评 6% 偏含蓄,实战可加大到 1.10 | | 未亮段 | 条件不渲染(非 opacity 0) | 收尾真静止的前提 |
已知坑
- demo 在灰阶/占位素材上调校通过——参数是调校起点非实战定稿,
首次实战须以真实素材回验
- 暗底上的辅助文字用亮灰——demo 首版顶部标题深灰压深底不可见(P1 自检抓到)
- 字数上限:4–6 字母词最佳;长词不可读期难控制,段数爆炸
- 本卡吃"识别瞬间",标题必须是观众认识的词(产品名/SHIP/LIVE 类),
生造词没有"认出"可言
- 声音:逐段点亮稀疏轻拟音或无声,落位帧一声 impact + 可接 riser 铺底
参考实现
demos/opening/stroke-segment-build/ (StrokeSegmentBuild.tsx)
Mã nguồn tham chiếu (Remotion)
- demos/opening/stroke-segment-build/StrokeSegmentBuild.tsx — https://raw.githubusercontent.com/Vincentwei1021/video-shotcraft/main/demos/opening/stroke-segment-build/StrokeSegmentBuild.tsx
Component import fixture chung từ demos/_fixtures và helper từ assets/lib của repo; xem SKILL.md trong repo để biết quy trình render.
Mọi thứ trên trang này đều có bản máy đọc. Đưa agent link JSON, hoặc thêm MCP server gimgs rồi bảo nó tìm motion template.
- Tải JSON — trong đó có công thức cảnh quay (timing, easing, bảng tham số, lỗi hay gặp) và toàn bộ source TSX.
- Clone repo video-shotcraft; component import fixture chung từ demos/_fixtures và helper từ assets/lib.
- Đăng ký component thành <Composition> trong project Remotion rồi render bằng `npx remotion render`, hoặc dựng lại công thức bằng engine của bạn.
curl -s https://gimgs.net/motion/stroke-segment-build.jsongit clone https://github.com/Vincentwei1021/video-shotcraft
# component: demos/opening/stroke-segment-build/StrokeSegmentBuild.tsx
npx remotion render <CompositionId> out.mp4claude mcp add --transport http gimgs https://gimgs.net/mcp
# then: search_motion_templates / get_motion_template("stroke-segment-build")Prompt
Use the video-shotcraft shot recipe "Nét chữ rời ghép thành chữ" (Remotion composition, Apache-2.0) published on gimgs.net. Recipe JSON (prompt = timing/easing/parameter table/pitfalls, files = TSX source): https://gimgs.net/motion/stroke-segment-build.json Raw TSX: https://gimgs.net/motion/stroke-segment-build/template.html Repository: https://github.com/Vincentwei1021/video-shotcraft (component: demos/opening/stroke-segment-build/StrokeSegmentBuild.tsx; imports demos/_fixtures and assets/lib) Spec: 1920x1080, 30 fps, 5.06s 1. Read the JSON and follow its "prompt" section (when to use, intention, parameter table, known pitfalls). 2. Adapt it for: <describe what you want>. 3. Either clone the repo, register the component as a <Composition> in a Remotion project and run npx remotion render <CompositionId> out.mp4 — or re-implement the recipe in your own engine (HTML/WAAPI works: keep the same timing and easing).
// ===== demos/opening/stroke-segment-build/StrokeSegmentBuild.tsx =====
// stroke-segment-build —— 断笔成字(《异形》式)
// "SHIP" 拆成 16 段互不相连的粗线段,按乱序表逐段点亮。
// 前 70%(11 段)读不出字,最后 3 段落位瞬间突然可读;
// 末段落位帧整字轻微 scale 脉冲(1→1.06→1)。
// 每段入场:opacity 0→1 + 沿笔画方向 12px 滑入(out 缓动),6f。
// f0–14 静置空场;末段落位于 f104,脉冲至 f112,真静止 ≥38f(150f 总长)。
import React from 'react';
import { useCurrentFrame, interpolate, Easing } from 'remotion';
import { G, TitleBlock } from '../../_fixtures/Fixtures';
// "SHIP" 手工笔画段。坐标系:每字 200 宽、320 高,字间距 60。
// 段 = {x1,y1,x2,y2},线宽 44,方形端帽(不连续感更强)。
type Seg = { x1: number; y1: number; x2: number; y2: number };
const K = 200; // 字宽
const H = 320; // 字高
const ADV = K + 60;
// S:4 段(上横、左上竖、中横、右下竖+下横 → 拆成 5 也行,取 4)
// H:3 段(左竖、右竖、中横)
// I:3 段(上横、中竖、下横)
// P:4 段(左竖、上横、右短竖、中横)—— 共 14 段;S 再拆 2 段成 16
const SEGS: Seg[] = [
// S (x offset 0) —— 6 段
{ x1: 30, y1: 22, x2: 185, y2: 22 }, // 0 上横
{ x1: 22, y1: 44, x2: 22, y2: 130 }, // 1 左上竖
{ x1: 30, y1: 152, x2: 175, y2: 152 }, // 2 中横
{ x1: 178, y1: 174, x2: 178, y2: 276 }, // 3 右下竖
{ x1: 15, y1: 298, x2: 170, y2: 298 }, // 4 下横
{ x1: 22, y1: 240, x2: 22, y2: 276 }, // 5 左下小竖(S 尾钩)
// H (x offset ADV) —— 3 段
{ x1: ADV + 22, y1: 22, x2: ADV + 22, y2: 298 }, // 6 左竖
{ x1: ADV + 178, y1: 22, x2: ADV + 178, y2: 298 }, // 7 右竖
{ x1: ADV + 44, y1: 160, x2: ADV + 156, y2: 160 }, // 8 中横
// I (x offset ADV*2) —— 3 段
{ x1: ADV * 2 + 40, y1: 22, x2: ADV * 2 + 160, y2: 22 }, // 9 上横
{ x1: ADV * 2 + 100, y1: 44, x2: ADV * 2 + 100, y2: 276 }, // 10 中竖
{ x1: ADV * 2 + 40, y1: 298, x2: ADV * 2 + 160, y2: 298 }, // 11 下横
// P (x offset ADV*3) —— 4 段
{ x1: ADV * 3 + 22, y1: 22, x2: ADV * 3 + 22, y2: 298 }, // 12 左竖
{ x1: ADV * 3 + 44, y1: 22, x2: ADV * 3 + 165, y2: 22 }, // 13 上横
{ x1: ADV * 3 + 178, y1: 44, x2: ADV * 3 + 178, y2: 140 }, // 14 右短竖
{ x1: ADV * 3 + 44, y1: 162, x2: ADV * 3 + 165, y2: 162 }, // 15 中横
];
// 乱序点亮表:刻意打散——前 13 段跨字乱跳(读不出),
// 最后 3 段(8 中横 / 10 I 竖 / 12 P 左竖)落位瞬间补全可读性。
const ORDER = [3, 9, 6, 15, 1, 11, 14, 4, 0, 7, 13, 2, 5, 8, 10, 12];
const FIRST = 14; // 首段起始帧
const STEP = 6; // 段间隔
const SEG_IN = 6; // 单段入场时长
const LAST_LAND = FIRST + 15 * STEP + SEG_IN; // = 110,末段落位
const PULSE_END = LAST_LAND + 8;
const WORD_W = ADV * 3 + K; // 980
const OX = (1920 - WORD_W) / 2;
const OY = (1080 - H) / 2 + 20;
export const StrokeSegmentBuild: React.FC = () => {
const frame = useCurrentFrame();
// 末段落位:整字脉冲 1 → 1.06 → 1(8f)
const pulse = interpolate(
frame,
[LAST_LAND, LAST_LAND + 3, PULSE_END],
[1, 1.06, 1],
{ easing: Easing.out(Easing.cubic), extrapolateLeft: 'clamp', extrapolateRight: 'clamp' },
);
return (
<div style={{ width: 1920, height: 1080, background: G.ink, overflow: 'hidden', position: 'relative' }}>
<div
style={{
position: 'absolute',
top: 110,
width: '100%',
textAlign: 'center',
fontFamily: 'Helvetica, Arial, sans-serif',
fontWeight: 800,
fontSize: 44,
color: G.mid,
letterSpacing: 2,
}}
>
STROKE SEGMENT BUILD
</div>
<svg
width={1920}
height={1080}
style={{ position: 'absolute', left: 0, top: 0, transform: `scale(${pulse})`, transformOrigin: '50% 55%' }}
>
{SEGS.map((seg, i) => {
const rank = ORDER.indexOf(i);
const start = FIRST + rank * STEP;
if (frame < start) return null; // 未开始的段不渲染
const t = interpolate(frame, [start, start + SEG_IN], [0, 1], {
easing: Easing.out(Easing.cubic),
extrapolateLeft: 'clamp',
extrapolateRight: 'clamp',
});
// 沿笔画方向滑入 12px
const dx = seg.x2 - seg.x1;
const dy = seg.y2 - seg.y1;
const len = Math.hypot(dx, dy) || 1;
const slide = 12 * (1 - t);
const ox = (-dx / len) * slide;
const oy = (-dy / len) * slide;
return (
<line
key={i}
x1={OX + seg.x1 + ox}
y1={OY + seg.y1 + oy}
x2={OX + seg.x2 + ox}
y2={OY + seg.y2 + oy}
stroke={G.panel}
strokeWidth={44}
strokeLinecap="butt"
opacity={t}
/>
);
})}
</svg>
</div>
);
};
- Read the recipePrompt = when to use, intention, parameter table with typical values and how each one feels, known pitfalls. Treat values as calibrated starting points.
- Get the codetool: git
git clone https://github.com/Vincentwei1021/video-shotcraft && cd video-shotcraft && npm install - Register + rendertool: remotion
npx remotion render <CompositionId> out.mp4 # component: demos/opening/stroke-segment-build/StrokeSegmentBuild.tsx - Or re-implementPort the timing/easing from the recipe to HTML + WAAPI (gimgs motion contract) or any engine; keep the same segment windows and easing.
| param | type | default | description |
|---|---|---|---|
| — | |||
Cùng danh mục

Chữ làm mặt nạ video
Chữ làm mặt nạ video — tiêu đề chữ siêu đậm để lộ hình sản phẩm lướt chậm bên trong, cuối đoạn chữ phóng to 26 lần tràn khung, hình bên trong tiếp quản toàn màn hình.

Đèn spotlight rọi thẻ hero
Đèn spotlight quét qua trang khóa vào một thẻ, đẩy máy nghiêng 45° rồi thẻ bật lên lơ lửng, luồng sáng quét quanh viền hai vòng, rồi áp lại vị trí cũ.

Vòng quỹ đạo mở tiêu đề
Tám thẻ nội dung xoay quanh hình elip 700×375 với tốc độ đều trong khi tiêu đề giữa màn hình rõ nét dần rồi an vị.

Ảo thuật lật bài xuất hiện
Trên nền đen tuyền, một tia sáng hình sao xanh chớp lên 0.3s, rồi một lá bài bắn ra từ điểm chớp sáng — xoay cực nhanh theo cung bay về phía máy quay, tốc độ xoay giảm dần khi tới gần, đóng băng cứng gần đầy khung hình, sau đó có một lần quét ánh sáng.