demo-video-maker
v1.1.1
Published
π¬ Create stunning cinematic demo videos automatically from your web applications with dynamic camera following, zoom effects, and gorgeous visual polish
Maintainers
Readme
π¬ Demo Video Maker
Create stunning cinematic demo videos automatically from your web applications
Transform your web application into professional demo videos with cinematic mouse movements, dynamic camera following, zoom effects, and gorgeous visual polish. Perfect for product launches, feature demonstrations, marketing materials, and investor presentations.
β¨ Features
- π― Configuration-Driven: JSON-based demo definitions for precise control
- π· Camera Follow: Dynamic zoom and pan that follows mouse movement
- β¨ Visual Effects: Click animations, element highlighting, and smooth transitions
- π¬ Cinematic Quality: Professional 1920x1080 HD video output with visible cursor
- π§ Highly Configurable: Customize timing, effects, interactions, and visual style
- π±οΈ Visible Cursor: Custom cursor that appears in video recordings
- π Viewport Protection: Smart zoom bounds prevent showing browser edges
- π Multiple Demos: Create separate demos for different features automatically
- π‘οΈ Enterprise Security: Path validation, input sanitization, memory management
- π― Simple CLI: Just run
demo-video-makerin your project directory
π Quick Start
1. Install the Tool
npm install -g demo-video-maker2. Create Your First Demo
# Navigate to your web app
cd /path/to/your/webapp
# Generate a sample demo.json
demo-video-maker --init
# Edit demo.json to match your app's elements3. Run the Demo
Important: Your web application must be running before generating demos!
# Step 1: Start your web app (in a separate terminal)
npm start # or npm run dev, yarn start, etc.
# Step 2: Generate the demo video (default port is 3000)
demo-video-maker
# If your app runs on a different port, specify it:
demo-video-maker --port 8080
demo-video-maker -p 3001
# Or provide the full URL:
demo-video-maker . http://localhost:4000That's it! Your demo video will be saved in demo-output-cinematic-[timestamp]/
π System Requirements
Required
- Node.js: 18.0.0 or higher
- Operating System: macOS, Linux, or Windows 10+
- Memory: 4GB RAM minimum, 8GB recommended
- Browser: Chromium/Chrome (automatically managed by Playwright)
Optional
- FFmpeg: For video format conversion (auto-detected)
- Git: For version control integration
Supported Web Frameworks
- β React (Create React App, Next.js, Vite)
- β Vue.js (Vue CLI, Nuxt.js, Vite)
- β Angular (Angular CLI)
- β Svelte/SvelteKit
- β Plain HTML/JavaScript
- β Any web framework running on localhost
π Configuration Guide
Demo Video Maker uses demo.json files to define interactive demonstrations. Place these files anywhere in your project to create targeted demos.
Basic Configuration Structure
{
"name": "Feature Name",
"description": "What this demo shows",
"entry": {
"url": "/feature-page",
"selector": "[data-testid='main-container']",
"waitTime": 2000
},
"interactions": [
{
"type": "click",
"selector": "[data-testid='button']",
"waitBeforeMove": 1000,
"waitAfterClick": 1500,
"zoomLevel": 2.0,
"description": "Click the main action button"
}
],
"effects": {
"cameraFollow": true,
"zoomLevel": 1.6,
"clickAnimations": true
},
"recording": {
"duration": 30000,
"outputName": "feature-demo"
}
}π― Entry Configuration
Controls where the demo starts and initial setup.
{
"entry": {
"url": "/dashboard", // Relative URL to navigate to
"selector": ".main-content", // Element to focus on (optional)
"waitTime": 3000 // Time to wait after navigation (ms)
}
}| Property | Type | Default | Description |
|----------|------|---------|-------------|
| url | string | "/" | Relative URL path to navigate to |
| selector | string | null | CSS selector to focus camera on entry |
| waitTime | number | 2000 | Milliseconds to wait after page load |
π Interaction Types
Define the sequence of user interactions to demonstrate.
Click Interaction
{
"type": "click",
"selector": "[data-testid='submit-button']",
"waitBeforeMove": 1000,
"waitAfter": 1500, // Time to wait after action completes
"zoomLevel": 2.0,
"skipIfNotFound": false,
"description": "Submit the form"
}Note: Each click interaction includes a brief pause (300-800ms) before execution to simulate natural user behavior.
Hover Interaction
{
"type": "hover",
"selector": ".tooltip-trigger",
"waitBeforeMove": 800,
"waitAfter": 1200, // Time to wait after hovering
"zoomLevel": 1.8,
"description": "Show tooltip on hover"
}Type Interaction
{
"type": "type",
"selector": "input[name='email']",
"text": "[email protected]",
"waitBeforeMove": 500,
"waitAfter": 2000, // Time to wait after typing completes
"zoomLevel": 1.9,
"description": "Enter email address"
}Note: Text is typed character-by-character with 80-200ms random delays between keystrokes for realistic typing animation.
Scroll Interaction
{
"type": "scroll",
"selector": "#bottom-section",
"waitBeforeMove": 800,
"waitAfter": 1500, // Time to wait after scroll completes
"description": "Scroll to bottom section"
}Wait Interaction
{
"type": "wait",
"waitTime": 3000,
"description": "Wait for animation to complete"
}Navigate Interaction
{
"type": "navigate",
"url": "/settings",
"waitBeforeMove": 1000,
"waitAfterClick": 2500,
"description": "Navigate to settings page"
}π¨ Visual Effects Configuration
Control the cinematic visual effects and camera behavior.
{
"effects": {
"cameraFollow": true, // Enable dynamic camera following
"zoomLevel": 1.6, // Default zoom level (1.0-5.0)
"clickAnimations": true, // Ripple effects on clicks
"mouseMoveSpeed": 60, // Mouse movement speed (10-200)
"attentionPattern": true // Figure-8 intro/outro animation (default: true)
}
}Note: The attentionPattern creates a figure-8 mouse movement at the beginning and end of the demo, adding ~5 seconds to the total video duration.
| Property | Type | Default | Range | Description |
|----------|------|---------|-------|-------------|
| cameraFollow | boolean | true | - | Enable dynamic zoom and camera following with 150ms transitions |
| zoomLevel | number | 1.6 | 1.0-5.0 | Default zoom level for interactions |
| clickAnimations | boolean | true | - | Show click ripple animations |
| mouseMoveSpeed | number | 60 | 10-200 | Mouse movement speed (steps per second) |
| attentionPattern | boolean | true | - | Show figure-8 pattern at start/end (adds ~5s) |
Zoom Behavior:
- Zoom values are automatically clamped to a minimum of 1.0 to prevent viewport edges from showing
- When zoomed in, camera panning is bounded to keep content within the viewport
- The page background is set to dark (#0a0a0a) to blend with any edge cases
β±οΈ Timing Configuration
Fine-tune the timing and pacing of interactions.
{
"timings": {
"waitBeforeMove": 1000, // Delay before moving mouse (ms)
"waitAfterClick": 1500, // Delay after clicking (ms)
"waitBetweenSteps": 800, // Delay between interaction steps (ms)
"pageLoadWait": 2000, // Wait time after navigation (ms)
"typingSpeed": [80, 200] // Min/max delay between keystrokes (ms)
}
}Important Timing Notes:
- The actual video duration may exceed the configured
durationdue to:- Attention pattern animations (~5s each at start/end)
- Camera follow transitions (150ms per movement)
- Accumulated wait times between interactions
- Character-by-character typing animations
- To minimize video length, disable
attentionPatternand reduce wait times
| Property | Type | Default | Range | Description |
|----------|------|---------|-------|-------------|
| waitBeforeMove | number | 1000 | 0-10000 | Milliseconds to wait before moving mouse |
| waitAfterClick | number | 1500 | 0-10000 | Milliseconds to wait after interaction |
| waitBetweenSteps | number | 800 | 0-5000 | Milliseconds between interaction steps |
| pageLoadWait | number | 2000 | 1000-30000 | Milliseconds to wait after page navigation |
| typingSpeed | array | [80, 200] | [10, 1000] | Min/max milliseconds between keystrokes |
π₯ Recording Configuration
Control video output and recording behavior.
{
"recording": {
"duration": 45000, // Maximum recording time (ms)
"skipErrors": true, // Continue recording on interaction errors
"outputName": "custom-name", // Custom filename (optional)
"fps": 30 // Frame rate (default: 30)
}
}Duration Note: The duration field sets the maximum recording time, but the actual video may be longer due to:
- Attention pattern animations (if enabled)
- Accumulated wait times and transitions
- The recording continues until all interactions complete or duration is reached
| Property | Type | Default | Description |
|----------|------|---------|-------------|
| duration | number | 30000 | Maximum recording duration in milliseconds (see note above) |
| skipErrors | boolean | true | Continue recording if interactions fail |
| outputName | string | null | Custom filename (auto-generated if not specified) |
| fps | number | 30 | Video frame rate (10-60 fps) |
π Security & Validation
All configuration values are validated and sanitized:
- Selectors: Checked for XSS patterns (
<script>,javascript:, etc.) - URLs: Only relative paths or
http(s)://URLs allowed - Text: HTML tags and dangerous content removed
- Timings: Must be positive numbers within reasonable bounds
- File paths: Protected against directory traversal attacks
π Project Structure & Organization
Recommended Directory Layout
your-project/
βββ src/
β βββ components/
β β βββ Button/
β β β βββ Button.jsx
β β β βββ demo.json # Button component demo
β β βββ Modal/
β β βββ Modal.jsx
β β βββ demo.json # Modal component demo
β βββ pages/
β β βββ Dashboard/
β β β βββ Dashboard.jsx
β β β βββ demo.json # Dashboard page demo
β β βββ Settings/
β β βββ Settings.jsx
β β βββ demo.json # Settings page demo
β βββ features/
β βββ UserManagement/
β β βββ UserTable.jsx
β β βββ demo.json # User management demo
β βββ Analytics/
β βββ Charts.jsx
β βββ demo.json # Analytics demo
βββ demo.json # Root-level overview demo
βββ package.jsonMultiple Demo Strategy
Create focused demos for different audiences:
/demo.json- Complete application overview/src/pages/*/demo.json- Individual page demonstrations/src/components/*/demo.json- Component-specific demos/src/features/*/demo.json- Feature-focused demonstrations
πͺ Example Configurations
Complete E-commerce Demo
{
"name": "E-commerce Checkout Flow",
"description": "Complete checkout process from cart to confirmation",
"entry": {
"url": "/cart",
"selector": "[data-testid='cart-container']",
"waitTime": 2500
},
"interactions": [
{
"type": "hover",
"selector": "[data-testid='cart-item']",
"waitBeforeMove": 1000,
"waitAfterClick": 1200,
"zoomLevel": 1.8,
"description": "Review cart items"
},
{
"type": "click",
"selector": "[data-testid='proceed-checkout']",
"waitBeforeMove": 1500,
"waitAfterClick": 2000,
"zoomLevel": 2.0,
"description": "Proceed to checkout"
},
{
"type": "type",
"selector": "[name='email']",
"text": "[email protected]",
"waitBeforeMove": 800,
"waitAfterClick": 1000,
"zoomLevel": 2.2,
"description": "Enter email address"
},
{
"type": "type",
"selector": "[name='address']",
"text": "123 Main St, City, State 12345",
"waitBeforeMove": 600,
"waitAfterClick": 1200,
"description": "Enter shipping address"
},
{
"type": "click",
"selector": "[data-testid='payment-credit-card']",
"waitBeforeMove": 1000,
"waitAfterClick": 1500,
"zoomLevel": 1.9,
"description": "Select credit card payment"
},
{
"type": "wait",
"waitTime": 2000,
"description": "Wait for payment form animation"
},
{
"type": "click",
"selector": "[data-testid='place-order']",
"waitBeforeMove": 1500,
"waitAfterClick": 3000,
"zoomLevel": 2.1,
"description": "Complete the purchase"
}
],
"effects": {
"cameraFollow": true,
"zoomLevel": 1.7,
"clickAnimations": true,
"mouseMoveSpeed": 55
},
"recording": {
"duration": 60000,
"skipErrors": false,
"outputName": "ecommerce-checkout-flow"
},
"timings": {
"waitBeforeMove": 1200,
"waitAfterClick": 1600,
"waitBetweenSteps": 900,
"pageLoadWait": 2500
}
}Dashboard Analytics Demo
{
"name": "Analytics Dashboard",
"description": "Interactive analytics dashboard with charts and filters",
"entry": {
"url": "/analytics",
"selector": "[data-testid='analytics-dashboard']",
"waitTime": 3000
},
"interactions": [
{
"type": "hover",
"selector": "[data-testid='revenue-chart']",
"waitBeforeMove": 1200,
"waitAfterClick": 1500,
"zoomLevel": 1.9,
"description": "Examine revenue trends"
},
{
"type": "click",
"selector": "[data-testid='time-filter']",
"waitBeforeMove": 1000,
"waitAfterClick": 1200,
"zoomLevel": 1.8,
"description": "Open time period filter"
},
{
"type": "click",
"selector": "[data-value='last-30-days']",
"waitBeforeMove": 800,
"waitAfterClick": 2000,
"zoomLevel": 2.0,
"description": "Select last 30 days"
},
{
"type": "scroll",
"selector": "[data-testid='detailed-metrics']",
"waitBeforeMove": 1000,
"waitAfterClick": 1500,
"description": "Scroll to detailed metrics"
},
{
"type": "hover",
"selector": "[data-testid='conversion-rate']",
"waitBeforeMove": 800,
"waitAfterClick": 1200,
"zoomLevel": 1.7,
"description": "Review conversion metrics"
}
],
"effects": {
"cameraFollow": true,
"zoomLevel": 1.6,
"clickAnimations": true,
"mouseMoveSpeed": 65
},
"recording": {
"duration": 40000,
"skipErrors": true,
"outputName": "analytics-dashboard"
}
}π§ Command Line Interface
Basic Usage
# Run all demos in current directory
demo-video-maker
# Run demos for specific directory
demo-video-maker ./src/features
# Specify custom base URL
demo-video-maker . http://localhost:8080
# Generate sample configuration
demo-video-maker --init
# Show help
demo-video-maker --helpCommand Line Options
# Default behavior (assumes app running on port 3000)
demo-video-maker
# Specify custom port
demo-video-maker --port 8080
demo-video-maker -p 3001
# Run for specific directory with custom port
demo-video-maker --port 8080 ./src/features
# Use custom base URL (when app runs on different port/host)
demo-video-maker . http://localhost:4200
# Full custom setup
demo-video-maker ./my-app http://localhost:5173Note: The default port is 3000. Always ensure your application is running before executing demo-video-maker.
π οΈ Integration Examples
Next.js Integration
// package.json
{
"scripts": {
"dev": "next dev",
"demo": "concurrently \"next dev\" \"wait-on http://localhost:3000 && demo-video-maker\"",
"demo:record": "next build && next start & wait-on http://localhost:3000 && demo-video-maker && kill %1"
},
"devDependencies": {
"demo-video-maker": "^1.0.0",
"concurrently": "^7.6.0",
"wait-on": "^7.0.1"
}
}React (Vite) Integration
// package.json
{
"scripts": {
"dev": "vite",
"demo": "concurrently \"vite\" \"wait-on http://localhost:5173 && demo-video-maker . http://localhost:5173\"",
"demo:ci": "vite build && vite preview & wait-on http://localhost:4173 && demo-video-maker . http://localhost:4173"
}
}Vue.js Integration
// package.json
{
"scripts": {
"serve": "vue-cli-service serve",
"demo": "concurrently \"vue-cli-service serve\" \"wait-on http://localhost:8080 && demo-video-maker . http://localhost:8080\""
}
}π¨ Customization
Custom CSS Selectors
Use data attributes for reliable element targeting:
<!-- Recommended: Use data-testid -->
<button data-testid="submit-form">Submit</button>
<!-- Alternative: Use semantic selectors -->
<button className="btn-primary" aria-label="Submit form">Submit</button>
<!-- Avoid: Generic selectors -->
<button className="btn">Submit</button>Responsive Design Considerations
{
"interactions": [
{
"type": "click",
"selector": "[data-testid='mobile-menu'], [data-testid='desktop-menu']",
"skipIfNotFound": true,
"description": "Open menu (responsive)"
}
]
}Conditional Interactions
{
"interactions": [
{
"type": "click",
"selector": "[data-testid='cookie-consent']",
"skipIfNotFound": true,
"description": "Accept cookies if banner is present"
},
{
"type": "click",
"selector": "[data-testid='main-action']",
"skipIfNotFound": false,
"description": "Required main action"
}
]
}π¬ Cinematic Effects Recipes
Create stunning visual effects by combining zoom levels, timing, and camera movements. Try these recipes with our cinematic showcase page or adapt them to your own content.
Dynamic Zoom Scroll Effect
This recipe creates a cinematic journey from a top-left element to a bottom-right element with dramatic zoom transitions.

{
"name": "Cinematic Scroll Effect",
"description": "Dynamic zoom scroll from top-left badge to bottom-right accent",
"entry": {
"url": "/cinematic-showcase",
"waitTime": 1500
},
"effects": {
"cameraFollow": true,
"attentionPattern": false,
"mouseMoveSpeed": 45,
"zoomLevel": 1.6
},
"interactions": [
{
"type": "hover",
"selector": "[data-testid='hero-badge']",
"waitBeforeMove": 500,
"waitAfterClick": 1200,
"zoomLevel": 2.5,
"description": "Start at top-left badge with zoom"
},
{
"type": "wait",
"waitTime": 800,
"description": "Hold the initial zoom on badge"
},
{
"type": "hover",
"selector": ".hero-content",
"waitBeforeMove": 200,
"waitAfterClick": 600,
"zoomLevel": 1.2,
"description": "Pull back to show hero title"
},
{
"type": "scroll",
"selector": "[data-testid='cta']",
"waitBeforeMove": 400,
"waitAfterClick": 800,
"zoomLevel": 1.0,
"description": "Scroll to bottom while fully zoomed out"
},
{
"type": "hover",
"selector": "[data-testid='bottom-accent']",
"waitBeforeMove": 600,
"waitAfterClick": 2000,
"zoomLevel": 2.8,
"description": "Zoom in on bottom-right accent"
}
],
"recording": {
"duration": 15000,
"outputName": "cinematic-scroll-effect"
}
}Key Techniques:
- Zoom transitions: Change
zoomLevelbetween interactions (2.5 β 1.0 β 2.8) - Speed control: Lower
mouseMoveSpeed(45) for smoother camera movements - Timing choreography: Carefully tuned wait times create rhythm
- Fallback selectors: Multiple selectors ensure compatibility
Tips for Best Results:
- Use contrasting zoom levels (1.0 to 2.5+) for dramatic effect
- Keep zoom-out sections brief to maintain viewer engagement
- End on a high zoom level for impact
- Adjust
mouseMoveSpeedbased on content complexity - Test with different viewport sizes
Creating Your Own Cinematic Content
For the best cinematic effects, design your pages with strategic element placement:
Key Design Principles:
- Corner Elements: Place important badges or logos in corners for dramatic start/end points
- Clear Sections: Use distinct sections with ample spacing for smooth scrolling
- Visual Hierarchy: Create elements at different sizes for varied zoom levels
- Focal Points: Add data-testid attributes to key elements for precise targeting
Example Page Structure:
<!-- Top-left starting point -->
<div class="top-left-badge" data-testid="start-badge">Featured</div>
<!-- Hero section for establishing shot -->
<section class="hero" data-testid="hero">
<h1>Main Title</h1>
</section>
<!-- Middle sections for journey -->
<section data-testid="features">
<!-- Feature cards for individual focus -->
</section>
<!-- Bottom-right ending point -->
<div class="bottom-right-cta" data-testid="end-cta">
<button>Get Started</button>
</div>Feature Spotlight Sequence
Highlight individual features with smooth transitions between focused and overview shots.
{
"name": "Feature Showcase Flow",
"description": "Highlight individual features with dramatic zoom transitions",
"entry": {
"url": "/cinematic-showcase",
"selector": "[data-testid='journey']",
"waitTime": 1000
},
"effects": {
"cameraFollow": true,
"attentionPattern": false,
"mouseMoveSpeed": 55
},
"interactions": [
{
"type": "scroll",
"selector": "[data-testid='journey']",
"zoomLevel": 1.3,
"description": "Scroll to features section"
},
{
"type": "hover",
"selector": "[data-testid='feature-1']",
"zoomLevel": 2.2,
"waitAfterClick": 1500,
"description": "Focus on first feature"
},
{
"type": "hover",
"selector": ".feature-grid",
"zoomLevel": 1.2,
"waitAfterClick": 800,
"description": "Pull back to show all features"
},
{
"type": "hover",
"selector": "[data-testid='feature-2']",
"zoomLevel": 2.3,
"waitAfterClick": 1500,
"description": "Focus on second feature"
}
]
}Story Progression Journey
Create a narrative flow through your content with carefully timed reveals.
{
"name": "Story Progression",
"description": "Cinematic journey through the entire page story",
"entry": {
"url": "/cinematic-showcase",
"waitTime": 1000
},
"effects": {
"cameraFollow": true,
"attentionPattern": true,
"mouseMoveSpeed": 50
},
"interactions": [
{
"type": "hover",
"selector": ".hero-title",
"zoomLevel": 1.8,
"waitAfterClick": 1500,
"description": "Focus on main title"
},
{
"type": "scroll",
"selector": "[data-testid='story']",
"zoomLevel": 1.4,
"description": "Continue to story section"
},
{
"type": "hover",
"selector": ".floating-element.element-2",
"zoomLevel": 2.1,
"waitAfterClick": 1000,
"description": "Focus on visual elements"
},
{
"type": "hover",
"selector": "[data-testid='main-cta']",
"zoomLevel": 2.6,
"waitAfterClick": 2500,
"description": "Final call to action"
}
]
}Quick Impact Demo
For short, punchy demos that get straight to the point.
{
"name": "Quick Impact",
"effects": {
"attentionPattern": false,
"mouseMoveSpeed": 80,
"cameraFollow": true
},
"timings": {
"waitBeforeMove": 400,
"waitAfterClick": 600,
"waitBetweenSteps": 300
},
"interactions": [
{
"type": "hover",
"selector": ".hero-title",
"zoomLevel": 2.0,
"waitAfterClick": 800
},
{
"type": "scroll",
"selector": "[data-testid='main-cta']",
"zoomLevel": 1.5
},
{
"type": "click",
"selector": "[data-testid='main-cta']",
"zoomLevel": 2.5,
"waitAfterClick": 1500
}
]
}π CI/CD Integration
GitHub Actions
# .github/workflows/demo-videos.yml
name: Generate Demo Videos
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
demo-videos:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: '18'
- name: Install dependencies
run: npm ci
- name: Install demo video maker
run: npm install -g demo-video-maker
- name: Install Playwright browsers
run: npx playwright install chromium
- name: Build application
run: npm run build
- name: Start application
run: npm start &
env:
PORT: 3000
- name: Wait for application
run: npx wait-on http://localhost:3000
- name: Generate demo videos
run: demo-video-maker --port 3000
env:
CI: true
HEADLESS: true
- name: Upload demo videos
uses: actions/upload-artifact@v3
with:
name: demo-videos
path: demo-output-cinematic-*/Docker Integration
# Dockerfile.demo
FROM node:18-slim
# Install system dependencies for Playwright
RUN apt-get update && apt-get install -y \
chromium \
fonts-liberation \
libasound2 \
libatk-bridge2.0-0 \
libdrm2 \
libgtk-3-0 \
libnspr4 \
libnss3 \
libxcomposite1 \
libxdamage1 \
libxrandr2 \
xvfb \
&& rm -rf /var/lib/apt/lists/*
WORKDIR /app
COPY package*.json ./
RUN npm ci
# Install demo video maker
RUN npm install -g demo-video-maker
COPY . .
RUN npm run build
EXPOSE 3000
# Start app and generate demos
CMD ["sh", "-c", "npm start & sleep 10 && demo-video-maker"]π Troubleshooting
Common Issues
Demo videos show 404 pages
# Ensure your app is running
npm start
# Check if the URL is accessible
curl http://localhost:3000
# Verify the correct port in your command
demo-video-maker . http://localhost:3000 # Adjust port as neededElements not found during demo
{
"interactions": [
{
"type": "click",
"selector": "[data-testid='button']",
"skipIfNotFound": true, // Add this to continue on missing elements
"description": "Optional interaction"
}
]
}Slow or jerky mouse movements
{
"effects": {
"mouseMoveSpeed": 80, // Increase for faster movement (10-200)
"cameraFollow": false // Disable if causing performance issues
}
}Browser crashes or timeouts
{
"timings": {
"waitBeforeMove": 2000, // Increase wait times
"waitAfterClick": 3000,
"pageLoadWait": 5000
},
"recording": {
"duration": 120000, // Increase recording duration
"skipErrors": true // Continue on errors
}
}Debug Mode
# Run in non-headless mode (see browser)
HEADLESS=false demo-video-maker
# Enable verbose logging
DEBUG=* demo-video-maker
# Test with specific directory
demo-video-maker ./src/components/Button
# Test with custom port
demo-video-maker --port 8080Performance Optimization
{
"effects": {
"cameraFollow": false, // Disable for better performance
"mouseMoveSpeed": 100 // Faster movements
},
"timings": {
"waitBetweenSteps": 500 // Reduce delays
}
}π±οΈ Visible Cursor in Recordings
Demo Video Maker includes a custom cursor that's visible in video recordings, solving Playwright's limitation where the native cursor doesn't appear in videos.
Cursor Features
- Visual Design: Blue circle with white border and subtle glow effect
- Automatic Tracking: Follows all mouse movements during the demo
- Click Animation: Briefly scales down on clicks for visual feedback
- High Visibility: Includes shadow for contrast on different backgrounds
- Always On Top: Proper z-index ensures cursor is never hidden
How It Works
The cursor is implemented as a DOM element that:
- Moves in sync with Playwright's mouse actions
- Updates position via the
updateCameraFollowfunction - Animates during click interactions
- Remains visible throughout the entire recording
No configuration needed - the cursor automatically appears in all recordings.
π API Reference
Configuration Schema
Complete TypeScript interface for configuration validation:
interface DemoConfig {
name: string;
description?: string;
entry: {
url?: string;
selector?: string;
waitTime?: number;
};
interactions: Interaction[];
effects?: EffectsConfig;
recording?: RecordingConfig;
timings?: TimingsConfig;
}
interface Interaction {
type: 'click' | 'hover' | 'type' | 'scroll' | 'wait' | 'navigate';
selector?: string;
text?: string; // For 'type' interactions
url?: string; // For 'navigate' interactions
waitTime?: number; // For 'wait' interactions
waitBeforeMove?: number;
waitAfterClick?: number;
zoomLevel?: number;
skipIfNotFound?: boolean;
description?: string;
}
interface EffectsConfig {
cameraFollow?: boolean;
zoomLevel?: number;
clickAnimations?: boolean;
mouseMoveSpeed?: number;
}
interface RecordingConfig {
duration?: number;
skipErrors?: boolean;
outputName?: string;
}
interface TimingsConfig {
waitBeforeMove?: number;
waitAfterClick?: number;
waitBetweenSteps?: number;
pageLoadWait?: number;
}π€ Contributing
We welcome contributions! Please see our Contributing Guide for details.
Development Setup
# Clone the repository
git clone https://github.com/demovideomaker/demo-video-maker.git
cd demo-video-maker
# Install dependencies
npm install
# Run tests
npm test
# Run tests in watch mode
npm run test:watch
# Build the project
npm run buildRunning Tests
# Unit tests
npm run test:unit
# Integration tests
npm run test:integration
# Coverage report
npm run test:coverage
# Security audit
npm auditπ§ Troubleshooting
Common Issues
Page Not Loading:
- Ensure your app is running on the specified port
- Check for HTTPS/SSL certificate issues
- Verify no authentication is blocking access
Selectors Not Found:
- Use stable selectors (data-testid, aria-label)
- Add
waitTimeto interactions for dynamic content - Enable
skipIfNotFoundfor optional elements
Video Output Issues:
- Ensure write permissions in output directory
- Check available disk space
- Verify ffmpeg is available for video processing
π License
MIT License - see LICENSE file for details.
π Acknowledgments
- Playwright for browser automation
- Chromium for rendering engine
- Community contributors and testers
π Support
- π Documentation
- π Issue Tracker
- π¬ Discussions
- π§ Email Support
Made with β€οΈ by the Demo Video Maker team
