mcpField
S
stitch-remotion

stitch-remotion

github.com/gabelul创意与媒体4737 次安装14 周前更新
代码仓库

关于 stitch-remotion

用于将 Stitch 应用设计制作成 Remotion 演示视频的工作流技能,涵盖获取界面、准备素材、构建画面、添加转场与文字叠加,以及预览和渲染。

主要功能

  1. 01获取 Stitch 界面和截图
  2. 02准备界面清单与素材
  3. 03构建含转场的 Remotion 幻灯片
  4. 04添加缩放效果和文字叠加
  5. 05预览并渲染视频

适用场景

  1. 01根据应用界面制作演示
  2. 02制作功能演示视频
  3. 03将设计演示文稿转换为视频

MCP 相关

使用 Stitch MCP 工具(如 list_projects、list_screens 和 get_screen)查找设计并获取截图 URL,再利用素材制作 Remotion 视频。

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/gabelul/stitch-kit --skill stitch-remotion

安装后在 Claude Code 中输入/stitch-remotion确认已加载。

详细介绍

Stitch → Remotion 演示视频

限制: 仅当用户明确提到“Stitch”以及演示视频、Demo 或 Remotion 时,才使用此技能。

你是一名视频制作专家,负责根据 Stitch 应用设计制作演示视频。你会获取 Stitch 截图并构建 Remotion 合成内容,包括幻灯片转场、缩放动画和文字叠加。

前提条件

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

步骤 1:收集 Stitch 资源

发现屏幕
  1. 运行 list_tools → 查找 Stitch MCP 前缀
  2. 调用 [prefix]:list_projects → 选择项目
  3. 调用 [prefix]:list_screens,并传入 projects/[projectId] → 列出所有屏幕
  4. 对视频中需要的每个屏幕,使用数字 ID 调用 [prefix]:get_screen
下载截图

对于每个屏幕:

# Download screenshot to assets directory
curl -L "[screenshot.downloadUrl]" -o "video/public/assets/[screen-name].png"

或使用获取脚本:

bash scripts/fetch-stitch.sh "[htmlCode.downloadUrl]" "temp/[screen-name].html"
# Screenshots are separate — download via curl with the screenshot URL
构建屏幕清单

创建 screens.json 来描述视频:

{
  "projectName": "My App",
  "fps": 30,
  "screens": [
    {
      "id": "home",
      "title": "Home Screen",
      "description": "Main dashboard with key metrics",
      "imagePath": "./public/assets/home.png",
      "width": 390,
      "height": 844,
      "durationSeconds": 4
    },
    {
      "id": "profile",
      "title": "User Profile",
      "description": "Settings and account management",
      "imagePath": "./public/assets/profile.png",
      "width": 390,
      "height": 844,
      "durationSeconds": 3
    }
  ]
}

步骤 2:设置 Remotion 项目

# Create new Remotion project inside the working directory
cd video
npm create video@latest -- --blank
cd walkthrough-video
npm install @remotion/transitions

步骤 3:构建合成内容

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

interface ScreenSlideProps {
  /** Path to the screenshot image */
  imagePath: string
  /** Screen title displayed as overlay */
  title: string
  /** Supporting description text */
  description: string
  /** Whether to zoom in slightly during display */
  withZoom?: boolean
}

/**
 * Single screen slide with optional zoom effect and text overlay.
 * Fades in, holds, then fades out.
 */
export function ScreenSlide({ imagePath, title, description, withZoom = true }: ScreenSlideProps) {
  const frame = useCurrentFrame()
  const { fps, durationInFrames } = useVideoConfig()

  // Fade in over first 15 frames
  const fadeIn = spring({ fps, frame, config: { damping: 200 } })

  // Subtle zoom: 100% → 105% over the duration
  const scale = withZoom
    ? interpolate(frame, [0, durationInFrames], [1, 1.05], { extrapolateRight: 'clamp' })
    : 1

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

      {/* Bottom text overlay */}
      <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>
  )
}
演示视频合成
// 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  // 0.5s at 30fps

/**
 * Main walkthrough composition — one screen per slide, fade/slide transitions.
 */
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>
          {/* Add transition between screens (except after the last) */}
          {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}
    />
  </>
)

步骤 4:预览并渲染

# Preview in browser
cd video/walkthrough-video
npm run dev

# Render to MP4
npx remotion render Walkthrough output.mp4

# Higher quality render
npx remotion render Walkthrough output.mp4 --jpeg-quality 95 --concurrency 4

常见视频风格

风格配置
快速 Demo(1–2 分钟)每个屏幕 2–3 秒,淡入淡出转场,仅标题
功能演示每个屏幕 4–5 秒,缩放 + 滑动,标题 + 描述
演示文稿每个屏幕 5–8 秒,仅淡入淡出,完整描述叠加层
社交媒体短片每个屏幕 1–2 秒,快速剪切,音乐轨道

文件结构

project/
├── screens.json             ← Screen manifest
├── scripts/fetch-stitch.sh  ← GCS downloader
└── video/
    ├── public/
    │   └── assets/          ← Downloaded screenshots
    └── 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

参考资料

评论

支持 Markdown