walkthrough-video

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Walkthrough Video Generator

演示视频生成器

Create professional walkthrough videos from app screenshots or live sites using Remotion. Produces smooth, polished MP4 videos with transitions, zoom effects, and text overlays.
使用Remotion从应用截图或线上站点创建专业的流程演示视频,可输出带有转场、缩放效果和文字叠加的流畅精致MP4视频。

Overview

概述

This skill takes a set of screenshots (or captures them from a running app) and orchestrates them into a Remotion video composition with:
  • Smooth transitions between screens (fade, slide, wipe)
  • Zoom effects to highlight specific UI areas
  • Text overlays with titles, descriptions, and callouts
  • Progress indicators showing position in the walkthrough
  • Optional voiceover narration track
本技能接收一组截图(或从运行中的应用捕获截图),并将其编排为Remotion视频合成文件,具备以下特性:
  • 页面间流畅转场(淡入淡出、滑动、擦除)
  • 缩放效果,用于高亮特定UI区域
  • 文字叠加层,支持标题、描述和标注提示
  • 进度指示器,显示当前演示所处位置
  • 可选旁白配音轨道

Prerequisites

前置要求

  • Node.js 18+ installed
  • Screenshots of the app (or a running app to screenshot)
  • No Remotion experience needed — the skill generates all code
  • 已安装 Node.js 18+版本
  • 准备好应用截图(或可运行的用于截图的应用)
  • 无需Remotion使用经验——本技能会自动生成所有代码

Workflow

工作流程

Step 1: Gather Screenshots

步骤1:收集截图

Choose one approach:
选择以下任意一种方案:

Option A: From Existing Screenshots

方案A:使用现有截图

If the user already has screenshots (e.g. from
design-loop
or
product-showcase
):
Read screenshots from:
- .design/screenshots/
- .jez/screenshots/
- User-specified directory
Sort them in walkthrough order (alphabetically by filename, or as user specifies).
如果用户已经准备好了截图(例如来自
design-loop
product-showcase
的产出):
从以下位置读取截图:
- .design/screenshots/
- .jez/screenshots/
- 用户指定的目录
按照演示顺序排序(按文件名自动排序,或按照用户指定的顺序排序)。

Option B: Capture from Running App

方案B:从运行中的本地应用捕获

If the app is running locally:
  1. Start Playwright CLI session
  2. Navigate through each screen in sequence
  3. Screenshot at consistent dimensions (1280x720 recommended for video)
  4. Save to
    video/public/screens/
bash
playwright-cli -s=walkthrough open http://localhost:3000
playwright-cli -s=walkthrough resize 1280 720
playwright-cli -s=walkthrough screenshot --filename=video/public/screens/01-home.png
如果应用正在本地运行:
  1. 启动Playwright CLI会话
  2. 按顺序访问每个页面
  3. 以统一尺寸截图(视频推荐使用1280x720分辨率)
  4. 保存到
    video/public/screens/
    目录
bash
playwright-cli -s=walkthrough open http://localhost:3000
playwright-cli -s=walkthrough resize 1280 720
playwright-cli -s=walkthrough screenshot --filename=video/public/screens/01-home.png

Navigate to next page...

导航到下一页...

playwright-cli -s=walkthrough screenshot --filename=video/public/screens/02-dashboard.png
undefined
playwright-cli -s=walkthrough screenshot --filename=video/public/screens/02-dashboard.png
undefined

Option C: From Live URL

方案C:从线上URL捕获

Same as Option B but with a public URL. Screenshot each key page.
和方案B逻辑一致,仅将地址替换为公开URL,对每个核心页面截图即可。

Step 2: Create Screen Manifest

步骤2:创建页面清单文件

