Motion · Kết

Chuyển động móc câu kết

Móc câu kết logo-sting-button — sau khi logo cuối định hình, chèn đột ngột 12f trứng phục sinh rồi mới kết thúc, kiểu button ending của trailer.

1920×108016:930 fps4.78s · 143 frameremotionGiấy phép: Apache-2.0#shotcraft#remotion#outro

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

Dùng để khép lại đoạn kết (toàn phim ≤1 lần).

Ý đồ

Các thẻ hình-tiếng trong thư viện đều quản "chuyện trên màn hình"; kiểu này quản tu từ của chính dòng thời gian — sự lật ngược ở điểm kết: về đen → logo mờ hiện và định hình (khán giả tưởng đã hết) → bất ngờ cắt cứng chèn vào 12f cận cảnh UI trứng phục sinh → cắt về logo để kết, kiểu button ending của trailer, để lại một cú móc câu cuối cùng. Đùa với kỳ vọng "đã kết thúc rồi" của khán giả.

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

  • Thời lượng: ~5s
  • Năng lượng: Thấp → trung bình tức thời → thấp

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)

意图

库内声画卡管的都是"画面上的事";这一式管时间线本身的修辞—— 终点的反悔:收黑→logo 淡入定住(观众以为结束)→突然 12f UI 特写 彩蛋硬切插入→切回 logo 收尾,预告片 button ending,留最后一个钩子。 拿观众的"已经结束了"的预期开玩笑。

单式选型

| 式 | 做法 | 适用 | |----|------|------| | B logo-sting-button | 收黑 6f→logo 入场 10f(opacity+scale 0.96→1)→定住 30f→彩蛋 12f 硬切插入→切回 logo 真静止 ≥60f | 片尾;正片收束后再给一记 |

参数表

| 参数 | 典型值 | 调节手感 | |------|--------|----------| | 彩蛋时长 | 12f 级,内含 tick 圆点只亮第 4–5f(2f,条件挂载) | 长于 20f 就不是"眨眼"是一个镜头 | | 彩蛋构图 | 面板 translate+scale(2.4) 特写按钮行,平移量把 sidebar 完全推出画面 | 彩蛋里露出旧构图残边读作切错了 | | 像素级一致 | logo 段 interpolate 全 clamp 到终值,彩蛋前后 logo 共用同一分支渲染 | 硬切回来 logo 跳 1px 都读作抖动 | | 剪辑方式 | 全程硬切分支渲染(frame 区间 return 不同子树),无交叉溶解 | 节奏靠剪不靠淡;任何溶解都泄劲 |

已知坑

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

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

  • 全片 ≤1 次且只在片尾——中段用 button ending 变成故障,

观众以为片子坏了

  • 彩蛋内容必须是全片未见的新特写——复用旧镜头读作剪辑失误

不是钩子,命门

参考实现

demos/outro/edit-hook-moves/ (LogoStingButton.tsx)

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

  • demos/outro/edit-hook-moves/LogoStingButton.tsx — https://raw.githubusercontent.com/Vincentwei1021/video-shotcraft/main/demos/outro/edit-hook-moves/LogoStingButton.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/edit-hook-moves.json
git clone https://github.com/Vincentwei1021/video-shotcraft
# component: demos/outro/edit-hook-moves/LogoStingButton.tsx
npx remotion render <CompositionId> out.mp4
claude mcp add --transport http gimgs https://gimgs.net/mcp
# then: search_motion_templates / get_motion_template("edit-hook-moves")

Prompt

Use the video-shotcraft shot recipe "Chuyển động móc câu kết" (Remotion composition, Apache-2.0) published on gimgs.net.
Recipe JSON (prompt = timing/easing/parameter table/pitfalls, files = TSX source): https://gimgs.net/motion/edit-hook-moves.json
Raw TSX: https://gimgs.net/motion/edit-hook-moves/template.html
Repository: https://github.com/Vincentwei1021/video-shotcraft  (component: demos/outro/edit-hook-moves/LogoStingButton.tsx; imports demos/_fixtures and assets/lib)
Spec: 1920x1080, 30 fps, 4.78s

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,905 chars · Apache-2.0Mở template gốc ↗
// ===== demos/outro/edit-hook-moves/LogoStingButton.tsx =====
// logo-sting-button —— 收尾按钮镜头(button ending)
// 上一镜收黑 → 黑场 → LOGO 入场定住(观众以为结束)→ 12f UI 特写彩蛋硬切 →
// 硬切回黑底 LOGO 定格。节奏是全部:彩蛋段短促像眨眼。收尾真静止 ≥40f。
import React from 'react';
import { useCurrentFrame, interpolate, Easing } from 'remotion';
import { FakeDashboard } from '../../_fixtures/Fixtures';

