Communitygithub.com

gabelul/stitch-kit

根据 Stitch 项目自动生成使用 Remotion 制作的产品演示视频。下载 Stitch 屏幕截图,构建带有过渡动画和文字叠加的 Remotion 合成,并渲染为 MP4。需配合 stitch-mcp-list-screens 和 stitch-mcp-get-screen 使用。

stitch-kit 是什么?

该技能专为需要从 Stitch 设计稿快速创建产品演示视频的开发者和设计师设计。它通过调用 Stitch MCP 服务器获取屏幕截图,利用 Remotion 框架构建具有滑动、淡入淡出、缩放等过渡效果的视频合成,并支持文字标题和描述叠加。最终输出为 MP4 格式。支持通过 stitch-mcp-list-screens 和 stitch-mcp-get-screen 进行屏幕发现与资源下载。用户只需提供项目 ID 和屏幕列表,技能会自动生成 screens.json 清单,并搭建 Remotion 项目结构,编写 ScreenSlide 和 Walkthrough 组件,最终预览和渲染视频。适用于应用演示、功能讲解、演示文稿、社交媒体短片等多种场景。

兼容平台~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/gabelul/stitch-kit/tree/HEAD/skills/stitch-remotion

在你喜欢的 AI 中提问

打开一个已预加载此 Agent Skill 的新对话。

文档

Stitch → Remotion 演示视频制作

约束: 仅在用户明确提到“Stitch”以及演示视频、演示或 Remotion 时使用此技能。

你是一位视频制作专家,负责根据 Stitch 应用设计稿制作演示视频。你将获取 Stitch 屏幕截图,并构建一个 Remotion 合成——包含滑动过渡、缩放动画和文字叠加。

前提条件

  • Stitch MCP 服务器(或已知的屏幕 ID)
  • Node.js 18+ 和 npm
  • Remotion CLI(npm install -g remotion 或通过 npx 使用)

第一步:收集 Stitch 素材

发现屏幕

  1. 运行 list_tools → 找到 Stitch MCP 前缀
  2. 调用 [前缀]:list_projects → 选择项目
  3. 调用 [前缀]:list_screens,参数为 projects/[项目ID] → 列出所有屏幕
  4. 对于视频中需要的每个屏幕,调用 [前缀]:get_screen,参数为数字 ID

下载屏幕截图

针对每个屏幕:

# 将截图下载到 assets 目录
curl -L "[screenshot.downloadUrl]" -o "video/public/assets/[屏幕名称].png"

或使用抓取脚本:

bash scripts/fetch-stitch.sh "[htmlCode.downloadUrl]" "temp/[屏幕名称].html"
# 截图是独立的 — 通过 curl 使用截图 URL 下载

构建屏幕清单

创建 screens.json 描述视频:

{
  "projectName": "我的应用",
  "fps": 30,
  "screens": [
    {
      "id": "home",
      "title": "首页",
      "description": "包含关键指标的主仪表盘",
      "imagePath": "./public/assets/home.png",
      "width": 390,
      "height": 844,
      "durationSeconds": 4
    },
    {
      "id": "profile",
      "title": "用户资料",
      "description": "设置和账户管理",
      "imagePath": "./public/assets/profile.png",
      "width": 390,
      "height": 844,
      "durationSeconds": 3
    }
  ]
}

第二步:设置 Remotion 项目

# 在工作目录内创建新的 Remotion 项目
cd video
npm create video@latest -- --blank
cd walkthrough-video
npm install @remotion/transitions

第三步:构建合成

ScreenSlide 组件

// video/src/ScreenSlide.tsx
import { AbsoluteFill, Img, interpolate, spring, useCurrentFrame, useVideoConfig } from 'remotion'

interface ScreenSlideProps {
  /** 截图图片路径 */
  imagePath: string
  /** 作为叠加层显示的屏幕标题 */
  title: string
  /** 辅助描述文本 */
  description: string
  /** 显示期间是否略微缩放 */
  withZoom?: boolean
}

/**
 * 单个屏幕幻灯片,带有可选的缩放效果和文字叠加。
 * 淡入、保持、然后淡出。
 */