Build a
screens.json
describing the walkthrough:
json
{
  "projectName": "My App Walkthrough",
  "fps": 30,
  "width": 1280,
  "height": 720,
  "screens": [
    {
      "id": "home",
      "title": "Welcome to MyApp",
      "description": "The landing page introduces the core value proposition",
      "imagePath": "screens/01-home.png",
      "durationSeconds": 4,
      "transition": "fade",
      "zoomTarget": null
    },
    {
      "id": "dashboard",
      "title": "Your Dashboard",
      "description": "See all your projects at a glance",
      "imagePath": "screens/02-dashboard.png",
      "durationSeconds": 5,
      "transition": "slide-left",
      "zoomTarget": { "x": 100, "y": 200, "width": 400, "height": 300, "delay": 2 }
    }
  ]
}
FieldTypeDescription
id
stringUnique screen identifier
title
stringText overlay title
description
stringSubtitle or narration text
imagePath
stringPath relative to
video/public/
durationSeconds
numberHow long to show this screen
transition
string
fade
,
slide-left
,
slide-right
,
slide-up
,
wipe
,
none
zoomTarget
object/nullIf set, zoom into this region after
delay
seconds
编写
screens.json
文件描述演示流程:
json
{
  "projectName": "My App Walkthrough",
  "fps": 30,
  "width": 1280,
  "height": 720,
  "screens": [
    {
      "id": "home",
      "title": "Welcome to MyApp",
      "description": "The landing page introduces the core value proposition",
      "imagePath": "screens/01-home.png",
      "durationSeconds": 4,
      "transition": "fade",
      "zoomTarget": null
    },
    {
      "id": "dashboard",
      "title": "Your Dashboard",
      "description": "See all your projects at a glance",
      "imagePath": "screens/02-dashboard.png",
      "durationSeconds": 5,
      "transition": "slide-left",
      "zoomTarget": { "x": 100, "y": 200, "width": 400, "height": 300, "delay": 2 }
    }
  ]
}
字段类型说明
id
string页面唯一标识
title
string文字叠加层标题
description
string副标题或旁白文本
imagePath
string相对于
video/public/
的文件路径
durationSeconds
number该页面展示时长(秒)
transition
string
fade
(淡入淡出)、
slide-left
(左滑)、
slide-right
(右滑)、
slide-up
(上滑)、
wipe
(擦除)、
none
(无)
zoomTarget
object/null如配置该项,会在
delay
秒后缩放至指定区域

Step 3: Scaffold Remotion Project

步骤3:初始化Remotion项目

If no Remotion project exists:
bash
mkdir -p video
cd video
npm init -y
npm install remotion @remotion/cli @remotion/transitions react react-dom
npm install -D typescript @types/react
Create the project structure:
video/
├── src/
│   ├── Root.tsx                    # Remotion entry point
│   ├── WalkthroughComposition.tsx  # Main composition
│   ├── components/
│   │   ├── ScreenSlide.tsx         # Individual screen display
│   │   ├── TextOverlay.tsx         # Title/description overlay
│   │   ├── ProgressBar.tsx         # Walkthrough progress indicator
│   │   └── ZoomEffect.tsx          # Zoom into regions
│   └── config.ts                   # Load screens.json, calculate durations
├── public/
│   └── screens/                    # Screenshot assets
│       ├── 01-home.png
│       └── 02-dashboard.png
├── screens.json                    # Screen manifest
├── remotion.config.ts
├── tsconfig.json
└── package.json
如果不存在Remotion项目:
bash
mkdir -p video
cd video
npm init -y
npm install remotion @remotion/cli @remotion/transitions react react-dom
npm install -D typescript @types/react
创建项目结构:
video/
├── src/
│   ├── Root.tsx                    # Remotion入口文件
│   ├── WalkthroughComposition.tsx  # 主合成文件
│   ├── components/
│   │   ├── ScreenSlide.tsx         # 单页面展示组件
│   │   ├── TextOverlay.tsx         # 标题/描述叠加层
│   │   ├── ProgressBar.tsx         # 演示进度指示器
│   │   └── ZoomEffect.tsx          # 区域缩放效果
│   └── config.ts                   # 加载screens.json,计算时长
├── public/
│   └── screens/                    # 截图资源
│       ├── 01-home.png
│       └── 02-dashboard.png
├── screens.json                    # 页面清单文件
├── remotion.config.ts
├── tsconfig.json
└── package.json

Step 4: Generate Remotion Components

步骤4:生成Remotion组件

Generate each component file. Key patterns:
生成每个组件文件,核心代码模式如下:

Root.tsx

Root.tsx

tsx
import { Composition } from "remotion";
import { WalkthroughComposition } from "./WalkthroughComposition";
import { screens, totalDurationInFrames, FPS, WIDTH, HEIGHT } from "./config";

export const RemotionRoot = () => (
  <Composition
    id="Walkthrough"
    component={WalkthroughComposition}
    durationInFrames={totalDurationInFrames}
    fps={FPS}
    width={WIDTH}
    height={HEIGHT}
    defaultProps={{ screens }}
  />
);
tsx
import { Composition } from "remotion";
import { WalkthroughComposition } from "./WalkthroughComposition";
import { screens, totalDurationInFrames, FPS, WIDTH, HEIGHT } from "./config";

