Motion · Typography
Glitch status cycle
The same slot cycles through 4 status phrases, each scrambling fully at the head and tail with occasional mid-phrase jitter, RGB split and a full-line shift at each switch; the last phrase resolves clean.
Source: video-shotcraft (Vincent Wei) ↗ · Apache-2.0 · Remotion composition (React/TSX) — preview video, no in-browser player
When to use
Status broadcasting for loading/build/deploy processes; the "system self-narration" of a tech-flavored opener; a backdrop for advancing time with a machine voice.
Intention
The clumsiest way to broadcast status is four lines fading in one after another. Cycling compresses them into one slot: each phrase "burns out" into scramble at head and tail then "solidifies", staying almost clean mid-phrase with only occasional twitches — what the audience reads is "the system is progressing step by step", not four independent captions. Scramble density is this card's grammar: dense = switching, clean = currently in this state. A progress bar at the bottom strings the four beats into one timeline, and the last phrase's probability resolves to 0 so it ends the moment it settles.
Duration & energy
- Duration: About 5.6s (168f@30fps, 4 phrases at 42f each)
- Energy: Medium-high (a sustained high-frequency noise pulse, with switch points as peaks)
Shot recipe (original Chinese — timing, easing, parameter table, known pitfalls)
意图
状态播报最笨的做法是四行字逐条淡入。轮播把它们压进一个槽位: 短语头尾用乱码"熔断"再"凝固",中段几乎干净只偶尔抽一下——观众读到的 是"系统在一步步推进",而不是四条独立文案。乱码浓度是这卡的语法: 浓 = 正在切换,淡 = 正在这一状态里。底部进度条把四拍串成一条时间线, 最后一条把概率收到 0,落定即结束。
动效核心
- 槽位按最长短语预建
MAXCH个 span(min-width:0.66em固定槽宽),
短短语右侧填空格——字符不增删,只换内容,整行永不重排
- 时段等分:
slot = floor(t·4),短语内进度p = t·4 - slot(每条 42f) - glitch 概率关键帧
KF=[1,0,0,0.1,0,0,1]按 p 线性插值:**开头 1.0 全乱、
中段 0、约 p=0.5 处回弹到 0.1(偶发抽字)、结尾又回 1.0 熔进下一条**
- 末条专用
KF_LAST=[1,0,0,0.1,0,0,0],结尾概率归零 → t=1 画面干净 - 逐字符判定:
rand(i·31 + bucket·17 + slot·97) < g才替换成字池字符,
命中字随机上 #6c8cff 蓝或 #4a5270 暗灰;bucket = floor(frame/2), 即每 2 帧重掷一次
- 整行抖动与 RGB 分离强度全部乘 g:
jx = ±g·10px、jy = ±g·4px,
text-shadow 左红右青各偏 g·3px(g>0.04 才开)——噪声浓度一个变量 同时驱动换字、位移、色散,所以三者永不打架;底部 120×2px 进度条 width = t·100% 线性走满,与四拍无关地铺底
参数表
| 参数 | 典型值 | 调节手感 | |------|--------|----------| | 短语表 | 4 条,最长 17 字符(COMPILING SHADERS) | 每条 42f 是"读得完一个状态"的下限;5 条以上单条不足 34f 观众只看到闪 | | 概率关键帧 | [1,0,0,0.1,0,0,1](6 段) | 中间那个 0.1 是"活着"的证据,删了短语中段死板;把 0 段调到 0.3+ 全片糊成故障 | | 重掷频率 | 每 2 帧(floor(frame/2)) | 1 帧一换糊成灰带;4 帧以上乱码看得清是"另一个词",不像噪声 | | 抖动幅度 | x ±g·10 / y ±g·4px | x 大于 y 是横向撕裂的关键(等比抖动读作地震);>20px 整行跳出槽位 | | RGB 分离 | 左红右青各 g·3px,阈值 g>0.04 | 这是"电子故障"的身份证;无阈值时中段那 0.1 的概率会让字常年带毛边 | | 槽宽字体 | SF Mono 26px、letter-spacing:3px、槽 0.66em | 等宽 + 固定槽宽是刚需;字距 3px 让乱码之间有呼吸,挤在一起读作乱码块 | | 进度条 | 120×2px,#6c8cff 填充,线性 | 唯一的线性元素,给四拍噪声一个稳定参照;删了轮播读不出"在推进" |
已知坑
- demo 在灰阶/占位素材上调校通过——参数是调校起点非实战定稿,
首次实战须以真实素材回验
- 换项目文案时四条短语字符数要接近(demo 12–17 字符):槽位数按最长
短语一次建好,短短语靠右填空格——如果一条只有 4 字符、另一条 30 字符, 短的那条在 30 格里孤零零居左,行宽全程被最长条撑着,节奏读作漂移
- 概率关键帧是 6 段等分映射到短语内进度:短语条数变了单条时长跟着变,
但关键帧形状不变——所以条数越多,"全乱码"那两段的绝对时长越短, 切换感越弱,超过 5 条就该把首尾的 1.0 段拉宽
- 末条必须用
KF_LAST(结尾收 0):用普通 KF 会让 t=1 停在满乱码上,
接下一镜时读作没渲染完
- 深底专用:#0a0b10 底 + 冷蓝噪声是整套配色的地基,浅底上 RGB 分离
几乎不可见;声音也强依赖——四个切换点天然是四个节奏点,实战必须配 电子故障/开关音; 配法纪律见 sound-design.md(同类元素同音,连发交替双样本防机枪感)
- 与 scramble 分工:那卡是一次性解密(乱→定,不再乱),本卡是
循环播报(乱→定→乱→定);同片只留一个,两个并置读作同一手法用了两遍
参考实现
demos/typography/glitch-cycle/ (GlitchCycle.tsx)
Reference implementation (Remotion)
- demos/typography/glitch-cycle/GlitchCycle.tsx — https://raw.githubusercontent.com/Vincentwei1021/video-shotcraft/main/demos/typography/glitch-cycle/GlitchCycle.tsx
The component imports shared fixtures from demos/_fixtures and helpers from assets/lib in the repo; SKILL.md there documents the render workflow.
Everything on this page is also machine-readable. Point your agent at the JSON, or add the gimgs MCP server and ask it to search motion templates.
- Fetch the JSON — it holds the shot recipe (timing, easing, parameter table, pitfalls) and the full TSX source.
- Clone the video-shotcraft repo; the component imports shared fixtures from demos/_fixtures and helpers from assets/lib.
- Register the component as a <Composition> in a Remotion project and render with `npx remotion render`, or re-implement the recipe in your own engine.
curl -s https://gimgs.net/motion/glitch-cycle.jsongit clone https://github.com/Vincentwei1021/video-shotcraft
# component: demos/typography/glitch-cycle/GlitchCycle.tsx
npx remotion render <CompositionId> out.mp4claude mcp add --transport http gimgs https://gimgs.net/mcp
# then: search_motion_templates / get_motion_template("glitch-cycle")Prompt
Use the video-shotcraft shot recipe "Glitch status cycle" (Remotion composition, Apache-2.0) published on gimgs.net. Recipe JSON (prompt = timing/easing/parameter table/pitfalls, files = TSX source): https://gimgs.net/motion/glitch-cycle.json Raw TSX: https://gimgs.net/motion/glitch-cycle/template.html Repository: https://github.com/Vincentwei1021/video-shotcraft (component: demos/typography/glitch-cycle/GlitchCycle.tsx; imports demos/_fixtures and assets/lib) Spec: 1920x1080, 30 fps, 6.1s 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/typography/glitch-cycle/GlitchCycle.tsx =====
// glitch-cycle — Glitch Cycle 乱码轮播(motion-lab 定稿转原生 Remotion)
// 同一位置循环轮播状态短语,每条短语头尾乱码、中段偶发轻微抖动
// (glitch 概率关键帧 [1,0,0,0.1,0,0,1],最后一条结尾收为 0 保证 t=1 画面干净),
// 切换瞬间伴随 RGB 分离与位移抖动;底部细进度条随 t 匀速填满。
// 设计坐标 480×270(DesignStage 等比放大),参数表数值以此坐标系标定。
import React from 'react';
import { DesignStage, lerp, rand, useT } from '../../_fixtures/Motion';
export const GLITCH_CYCLE_DURATION = 168; // 5600ms @30fps
const PHRASES = ['INITIALIZING', 'LOADING ASSETS', 'COMPILING SHADERS', 'READY TO SHIP'];
const POOL = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789#$%&<>/\\';
// glitch 概率关键帧 [1,0,0,0.1,0,0,1](最后一条结尾收为 0,保证 t=1 画面干净)
const KF = [1, 0, 0, 0.1, 0, 0, 1];
const KF_LAST = [1, 0, 0, 0.1, 0, 0, 0];
const MAXCH = Math.max(...PHRASES.map((p) => p.length));
// 关键帧折线采样:p∈[0,1] 映射到 kf 段内线性插值
const glitchAt = (kf: number[], p: number) => {
const segs = kf.length - 1;
const x = Math.min(segs - 1e-6, Math.max(0, p * segs));
const i = Math.floor(x);
return lerp(x - i, kf[i], kf[i + 1]);
};
export const GlitchCycle: React.FC = () => {
const t = useT();
const N = PHRASES.length;
const slot = Math.min(N - 1, Math.floor(t * N));
const p = t * N - slot; // 短语内进度 0..1
const text = PHRASES[slot];
const g = glitchAt(slot === N - 1 ? KF_LAST : KF, p);
const frame = Math.floor(t * 168);
const bucket = Math.floor(frame / 2); // 乱码跳字节流:每 2 帧换一批随机字符
// 整行抖动 + RGB 分离,强度跟随 glitch 概率
const jx = (rand(bucket * 5 + slot) - 0.5) * g * 10;
const jy = (rand(bucket * 9 + slot + 40) - 0.5) * g * 4;
return (
<DesignStage bg="#0a0b10">
<div
style={{
position: 'absolute',
inset: 0,
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
background: '#0a0b10',
}}
>
<div
style={{
display: 'flex',
fontFamily: '"SF Mono",Menlo,monospace',
fontSize: 26,
letterSpacing: 3,
color: '#dfe6f5',
transform: `translate(${jx}px,${jy}px)`,
textShadow:
g > 0.04
? `${g * 3}px 0 rgba(255,60,90,${g * 0.8}), ${-g * 3}px 0 rgba(60,220,255,${g * 0.8})`
: 'none',
}}
>
{Array.from({ length: MAXCH }, (_, i) => {
const ch = i < text.length ? text[i] : ' ';
let content = ch;
let color: string | undefined;
if (ch !== ' ') {
// 逐字符按种子掷 glitch:命中显示乱码 + 变色,未命中显示真字符
const hit = rand(i * 31 + bucket * 17 + slot * 97) < g;
if (hit) {
content = POOL[Math.floor(rand(i * 131 + bucket * 7 + slot * 13) * POOL.length)];
color = rand(i + bucket) > 0.5 ? '#6c8cff' : '#4a5270';
} else {
color = '#dfe6f5';
}
}
return (
<span key={i} style={{ minWidth: '0.66em', textAlign: 'center', color }}>
{content}
</span>
);
})}
</div>
</div>
{/* 底部细进度条:随 t 匀速填满 */}
<div
style={{
position: 'absolute',
left: '50%',
top: '63%',
width: 120,
height: 2,
marginLeft: -60,
background: '#232840',
borderRadius: 1,
overflow: 'hidden',
}}
>
<div style={{ height: '100%', width: `${t * 100}%`, background: '#6c8cff' }} />
</div>
</DesignStage>
);
};
- 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/typography/glitch-cycle/GlitchCycle.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 |
|---|---|---|---|
| — | |||
More in this category

Word relay geometry
Three benefit words each carry their own dedicated geometry relay — a dashed circle spins and shrinks → three solid circles trim-grow in sequence → a metallic sheen sweeps then collapses to pure white; each new word outlines then fills in.

Word relay filmstrip
A left column of black-and-white page cards steps forward while a serif big word on the right relays in place (a fixed noun + a cycling verb) — the column steps only when the word changes, aligned to the current page card's midpoint.

Vertical word-roll cycle
The sentence's last word cycles on a vertical roller, 3 swaps at 0.55s each, fast then very slow with a slight overshoot; neighboring rows carry vertical blur and grayscale by distance, the centered word snapping from gray to accent color as it lands.

Two code reveals, side by side
The same syntax-highlighted code reveals two ways side by side — left: line-level stagger fading up 8px, right: character-by-character typing keeping each token's original color, with a #3a4468 block cursor on the current character.