{
  "slug": "ai-stream-response",
  "title": "AI Response Stream-In",
  "tagline": "The AI response panel drops a readable summary first, then status-icon evidence rows stream in one by one, settling into a completed state.",
  "description": "The AI response panel drops a readable summary first, then status-icon evidence rows stream in one by one, settling into a completed state.",
  "category": "interaction",
  "tags": [
    "shotcraft",
    "remotion",
    "interaction"
  ],
  "tier": "free",
  "license": "Apache-2.0",
  "spec": {
    "width": 1920,
    "height": 1080,
    "fps": 30,
    "duration": 5.06,
    "aspect": "16:9"
  },
  "kind": "remotion",
  "params_schema": {
    "type": "object",
    "properties": {}
  },
  "default_params": {},
  "preview": {
    "poster": "https://gimgs.net/motion/media/ai-stream-response/poster-d76240199627.jpg",
    "video": "https://gimgs.net/motion/media/ai-stream-response/video-b9a2188312d0.mp4"
  },
  "variants": [
    {
      "key": "ai-stream-response",
      "label": "ai-stream-response",
      "description": "The AI response panel drops a readable summary first, then status-icon evidence rows stream in one by one, settling into a completed state.",
      "use": "",
      "video": "https://gimgs.net/motion/media/ai-stream-response/video-b9a2188312d0.mp4",
      "poster": "https://gimgs.net/motion/media/ai-stream-response/poster-d76240199627.jpg"
    }
  ],
  "credits": {
    "author": "video-shotcraft (Vincent Wei)",
    "url": "https://github.com/Vincentwei1021/video-shotcraft"
  },
  "page_url": "https://gimgs.net/motion/ai-stream-response.html",
  "json_url": "https://gimgs.net/motion/ai-stream-response.json",
  "template_url": "https://gimgs.net/motion/ai-stream-response/template.html",
  "play_url": null,
  "markdown_url": "https://gimgs.net/motion/ai-stream-response.md",
  "updated_at": "2026-09-24T07:39:41.965Z",
  "prompt": "## When to use\n\nResult-generation shot for AI assistants/agents/search/copilot; emphasizes \"conclusion first, evidence follows, task complete.\"\n\n## Intention\n\nShoot \"the AI is working\" as a readable causal chain, not a log-scroll flood: viewers first read the answer summary, then watch evidence/sub-tasks fill in one by one, and finally the completed state confirms this round of work is done.\n\n## Duration & energy\n\n- Duration: About 4–5s (120–150f, including ≥15f hold on the completed state).\n- Energy: Medium-high (information keeps accumulating, but readability outranks speed showmanship).\n\n## Shot recipe (original Chinese — timing, easing, parameter table, known pitfalls)\n\n## 意图\n把“AI 正在工作”拍成可读的因果链，而不是日志刷屏：观众先看懂答案摘要，\n再看到证据/子任务逐条补齐，最后由完成态确认这轮工作结束。\n\n## 动效核心\n- 用目标产品真实响应面板截图做 backplate；动态区截图前隐藏，按 layout 坐标重叠回真实槽位（Q1/Q9）\n- 面板进入后摘要句先以短 wipe/淡入落定，落定后至少 12f 才起首条证据\n- 6–8 条证据行自下方 14–24px + 轻微 blur 逐行汇入；间隔逐渐收紧但保留可数节拍\n- 行体先停，状态图标晚 2–4f 由 pending 转 running/done，形成主次拖拽层级\n  （模式已沉为 assets/lib/helpers/motion.ts lagged）\n- 末条完成后只做一次面板级完成脉冲，随后全画面静止 ≥15f；不逐行 glint\n\n## 参数表\n| 参数 | 典型值 | 调节手感 |\n|------|--------|----------|\n| 摘要 | cue 18，10–14f reveal；摘要落定后 hold ≥12f，首行 cue ≥42 | 摘要与首行粘连会失去“结论先到”的叙事；正常速度必须能先读到一句完整结论 |\n| 行节拍 | `cue[i]=42+[0,11,21,30,38,45,51,56][i]`，每行 10–14f | 间隔 11→5f 逐渐收紧，表达工作加速；不要密到所有行同时糊成一团（R2） |\n| 行入场 | y 18px→0，blur 6px→0，opacity 0→1，bezier(0.2,0.75,0.25,1) | 位移须过正常速度肉眼阈值；大幅横飞会像通知列表，不像证据归档 |\n| 状态图标 | 比行体 cue 晚 3f；pending 环 → running 缺口环 → done 实心勾，6–8f | 图标是状态回执，不抢行文本；同帧切换全部图标会读作假 loading |\n| 完成收束 | 末图标 done 后 6f，面板边框/摘要底色 opacity 0.25→0.55→0.25 共 10f | 只做面板级一次，不逐行发光（Q4）；完成脉冲后留 ≥15f 真静止（R1） |\n| 相机 | 信息密集默认正视，zoom 1.04→1.0 微退；暗场斜拍仅作情绪变体 | Linear 参考片的斜拍不是通用命令；文字读不清时立即回正视（Q6） |\n\n## 声音\n摘要落定配一发 `transition-soft`；前 3–4 行用短 `pop` 轻声递减\n0.32→0.20，后半加速密集段合并成一条低音量 `whoosh-fast`，避免逐行机枪感；\n最终完成态用 `click-camera` 的轻量版本（约 vol 0.3）。声音在画面锁定后钉帧。\n\n## 已知坑\n- 逐字符流式打字会把视线困在字符层；宣传片时长里优先按“语义块”揭示摘要，\n  真正展示输入操作时另用 `type-and-filter`\n- 行体和状态图标若同帧落定，会像静态列表整体切换；保留 2–4f 拖拽层级\n- 行终点必须是截图里真实列表槽位，不在面板上方悬浮；动态内容也必须用虚构数据\n- 此卡借鉴 Linear Agent 发布片 t≈13–17s（进化轮 #3 breakdown #6），非用户判例；\n  参数未经本库实战项目验证，首次使用必须按 P1 在正常速度下看片，不以逐帧 diff 代替体感\n\n## 参考实现\ndemos/interaction/ai-stream-response/\n（StreamResponse.tsx）\n\n## Reference implementation (Remotion)\n\n- demos/interaction/ai-stream-response/StreamResponse.tsx — https://raw.githubusercontent.com/Vincentwei1021/video-shotcraft/main/demos/interaction/ai-stream-response/StreamResponse.tsx\n\nThe component imports shared fixtures from `demos/_fixtures` and helpers from `assets/lib` in the repo; SKILL.md there documents the render workflow.\n",
  "flow": [
    {
      "step": "Read the recipe",
      "note": "Prompt = when to use, intention, parameter table with typical values and how each one feels, known pitfalls. Treat values as calibrated starting points."
    },
    {
      "step": "Get the code",
      "tool": "git",
      "cmd": "git clone https://github.com/Vincentwei1021/video-shotcraft && cd video-shotcraft && npm install"
    },
    {
      "step": "Register + render",
      "tool": "remotion",
      "cmd": "npx remotion render <CompositionId> out.mp4   # component: demos/interaction/ai-stream-response/StreamResponse.tsx"
    },
    {
      "step": "Or re-implement",
      "note": "Port the timing/easing from the recipe to HTML + WAAPI (gimgs motion contract) or any engine; keep the same segment windows and easing."
    }
  ],
  "files": [
    {
      "path": "demos/interaction/ai-stream-response/StreamResponse.tsx",
      "url": "https://raw.githubusercontent.com/Vincentwei1021/video-shotcraft/main/demos/interaction/ai-stream-response/StreamResponse.tsx"
    }
  ],
  "contract": "React/Remotion composition (TSX) from the open-source video-shotcraft library (Apache-2.0). It is not a browser-playable template: clone the repo, register the component in a Remotion project and render with `npx remotion render`. The recipe (prompt) describes timing, easing and parameters so you can also re-implement the shot in any engine.",
  "render": {
    "engine": "remotion",
    "frames": 152,
    "repo": "https://github.com/Vincentwei1021/video-shotcraft",
    "files": [
      "https://raw.githubusercontent.com/Vincentwei1021/video-shotcraft/main/demos/interaction/ai-stream-response/StreamResponse.tsx"
    ],
    "note": "Clone https://github.com/Vincentwei1021/video-shotcraft (npm install). The component lives under demos/{category}/{name}/ and imports shared fixtures from demos/_fixtures and helpers from assets/lib. Copy it (with those imports) into a Remotion project, register a <Composition> with the template's width/height/fps/duration in Root.tsx, then `npx remotion render <CompositionId> out.mp4`. SKILL.md in the repo documents the full Claude Code / Codex workflow. The prompt below is the shot recipe (timing, easing, parameter table, pitfalls) — enough to re-implement the shot in HTML/WAAPI or another engine if you prefer."
  },
  "source": "// ===== demos/interaction/ai-stream-response/StreamResponse.tsx =====\nimport React from 'react';\nimport {\n  AbsoluteFill,\n  Easing,\n  Img,\n  interpolate,\n  useCurrentFrame,\n} from 'remotion';\nimport backplate from './agent-stream.jpg';\n\nconst ROW_CUES = [42, 53, 63, 72, 80, 87, 93];\nconst ROWS = [\n  ['Indexed the workspace', '128 files'],\n  ['Mapped the authentication flow', '12 modules'],\n  ['Checked recent error traces', 'No blockers'],\n  ['Matched API contracts to handlers', '24 routes'],\n  ['Verified permission boundaries', '6 roles'],\n  ['Cross-checked release notes', '3 changes'],\n  ['Prepared an implementation plan', 'Ready'],\n] as const;\n\nconst clamp = {extrapolateLeft: 'clamp', extrapolateRight: 'clamp'} as const;\nconst ease = Easing.bezier(0.2, 0.75, 0.25, 1);\n\nconst CheckIcon: React.FC<{progress: number}> = ({progress}) => {\n  const ringOpacity = interpolate(progress, [0, 0.45, 0.75], [0.36, 1, 0], clamp);\n  const checkOpacity = interpolate(progress, [0.62, 1], [0, 1], clamp);\n  const checkScale = interpolate(progress, [0.62, 1], [0.72, 1], {...clamp, easing: ease});\n\n  return (\n    <div style={{position: 'relative', width: 27, height: 27, flex: '0 0 auto'}}>\n      <div\n        style={{\n          position: 'absolute', inset: 2, borderRadius: 99,\n          border: '2px solid rgba(183, 190, 199, .6)',\n          borderTopColor: '#d4ff77', opacity: ringOpacity,\n          transform: `rotate(${progress * 100}deg)`,\n        }}\n      />\n      <div\n        style={{\n          position: 'absolute', inset: 1, borderRadius: 99,\n          background: '#b8f36a', opacity: checkOpacity,\n          transform: `scale(${checkScale})`,\n          display: 'grid', placeItems: 'center',\n          boxShadow: '0 0 16px rgba(184,243,106,.18)',\n        }}\n      >\n        <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\">\n          <path d=\"M3.4 8.3 6.6 11l6-6\" stroke=\"#15200d\" strokeWidth=\"2.1\" strokeLinecap=\"round\" strokeLinejoin=\"round\"/>\n        </svg>\n      </div>\n    </div>\n  );\n};\n\nconst EvidenceRow: React.FC<{cue: number; title: string; meta: string; index: number}> = ({cue, title, meta, index}) => {\n  const frame = useCurrentFrame();\n  const body = interpolate(frame, [cue, cue + 12], [0, 1], {...clamp, easing: ease});\n  const status = interpolate(frame, [cue + 3, cue + 11], [0, 1], {...clamp, easing: ease});\n  return (\n    <div\n      style={{\n        position: 'absolute', left: 0, right: 0, top: index * 68,\n        height: 58, borderRadius: 13,\n        border: '1px solid rgba(255,255,255,.065)',\n        background: 'rgba(255,255,255,.025)',\n        display: 'flex', alignItems: 'center', padding: '0 20px', gap: 15,\n        opacity: body,\n        transform: `translateY(${18 * (1 - body)}px)`,\n        filter: `blur(${6 * (1 - body)}px)`,\n      }}\n    >\n      <CheckIcon progress={status}/>\n      <div style={{fontSize: 21, color: '#e8eaed', letterSpacing: '-0.015em', flex: 1}}>{title}</div>\n      <div style={{fontSize: 16, color: status > 0.78 ? '#a9c77f' : '#777f89', fontVariantNumeric: 'tabular-nums'}}>{meta}</div>\n    </div>\n  );\n};\n\nexport const StreamResponse: React.FC = () => {\n  const frame = useCurrentFrame();\n  const panelIn = interpolate(frame, [0, 16], [0, 1], {...clamp, easing: ease});\n  const summary = interpolate(frame, [18, 30], [0, 1], {...clamp, easing: ease});\n  const camera = interpolate(frame, [0, 100], [1.04, 1], {...clamp, easing: ease});\n  const pulse = interpolate(frame, [110, 115, 120], [0.25, 0.55, 0.25], clamp);\n  const complete = interpolate(frame, [110, 120], [0, 1], {...clamp, easing: ease});\n\n  return (\n    <AbsoluteFill style={{background: '#07090a', fontFamily: 'Inter, ui-sans-serif, -apple-system, BlinkMacSystemFont, \"Segoe UI\", sans-serif', overflow: 'hidden'}}>\n      <AbsoluteFill style={{transform: `scale(${camera})`}}>\n        <Img src={backplate} style={{width: '100%', height: '100%', objectFit: 'cover', filter: 'brightness(.58) saturate(.76) blur(1px)', opacity: .7}}/>\n        <AbsoluteFill style={{background: 'radial-gradient(circle at 50% 44%, rgba(6,9,10,.08) 10%, rgba(4,6,7,.72) 92%)'}}/>\n      </AbsoluteFill>\n\n      <div\n        style={{\n          position: 'absolute', left: 344, top: 72, width: 1232, height: 936,\n          borderRadius: 29, overflow: 'hidden',\n          background: 'linear-gradient(145deg, rgba(25,29,32,.985), rgba(12,15,17,.99))',\n          border: `1px solid rgba(184,243,106,${pulse})`,\n          boxShadow: '0 46px 100px rgba(0,0,0,.58), inset 0 1px 0 rgba(255,255,255,.06)',\n          opacity: panelIn,\n          transform: `translateY(${12 * (1 - panelIn)}px) scale(${.985 + .015 * panelIn})`,\n        }}\n      >\n        <div style={{height: 76, display: 'flex', alignItems: 'center', padding: '0 34px', borderBottom: '1px solid rgba(255,255,255,.065)'}}>\n          <div style={{width: 29, height: 29, borderRadius: 9, background: '#e9edf0', color: '#15191b', display: 'grid', placeItems: 'center', fontWeight: 800, fontSize: 17}}>A</div>\n          <div style={{marginLeft: 13, fontSize: 22, fontWeight: 590, color: '#f1f3f4'}}>Ask Atlas</div>\n          <div style={{marginLeft: 'auto', display: 'flex', alignItems: 'center', gap: 9, color: '#7d858e', fontSize: 15}}>\n            <span style={{width: 7, height: 7, background: '#b8f36a', borderRadius: 99}}/> Workspace agent\n          </div>\n        </div>\n\n        <div style={{padding: '28px 38px 34px'}}>\n          <div style={{height: 48, borderRadius: 12, background: 'rgba(255,255,255,.048)', display: 'flex', alignItems: 'center', padding: '0 18px', color: '#b9bec4', fontSize: 18}}>\n            Review this codebase and identify the safest implementation path\n          </div>\n\n          <div style={{height: 119, marginTop: 21, borderBottom: '1px solid rgba(255,255,255,.07)', overflow: 'hidden', position: 'relative'}}>\n            <div style={{position: 'absolute', inset: 0, opacity: summary, transform: `translateY(${10 * (1 - summary)}px)`, clipPath: `inset(0 ${100 * (1 - summary)}% 0 0)`}}>\n              <div style={{color: '#838b94', fontSize: 15, textTransform: 'uppercase', letterSpacing: '.12em', marginBottom: 10}}>Result summary</div>\n              <div style={{color: '#f3f4f5', fontSize: 26, fontWeight: 510, lineHeight: 1.35, letterSpacing: '-.022em'}}>\n                The codebase is ready for a focused, low-risk implementation.\n              </div>\n            </div>\n          </div>\n\n          <div style={{position: 'relative', height: 466, marginTop: 17}}>\n            {ROWS.map(([title, meta], index) => <EvidenceRow key={title} cue={ROW_CUES[index]} title={title} meta={meta} index={index}/>)}\n          </div>\n\n          <div style={{height: 60, marginTop: 2, borderTop: '1px solid rgba(255,255,255,.07)', display: 'flex', alignItems: 'flex-end'}}>\n            <div style={{display: 'flex', alignItems: 'center', gap: 11, opacity: complete, transform: `translateY(${5 * (1 - complete)}px)`}}>\n              <div style={{width: 24, height: 24, borderRadius: 99, background: '#b8f36a', display: 'grid', placeItems: 'center'}}>\n                <svg width=\"14\" height=\"14\" viewBox=\"0 0 16 16\" fill=\"none\"><path d=\"M3.4 8.3 6.6 11l6-6\" stroke=\"#15200d\" strokeWidth=\"2.2\" strokeLinecap=\"round\" strokeLinejoin=\"round\"/></svg>\n              </div>\n              <span style={{color: '#dce7d0', fontSize: 17, fontWeight: 560}}>Analysis complete</span>\n              <span style={{color: '#69717a', fontSize: 15}}>7 checks finished · ready to build</span>\n            </div>\n          </div>\n        </div>\n      </div>\n    </AbsoluteFill>\n  );\n};\n\n\n"
}