export const RemotionRoot = () => (
  <Composition
    id="Walkthrough"
    component={WalkthroughComposition}
    durationInFrames={totalDurationInFrames}
    fps={FPS}
    width={WIDTH}
    height={HEIGHT}
    defaultProps={{ screens }}
  />
);

ScreenSlide.tsx Pattern

ScreenSlide.tsx 代码模式

tsx
import { AbsoluteFill, Img, spring, useCurrentFrame, useVideoConfig } from "remotion";

interface ScreenSlideProps {
  imageSrc: string;
  title: string;
  description: string;
}

export const ScreenSlide: React.FC<ScreenSlideProps> = ({ imageSrc, title, description }) => {
  const frame = useCurrentFrame();
  const { fps } = useVideoConfig();

  // Fade in
  const opacity = spring({ frame, fps, config: { damping: 20 } });

  // Subtle zoom (Ken Burns effect)
  const scale = 1 + frame * 0.0002;

  return (
    <AbsoluteFill style={{ backgroundColor: "#000" }}>
      <Img
        src={imageSrc}
        style={{
          width: "100%",
          height: "100%",
          objectFit: "contain",
          opacity,
          transform: `scale(${scale})`,
        }}
      />
      {/* Text overlay at bottom */}
      <div style={{
        position: "absolute",
        bottom: 40,
        left: 40,
        right: 40,
        opacity: spring({ frame: frame - 15, fps, config: { damping: 20 } }),
      }}>
        <h2 style={{ color: "#fff", fontSize: 32, fontWeight: 700, textShadow: "0 2px 8px rgba(0,0,0,0.8)" }}>
          {title}
        </h2>
        <p style={{ color: "#ccc", fontSize: 18, textShadow: "0 1px 4px rgba(0,0,0,0.8)" }}>
          {description}
        </p>
      </div>
    </AbsoluteFill>
  );
};
tsx
import { AbsoluteFill, Img, spring, useCurrentFrame, useVideoConfig } from "remotion";

interface ScreenSlideProps {
  imageSrc: string;
  title: string;
  description: string;
}

export const ScreenSlide: React.FC<ScreenSlideProps> = ({ imageSrc, title, description }) => {
  const frame = useCurrentFrame();
  const { fps } = useVideoConfig();

  // 淡入效果
  const opacity = spring({ frame, fps, config: { damping: 20 } });

  // 轻微缩放(肯·伯恩斯效应)
  const scale = 1 + frame * 0.0002;

  return (
    <AbsoluteFill style={{ backgroundColor: "#000" }}>
      <Img
        src={imageSrc}
        style={{
          width: "100%",
          height: "100%",
          objectFit: "contain",
          opacity,
          transform: `scale(${scale})`,
        }}
      />
      {/* 底部文字叠加层 */}
      <div style={{
        position: "absolute",
        bottom: 40,
        left: 40,
        right: 40,
        opacity: spring({ frame: frame - 15, fps, config: { damping: 20 } }),
      }}>
        <h2 style={{ color: "#fff", fontSize: 32, fontWeight: 700, textShadow: "0 2px 8px rgba(0,0,0,0.8)" }}>
          {title}
        </h2>
        <p style={{ color: "#ccc", fontSize: 18, textShadow: "0 1px 4px rgba(0,0,0,0.8)" }}>
          {description}
        </p>
      </div>
    </AbsoluteFill>
  );
};

Transitions Between Screens

页面间转场效果

Use
@remotion/transitions
for transitions:
tsx
import { TransitionSeries } from "@remotion/transitions";
import { fade } from "@remotion/transitions/fade";
import { slide } from "@remotion/transitions/slide";

// In WalkthroughComposition:
<TransitionSeries>
  {screens.map((screen, i) => (
    <TransitionSeries.Sequence
      key={screen.id}
      durationInFrames={screen.durationSeconds * FPS}
    >
      <ScreenSlide {...screen} />
    </TransitionSeries.Sequence>
    // Add transition between screens (not after last)
    {i < screens.length - 1 && (
      <TransitionSeries.Transition
        presentation={getTransition(screens[i + 1].transition)}
        timing={springTiming({ config: { damping: 20 }, durationInFrames: 15 })}
      />
    )}
  ))}
