Agent Skills › alinaqi/maggy › demo-video

demo-video

GitHub

利用 Playwright 录制带字幕的 Web 应用演示视频,用于产品验证、功能展示及 Bug 修复证据。结合自动化测试与视觉回放,确保端到端流程的正确性并提供直观的证明。

skills/demo-video/SKILL.md alinaqi/maggy

Trigger Scenarios

需要制作产品功能演示视频 生成用户操作流程的视觉验证记录 作为 E2E 测试的补充以证明端到端流程

Install

npx skills add alinaqi/maggy --skill demo-video -g -y
More Options

Use without installing

npx skills use alinaqi/maggy@demo-video

指定 Agent (Claude Code)

npx skills add alinaqi/maggy --skill demo-video -a claude-code -g -y

安装 repo 全部 skill

npx skills add alinaqi/maggy --all -g -y

预览 repo 内 skill

npx skills add alinaqi/maggy --list

SKILL.md

Frontmatter
{
    "name": "demo-video",
    "effort": "medium",
    "description": "Record captioned product walkthrough videos of any web app with Playwright + ffmpeg — proof videos for stakeholders, feature demos, bug-fix evidence",
    "when-to-use": "Default visual validation for web projects — when asked for a video, screen recording, walkthrough, or visual proof of features\/fixes in a web app, and as the user-facing-flow evidence in the Definition of Done",
    "user-invocable": true
}

Demo Video Skill — visual validation for web apps

Record a captioned walkthrough video of a running web app, verify it frame-by-frame, convert to mp4, and deliver it. Battle-tested on real client-feedback proof videos.

This is the harness's default visual validation for web projects: a demo video walks a real user flow end-to-end and doubles as a passing E2E test, so "it works" is proven visually, not claimed. It complements [[visual-validation]] (autonomous screenshot-regression checks) and [[playwright-testing]] (the E2E suite): screenshots catch pixel regressions, the suite proves behavior, and a demo video proves the whole user-facing flow the way a person would see it.

The method

  1. Write a temporary Playwright spec (e2e/zz-<name>-video.spec.ts or scratchpad) that walks the real flows as one continuous test. One test = one video.
  2. Record via Playwright's built-in video, never external screen capture:
    test.use({ video: { mode: 'on', size: { width: 1280, height: 800 } }, viewport: { width: 1280, height: 800 } })
    test.setTimeout(240000)
    
  3. Narrate with an injected caption bar — the video must explain itself without audio. Call before each chapter; the pause gives viewers time to read:
    async function caption(page: Page, text: string) {
      await page.evaluate((t) => {
        let bar = document.getElementById('demo-caption')
        if (!bar) {
          bar = document.createElement('div')
          bar.id = 'demo-caption'
          bar.style.cssText =
            'position:fixed;left:0;right:0;bottom:0;z-index:99999;background:#142b1e;color:#f7f5f0;' +
            'font:600 15px/1.4 Inter,system-ui,sans-serif;padding:12px 20px;letter-spacing:0.01em'
          document.body.appendChild(bar)
        }
        bar.textContent = t
      }, text)
      await page.waitForTimeout(2200)
    }
    
    The caption bar is re-injected automatically because caption() re-creates it after each page.goto (the element does not survive navigation — call caption AFTER navigating).
  4. Structure as chapters: caption → act → assert → caption the outcome. Keep real assertions in the spec so the video doubles as a passing test — a video of a broken flow must fail loudly, never ship silently.
  5. Reuse the project's e2e helpers (logins, seeded data, fixtures) instead of hand-rolling flows. Prefer fake/deterministic AI modes so runs are repeatable.

Recording gotchas (learned the hard way)

  • Scroll-reveal animations: elements animated in by IntersectionObserver stay invisible in captures unless you actually scroll. Walk the page (scrollIntoViewIfNeeded or step-scroll) before asserting/capturing.
  • OTP/async steps: after submitting a form that triggers an email/side effect, wait for the next UI state (await expect(page.locator('#code')).toBeVisible()) before reading outboxes/fixtures — racing the write is the #1 flake.
  • Selector traps: "first link" often matches a New/Create button; exclude it (a[href^="/x/"]:not([href$="/new"])).
  • Demonstrating error states: drive the app's real error surface (e.g. navigate to the URL the failing action redirects to) rather than mocking pages that don't exist.

Produce and verify

