SuperAPI AI Directory

recording

Testing & quality

View repository

Updated 10-16 00:21

About this skill

Browser screen recording skill

Core requirements

  1. Single continuous recording - Do not record in segments
  2. Record the timeline - Precise timestamp for each operation
  3. Real data - Use real or meaningful test data
  4. Appropriate pacing - Leave enough time for the visuals to be presented

Screen recording script structure

const { chromium } = require("playwright");
const path = require("path");
const fs = require("fs/promises");

const BASE_URL = "http://localhost:5173";
const OUTPUT_DIR = path.join(__dirname, "..", "public", "recordings");
const VIEWPORT = { width: 1920, height: 1080 };

// Test data - use real and meaningful data const TEST_DATA = { // Define test data };

// Timeline recorder - key component class TimelineRecorder { constructor() { this.startTime = Date.now(); this.events = []; }

mark(event) { const elapsed = (Date.now() - this.startTime) / 1000; this.events.push({ time: elapsed, event }); console.log( [${elapsed.toFixed(1)}s] ${event}); return elapsed; }

getTimeline() { return this.events; } }

async function recordDemo() { await fs.mkdir(OUTPUT_DIR, { recursive: true });

const browser = await chromium.launch({ headless: false, slowMo: 50, // Slow down operations slightly for a more natural feel });

const context = await browser.newContext({ viewport: VIEWPORT, recordVideo: { dir: OUTPUT_DIR, size: VIEWPORT, }, locale: "zh-CN", });

const page = await context.newPage(); const timeline = new TimelineRecorder();

try { // Scenario recording...

} finally { // Save the timeline const timelineData = { totalDuration: (Date.now() - timeline.startTime) / 1000, events: timeline.getTimeline(), };

await fs.writeFile(
  path.join(OUTPUT_DIR, "timeline.json"),
  JSON.stringify(timelineData, null, 2)
);

await page.close();
await context.close();
await browser.close();

} }


## 录屏最佳实践

### 1. 等待时间设置

```javascript
// 页面加载后等待
await page.goto(url, { waitUntil: "networkidle" });
await page.waitForTimeout(1500);

// 点击后等待响应
await element.click();
await page.waitForTimeout(2000);

// 表单输入后等待
await input.fill(value);
await page.waitForTimeout(500);

// 弹窗打开后等待
await dialog.waitFor({ state: "visible" });
await page.waitForTimeout(1500);

2. Operation pacing

Operation type Recommended wait time
Page load 1.5-3 seconds
Button click 1-2 seconds
Form input 0.5-1 second
Pop-up appears 1.5-2 seconds
Data loading 2-3 seconds
Scene transition 2-3 seconds

3. Hover display

// 悬停显示 tooltip
await element.hover();
timeline.mark("悬停显示提示");
await page.waitForTimeout(3000);  // 留足时间让观众看清

4. Character-by-character input effect

// 更真实的输入效果
for (const char of text) {
  await input.type(char, { delay: 80 });
}

Timeline recording specification

Events that must be recorded

  • Page load complete
  • Main area ready
  • Every click operation
  • Each data load complete
  • Pop-up opened/closed
  • Recording ended

Event naming specification

timeline.mark("页面加载完成");
timeline.mark("点击[按钮名]按钮");
timeline.mark("输入用户名: xxx");
timeline.mark("[弹窗名]弹窗打开");
timeline.mark("显示查询结果");
timeline.mark("录制结束");

Video format conversion

Convert to MP4 after recording:

// 使用 FFmpeg 转换
const { execSync } = require("child_process");

execSync(`ffmpeg -y -i ${webmPath} -c:v libx264 -preset fast -crf 23 ${mp4Path}`);

Troubleshooting

Chromium not installed

npx playwright install chromium

Recording is black

Ensure headless: false

Operations are too fast

Increase the slowMo value or waitForTimeout

Element not found

Use more stable selectors:

// 推荐
page.locator('button:has-text("查询")')
page.locator('.el-button--primary')

// 避免
page.locator('button:nth-child(2)')