</TransitionSeries>
使用
@remotion/transitions
实现转场:
tsx
import { TransitionSeries } from "@remotion/transitions";
import { fade } from "@remotion/transitions/fade";
import { slide } from "@remotion/transitions/slide";

// 在WalkthroughComposition组件中:
<TransitionSeries>
  {screens.map((screen, i) => (
    <TransitionSeries.Sequence
      key={screen.id}
      durationInFrames={screen.durationSeconds * FPS}
    >
      <ScreenSlide {...screen} />
    </TransitionSeries.Sequence>
    // 在页面间添加转场(最后一页后不需要)
    {i < screens.length - 1 && (
      <TransitionSeries.Transition
        presentation={getTransition(screens[i + 1].transition)}
        timing={springTiming({ config: { damping: 20 }, durationInFrames: 15 })}
      />
    )}
  ))}
</TransitionSeries>

Step 5: Preview and Refine

步骤5:预览与调整

bash
cd video
npx remotion studio
This opens a browser-based preview. Check:
  • Timing feels right for each screen
  • Transitions are smooth
  • Text overlays are readable
  • Zoom targets hit the right area
  • Progress bar (if included) is accurate
bash
cd video
npx remotion studio
该命令会打开浏览器端预览页面,检查以下内容:
  • 每个页面的展示时长合理
  • 转场效果流畅
  • 文字叠加层清晰可读
  • 缩放目标区域准确
  • 进度条(如启用)显示正确

Step 6: Render the Video

步骤6:渲染视频

bash
cd video
npx remotion render Walkthrough output.mp4 --codec h264
For higher quality:
bash
npx remotion render Walkthrough output.mp4 --codec h264 --quality 90
For web-optimised (smaller file):
bash
npx remotion render Walkthrough output.webm --codec vp8
bash
cd video
npx remotion render Walkthrough output.mp4 --codec h264
如需更高画质:
bash
npx remotion render Walkthrough output.mp4 --codec h264 --quality 90
如需网页优化版本(更小文件体积):
bash
npx remotion render Walkthrough output.webm --codec vp8

Advanced Features

高级功能

Zoom to Region

区域缩放

Zoom into a specific area of the screen to highlight a feature:
tsx
// In ZoomEffect.tsx — interpolate scale and translate
const zoomScale = interpolate(frame, [delayFrames, delayFrames + 30], [1, 2.5], {
  extrapolateRight: "clamp",
});
const translateX = interpolate(frame, [delayFrames, delayFrames + 30], [0, -targetX], {
  extrapolateRight: "clamp",
});
缩放至屏幕的特定区域以高亮功能点:
tsx
// 在ZoomEffect.tsx中 — 插值计算缩放比例和位移
const zoomScale = interpolate(frame, [delayFrames, delayFrames + 30], [1, 2.5], {
  extrapolateRight: "clamp",
});
const translateX = interpolate(frame, [delayFrames, delayFrames + 30], [0, -targetX], {
  extrapolateRight: "clamp",
});

Animated Callout Circles

动态标注圆圈

Draw attention to UI elements:
tsx
// Pulsing circle that appears at a specific point
const scale = spring({ frame: frame - delay, fps, config: { damping: 8, stiffness: 80 } });
<div style={{
  position: "absolute",
  left: x - 20, top: y - 20,
  width: 40, height: 40,
  borderRadius: "50%",
  border: "3px solid #3B82F6",
  transform: `scale(${scale})`,
  opacity: Math.min(1, scale),
}} />
吸引用户注意UI元素:
tsx
// 在指定位置显示脉动圆圈
const scale = spring({ frame: frame - delay, fps, config: { damping: 8, stiffness: 80 } });
<div style={{
  position: "absolute",
  left: x - 20, top: y - 20,
  width: 40, height: 40,
  borderRadius: "50%",
  border: "3px solid #3B82F6",
  transform: `scale(${scale})`,
  opacity: Math.min(1, scale),
}} />

Background Music

背景音乐

Add a subtle background track:
tsx
import { Audio } from "remotion";

<Audio src={staticFile("music/background.mp3")} volume={0.15} />
添加轻柔的背景音轨:
tsx
import { Audio } from "remotion";

<Audio src={staticFile("music/background.mp3")} volume={0.15} />

Intro and Outro Slides

开场和结束页

