Motion · Light & emphasis
Line boil
Line boil — during a hold, text/outline contours wriggle slightly every 3 frames like a hand-redrawn frame, keeping a still image "alive" and breathing.
Source: video-shotcraft (Vincent Wei) ↗ · Apache-2.0 · Remotion composition (React/TSX) — preview video, no in-browser player
When to use
For long holds on title cards/outlined elements (the go-to upgrade for a black-scene title card); a textural technique that piggybacks on another shot.
Intention
The library's precedent demands "real stillness" once things settle, but a long title card freezing completely reads as "the film froze". This card offers a third state: living stillness — the outline gets "redrawn" every 3 frames, position and content completely unchanged, only the line edges breathing very slightly, a century-old convention of hand-drawn animation hold frames. The difference from a rejected drift technique: perceptibility — drift is an overall shift imperceptible to the eye, boiling is contour deformation with stepped jumps that are visible. In a paper-and-ink aesthetic, this is the direct source of "handmade feel".
Duration & energy
- Duration: Parasitic — the boil segment lasts as long as its host's hold; it has no duration of its own
- Energy: Low (ambient-noise level)
Shot recipe (original Chinese — timing, easing, parameter table, known pitfalls)
意图
库内 R 系判例要求落定后"真静止",但长字卡(3s+ 的黑场字卡、片尾) 完全冻结会读作"片子卡了"。本卡给第三种状态:活着的静止——轮廓 每 3 帧被"重描"一次,位置内容全然不动,只有线条边缘在极轻微地呼吸, 手绘动画 hold 帧的百年惯例。与 noise-drift(被否决)的区别正是可感性: 漂移是整体 1–3px 位移(肉眼读不出),沸腾是轮廓形变+阶梯跳变(每次 换 seed 都是一次可见的"重描")。纸墨审美里这是"手工感"的直接来源。
动效核心
- SVG filter:feTurbulence(fractalNoise, baseFrequency 0.015,
numOctaves 2) + feDisplacementMap scale=8(原案 3–6 不可感, 已加码)作用于文字/描边层
- seed = Math.floor(f/3) 阶梯换——每 3 帧跳一次新形变,
10fps 的手翻书质感;逐帧换 seed 读作电噪不是手绘
- 摘罩命门(feTurbulence 判例):沸腾段之外 filter 与 SVG defs
根本不渲染(条件挂载),不是 opacity 到 0——否则永不真静止
- 结构靠对比:demo 用 静止 35f → 沸腾 70f → 摘罩静止 35f 三段
自证可感;实战沸腾段直接铺满宿主 hold
参数表
| 参数 | 典型值 | 调节手感 | |------|--------|----------| | displacement scale | 8(大字标题);小字/细线 5–6 | >12 读作故障扭曲;<4 不可感 | | seed 节拍 | floor(f/3),即每 3 帧重描 | /2 太贼、/4 以上读作卡顿跳帧 | | baseFrequency | 0.015(形变尺度约字高级) | 0.05+ 变成毛边噪点,不是"重描" | | 适用对象 | 大标题、描边框、手绘圈注 | 实心小元素(图标/头像)沸腾读作模糊 | | 与 R 系关系 | 沸腾段视作合法 hold;宿主镜头收尾若需绝对静止则提前 ≥15f 摘罩 | 摘罩瞬间轮廓归位本身就是一次收束 |
已知坑
- demo 在灰阶/占位素材上调校通过——参数是调校起点非实战定稿,
首次实战须以真实素材回验
- 全片同时沸腾的元素 ≤1 组——标题在沸腾、卡片框也在沸腾,观众
找不到该看哪(P4)
- 与 speed-lines/集中线的"沸腾"(impact-feedback C 式每 2 帧换形态)
同族不同职:那是冲击帧的高能沸腾,这是 hold 帧的底噪沸腾,能量 档位差两级,别互换参数
- SVG filter 对大面积层有渲染开销;1920 全幅文字层可接受,整页
截图套 boil 渲染时间翻倍且语义不对(页面不是手绘物)
- paper-title-card/黑场字卡(shot-transitions D 式)是本卡首选宿主,
组合时字卡的打字机/压印入场完成后再起沸腾
参考实现
demos/effects/line-boil/ (LineBoil.tsx)
Reference implementation (Remotion)
- demos/effects/line-boil/LineBoil.tsx — https://raw.githubusercontent.com/Vincentwei1021/video-shotcraft/main/demos/effects/line-boil/LineBoil.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/line-boil.jsongit clone https://github.com/Vincentwei1021/video-shotcraft
# component: demos/effects/line-boil/LineBoil.tsx
npx remotion render <CompositionId> out.mp4claude mcp add --transport http gimgs https://gimgs.net/mcp
# then: search_motion_templates / get_motion_template("line-boil")Prompt
Use the video-shotcraft shot recipe "Line boil" (Remotion composition, Apache-2.0) published on gimgs.net. Recipe JSON (prompt = timing/easing/parameter table/pitfalls, files = TSX source): https://gimgs.net/motion/line-boil.json Raw TSX: https://gimgs.net/motion/line-boil/template.html Repository: https://github.com/Vincentwei1021/video-shotcraft (component: demos/effects/line-boil/LineBoil.tsx; imports demos/_fixtures and assets/lib) Spec: 1920x1080, 30 fps, 4.72s 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/line-boil/LineBoil.tsx =====
// 线条沸腾(line-boil)——手绘动画 line boil 质感:静止线稿在"沸腾段"
// 边缘逐帧微颤,像手绘逐帧描线的抖动。SVG filter feTurbulence(baseFrequency
// 0.015, numOctaves 2, seed = Math.floor(f/3) 每 3 帧阶梯换) + feDisplacementMap
// scale=8(原案 3–6 已按可感性加码)作用于大标题 "ALIVE" 与描边卡整层。
// 结构靠"对比"可感:先静止(干净版)→ 沸腾 → 摘罩回静止;判例:feTurbulence
// 收尾必须整个 filter 移除(沸腾段外根本不渲染 filter 与 SVG def),
// 105f 起逐帧完全相同,真静止 ≥35f。
// 关键帧:0–35 完全静止(boil off) → 35–105 沸腾(boil on, seed 每 3 帧一换)
// → 105 摘罩 → 105–140 真静止(boil off)。
import React, { useId } from 'react';
import { useCurrentFrame, interpolate } from 'remotion';
import { G, TitleBlock } from '../../_fixtures/Fixtures';
const BOIL_START = 35;
const BOIL_END = 105;
const BOIL_SCALE = 8; // 原案 3–6 已按可感性加码;QA 看不出再加到 12
const CornerTag: React.FC<{ text: string; opacity: number }> = ({ text, opacity }) => (
<div
style={{
position: 'absolute',
right: 72,
bottom: 56,
padding: '10px 22px',
border: `3px solid ${G.ink}`,
borderRadius: 999,
color: G.ink,
background: G.bg,
fontFamily: 'Helvetica, Arial, sans-serif',
fontWeight: 700,
fontSize: 30,
letterSpacing: 2,
opacity,
}}
>
{text}
</div>
);
export const LineBoil: React.FC = () => {
const f = useCurrentFrame();
// 滤镜 ID 按实例生成,多实例同场不串引(useId 的 «:» 在 url() 里非法,需清洗)
const boilId = `boil-${useId().replace(/[^a-zA-Z0-9]/g, '')}`;
const boiling = f >= BOIL_START && f < BOIL_END;
// seed 每 3 帧阶梯换 → 8~10Hz 的手绘颤动感;帧确定,无随机源
const seed = Math.floor(f / 3);
// 角标:boil on 只在沸腾段淡入淡出;boil off 与之互补。
// 全部过渡在 105f 前完成 → 105–140 逐帧完全相同
const onOp = interpolate(f, [35, 40, 100, 105], [0, 1, 1, 0], {
extrapolateLeft: 'clamp',
extrapolateRight: 'clamp',
});
const offOp = 1 - onOp;
return (
<div style={{ width: 1920, height: 1080, background: G.bg, position: 'relative', overflow: 'hidden' }}>
{/* 沸腾段才渲染 filter 定义——摘罩即整个 SVG def 消失,收尾天然真静止 */}
{boiling && (
<svg width={0} height={0} style={{ position: 'absolute' }}>
<defs>
<filter id={boilId} x="-15%" y="-15%" width="130%" height="130%">
<feTurbulence
type="fractalNoise"
baseFrequency={0.015}
numOctaves={2}
seed={seed}
result="noise"
/>
<feDisplacementMap
in="SourceGraphic"
in2="noise"
scale={BOIL_SCALE}
xChannelSelector="R"
yChannelSelector="G"
/>
</filter>
</defs>
</svg>
)}
{/* 手法名标签:不入滤镜层,作为静止参照物 */}
<div style={{ position: 'absolute', left: 120, top: 96 }}>
<TitleBlock text="LINE BOIL" size={54} />
</div>
{/* 被沸腾的整层:大标题 + 描边卡 */}
<div
style={{
position: 'absolute',
inset: 0,
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
justifyContent: 'center',
gap: 56,
filter: boiling ? `url(#${boilId})` : undefined,
}}
>
<div
style={{
fontFamily: 'Helvetica, Arial, sans-serif',
fontWeight: 800,
fontSize: 170,
color: G.ink,
letterSpacing: 4,
lineHeight: 1,
}}
>
ALIVE
</div>
{/* 描边卡:透明底 3px ink 描边 520×300 圆角框 + 几条灰线 */}
<div
style={{
width: 520,
height: 300,
border: `3px solid ${G.ink}`,
borderRadius: 20,
boxSizing: 'border-box',
padding: '36px 40px',
display: 'flex',
flexDirection: 'column',
gap: 26,
}}
>
<div style={{ height: 16, width: '62%', background: G.mid, borderRadius: 8 }} />
<div style={{ height: 12, width: '88%', background: G.bar, borderRadius: 6 }} />
<div style={{ height: 12, width: '74%', background: G.bar, borderRadius: 6 }} />
<div style={{ height: 12, width: '81%', background: G.bar, borderRadius: 6 }} />
<div style={{ marginTop: 'auto', display: 'flex', gap: 12, alignItems: 'center' }}>
<div style={{ width: 30, height: 30, borderRadius: 15, border: `3px solid ${G.ink}`, boxSizing: 'border-box' }} />
<div style={{ height: 12, width: 120, background: G.mid, borderRadius: 6 }} />
</div>
</div>
</div>
{/* 状态角标:沸腾段 boil on,静止段 boil off */}
<CornerTag text="boil on" opacity={onOp} />
<CornerTag text="boil off" opacity={offOp} />
</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/line-boil/LineBoil.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

Dark-stage spotlight reveals
Three dark-stage spotlight reveals — A wake-sleep sweep (light in = bright, light out = dark), B edge-hugging glow pan (violet light seeps along UI edges + steady rightward sweep), C corner reveal (radial light expands steadily from a corner to light the whole screen); light itself narrates in the dark.

Slam entrance moves
Three high-energy slam entrances: a whip-in perspective stop, a heavy KPI drop, and a shockwave that hits neighboring cards.

Scanline assemble fly-in
A scan line sweeps down an empty grid, flying each region's component in from off-screen — finishing as the scan ends.

Scanline annotate focus
A bright scan line sweeps down the page, framing each element it passes and labeling it with monospace annotations.