Motion · Ánh sáng & nhấn
Va chạm in Riso
Hai kiểu lệch bản in: misregistration-hit va chạm một phát tách hai màu rồi rung khớp lại, và beat-pump là bản lặp theo nhịp.
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
Biến thể
Tiêu đề va vào và dừng cứng trong 8f, tách hai bản lệch nhau ~32px theo hướng ngược nhau, dao động tắt dần trong 44f rồi cắt cứng khớp bản kèm rung nhấn scale.
Đóng dấu va chạm dùng 1-2 lần trong cả phim; khoảnh khắc tiêu đề/chữ lớn vào đúng vị trí
Mỗi 24f một nhịp: toàn khung hình nhảy vọt scale 1.08 rồi hạ theo hàm mũ, kèm lệch bản tiêu đề tăng dần theo từng nhịp 8/14/22/32px trước khi khớp bản.
Đoạn nhạc bắt điểm nhịp; chuỗi va chạm tích lũy kiểu "càng đánh càng mạnh"
Khi nào dùng
Nhấn mạnh cú va chạm cho tiêu đề/thẻ, phiên bản "nhấp nháy lỗi" kiểu thẩm mỹ giấy/mực; A cao trào một phát, B liên tục theo đoạn nhịp
Ý đồ
Nhấp nháy lỗi tán sắc RGB (một phần của kiểu C trong impact-feedback) là ngôn ngữ thuộc về màn hình, xung khắc với tông giấy/mực. Hai kiểu này đưa ra phiên bản thay thế theo lối in ấn: yếu tố tách thành hai bản in đơn sắc xám nhạt/mực đậm (cảm giác mực chồng multiply chứ không phải phát sáng screen), như một bản in risograph chưa khớp, rung vài cái rồi "bốp" khớp lại — cùng lực va chạm, nhưng chất liệu tưởng tượng đổi hẳn sang mực trên giấy. A là một phát: khoảnh khắc va chạm dừng hình tách bản, rung tắt dần, rồi cắt cứng khớp bản + rung nhấn scale, đóng dấu một cú va chạm; B là phiên bản theo nhịp của nó: mỗi tiếng trống toàn khung hình nhảy 8% + tiêu đề tách bản, lệch bản tăng dần theo từng nhịp — càng đánh càng mạnh, một tiếng trống bass thị giác cho đoạn theo nhịp. Cùng gốc kỹ thuật (lệch hai bản dao động tắt dần), chọn một phát hoặc đánh liên tục.
Thời lượng & năng lượng
- Thời lượng: A 4s (một phát); B 4.7s (bốn nhịp)
- Năng lượng: Cao
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)
意图
RGB 色散故障闪(impact-feedback C 式的一部分)是荧光屏语言,与纸墨 调性相克。这两式给出印刷版平替:元素裂成浅灰/深墨两份单色印版 (multiply 油墨感而非 screen 荧光感),像 risograph 没对准版,抖几下 "啪"地套准——同样的冲击力,介质想象完全换成纸上油墨。A 是单发: 撞停瞬间裂版、震荡衰减、硬切套准,给一次命中盖章;B 是它的节奏化: 每个鼓点整画面跳大 8% + 标题裂版,错位逐拍加码,越打越狠—— 卡点段的视觉低音鼓。同技术根(衰减震荡的双版错位),单发/连打二选一。
两式选型
| 式 | 做法 | 适用 | |----|------|------| | A misregistration-hit 单发 | 标题 8f 撞入撞停,裂两版反向错 ~32px,44f 衰减震荡后硬切套准 + scale 脉冲 | 全片 1–2 次的命中盖章;标题/大字的到位一瞬 | | B beat-pump 节拍泵 | 每 24f 一拍:整画面瞬跳 1.08 指数回落 + 标题错版逐拍 8/14/22/32px 加码套准 | 音乐卡点段;"越打越狠"的蓄力连打 |
参数表
| 参数 | 典型值 | 调节手感 | |------|--------|----------| | 双版 | 浅灰版(G.mid)+ 深墨版(G.ink),mix-blend-mode: multiply,位移反向 | multiply 叠出的重影灰阶就是"油墨没对准";screen 叠加立刻变荧光故障 | | A 错位包络 | offset = A·cos(2πt/18)·exp(-t/60),A=(16,7)px 两版反向;帧 72 硬切归零 | 命门:套准是硬切跳变不是渐收——衰减到 ~14px 残余时啪地归零才有"啪";纯渐收读不出套准一拍 | | A 撞入 | 8f Easing.in(cubic) 从画外撞停,命中帧即裂版 | 裂版必须与撞停同帧——晚 2f 就读作两件事 | | A 套准脉冲 | 归零帧 4f scale 1.03→1 | 盖章的一拍;省略则套准无重量 | | B 泵 | scale = 1 + 0.08·exp(-t/3)(t=0 即满值、一帧到位无渐入),14f 窗口外精确归 1 | 瞬跳是"顿推"本体——加渐入就成了普通 zoom 呼吸 | | B 错版加码 | AMP 逐拍 4/7/11/16px(单版,双版反向即总分离 8/14/22/32px),AMP·cos(2πt/6)·exp(-t/3) 12f 窗口 | 逐次加码是命门(同 hit-counter 判例):四拍一样大读不出"越打越狠" | | B 作用域 | scale 作用整画面容器,错版只作用标题 | 整画面全裂读作故障而非印刷 | | B 节拍参照物 | 底部节拍刻度点,命中闪深常驻 | 静音预览环境的节拍可读性 | | 收尾 | A 套准后 ≥40f / B 末拍归零后 ≥20f 真静止 | R1 |
已知坑
- demo 在灰阶/占位素材上调校通过——参数是调校起点非实战定稿,
首次实战须以真实素材回验
- 错位幅度可感性判例(本批实渲):词汇表原案 ±5px 在 1920 宽画面
正常速度下肉眼几乎不可见——单版 16px/总分离 32px 起步才可感; 幅度存疑时做极端版给用户看(可感性优先)
- 两式与 impact-feedback C(负片冲击帧)语义重叠——纸墨调性片子用本卡、
游戏/动漫调性用 C 式,同片不并用(P4)
- B 式是声音强依赖:命中帧必须钉鼓点(sound-design §4.5);无音轨
段落读作画面抽搐
- A 式错位方向一横一纵混合(x 为主 y 少量)更像没对准版;纯横向读作
左右晃动
- B 式四拍后必须接足量 hold(≥24f)——连打完不还呼吸,观众的耳朵还
在等第五拍
参考实现
demos/effects/riso-print-hits/ (RisoBeatPump.tsx / RisoMisregistrationHit.tsx)
Mã nguồn tham chiếu (Remotion)
- demos/effects/riso-print-hits/RisoBeatPump.tsx — https://raw.githubusercontent.com/Vincentwei1021/video-shotcraft/main/demos/effects/riso-print-hits/RisoBeatPump.tsx
- demos/effects/riso-print-hits/RisoMisregistrationHit.tsx — https://raw.githubusercontent.com/Vincentwei1021/video-shotcraft/main/demos/effects/riso-print-hits/RisoMisregistrationHit.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/riso-print-hits.jsongit clone https://github.com/Vincentwei1021/video-shotcraft
# component: demos/effects/riso-print-hits/RisoBeatPump.tsx, demos/effects/riso-print-hits/RisoMisregistrationHit.tsx
npx remotion render <CompositionId> out.mp4claude mcp add --transport http gimgs https://gimgs.net/mcp
# then: search_motion_templates / get_motion_template("riso-print-hits")Prompt
Use the video-shotcraft shot recipe "Va chạm in Riso" (Remotion composition, Apache-2.0) published on gimgs.net. Recipe JSON (prompt = timing/easing/parameter table/pitfalls, files = TSX source): https://gimgs.net/motion/riso-print-hits.json Raw TSX: https://gimgs.net/motion/riso-print-hits/template.html Repository: https://github.com/Vincentwei1021/video-shotcraft (component: demos/effects/riso-print-hits/RisoBeatPump.tsx, demos/effects/riso-print-hits/RisoMisregistrationHit.tsx; imports demos/_fixtures and assets/lib) Spec: 1920x1080, 30 fps, 4.05s 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/effects/riso-print-hits/RisoBeatPump.tsx =====
// 套印节拍泵(riso-beat-pump)——beat-punch-in(卡点顿推)× riso-misregistration-hit
// (套印错位)的组合节奏。节拍帧 [30,54,78,102](每 24f 一拍),每命中帧:
// ① 整画面 scale 一帧瞬跳 1.08(无渐入),14f 内按 exp(-t/3) 指数衰减回 1;
// ② 标题裂成 G.mid/G.ink 双色印版 multiply 错位,初始错位逐拍加码 4/7/11/16px
// (每版反向 → 总分离 8/14/22/32px),12f 衰减余弦震荡收敛套准;
// ③ 底部对应节拍刻度点闪深并常驻。结构:0–29f hold;30–115f 四拍;116–139f 真静止。
import React from 'react';
import { useCurrentFrame } from 'remotion';
import { G, Card, TitleBlock } from '../../_fixtures/Fixtures';
const HITS = [30, 54, 78, 102]; // 节拍命中帧
const AMP = [4, 7, 11, 16]; // 每拍单版初始错位(px),逐拍加码
const PUMP_WIN = 14; // scale 泵窗口:14f 后精确归 1(保证结尾真静止)
const SPLIT_WIN = 12; // 错位窗口:12f 后精确归 0(余量 <0.4px,硬切套准)
// 与 TitleBlock 同字形的单色印版(错位需要可调色副本)
const Plate: React.FC<{ color: string; dx: number; dy: number }> = ({ color, dx, dy }) => (
<div
style={{
position: 'absolute',
inset: 0,
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
transform: `translate(${dx}px, ${dy}px)`,
mixBlendMode: 'multiply',
}}
>
<div
style={{
fontFamily: 'Helvetica, Arial, sans-serif',
fontWeight: 800,
fontSize: 160,
color,
letterSpacing: -1,
whiteSpace: 'nowrap',
}}
>
ON THE BEAT
</div>
</div>
);
export const RisoBeatPump: React.FC = () => {
const frame = useCurrentFrame();
// 找最近一次已命中的节拍(24f 间隔 > 14f 窗口,永远只有一拍在作用)
let beatIdx = -1;
for (let i = 0; i < HITS.length; i++) {
if (frame >= HITS[i]) beatIdx = i;
}
const t = beatIdx >= 0 ? frame - HITS[beatIdx] : Infinity;
// ① 整画面泵:命中帧一帧到位 1.08(t=0 即满值,无渐入),指数衰减回 1
const pump = t < PUMP_WIN ? 1 + 0.08 * Math.exp(-t / 3) : 1;
// ② 标题错位:衰减余弦震荡(周期 6f 抖两下),窗口外精确 0 = 套准
const split = t < SPLIT_WIN;
const m = split ? Math.cos((2 * Math.PI * t) / 6) * Math.exp(-t / 3) : 0;
const dx = beatIdx >= 0 ? AMP[beatIdx] * m : 0;
const dy = dx * 0.45; // y 少量,更像没对准版
return (
<div
style={{
width: 1920,
height: 1080,
background: G.bg,
position: 'relative',
overflow: 'hidden',
}}
>
{/* 整画面容器:scale 泵作用在全部内容上 */}
<div
style={{
position: 'absolute',
inset: 0,
transform: `scale(${pump})`,
transformOrigin: 'center center',
}}
>
{/* 标题区:正体 / 双版错位互斥切换 */}
<div style={{ position: 'absolute', left: 0, right: 0, top: 0, height: 660 }}>
{!split && (
<div
style={{
position: 'absolute',
inset: 0,
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
}}
>
<TitleBlock text="ON THE BEAT" size={160} />
</div>
)}
{split && (
<>
<Plate color={G.mid} dx={-dx} dy={dy} />
<Plate color={G.ink} dx={dx} dy={-dy} />
</>
)}
</div>
{/* 底下一排 3 张小卡 */}
<div
style={{
position: 'absolute',
left: 0,
right: 0,
top: 660,
display: 'flex',
justifyContent: 'center',
gap: 44,
}}
>
<Card w={330} h={200} seed={2} />
<Card w={330} h={200} seed={5} />
<Card w={330} h={200} seed={8} />
</div>
{/* 节拍刻度:命中即闪深(8f 缩放脉冲 1.8→1)并常驻深色 */}
<div
style={{
position: 'absolute',
left: 0,
right: 0,
top: 950,
display: 'flex',
justifyContent: 'center',
gap: 60,
}}
>
{HITS.map((hit, i) => {
const dt = frame - hit;
const on = dt >= 0;
const s = on && dt < 8 ? 1 + 0.8 * (1 - dt / 8) : 1;
return (
<div
key={i}
style={{
width: 22,
height: 22,
borderRadius: 11,
background: on ? G.ink : G.bar,
transform: `scale(${s})`,
}}
/>
);
})}
</div>
</div>
</div>
);
};
// ===== demos/effects/riso-print-hits/RisoMisregistrationHit.tsx =====
// 套印错位冲击帧(riso-misregistration-hit)——标题撞停瞬间裂成两份单色"印版"
// (浅灰琥珀版 G.mid + 深墨版 G.ink,mix-blend-mode: multiply 叠加),像 riso 印刷
// 没对准版;两版反向错位(x 为主 y 少量)做衰减震荡 offset = A*cos(ωt)*exp(-t/τ)
// 抖两下,帧 72 啪地硬切回单一正体(套准合一),带 4f scale 1.03→1 脉冲收束。
// 结构:0–19f 空场 hold(只有底部装饰线);20–28f 标题从右画外 Easing.in(cubic)
// 撞入屏心(帧 28 命中);28–71f 双版错位震荡;72–75f 套准脉冲;76–119f 真静止 44f。
import React from 'react';
import { useCurrentFrame, interpolate, Easing } from 'remotion';
import { G, TitleBlock } from '../../_fixtures/Fixtures';
const HIT = 28; // 撞停命中帧
const SNAP = 72; // 套准合一帧
const AX = 16; // 单版 x 错位振幅(两版反向 → 总分离 ~32px,肉眼明显)
const AY = 7; // 单版 y 错位振幅(少量,更像没对准版)
const OMEGA = (2 * Math.PI) / 18; // 震荡周期 18f,44f 内抖两下半
const TAU = 60; // 缓衰减:帧 72 前仍余 ~14px 总分离,被"啪地"硬切归零
// 与 TitleBlock 同字形的可调色标题(错位印版需要单色副本)
const Plate: React.FC<{ color: string; dx: number; dy: number }> = ({ color, dx, dy }) => (
<div
style={{
position: 'absolute',
inset: 0,
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
transform: `translate(${dx}px, ${dy}px)`,
mixBlendMode: 'multiply',
}}
>
<div
style={{
fontFamily: 'Helvetica, Arial, sans-serif',
fontWeight: 800,
fontSize: 200,
color,
letterSpacing: -1,
whiteSpace: 'nowrap',
}}
>
IMPACT
</div>
</div>
);
export const RisoMisregistrationHit: React.FC = () => {
const frame = useCurrentFrame();
// 阶段判定
const entering = frame >= 20 && frame < HIT; // 撞入
const split = frame >= HIT && frame < SNAP; // 双版错位震荡
const showSingle = frame < HIT || frame >= SNAP; // 正体(画外/撞入/套准后)
// 撞入位移:右画外 1400px → 0,8f Easing.in(cubic)(加速撞停)
const slideX = interpolate(frame, [20, HIT], [1400, 0], {
easing: Easing.in(Easing.cubic),
extrapolateLeft: 'clamp',
extrapolateRight: 'clamp',
});
// 错位震荡包络:t 自命中起,衰减余弦(帧 72 前仍有可见残余,硬切归零成"啪")
const t = frame - HIT;
const m = split ? Math.cos(OMEGA * t) * Math.exp(-t / TAU) : 0;
const dx = AX * m;
const dy = AY * m;
// 套准合一脉冲:帧 72 起 4f scale 1.03 → 1,之后精确 1(保证结尾真静止)
const pulse =
frame >= SNAP && frame < SNAP + 4 ? 1 + 0.03 * (1 - (frame - SNAP) / 4) : 1;
return (
<div
style={{
width: 1920,
height: 1080,
background: G.bg,
position: 'relative',
overflow: 'hidden',
}}
>
{/* 底部装饰线:全程静止的布景锚点 */}
<div
style={{
position: 'absolute',
left: 510,
top: 740,
width: 900,
height: 6,
borderRadius: 3,
background: G.bar,
}}
/>
{/* 正体:画外等待 / 撞入 / 套准后(撞入前 frame<20 时在画外,视觉等同空场) */}
{showSingle && (
<div
style={{
position: 'absolute',
inset: 0,
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
transform: `translateX(${entering || frame < 20 ? slideX : 0}px) scale(${pulse})`,
transformOrigin: 'center center',
}}
>
<TitleBlock text="IMPACT" size={200} />
</div>
)}
{/* 双版错位:浅灰版与深墨版反向偏移,multiply 叠加出"重影套印" */}
{split && (
<>
<Plate color={G.mid} dx={-dx} dy={dy} />
<Plate color={G.ink} dx={dx} dy={-dy} />
</>
)}
</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/effects/riso-print-hits/RisoBeatPump.tsx, demos/effects/riso-print-hits/RisoMisregistrationHit.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

Đèn rọi hiện hình trên nền tối
Ba kiểu đèn rọi hiện hình trên nền tối — A quét thức-ngủ (đèn tới thì sáng, đèn đi thì tối), B quét ngang rìa viền (ánh tím bám mép UI thấm vào + đèn quét phải đều), C hiện hình đều từ góc (đèn hình tròn nở đều từ góc sáng cả màn hình); ánh sáng chính là lời kể trên nền đen.

Đập vào cảnh năng lượng cao
Ba kiểu đập vào cảnh năng lượng cao: dừng phối cảnh kiểu Kanada, đập rơi tỷ số, hoặc lan chấn động sang thẻ lân cận.

Vệt sáng quét lắp ráp bay vào
Vệt sáng quét từ trên xuống lưới nền tối trống, tới đâu thành phần vùng đó bay vào khớp vị trí — quét xong là lắp ráp xong.

Vệt sáng quét chú thích tiêu điểm
Một vệt sáng quét từ trên xuống dưới trang, khoanh khung ngắm kiểu máy ảnh vào từng vùng nó đi qua rồi gắn chú thích chữ mono.