Add title card at start and CTA at end:
tsx
// First sequence: Title card (3 seconds)
<TransitionSeries.Sequence durationInFrames={90}>
  <TitleCard projectName="MyApp" tagline="The future of project management" />
</TransitionSeries.Sequence>

// ... screen sequences ...

// Last sequence: CTA card (4 seconds)
<TransitionSeries.Sequence durationInFrames={120}>
  <CtaCard url="myapp.com" text="Try it free" />
</TransitionSeries.Sequence>
在开头添加标题卡片,结尾添加行动引导卡片:
tsx
// 第一个序列:标题卡片(3秒)
<TransitionSeries.Sequence durationInFrames={90}>
  <TitleCard projectName="MyApp" tagline="The future of project management" />
</TransitionSeries.Sequence>

// ... 页面序列 ...

// 最后一个序列:行动引导卡片(4秒)
<TransitionSeries.Sequence durationInFrames={120}>
  <CtaCard url="myapp.com" text="Try it free" />
</TransitionSeries.Sequence>

Transition Reference

转场效果参考

NameEffectBest for
fade
Cross-fade dissolveDefault, works everywhere
slide-left
New screen slides in from rightSequential flow (next page)
slide-right
New screen slides in from leftGoing back
slide-up
New screen slides in from bottomDrill-down into detail
wipe
Wipe transitionDramatic reveal
none
Hard cutQuick comparison
名称效果适用场景
fade
交叉淡入淡出默认效果,通用所有场景
slide-left
新页面从右侧滑入顺序流程(下一页)
slide-right
新页面从左侧滑入返回上一页场景
slide-up
新页面从底部滑入进入详情页场景
wipe
擦除转场戏剧化展示场景
none
硬切快速对比场景

Output Options

输出选项

FormatCommandUse case
MP4 (H.264)
--codec h264
Universal compatibility
WebM (VP8)
--codec vp8
Web embedding, smaller files
GIF
--image-format png
then
ffmpeg
Short loops, social media
PNG sequence
--image-format png --sequence
Post-production editing
格式命令适用场景
MP4 (H.264)
--codec h264
通用兼容场景
WebM (VP8)
--codec vp8
网页嵌入场景,文件体积更小
GIF
--image-format png
配合
ffmpeg
转换
短循环内容,社交媒体场景
PNG序列
--image-format png --sequence
后期编辑场景

Tips

使用提示

  • 1280x720 is ideal for web walkthrough videos (good quality, reasonable file size)
  • 3-5 seconds per screen feels natural — longer for complex screens
  • Fade is the safest transition — use others sparingly for emphasis
  • Text overlays need contrast — use text-shadow or semi-transparent background
  • Ken Burns effect (subtle zoom) prevents static screenshots from feeling dead
  • Preview before rendering
    npx remotion studio
    saves time vs full renders
  • Keep it under 90 seconds — attention drops sharply after that
  • 1280x720是网页演示视频的理想分辨率(画质优秀,文件体积合理)
  • 每个页面展示3-5秒体验最自然,复杂页面可适当延长
  • 淡入淡出是最稳妥的转场效果——其他效果按需少量使用用于强调
  • 文字叠加层需要足够对比度——使用文字阴影或半透明背景提升可读性
  • **肯·伯恩斯效应(轻微缩放)**可避免静态截图显得呆板
  • 渲染前先预览——
    npx remotion studio
    比全量渲染节省大量时间
  • 视频时长控制在90秒以内——超过该时长用户注意力会大幅下降

Common Pitfalls

常见问题

  • ❌ Using screenshots at different dimensions (causes scaling issues)
  • ❌ Too many transition types (pick 1-2 and stay consistent)
  • ❌ Text overlays that are too small or lack contrast
  • ❌ No intro/outro — video feels abrupt
  • ❌ Rendering before previewing (wastes time on fixable issues)
  • ❌ Forgetting
    staticFile()
    for assets in
    public/
    directory
  • ❌ 使用不同尺寸的截图(会导致缩放异常)
  • ❌ 使用过多转场类型(选择1-2种保持风格一致即可)
  • ❌ 文字叠加层太小或对比度不足
  • ❌ 缺少开场/结束页——视频会显得很突兀
  • ❌ 预览前就渲染(会在可修复的问题上浪费大量时间)
  • ❌ 忘记使用
    staticFile()
    引用
    public/
    目录下的资源