Motion · Chuyển cảnh

Chuyển cảnh chất liệu in ấn

Chuyển cảnh chất liệu in ấn: ink-bleed-reveal, mép loang tua tủa thấm ra nuốt trọn cảnh cũ.

1920×108016:930 fps4.39s · 132 frameremotionGiấy phép: Apache-2.0#shotcraft#remotion#transition

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

Kiểu thẩm mỹ giấy/mực cho mối nối đổi cảnh; họ thứ ba song song với sáu kiểu bàn giao/ba kiểu xuyên cảnh — chuyển cảnh kiểu "hiện hình chất liệu"

Ý đồ

Ngôn ngữ chuyển cảnh đã có kiểu bàn giao (sáu kiểu shot-transitions) và kiểu xuyên cảnh (transition-travel), đều là ẩn dụ không gian/quang học. Kiểu này mở ra họ thứ ba: ẩn dụ chất liệu — hình ảnh mới không "đến" mà được "in ra", vận dụng trực tiếp trí tưởng tượng vật lý giấy/mực có sẵn trong kho: như một giọt mực rơi trên giấy dó rồi loang ra nuốt trọn cảnh cũ, hữu cơ, mang cảm giác viết tay. Tự nhiên phù hợp với phim mang tông giấy/mực, là một lựa chọn mối nối "hệ chất liệu" khác bên cạnh light-leak-burn (rò sáng màu nhấn).

Thời lượng & năng lượng

  • Thời lượng: 4–4.5s (đoạn loang 55–80f + kết đứng yên từ 30f trở lên)
  • Năng lượng: Trung bình (hiện hình dần dần, không có nhịp va chạm)

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)

意图

转场语言已有交棒(shot-transitions 六式)和穿越(transition-travel) ,都是空间/光学隐喻。本式开第三族:介质隐喻——新画面不是"到来" 而是"印染"出来的,直接调用库内纸墨审美的物理想象:像一滴墨落在 宣纸上洇开吃掉旧景,有机、书写感。天然亲和 paper/ink 调性的片子, 是 light-leak-burn(强调色漏光)之外的另一个"介质系"接缝选择。

单式选型

| 式 | 做法 | 适用 | |----|------|------| | B ink-bleed-reveal 墨渗揭示 | 新页透过须状渗边的有机圆形遮罩从落墨点洇开,快慢不匀吃掉旧景 | 旧景→新景替换;书写感、叙事调性 |

参数表

| 参数 | 典型值 | 调节手感 | |------|--------|----------| | 渗边 | SVG mask 白圆挂 feTurbulence(fractalNoise, baseFrequency 0.02, octaves 3, seed 固定) + feDisplacementMap scale 60→160 随帧涨 | filter 只揉遮罩形状、内容始终清晰;seed 必须写死(确定性) | | 洇开 | 半径 [20,98f]→[0,1450px] Easing.out(quad),乘 1+0.08·sin(0.32f)·env 快慢不匀扰动(env 末 20f 衰减归零) | 匀速圆扩张读作普通 iris——扰动即"墨的脾气" | | 收尾摘罩 | 洇满后(帧 ~100)摘掉 SVG mask 直接铺新景 | feTurbulence 有亚像素抖动,不摘则结尾永不真静止(本批实渲判例) | | 收尾 | 新景就位后真静止 ≥30f | R1 |

已知坑

  • demo 在灰阶/占位素材上调校通过——参数是调校起点非实战定稿,

首次实战须以真实素材回验

  • 一缝一式规矩同 shot-transitions:介质转场不与白闪/震屏叠加;

本式与 light-leak-burn 介质系同片合计 ≤2 次,多了片子读作印刷厂宣传

  • 洇开中段旧景内容会透过噪声孔洞碎片式短暂露出——读作墨渍肌理

属可接受有机效果,但旧景若是人脸/logo 等高辨识元素会读作故障,避开

  • 慢转场(55–80f 动作段),高节奏连打段落别用——那里去 E 式甩镜

参考实现

demos/transition/print-texture-transitions/ (InkBleedReveal.tsx)

Mã nguồn tham chiếu (Remotion)

  • demos/transition/print-texture-transitions/InkBleedReveal.tsx — https://raw.githubusercontent.com/Vincentwei1021/video-shotcraft/main/demos/transition/print-texture-transitions/InkBleedReveal.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.

  1. 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.
  2. Clone repo video-shotcraft; component import fixture chung từ demos/_fixtures và helper từ assets/lib.
  3. Đă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/print-texture-transitions.json
git clone https://github.com/Vincentwei1021/video-shotcraft
# component: demos/transition/print-texture-transitions/InkBleedReveal.tsx
npx remotion render <CompositionId> out.mp4
claude mcp add --transport http gimgs https://gimgs.net/mcp
# then: search_motion_templates / get_motion_template("print-texture-transitions")

Prompt

Use the video-shotcraft shot recipe "Chuyển cảnh chất liệu in ấn" (Remotion composition, Apache-2.0) published on gimgs.net.
Recipe JSON (prompt = timing/easing/parameter table/pitfalls, files = TSX source): https://gimgs.net/motion/print-texture-transitions.json
Raw TSX: https://gimgs.net/motion/print-texture-transitions/template.html
Repository: https://github.com/Vincentwei1021/video-shotcraft  (component: demos/transition/print-texture-transitions/InkBleedReveal.tsx; imports demos/_fixtures and assets/lib)
Spec: 1920x1080, 30 fps, 4.39s

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).