rm -rf test-results/zz-<name>*          # stale videos have the same filename
npx playwright test e2e/zz-<name>-video.spec.ts
find test-results -name "video.webm"    # the recording

# Convert to mp4 (universal playback, ~2-3x smaller)
ffmpeg -y -i "<video.webm>" -c:v libx264 -pix_fmt yuv420p -movflags +faststart out.mp4

# ALWAYS spot-check frames before delivering — extract a few and LOOK at them
ffmpeg -y -i out.mp4 -vf "select='eq(n\,60)+eq(n\,300)+eq(n\,600)'" -vsync vfr frame_%d.png

Read the extracted frames with the Read tool and confirm captions render and each chapter shows what it claims. Never deliver an unviewed video.

Deliver and clean up

  • Copy the mp4 to your stakeholder-updates archive (e.g. ~/Documents/updates/<project>/, the house archive for stakeholder updates), and send it to the user (SendUserFile or equivalent).
  • Naming is mandatory and identifying: YYYY-MM-DD-NN-<project>-<what-it-proves>.mp4 — the date it was recorded, then a two-digit index so several videos on the same day stay ordered and every video is uniquely identifiable at a glance. Allocate the next free index with a no-clobber loop — never a count (wc -l), which reuses an index if an earlier file was deleted and silently overwrites an existing mp4:
    DIR=~/Documents/updates/<project>; DATE=$(date +%F); mkdir -p "$DIR"
    NN=1
    while printf -v F '%s/%s-%02d-<project>-<what-it-proves>.mp4' "$DIR" "$DATE" "$NN" && [ -e "$F" ]; do
      NN=$((NN+1))
    done
    cp out.mp4 "$F"
    
    Never video.mp4, never a name without its date and index.
  • Delete the temporary spec — it is a capture script, not a test; it must not join the suite or CI.

Prerequisites

  • Playwright installed in the project (@playwright/test) with a working dev/preview server.
  • ffmpeg on PATH for the webm→mp4 conversion and frame extraction.

Version History

  • 8723129 Current 2026-09-22 14:37

Same Skill Collection

skills/aeo-optimization/SKILL.md
skills/agent-teams/SKILL.md
skills/agentic-development/SKILL.md
skills/ai-models/SKILL.md
skills/android-java/SKILL.md
skills/android-kotlin/SKILL.md
skills/autonomous-testing/SKILL.md
skills/aws-aurora/SKILL.md
skills/aws-dynamodb/SKILL.md
skills/azure-cosmosdb/SKILL.md
skills/base/SKILL.md
skills/build-in-public/SKILL.md
skills/cloudflare-d1/SKILL.md
skills/code-deduplication/SKILL.md
skills/code-graph/SKILL.md
skills/codex-review/SKILL.md
skills/commit-hygiene/SKILL.md
skills/context-shunt/SKILL.md
skills/council-review/SKILL.md
skills/cpg-analysis/SKILL.md
skills/cross-agent-delegation/SKILL.md
skills/database-schema/SKILL.md
skills/dataforseo/SKILL.md
skills/existing-repo/SKILL.md
skills/external-model-delegation/SKILL.md
skills/firebase/SKILL.md
skills/flutter/SKILL.md
skills/gemini-review/SKILL.md
skills/icpg/SKILL.md
skills/iterative-development/SKILL.md
skills/klaviyo/SKILL.md
skills/llm-patterns/SKILL.md
skills/maggy/SKILL.md
skills/medusa/SKILL.md
skills/mnemos/SKILL.md
skills/model-routing/SKILL.md
skills/ms-teams-apps/SKILL.md
skills/nodejs-backend/SKILL.md
skills/playwright-testing/SKILL.md
skills/polyphony/SKILL.md
skills/project-tooling/SKILL.md
skills/pwa-development/SKILL.md
skills/python/SKILL.md
skills/react-native/SKILL.md
skills/react-web/SKILL.md
skills/reddit-api/SKILL.md
skills/security-audit/SKILL.md
skills/session-management/SKILL.md
skills/shopify-apps/SKILL.md

Metadata

Files
0
Version
72a456e
Hash
6c5c379a
Indexed
2026-09-22 14:37

ホーム - Wiki
Copyright © 2011-2026 iteam. Current version is 2.155.2. UTC+08:00, 2026-09-30 20:40
浙ICP备14020137号-1