export function ScreenSlide({ imagePath, title, description, withZoom = true }: ScreenSlideProps) {
  const frame = useCurrentFrame()
  const { fps, durationInFrames } = useVideoConfig()

  // 前15帧淡入
  const fadeIn = spring({ fps, frame, config: { damping: 200 } })

  // 细微缩放:100% → 105%
  const scale = withZoom
    ? interpolate(frame, [0, durationInFrames], [1, 1.05], { extrapolateRight: 'clamp' })
    : 1

  return (
    <AbsoluteFill style={{ backgroundColor: '#000' }}>
      {/* 截图 */}
      <AbsoluteFill style={{ opacity: fadeIn, transform: `scale(${scale})`, transformOrigin: 'center' }}>
        <Img src={imagePath} style={{ width: '100%', height: '100%', objectFit: 'contain' }} />
      </AbsoluteFill>

      {/* 底部文字叠加 */}
      <AbsoluteFill
        style={{
          justifyContent: 'flex-end',
          padding: '40px 60px',
          background: 'linear-gradient(transparent, rgba(0,0,0,0.7))',
          opacity: fadeIn,
        }}
      >
        <h2 style={{ color: '#fff', fontSize: 36, fontWeight: 700, margin: 0 }}>{title}</h2>
        {description ? (
          <p style={{ color: 'rgba(255,255,255,0.8)', fontSize: 20, margin: '8px 0 0' }}>
            {description}
          </p>
        ) : null}
      </AbsoluteFill>
    </AbsoluteFill>
  )
}

Walkthrough 合成

// video/src/WalkthroughComposition.tsx
import { Series, TransitionSeries } from '@remotion/transitions'
import { fade } from '@remotion/transitions/fade'
import { slide } from '@remotion/transitions/slide'
import screensData from '../../screens.json'
import { ScreenSlide } from './ScreenSlide'

const TRANSITION_FRAMES = 15  // 30fps 下 0.5 秒

/**
 * 主演示合成 —— 每个屏幕一个幻灯片,带淡入/滑动过渡。
 */
export function WalkthroughComposition() {
  return (
    <TransitionSeries>
      {screensData.screens.map((screen, i) => (
        <>
          <TransitionSeries.Sequence
            key={screen.id}
            durationInFrames={screen.durationSeconds * screensData.fps}
          >
            <ScreenSlide
              imagePath={screen.imagePath}
              title={screen.title}
              description={screen.description}
            />
          </TransitionSeries.Sequence>
          {/* 屏幕之间添加过渡(最后一个之后不添加) */}
          {i < screensData.screens.length - 1 && (
            <TransitionSeries.Transition
              key={`t-${screen.id}`}
              timing={fade({ durationInFrames: TRANSITION_FRAMES })}
            />
          )}
        </>
      ))}
    </TransitionSeries>
  )
}

在 Root.tsx 中注册

// video/src/Root.tsx
import { Composition } from 'remotion'
import { WalkthroughComposition } from './WalkthroughComposition'
import screensData from '../../screens.json'

const TOTAL_FRAMES = screensData.screens.reduce(
  (acc, s) => acc + s.durationSeconds * screensData.fps,
  0
)

export const RemotionRoot = () => (
  <>
    <Composition
      id="Walkthrough"
      component={WalkthroughComposition}
      durationInFrames={TOTAL_FRAMES}
      fps={screensData.fps}
      width={screensData.screens[0]?.width ?? 390}
      height={screensData.screens[0]?.height ?? 844}
    />
  </>
)

第四步:预览和渲染

# 在浏览器中预览
cd video/walkthrough-video
npm run dev

# 渲染为 MP4
npx remotion render Walkthrough output.mp4

# 更高品质渲染
npx remotion render Walkthrough output.mp4 --jpeg-quality 95 --concurrency 4

常见视频风格

风格配置
快速演示(1–2 分钟)每个屏幕 2–3 秒,淡入过渡,仅标题
功能讲解每个屏幕 4–5 秒,缩放+滑动,标题+描述
演示文稿每个屏幕 5–8 秒,仅淡入,完整描述叠加
社交媒体短视频每个屏幕 1–2 秒,快速切换,背景音乐

文件结构

project/
├── screens.json             ← 屏幕清单
├── scripts/fetch-stitch.sh  ← GCS 下载器
└── video/
    ├── public/
    │   └── assets/          ← 下载的截图
    └── walkthrough-video/
        ├── src/
        │   ├── WalkthroughComposition.tsx
        │   ├── ScreenSlide.tsx
        │   └── Root.tsx
        ├── remotion.config.ts
        └── package.json

故障排除

问题解决方法
截图模糊下载全分辨率:直接使用截图 URL,而非缩略图
布局不匹配将 Remotion 合成尺寸设置为与 get_screen 中的屏幕 width + height 一致
过渡卡顿增加 TRANSITION_FRAMES 或从 slide 切换到 fade
构建因 ESM 失败在 package.json 中添加 "type": "module",并检查 Remotion 版本兼容性
MP4 无法播放检查是否安装了 FFmpeg:ffmpeg -version

参考资料

相关技能