// 时间轴(30fps,共 142f)
const T = {
  shotAEnd: 24,     // 0–24f 上一镜(B),f14–24 压暗到纯黑
  darkenStart: 14,
  blackEnd: 30,     // 24–30f 黑场 6f
  logoInEnd: 40,    // 30–40f LOGO 入场 10f
  holdEnd: 70,      // 40–70f 定住 30f(观众以为结束)
  eggEnd: 82,       // 70–82f 彩蛋硬切 12f
  total: 142,       // 82–142f 黑底 LOGO 真静止 60f
};

const LogoLockup: React.FC<{ opacity: number; scale: number }> = ({ opacity, scale }) => (
  <div style={{
    width: 1920, height: 1080, background: '#000',
    display: 'flex', alignItems: 'center', justifyContent: 'center',
  }}>
    <div style={{
      display: 'flex', alignItems: 'center', gap: 44,
      opacity, transform: `scale(${scale})`,
    }}>
      <div style={{
        width: 120, height: 120, borderRadius: 28, background: '#fff',
        display: 'flex', alignItems: 'center', justifyContent: 'center',
      }}>
        {/* 方块内一个黑色小标记,避免纯白块太空 */}
        <div style={{ width: 44, height: 44, borderRadius: 12, background: '#000' }} />
      </div>
      <div style={{
        fontFamily: 'Helvetica, Arial, sans-serif', fontWeight: 800,
        fontSize: 90, color: '#fff', letterSpacing: 2,
      }}>
        ACME
      </div>
    </div>
  </div>
);

export const LogoStingButton: React.FC = () => {
  const frame = useCurrentFrame();

  // —— 段 1:上一镜(FakeDashboard B)压暗收黑 ——
  if (frame < T.shotAEnd) {
    const dark = interpolate(frame, [T.darkenStart, T.shotAEnd - 1], [0, 1], {
      extrapolateLeft: 'clamp', extrapolateRight: 'clamp',
      easing: Easing.in(Easing.cubic),
    });
    return (
      <div style={{ width: 1920, height: 1080, background: '#000', position: 'relative', overflow: 'hidden' }}>
        <FakeDashboard variant="B" />
        <div style={{ position: 'absolute', inset: 0, background: '#000', opacity: dark }} />
      </div>
    );
  }

  // —— 段 2:黑场 6f ——
  if (frame < T.blackEnd) {
    return <div style={{ width: 1920, height: 1080, background: '#000' }} />;
  }

  // —— 段 4:彩蛋硬切 12f(variant A 按钮区 2.4x 裁切 + 角落小圆点 tick 闪 2f)——
  if (frame >= T.holdEnd && frame < T.eggEnd) {
    const egg = frame - T.holdEnd; // 0..11
    // tick 圆点:第 4–5f 亮 2f,像眨眼
    const tickOn = egg >= 4 && egg < 6;
    return (
      <div style={{ width: 1920, height: 1080, background: '#ececea', position: 'relative', overflow: 'hidden' }}>
        <div style={{
          position: 'absolute', inset: 0,
          // 2.4x 放大:把第 1 张卡片底部"按钮行"(头像圆+文字条)平移到画面中心
          // 原坐标 (839, 531)(第 2 列卡片底部头像圆+文字条)→ 屏幕中心 (960, 540)
          // 选中列卡片可把左侧深色 sidebar 完全推出画面,特写更纯粹
          transform: 'translate(-1054px, -734px) scale(2.4)', transformOrigin: '0 0',
        }}>
          <FakeDashboard variant="A" />
        </div>
        {tickOn && (
          <div style={{
            position: 'absolute', right: 90, bottom: 80,
            width: 56, height: 56, borderRadius: 28, background: '#2f2f2f',
            display: 'flex', alignItems: 'center', justifyContent: 'center',
          }}>
            <div style={{ width: 20, height: 20, borderRadius: 10, background: '#fff' }} />
          </div>
        )}
      </div>
    );
  }

  // —— 段 3 + 段 5:黑底 LOGO(入场 → 定住 → 彩蛋后定格收尾,真静止)——
  const opacity = interpolate(frame, [T.blackEnd, T.logoInEnd], [0, 1], {
    extrapolateLeft: 'clamp', extrapolateRight: 'clamp',
    easing: Easing.out(Easing.cubic),
  });
  const scale = interpolate(frame, [T.blackEnd, T.logoInEnd], [0.96, 1], {
    extrapolateLeft: 'clamp', extrapolateRight: 'clamp',
    easing: Easing.out(Easing.cubic),
  });
  return <LogoLockup opacity={opacity} scale={scale} />;
};


  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/outro/edit-hook-moves/LogoStingButton.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