JSON · Markdown · llms.txt

3,380 chars · Apache-2.0Mở template gốc ↗
// ===== demos/transition/print-texture-transitions/InkBleedReveal.tsx =====
// 墨渗揭示(ink-bleed-reveal)——水墨转场(轨道遮罩法)。
// 旧景:G.bg 纸底 + 居中 TitleBlock "BEFORE";新景 FakeDashboard(A) 放进
// SVG <foreignObject>,套 <mask>:中心偏左上 (800,420) 的白圆当轨道遮罩。
// 圆本身套 feTurbulence(baseFrequency 0.02, octaves 3, seed 7 固定) +
// feDisplacementMap(scale 60→160 随帧涨)造须状渗边——filter 只作用在
// mask 形状上,新景内容始终清晰。帧 0–20 hold 旧景;帧 20–98 半径
// 0→1450(Easing.out(quad))再叠 ±8% 低频正弦扰动(帧 78–98 扰动衰减到 0,
// 洇满全屏);帧 100–130 摘掉 mask 直接铺新景,真静止 30f。
import React, { useId } from 'react';
import { useCurrentFrame, interpolate, Easing } from 'remotion';
import { G, FakeDashboard, TitleBlock } from '../../_fixtures/Fixtures';

export const InkBleedReveal: React.FC = () => {
  const frame = useCurrentFrame();
  // 滤镜/mask ID 按实例生成,多实例同场不串引(useId 的 «:» 在 url() 里非法,需清洗)
  const uid = useId().replace(/[^a-zA-Z0-9]/g, '');
  const bleedId = `inkBleed-${uid}`;
  const maskId = `inkMask-${uid}`;

  // 墨滴落点:画面中心偏左上
  const cx = 800;
  const cy = 420;

  // 基础半径:帧 20–98,0 → 1450px(最远角 ~1300px + 渗边位移余量 150px)
  const baseR = interpolate(frame, [20, 98], [0, 1450], {
    easing: Easing.out(Easing.quad),
    extrapolateLeft: 'clamp',
    extrapolateRight: 'clamp',
  });

  // ±8% 低频正弦扰动 = 快慢不匀的洇开;帧 78–98 幅度衰减到 0,保证吃满后能真静止
  const wobbleEnv = interpolate(frame, [78, 98], [1, 0], {
    extrapolateLeft: 'clamp',
    extrapolateRight: 'clamp',
  });
  const r = Math.max(0, baseR * (1 + 0.08 * Math.sin(frame * 0.32) * wobbleEnv));

  // 渗边发散度:displacement scale 60 → 160(边缘越洇越散、指尖分叉越长)
  const dispScale = interpolate(frame, [20, 98], [60, 160], {
    extrapolateLeft: 'clamp',
    extrapolateRight: 'clamp',
  });

  // 帧 100 起 mask 已全白:摘掉 SVG 直接铺新景,确保结尾像素级真静止
  const settled = frame >= 100;

  return (
    <div style={{ width: 1920, height: 1080, background: G.bg, position: 'relative', overflow: 'hidden' }}>
      {/* 旧景:纸底 + BEFORE 标题 */}
      <div style={{ position: 'absolute', inset: 0, background: G.bg, display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
        <TitleBlock text="BEFORE" size={120} />
      </div>

      {settled ? (
        <div style={{ position: 'absolute', inset: 0 }}>
          <FakeDashboard variant="A" />
        </div>
      ) : (
        <svg
          width={1920}
          height={1080}
          viewBox="0 0 1920 1080"
          style={{ position: 'absolute', inset: 0, display: 'block' }}
        >
          <defs>
            {/* filter 只挂在 mask 的圆上——揉的是遮罩边,不是画面内容 */}
            <filter id={bleedId} x="-40%" y="-40%" width="180%" height="180%">
              <feTurbulence type="fractalNoise" baseFrequency="0.02" numOctaves="3" seed="7" result="noise" />
              <feDisplacementMap in="SourceGraphic" in2="noise" scale={dispScale} xChannelSelector="R" yChannelSelector="G" />
            </filter>
            <mask id={maskId} maskUnits="userSpaceOnUse" x="0" y="0" width="1920" height="1080">
              <rect x="0" y="0" width="1920" height="1080" fill="black" />
              {r > 0.5 && <circle cx={cx} cy={cy} r={r} fill="white" filter={`url(#${bleedId})`} />}
            </mask>
          </defs>
          <g mask={`url(#${maskId})`}>
            <foreignObject x="0" y="0" width="1920" height="1080">
              <FakeDashboard variant="A" />
            </foreignObject>
          </g>
        </svg>
      )}
    </div>
  );
};


  1. Read the recipe
    Prompt = when to use, intention, parameter table with typical values and how each one feels, known pitfalls. Treat values as calibrated starting points.
  2. Get the code
    tool: git
    git clone https://github.com/Vincentwei1021/video-shotcraft && cd video-shotcraft && npm install
  3. Register + render
    tool: remotion
    npx remotion render <CompositionId> out.mp4 # component: demos/transition/print-texture-transitions/InkBleedReveal.tsx
  4. Or re-implement
    Port the timing/easing from the recipe to HTML + WAAPI (gimgs motion contract) or any engine; keep the same segment windows and easing.
paramtypedefaultdescription
—

Cùng danh mục