š¬ Create stunning cinematic demo videos automatically from your web applications with dynamic camera following, zoom effects, and gorgeous visual polish
npm install demo-video-makerCreate 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.
- šÆ 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-maker in your project directory
``bash`
npm install -g demo-video-maker
`bashNavigate to your web app
cd /path/to/your/webapp
$3
Important: Your web application must be running before generating demos!
`bash
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-makerIf your app runs on a different port, specify it:
demo-video-maker --port 8080
demo-video-maker -p 3001Or provide the full URL:
demo-video-maker . http://localhost:4000
`That's it! Your demo video will be saved in
demo-output-cinematic-[timestamp]/š System Requirements
$3
- 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)$3
- FFmpeg: For video format conversion (auto-detected)
- Git: For version control integration$3
- ā
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.$3
`json
{
"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"
}
}
`$3
Controls where the demo starts and initial setup.
`json
{
"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 |$3
Define the sequence of user interactions to demonstrate.
#### Click Interaction
`json
{
"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
`json
{
"type": "hover",
"selector": ".tooltip-trigger",
"waitBeforeMove": 800,
"waitAfter": 1200, // Time to wait after hovering
"zoomLevel": 1.8,
"description": "Show tooltip on hover"
}
`#### Type Interaction
`json
{
"type": "type",
"selector": "input[name='email']",
"text": "user@example.com",
"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
`json
{
"type": "scroll",
"selector": "#bottom-section",
"waitBeforeMove": 800,
"waitAfter": 1500, // Time to wait after scroll completes
"description": "Scroll to bottom section"
}
`#### Wait Interaction
`json
{
"type": "wait",
"waitTime": 3000,
"description": "Wait for animation to complete"
}
`#### Navigate Interaction
`json
{
"type": "navigate",
"url": "/settings",
"waitBeforeMove": 1000,
"waitAfterClick": 2500,
"description": "Navigate to settings page"
}
`$3
Control the cinematic visual effects and camera behavior.
`json
{
"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
$3
Fine-tune the timing and pacing of interactions.
`json
{
"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
duration due 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 attentionPattern and 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 |$3
Control video output and recording behavior.
`json
{
"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) |$3
All configuration values are validated and sanitized:
- Selectors: Checked for XSS patterns (