clipwise 0.5.1 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.ko.md +112 -15
- package/README.md +111 -22
- package/dist/cli/index.js +312 -61
- package/dist/compose/frame-worker.js +2 -1
- package/dist/index.d.ts +1649 -186
- package/dist/index.js +269 -62
- package/package.json +2 -1
- package/skills/clipwise.md +373 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "clipwise",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"description": "Scriptable cinematic screen recorder for product demos — YAML in, polished MP4 out",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
},
|
|
11
11
|
"files": [
|
|
12
12
|
"dist",
|
|
13
|
+
"skills",
|
|
13
14
|
"README.md",
|
|
14
15
|
"LICENSE"
|
|
15
16
|
],
|
|
@@ -0,0 +1,373 @@
|
|
|
1
|
+
# Clipwise — Cinematic Screen Recorder
|
|
2
|
+
|
|
3
|
+
You are an expert at creating Clipwise YAML scenarios. Clipwise is a Playwright + CDP-based scriptable screen recorder that turns YAML scenarios into polished MP4/GIF demo videos with cinematic effects (zoom, cursor trail, device frame, keystroke HUD, etc.).
|
|
4
|
+
|
|
5
|
+
TRIGGER: when the user wants to record a demo video, create a screen recording scenario, generate a product demo, or mentions "clipwise".
|
|
6
|
+
|
|
7
|
+
## Setup Check
|
|
8
|
+
|
|
9
|
+
Before creating a scenario, verify clipwise is installed:
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
npx clipwise --version
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
If not installed:
|
|
16
|
+
```bash
|
|
17
|
+
npm install -D clipwise
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
ffmpeg is required for MP4 output:
|
|
21
|
+
```bash
|
|
22
|
+
# macOS
|
|
23
|
+
brew install ffmpeg
|
|
24
|
+
# Ubuntu
|
|
25
|
+
sudo apt install ffmpeg
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## YAML Schema Reference
|
|
29
|
+
|
|
30
|
+
### Top-Level Structure
|
|
31
|
+
|
|
32
|
+
```yaml
|
|
33
|
+
name: string # Scenario name (required)
|
|
34
|
+
description: string # Optional description
|
|
35
|
+
|
|
36
|
+
viewport:
|
|
37
|
+
width: 1280 # Browser width (100-3840, default: 1280)
|
|
38
|
+
height: 800 # Browser height (100-3840, default: 800)
|
|
39
|
+
|
|
40
|
+
effects: # All optional, sensible defaults
|
|
41
|
+
zoom: ...
|
|
42
|
+
cursor: ...
|
|
43
|
+
background: ...
|
|
44
|
+
deviceFrame: ...
|
|
45
|
+
keystroke: ...
|
|
46
|
+
watermark: ...
|
|
47
|
+
speedRamp: ...
|
|
48
|
+
|
|
49
|
+
output:
|
|
50
|
+
format: mp4 # mp4 | gif | png-sequence
|
|
51
|
+
width: 1280 # Output width
|
|
52
|
+
height: 800 # Output height
|
|
53
|
+
fps: 30 # 1-60
|
|
54
|
+
preset: balanced # social | balanced | archive
|
|
55
|
+
outputDir: "./output"
|
|
56
|
+
filename: "my-recording"
|
|
57
|
+
|
|
58
|
+
steps: [] # Array of steps (min 1, first must have navigate)
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
### Step Structure
|
|
62
|
+
|
|
63
|
+
```yaml
|
|
64
|
+
- name: "Step name" # Optional label
|
|
65
|
+
captureDelay: 50 # ms to wait after actions before capturing (50-100 for snappy)
|
|
66
|
+
holdDuration: 700 # ms to hold on result (500-800 for snappy)
|
|
67
|
+
transition: none # none | fade
|
|
68
|
+
actions: [] # Array of actions
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
### Actions (12 types)
|
|
72
|
+
|
|
73
|
+
#### Basic Actions
|
|
74
|
+
|
|
75
|
+
1. **navigate** — Open a URL (MUST be the first action in step 1)
|
|
76
|
+
```yaml
|
|
77
|
+
- action: navigate
|
|
78
|
+
url: "https://example.com"
|
|
79
|
+
waitUntil: load # load | domcontentloaded | networkidle (default)
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
2. **click** — Click an element
|
|
83
|
+
```yaml
|
|
84
|
+
- action: click
|
|
85
|
+
selector: "#my-button"
|
|
86
|
+
delay: 0 # Optional click delay (ms)
|
|
87
|
+
timeout: 15000 # Optional element wait timeout
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
3. **type** — Type text character-by-character (auto-focuses the element)
|
|
91
|
+
```yaml
|
|
92
|
+
- action: type
|
|
93
|
+
selector: "#email-input"
|
|
94
|
+
text: "user@example.com"
|
|
95
|
+
delay: 18 # ms per character (15-25 recommended, default: 50)
|
|
96
|
+
timeout: 15000 # Optional
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
4. **hover** — Hover over an element
|
|
100
|
+
```yaml
|
|
101
|
+
- action: hover
|
|
102
|
+
selector: ".card"
|
|
103
|
+
timeout: 15000 # Optional
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
5. **scroll** — Scroll the page
|
|
107
|
+
```yaml
|
|
108
|
+
- action: scroll
|
|
109
|
+
y: 400 # Vertical px (positive=down, negative=up)
|
|
110
|
+
x: 0 # Horizontal px
|
|
111
|
+
selector: ".container" # Optional: scroll within element
|
|
112
|
+
smooth: true # Default: true
|
|
113
|
+
timeout: 15000 # Optional
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
6. **wait** — Pause for a fixed duration
|
|
117
|
+
```yaml
|
|
118
|
+
- action: wait
|
|
119
|
+
duration: 1000 # ms
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
7. **screenshot** — Capture marker (for png-sequence)
|
|
123
|
+
```yaml
|
|
124
|
+
- action: screenshot
|
|
125
|
+
name: "result" # Optional label
|
|
126
|
+
fullPage: false # Default: false
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
#### Async Wait Actions (for dynamic/API content)
|
|
130
|
+
|
|
131
|
+
8. **waitForSelector** — Wait for element state
|
|
132
|
+
```yaml
|
|
133
|
+
- action: waitForSelector
|
|
134
|
+
selector: ".result-panel"
|
|
135
|
+
state: visible # visible (default) | attached | hidden
|
|
136
|
+
timeout: 15000
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
9. **waitForNavigation** — Wait for page load
|
|
140
|
+
```yaml
|
|
141
|
+
- action: waitForNavigation
|
|
142
|
+
waitUntil: networkidle # load | domcontentloaded | networkidle
|
|
143
|
+
timeout: 15000
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
10. **waitForURL** — Wait for URL match
|
|
147
|
+
```yaml
|
|
148
|
+
- action: waitForURL
|
|
149
|
+
url: "https://example.com/dashboard"
|
|
150
|
+
timeout: 15000
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
11. **waitForFunction** — Wait for JS expression to be truthy
|
|
154
|
+
```yaml
|
|
155
|
+
- action: waitForFunction
|
|
156
|
+
expression: "document.querySelector('.done') !== null"
|
|
157
|
+
polling: raf # raf (default) | number in ms (e.g. 500)
|
|
158
|
+
timeout: 30000
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
12. **waitForResponse** — Wait for network response (URL substring match)
|
|
162
|
+
```yaml
|
|
163
|
+
- action: waitForResponse
|
|
164
|
+
url: "/api/chat/completions"
|
|
165
|
+
status: 200 # Optional HTTP status filter
|
|
166
|
+
timeout: 30000
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
### Effects Configuration
|
|
170
|
+
|
|
171
|
+
#### Zoom — Adaptive zoom follows cursor on clicks
|
|
172
|
+
```yaml
|
|
173
|
+
zoom:
|
|
174
|
+
enabled: true
|
|
175
|
+
intensity: moderate # subtle(1.15x) | light(1.25x) | moderate(1.35x) | strong(1.5x) | dramatic(1.8x)
|
|
176
|
+
# scale: 1.35 # Or use numeric value (overridden by intensity)
|
|
177
|
+
duration: 500 # Zoom animation ms
|
|
178
|
+
easing: ease-in-out # ease-in-out | ease-in | ease-out | linear
|
|
179
|
+
autoZoom:
|
|
180
|
+
followCursor: true
|
|
181
|
+
transitionDuration: 300
|
|
182
|
+
padding: 200
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
#### Cursor — Custom cursor with click effect, trail, highlight
|
|
186
|
+
```yaml
|
|
187
|
+
cursor:
|
|
188
|
+
enabled: true
|
|
189
|
+
size: 20
|
|
190
|
+
color: "#000000"
|
|
191
|
+
speed: fast # fast (~72ms) | normal (~144ms) | slow (~288ms)
|
|
192
|
+
smoothing: true
|
|
193
|
+
clickEffect: true
|
|
194
|
+
clickColor: "rgba(59, 130, 246, 0.3)"
|
|
195
|
+
clickRadius: 30
|
|
196
|
+
trail: true
|
|
197
|
+
trailLength: 8
|
|
198
|
+
trailColor: "rgba(59, 130, 246, 0.2)"
|
|
199
|
+
highlight: true
|
|
200
|
+
highlightRadius: 40
|
|
201
|
+
highlightColor: "rgba(255, 215, 0, 0.18)"
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
#### Background — Gradient/solid padding with corners and shadow
|
|
205
|
+
```yaml
|
|
206
|
+
background:
|
|
207
|
+
type: gradient # gradient | solid | image
|
|
208
|
+
value: "linear-gradient(135deg, #667eea 0%, #764ba2 100%)"
|
|
209
|
+
padding: 48
|
|
210
|
+
borderRadius: 14
|
|
211
|
+
shadow: true
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
#### Device Frame — Wraps recording in a device mockup
|
|
215
|
+
```yaml
|
|
216
|
+
deviceFrame:
|
|
217
|
+
enabled: true
|
|
218
|
+
type: browser # browser | macbook | iphone | ipad | android | none
|
|
219
|
+
darkMode: true
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
| Type | Description |
|
|
223
|
+
|------|-------------|
|
|
224
|
+
| browser | macOS browser chrome with traffic lights |
|
|
225
|
+
| macbook | MacBook Pro frame |
|
|
226
|
+
| iphone | iPhone 15 Pro with Dynamic Island |
|
|
227
|
+
| ipad | iPad Pro with camera dot |
|
|
228
|
+
| android | Android with punch-hole camera |
|
|
229
|
+
|
|
230
|
+
#### Keystroke HUD — Shows typed keys on screen
|
|
231
|
+
```yaml
|
|
232
|
+
keystroke:
|
|
233
|
+
enabled: true
|
|
234
|
+
showTyping: false # true = show regular typing; false = shortcuts only (industry default)
|
|
235
|
+
position: bottom-center # bottom-center | bottom-left | bottom-right
|
|
236
|
+
fontSize: 16
|
|
237
|
+
backgroundColor: "rgba(0, 0, 0, 0.75)"
|
|
238
|
+
textColor: "#ffffff"
|
|
239
|
+
padding: 8
|
|
240
|
+
fadeAfter: 1500
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
#### Watermark — Text overlay at corner
|
|
244
|
+
```yaml
|
|
245
|
+
watermark:
|
|
246
|
+
enabled: true
|
|
247
|
+
text: "My App"
|
|
248
|
+
position: bottom-right # top-left | top-right | bottom-left | bottom-right
|
|
249
|
+
opacity: 0.5
|
|
250
|
+
fontSize: 14
|
|
251
|
+
color: "#ffffff"
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
#### Speed Ramp — Auto-adjusts speed near actions
|
|
255
|
+
```yaml
|
|
256
|
+
speedRamp:
|
|
257
|
+
enabled: true
|
|
258
|
+
idleSpeed: 3.0 # Skip factor for idle frames (0.5-8)
|
|
259
|
+
actionSpeed: 0.8 # Slow factor near clicks (0.25-2)
|
|
260
|
+
transitionFrames: 15
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
### Output Presets
|
|
264
|
+
|
|
265
|
+
| Preset | Use case | Approx size (30s) |
|
|
266
|
+
|--------|----------|--------------------|
|
|
267
|
+
| social | Twitter, LinkedIn, Loom | ~2-4 MB |
|
|
268
|
+
| balanced | General purpose, portfolio | ~4-6 MB |
|
|
269
|
+
| archive | High-fidelity storage | larger |
|
|
270
|
+
|
|
271
|
+
## Critical Rules
|
|
272
|
+
|
|
273
|
+
1. **First step MUST contain a `navigate` action** — the browser needs a page to start
|
|
274
|
+
2. **Selectors**: use CSS selectors (`#id`, `.class`, `[data-testid="..."]`). No control chars, semicolons, backticks, or backslashes
|
|
275
|
+
3. **Type needs focus**: the `type` action auto-focuses, but the element must exist and be visible
|
|
276
|
+
4. **Scroll before interact**: if an element is below the fold, `scroll` to it first
|
|
277
|
+
5. **Prefer async waits over fixed `wait`**: use `waitForSelector`, `waitForFunction`, `waitForResponse` instead of guessing durations
|
|
278
|
+
6. **Viewport = output**: if viewport and output dimensions differ, output will be scaled (a warning is shown)
|
|
279
|
+
7. **Mobile scenarios**: use `viewport: {width: 390, height: 844}` with `deviceFrame.type: iphone` and `output: {width: 540, height: 1080}`
|
|
280
|
+
|
|
281
|
+
## Timing Presets
|
|
282
|
+
|
|
283
|
+
### Snappy demo (~30s)
|
|
284
|
+
- `captureDelay: 50-100`
|
|
285
|
+
- `holdDuration: 500-800`
|
|
286
|
+
- `type.delay: 15-25`
|
|
287
|
+
|
|
288
|
+
### Cinematic demo (~60s)
|
|
289
|
+
- `captureDelay: 200-400`
|
|
290
|
+
- `holdDuration: 1500-2500`
|
|
291
|
+
- `type.delay: 40-60`
|
|
292
|
+
|
|
293
|
+
## CLI Commands
|
|
294
|
+
|
|
295
|
+
```bash
|
|
296
|
+
# Record from YAML scenario
|
|
297
|
+
npx clipwise record <scenario.yaml> -f mp4 -o ./output
|
|
298
|
+
|
|
299
|
+
# Instant demo with built-in dashboard
|
|
300
|
+
npx clipwise demo
|
|
301
|
+
npx clipwise demo --device iphone
|
|
302
|
+
npx clipwise demo --url https://my-app.com
|
|
303
|
+
|
|
304
|
+
# Create template YAML
|
|
305
|
+
npx clipwise init
|
|
306
|
+
|
|
307
|
+
# Validate scenario without recording
|
|
308
|
+
npx clipwise validate <scenario.yaml>
|
|
309
|
+
```
|
|
310
|
+
|
|
311
|
+
## Workflow
|
|
312
|
+
|
|
313
|
+
1. Ask the user for: target URL, what actions to demo, and preferred style (snappy/cinematic)
|
|
314
|
+
2. Generate a complete `clipwise.yaml` scenario
|
|
315
|
+
3. Run `npx clipwise validate clipwise.yaml` to check for errors
|
|
316
|
+
4. If valid, run `npx clipwise record clipwise.yaml -f mp4 -o ./output`
|
|
317
|
+
5. If the user has specific selectors, use them. Otherwise suggest inspecting the page first
|
|
318
|
+
|
|
319
|
+
## Selector Discovery
|
|
320
|
+
|
|
321
|
+
If the user doesn't know selectors, help them find them:
|
|
322
|
+
```bash
|
|
323
|
+
# Open the target URL in a browser and inspect elements
|
|
324
|
+
npx playwright open <url>
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
Or read the page HTML to find appropriate selectors:
|
|
328
|
+
```bash
|
|
329
|
+
curl -s <url> | head -200
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
## Example: Minimal Scenario
|
|
333
|
+
|
|
334
|
+
```yaml
|
|
335
|
+
name: "My App Demo"
|
|
336
|
+
viewport:
|
|
337
|
+
width: 1280
|
|
338
|
+
height: 800
|
|
339
|
+
|
|
340
|
+
effects:
|
|
341
|
+
deviceFrame:
|
|
342
|
+
enabled: true
|
|
343
|
+
type: browser
|
|
344
|
+
cursor:
|
|
345
|
+
enabled: true
|
|
346
|
+
clickEffect: true
|
|
347
|
+
highlight: true
|
|
348
|
+
background:
|
|
349
|
+
padding: 48
|
|
350
|
+
borderRadius: 14
|
|
351
|
+
shadow: true
|
|
352
|
+
|
|
353
|
+
output:
|
|
354
|
+
format: mp4
|
|
355
|
+
fps: 30
|
|
356
|
+
preset: balanced
|
|
357
|
+
|
|
358
|
+
steps:
|
|
359
|
+
- name: "Open app"
|
|
360
|
+
captureDelay: 100
|
|
361
|
+
holdDuration: 1000
|
|
362
|
+
actions:
|
|
363
|
+
- action: navigate
|
|
364
|
+
url: "http://localhost:3000"
|
|
365
|
+
waitUntil: load
|
|
366
|
+
|
|
367
|
+
- name: "Click CTA"
|
|
368
|
+
captureDelay: 50
|
|
369
|
+
holdDuration: 800
|
|
370
|
+
actions:
|
|
371
|
+
- action: click
|
|
372
|
+
selector: "#cta-button"
|
|
373
|
+
```
|