clipwise 0.7.1 → 0.9.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 +130 -15
- package/README.md +138 -22
- package/dist/cli/index.js +2982 -1936
- package/dist/compose/frame-worker.js +146 -50
- package/dist/index.d.ts +6531 -331
- package/dist/index.js +943 -133
- package/package.json +3 -2
- package/skills/clipwise.md +112 -9
- package/templates/motion/feature-callout.html +81 -0
- package/templates/motion/intro-title.html +146 -0
- package/templates/motion/kinetic-type.html +205 -0
- package/templates/motion/vignette.html +288 -0
package/README.ko.md
CHANGED
|
@@ -5,26 +5,26 @@
|
|
|
5
5
|
YAML 시나리오를 작성하면 시네마틱 데모 영상(MP4/GIF)을 자동으로 만들어주는 스크린 레코더. Playwright CDP 기반.
|
|
6
6
|
|
|
7
7
|
<p align="center">
|
|
8
|
-
<video src="https://github.com/user-attachments/assets/
|
|
8
|
+
<video src="https://github.com/user-attachments/assets/800d956f-ecf3-40c4-8750-c93b34285f11" autoplay loop muted playsinline width="100%"></video>
|
|
9
9
|
</p>
|
|
10
10
|
|
|
11
|
-
> *`npx clipwise demo` 한 줄로 생성된 영상입니다 — YAML 파일 1개,
|
|
11
|
+
> *`npx clipwise demo` 한 줄로 생성된 영상입니다 — YAML 파일 1개, 248줄.*
|
|
12
12
|
|
|
13
13
|
## 빠른 시작
|
|
14
14
|
|
|
15
15
|
```bash
|
|
16
|
-
# 설치
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
# 내장 데모 즉시 실행
|
|
20
|
-
npx clipwise demo
|
|
16
|
+
# 설치 불필요 — npx로 바로 실행 (package.json 무수정)
|
|
17
|
+
npx clipwise@latest demo # 내장 데모 즉시 실행
|
|
21
18
|
|
|
22
19
|
# 또는 직접 시나리오 작성
|
|
23
|
-
npx clipwise init
|
|
24
|
-
# clipwise.yaml 편집 — URL을 내 사이트로 변경
|
|
25
|
-
npx clipwise record clipwise.yaml
|
|
20
|
+
npx clipwise@latest init # .clipwise/ 스캐폴딩 생성
|
|
21
|
+
# .clipwise/scenarios/demo.yaml 편집 — URL을 내 사이트로 변경
|
|
22
|
+
npx clipwise@latest record .clipwise/scenarios/demo.yaml
|
|
26
23
|
```
|
|
27
24
|
|
|
25
|
+
**Zero footprint**: Clipwise가 남기는 모든 것(시나리오, 픽스처, 인증 상태, 출력물)은
|
|
26
|
+
`.clipwise/` 디렉토리 하나에 담깁니다. `rm -rf .clipwise` 한 줄로 모든 흔적이 사라집니다.
|
|
27
|
+
|
|
28
28
|
## 요구사항
|
|
29
29
|
|
|
30
30
|
- **Node.js** >= 18
|
|
@@ -54,11 +54,11 @@ npx clipwise demo --device android # Android 목업
|
|
|
54
54
|
npx clipwise demo --device ipad # iPad 목업
|
|
55
55
|
npx clipwise demo --url https://my-app.com # 내 사이트 데모
|
|
56
56
|
|
|
57
|
-
# YAML 시나리오로 녹화
|
|
58
|
-
npx clipwise record <scenario.yaml> -f mp4
|
|
59
|
-
npx clipwise record <scenario.yaml> -f gif -o ./
|
|
57
|
+
# YAML 시나리오로 녹화 (출력 기본 위치: .clipwise/output)
|
|
58
|
+
npx clipwise record <scenario.yaml> -f mp4
|
|
59
|
+
npx clipwise record <scenario.yaml> -f gif -o ./custom-dir
|
|
60
60
|
|
|
61
|
-
#
|
|
61
|
+
# .clipwise/ 스캐폴딩 (시나리오, 픽스처, prepare 에셋, 인증 — 단일 디렉토리)
|
|
62
62
|
npx clipwise init
|
|
63
63
|
|
|
64
64
|
# 녹화 없이 검증만
|
|
@@ -107,9 +107,11 @@ Claude가 자동으로:
|
|
|
107
107
|
2. `npx clipwise validate`로 검증
|
|
108
108
|
3. `npx clipwise record`로 MP4 녹화
|
|
109
109
|
|
|
110
|
-
### 업데이트
|
|
110
|
+
### 업데이트 / 제거
|
|
111
111
|
|
|
112
112
|
clipwise 업그레이드 후 `npx clipwise install-skill`을 다시 실행하면 최신 스킬로 업데이트됩니다.
|
|
113
|
+
`npx clipwise install-skill --remove`로 언제든 제거할 수 있습니다 — 스킬 파일은
|
|
114
|
+
Clipwise가 `.clipwise/` 밖에 남기는 유일한 파일입니다.
|
|
113
115
|
|
|
114
116
|
## YAML 시나리오 형식
|
|
115
117
|
|
|
@@ -212,6 +214,118 @@ steps:
|
|
|
212
214
|
- `holdDuration: 1500-2500` ms
|
|
213
215
|
- `type.delay: 40-60` ms/글자
|
|
214
216
|
|
|
217
|
+
### 인증
|
|
218
|
+
|
|
219
|
+
브라우저 세션을 복원해 로그인 뒤 페이지를 녹화합니다. Playwright `storageState`
|
|
220
|
+
파일(권장) 또는 인라인 쿠키를 지원합니다.
|
|
221
|
+
|
|
222
|
+
```yaml
|
|
223
|
+
# 방법 1: Playwright storageState 파일 (쿠키 + localStorage)
|
|
224
|
+
auth:
|
|
225
|
+
storageState: ../auth/auth-state.json
|
|
226
|
+
|
|
227
|
+
# 방법 2: 인라인 쿠키
|
|
228
|
+
auth:
|
|
229
|
+
cookies:
|
|
230
|
+
- name: session_id
|
|
231
|
+
value: abc123
|
|
232
|
+
domain: .example.com
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
대화형 로그인으로 `storageState` 파일 생성:
|
|
236
|
+
|
|
237
|
+
```bash
|
|
238
|
+
npx playwright codegen --save-storage=.clipwise/auth/auth-state.json https://my-app.com
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
### Prepare — 녹화 시 런타임 주입
|
|
242
|
+
|
|
243
|
+
**앱 코드를 건드리지 않고** 데모용으로 페이지를 조정합니다. `prepare`의 모든
|
|
244
|
+
항목은 녹화 브라우저에만 주입됩니다 — 소스, 빌드, DB는 무접촉이며 참조 파일은
|
|
245
|
+
전부 `.clipwise/` 안에 둡니다.
|
|
246
|
+
|
|
247
|
+
```yaml
|
|
248
|
+
prepare:
|
|
249
|
+
# 데모에 어울리지 않는 요소 숨김 (쿠키 배너, dev 오버레이)
|
|
250
|
+
hide:
|
|
251
|
+
- "#cookie-banner"
|
|
252
|
+
- "[data-nextjs-toast]"
|
|
253
|
+
|
|
254
|
+
# 시계 동결 — 매 녹화마다 동일한 날짜 표시
|
|
255
|
+
freezeTime: "2026-06-10T09:00:00Z"
|
|
256
|
+
|
|
257
|
+
# Math.random 결정론화 — 매번 같은 차트/데이터
|
|
258
|
+
seedRandom: 42
|
|
259
|
+
|
|
260
|
+
# 앱 부팅 전 웹 스토리지 시드 (온보딩 건너뛰기, 플래그 설정)
|
|
261
|
+
storage:
|
|
262
|
+
localStorage:
|
|
263
|
+
onboarding_done: "true"
|
|
264
|
+
|
|
265
|
+
# API 응답 목(mock) — DB 시드 없이 데모 데이터 제공
|
|
266
|
+
mock:
|
|
267
|
+
- url: "/api/dashboard/stats" # URL 부분 문자열 매칭
|
|
268
|
+
fixture: ../fixtures/stats.json # 이 YAML 기준 상대 경로
|
|
269
|
+
- url: "/api/user"
|
|
270
|
+
body: { name: "Demo User" } # 또는 인라인
|
|
271
|
+
|
|
272
|
+
# 그 외 모든 것 — 임의 CSS/JS 주입
|
|
273
|
+
inject:
|
|
274
|
+
css: ../prepare/demo.css
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
| 앱 코드를 수정하게 되는 압력 | Prepare 대체 |
|
|
278
|
+
|------------------------------|--------------|
|
|
279
|
+
| dev 오버레이/쿠키 배너 조건부 숨김 코드 | `hide:` |
|
|
280
|
+
| 시드 데이터를 가진 "데모 모드" 구현 | `mock:` |
|
|
281
|
+
| 일관된 데모를 위한 날짜/랜덤 스텁 | `freezeTime:` + `seedRandom:` |
|
|
282
|
+
| 녹화용 온보딩 사전 완료 분기 | `storage:` |
|
|
283
|
+
|
|
284
|
+
`freezeTime` + `seedRandom`을 함께 쓰면 녹화가 **결정론적**이 됩니다 —
|
|
285
|
+
같은 시나리오는 몇 번을 돌려도 바이트 단위로 동일한 프레임을 만듭니다.
|
|
286
|
+
|
|
287
|
+
### Scenes — 키노트 스타일 런치 영상 <sup>v0.9</sup>
|
|
288
|
+
|
|
289
|
+
`scenes:` 타임라인을 선언하면 `clipwise record` 한 번으로 완성된 런치 영상이
|
|
290
|
+
렌더됩니다: 키네틱 타이포 → 푸티지 비네트(크롭/푸시인/분할, 셀렉터 기반 선
|
|
291
|
+
드로잉 주석) → 아웃트로 — 컷을 넘어 이어지는 잉크 스레드로 연결됩니다.
|
|
292
|
+
|
|
293
|
+
```yaml
|
|
294
|
+
viewport: { width: 1280, height: 800, deviceScaleFactor: 2 } # 2 = 레티나 출력
|
|
295
|
+
|
|
296
|
+
scenes:
|
|
297
|
+
- type: screen # 푸티지 테이크 — 1회 녹화, 비네트들이 인용
|
|
298
|
+
id: demo
|
|
299
|
+
steps: [...] # 기존 steps 문법 그대로
|
|
300
|
+
|
|
301
|
+
- type: motion # 키네틱 타이포 (내장 템플릿)
|
|
302
|
+
template: kinetic-type
|
|
303
|
+
duration: 2200
|
|
304
|
+
props: { lines: "Ship *demos*,||not edits.", size: 86 }
|
|
305
|
+
|
|
306
|
+
- type: vignette # 푸티지를 레이어로 — 카메라를 선언으로
|
|
307
|
+
footage: demo
|
|
308
|
+
duration: 4200
|
|
309
|
+
layout: crop # hero | crop | split
|
|
310
|
+
label: "Smart Speed"
|
|
311
|
+
caption: "로딩은 빠르게, *결과는 또렷하게*"
|
|
312
|
+
crop: { selector: ".panel", pad: 14 } # 픽셀이 아니라 셀렉터
|
|
313
|
+
push: { from: 1.05, to: 1 }
|
|
314
|
+
start: { step: 3 } # step 경계에서 인용 시작
|
|
315
|
+
rate: 1.15
|
|
316
|
+
fx: [{ kind: circle, selector: "#revenue", delay: 2500 }]
|
|
317
|
+
```
|
|
318
|
+
|
|
319
|
+
**고퀄리티 레시피** (쇼케이스 영상이 이렇게 나오는 이유):
|
|
320
|
+
1. `viewport.deviceScaleFactor: 2` — 레티나 해상도 캡처 (푸티지·타이포 전부)
|
|
321
|
+
2. `prepare:` — 배너 숨김, 시간 동결, 랜덤 시드, API 목킹
|
|
322
|
+
3. `.clipwise/brand.yaml` — 톤 프리셋, accent, 폰트 프리셋(`editorial` = Inter + Fraunces),
|
|
323
|
+
캐치프레이즈. 선 드로잉 주석 + 연결 스레드는 자동 적용
|
|
324
|
+
4. 구성: 키네틱 훅 → 히어로 푸시인 → 클로즈업 비네트 → 인터스티셜 → 분할(YAML × 푸티지) → 아웃트로
|
|
325
|
+
|
|
326
|
+
가장 빠른 길: Claude Code 스킬 설치(`npx clipwise install-skill`) 후
|
|
327
|
+
`/clipwise`에 자연어로 요청하면 — 이 YAML을 대신 만들어줍니다.
|
|
328
|
+
|
|
215
329
|
## 이펙트
|
|
216
330
|
|
|
217
331
|
모든 이펙트는 선택사항이며 합리적인 기본값이 있습니다.
|
|
@@ -279,6 +393,7 @@ deviceFrame:
|
|
|
279
393
|
enabled: true
|
|
280
394
|
type: browser # browser | iphone | ipad | android | none
|
|
281
395
|
darkMode: true
|
|
396
|
+
url: "app.example.com" # 주소창 표시 URL (기본: localhost)
|
|
282
397
|
```
|
|
283
398
|
|
|
284
399
|
| 타입 | 설명 |
|
package/README.md
CHANGED
|
@@ -5,26 +5,26 @@
|
|
|
5
5
|
Scriptable cinematic screen recorder for product demos — YAML in, polished MP4 out. Powered by Playwright CDP.
|
|
6
6
|
|
|
7
7
|
<p align="center">
|
|
8
|
-
<video src="https://github.com/user-attachments/assets/
|
|
8
|
+
<video src="https://github.com/user-attachments/assets/800d956f-ecf3-40c4-8750-c93b34285f11" autoplay loop muted playsinline width="100%"></video>
|
|
9
9
|
</p>
|
|
10
10
|
|
|
11
|
-
> *Generated with `npx clipwise demo` — 1 YAML file,
|
|
11
|
+
> *Generated with `npx clipwise demo` — 1 YAML file, 248 lines, one command.*
|
|
12
12
|
|
|
13
13
|
## Quick Start
|
|
14
14
|
|
|
15
15
|
```bash
|
|
16
|
-
#
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
# Try the built-in demo instantly
|
|
20
|
-
npx clipwise demo
|
|
16
|
+
# No install needed — run straight from npx (your package.json stays untouched)
|
|
17
|
+
npx clipwise@latest demo # Try the built-in demo instantly
|
|
21
18
|
|
|
22
19
|
# Or create your own scenario
|
|
23
|
-
npx clipwise init
|
|
24
|
-
# Edit clipwise.yaml — change URL to your site
|
|
25
|
-
npx clipwise record clipwise.yaml
|
|
20
|
+
npx clipwise@latest init # Scaffolds .clipwise/ (single footprint dir)
|
|
21
|
+
# Edit .clipwise/scenarios/demo.yaml — change the URL to your site
|
|
22
|
+
npx clipwise@latest record .clipwise/scenarios/demo.yaml
|
|
26
23
|
```
|
|
27
24
|
|
|
25
|
+
**Zero footprint**: everything Clipwise touches lives in one `.clipwise/` directory —
|
|
26
|
+
scenarios, fixtures, auth state, output. Remove every trace with `rm -rf .clipwise`.
|
|
27
|
+
|
|
28
28
|
## Requirements
|
|
29
29
|
|
|
30
30
|
- **Node.js** >= 18
|
|
@@ -54,11 +54,11 @@ npx clipwise demo --device android # Android mockup
|
|
|
54
54
|
npx clipwise demo --device ipad # iPad mockup
|
|
55
55
|
npx clipwise demo --url https://my-app.com # Your deployed site
|
|
56
56
|
|
|
57
|
-
# Record from YAML scenario
|
|
58
|
-
npx clipwise record <scenario.yaml> -f mp4
|
|
59
|
-
npx clipwise record <scenario.yaml> -f gif -o ./
|
|
57
|
+
# Record from YAML scenario (output defaults to .clipwise/output)
|
|
58
|
+
npx clipwise record <scenario.yaml> -f mp4
|
|
59
|
+
npx clipwise record <scenario.yaml> -f gif -o ./custom-dir
|
|
60
60
|
|
|
61
|
-
#
|
|
61
|
+
# Scaffold .clipwise/ (scenarios, fixtures, prepare assets, auth — one dir, zero footprint)
|
|
62
62
|
npx clipwise init
|
|
63
63
|
|
|
64
64
|
# Validate without recording
|
|
@@ -107,9 +107,11 @@ Claude will:
|
|
|
107
107
|
2. Run `npx clipwise validate` to check for errors
|
|
108
108
|
3. Run `npx clipwise record` to produce the MP4
|
|
109
109
|
|
|
110
|
-
### Update
|
|
110
|
+
### Update / Remove
|
|
111
111
|
|
|
112
112
|
Re-run `npx clipwise install-skill` after upgrading clipwise to get the latest skill.
|
|
113
|
+
Remove it anytime with `npx clipwise install-skill --remove` — the skill file is the
|
|
114
|
+
only thing Clipwise leaves outside `.clipwise/`.
|
|
113
115
|
|
|
114
116
|
## YAML Scenario Format
|
|
115
117
|
|
|
@@ -154,7 +156,7 @@ steps:
|
|
|
154
156
|
|--------|-----------|---------|-------------|
|
|
155
157
|
| `navigate` | `url`, `waitUntil?` | `waitUntil: "networkidle"` | Navigate to URL |
|
|
156
158
|
| `click` | `selector`, `delay?`, `timeout?` | | Click an element |
|
|
157
|
-
| `type` | `selector`, `text`, `delay?`, `timeout?` | `delay: 50` | Type text (char-by-char) |
|
|
159
|
+
| `type` | `selector`, `text`, `delay?`, `timeout?` | `delay: 50` | Type text (char-by-char, React/Vue compatible) |
|
|
158
160
|
| `hover` | `selector`, `timeout?` | | Hover over element |
|
|
159
161
|
| `scroll` | `y?`, `x?`, `selector?`, `smooth?`, `timeout?` | `y: 0`, `x: 0`, `smooth: true` | Scroll by offset |
|
|
160
162
|
| `wait` | `duration` | | Wait (ms) |
|
|
@@ -164,13 +166,15 @@ steps:
|
|
|
164
166
|
|
|
165
167
|
| Action | Parameters | Default | Description |
|
|
166
168
|
|--------|-----------|---------|-------------|
|
|
167
|
-
| `waitForSelector` | `selector`, `state?`, `timeout?` | `state: "visible"`, `timeout: 15000` | Wait for element state |
|
|
168
|
-
| `waitForNavigation` | `waitUntil?`, `timeout?` | `waitUntil: "networkidle"`, `timeout: 15000` | Wait for page load |
|
|
169
|
-
| `waitForURL` | `url`, `timeout?` | `timeout: 15000` | Wait for URL match |
|
|
170
|
-
| `waitForFunction` | `expression`, `polling?`, `timeout?` | `polling: "raf"`, `timeout: 30000` | Wait for JS expression to be truthy |
|
|
171
|
-
| `waitForResponse` | `url`, `status?`, `timeout?` | `timeout: 30000` | Wait for network response (URL substring match) |
|
|
169
|
+
| `waitForSelector` | `selector`, `state?`, `timeout?`, `captureWhileWaiting?`, `displaySpeed?` | `state: "visible"`, `timeout: 15000` | Wait for element state |
|
|
170
|
+
| `waitForNavigation` | `waitUntil?`, `timeout?`, `captureWhileWaiting?`, `displaySpeed?` | `waitUntil: "networkidle"`, `timeout: 15000` | Wait for page load |
|
|
171
|
+
| `waitForURL` | `url`, `timeout?`, `captureWhileWaiting?`, `displaySpeed?` | `timeout: 15000` | Wait for URL match |
|
|
172
|
+
| `waitForFunction` | `expression`, `polling?`, `timeout?`, `captureWhileWaiting?`, `displaySpeed?` | `polling: "raf"`, `timeout: 30000` | Wait for JS expression to be truthy |
|
|
173
|
+
| `waitForResponse` | `url`, `status?`, `timeout?`, `captureWhileWaiting?`, `displaySpeed?` | `timeout: 30000` | Wait for network response (URL substring match) |
|
|
172
174
|
| `smartWait` | `until`, `selector?`, `timeout?`, `displaySpeed?` | `until: "networkIdle"`, `timeout: 30000`, `displaySpeed: 8` | Smart wait — records real wait, auto-speeds in output |
|
|
173
175
|
|
|
176
|
+
**`captureWhileWaiting`**: When `true`, continuously captures frames during the wait (like `smartWait`). Useful for recording loading animations, progress bars, streaming responses. Pairs with `displaySpeed` (1-32, default: 8) to auto-compress wait frames in the output.
|
|
177
|
+
|
|
174
178
|
**`waitUntil`** options: `"load"`, `"domcontentloaded"`, `"networkidle"` (default)
|
|
175
179
|
**`state`** options: `"visible"` (default), `"attached"`, `"hidden"`
|
|
176
180
|
**`polling`** options: `"raf"` (requestAnimationFrame, default) or milliseconds (e.g. `500`)
|
|
@@ -213,6 +217,117 @@ For slower, cinematic demos:
|
|
|
213
217
|
- `holdDuration: 1500-2500` ms
|
|
214
218
|
- `type.delay: 40-60` ms per character
|
|
215
219
|
|
|
220
|
+
### Authentication
|
|
221
|
+
|
|
222
|
+
Record pages behind login by restoring a browser session. Supports Playwright's `storageState` file (recommended) or inline cookies.
|
|
223
|
+
|
|
224
|
+
```yaml
|
|
225
|
+
# Option 1: Playwright storageState file (cookies + localStorage)
|
|
226
|
+
auth:
|
|
227
|
+
storageState: ./auth-state.json
|
|
228
|
+
|
|
229
|
+
# Option 2: Inline cookies
|
|
230
|
+
auth:
|
|
231
|
+
cookies:
|
|
232
|
+
- name: session_id
|
|
233
|
+
value: abc123
|
|
234
|
+
domain: .example.com
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
Generate a `storageState` file by logging in interactively:
|
|
238
|
+
|
|
239
|
+
```bash
|
|
240
|
+
npx playwright codegen --save-storage=.clipwise/auth/auth-state.json https://my-app.com
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
### Prepare — Recording-Time Injection
|
|
244
|
+
|
|
245
|
+
Tweak the page for the demo **without touching your app code**. Everything in
|
|
246
|
+
`prepare` is injected only into the recording browser — your source, build, and
|
|
247
|
+
database stay untouched, and all referenced files live in `.clipwise/`.
|
|
248
|
+
|
|
249
|
+
```yaml
|
|
250
|
+
prepare:
|
|
251
|
+
# Hide elements that don't belong in a demo (cookie banners, dev overlays)
|
|
252
|
+
hide:
|
|
253
|
+
- "#cookie-banner"
|
|
254
|
+
- "[data-nextjs-toast]"
|
|
255
|
+
|
|
256
|
+
# Freeze the clock — dates render identically on every recording
|
|
257
|
+
freezeTime: "2026-06-10T09:00:00Z"
|
|
258
|
+
|
|
259
|
+
# Make Math.random deterministic — same charts/data every run
|
|
260
|
+
seedRandom: 42
|
|
261
|
+
|
|
262
|
+
# Seed web storage before the app boots (skip onboarding, set flags)
|
|
263
|
+
storage:
|
|
264
|
+
localStorage:
|
|
265
|
+
onboarding_done: "true"
|
|
266
|
+
|
|
267
|
+
# Mock API responses — demo data without seeding your database
|
|
268
|
+
mock:
|
|
269
|
+
- url: "/api/dashboard/stats" # URL substring match
|
|
270
|
+
fixture: ../fixtures/stats.json # relative to this YAML
|
|
271
|
+
- url: "/api/user"
|
|
272
|
+
body: { name: "Demo User" } # or inline
|
|
273
|
+
|
|
274
|
+
# Inject arbitrary CSS/JS for anything else
|
|
275
|
+
inject:
|
|
276
|
+
css: ../prepare/demo.css
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
| Pressure to modify app code | Prepare replacement |
|
|
280
|
+
|------------------------------|---------------------|
|
|
281
|
+
| Hide dev overlays / cookie banners conditionally | `hide:` |
|
|
282
|
+
| Build a "demo mode" with seeded data | `mock:` |
|
|
283
|
+
| Stub dates and randomness for consistent demos | `freezeTime:` + `seedRandom:` |
|
|
284
|
+
| Pre-complete onboarding for recordings | `storage:` |
|
|
285
|
+
|
|
286
|
+
Combined with `freezeTime` + `seedRandom`, recordings become **deterministic** —
|
|
287
|
+
the same scenario produces byte-identical frames run after run.
|
|
288
|
+
|
|
289
|
+
### Scenes — Keynote-style launch videos <sup>v0.9</sup>
|
|
290
|
+
|
|
291
|
+
Declare a `scenes:` timeline and one `clipwise record` renders a complete
|
|
292
|
+
launch video: kinetic typography → footage vignettes (crop / push-in / split,
|
|
293
|
+
selector-anchored line annotations) → outro — connected by an ink thread that
|
|
294
|
+
travels across cuts.
|
|
295
|
+
|
|
296
|
+
```yaml
|
|
297
|
+
viewport: { width: 1280, height: 800, deviceScaleFactor: 2 } # 2 = retina output
|
|
298
|
+
|
|
299
|
+
scenes:
|
|
300
|
+
- type: screen # footage take — recorded once, quoted by vignettes
|
|
301
|
+
id: demo
|
|
302
|
+
steps: [...] # the same steps you already know
|
|
303
|
+
|
|
304
|
+
- type: motion # kinetic typography (built-in templates)
|
|
305
|
+
template: kinetic-type
|
|
306
|
+
duration: 2200
|
|
307
|
+
props: { lines: "Ship *demos*,||not edits.", size: 86 }
|
|
308
|
+
|
|
309
|
+
- type: vignette # footage as a layer — camera is declarative
|
|
310
|
+
footage: demo
|
|
311
|
+
duration: 4200
|
|
312
|
+
layout: crop # hero | crop | split
|
|
313
|
+
label: "Smart Speed"
|
|
314
|
+
caption: "Loading compressed, *results crisp*"
|
|
315
|
+
crop: { selector: ".panel", pad: 14 } # selectors, not pixels
|
|
316
|
+
push: { from: 1.05, to: 1 }
|
|
317
|
+
start: { step: 3 } # quote from a step boundary
|
|
318
|
+
rate: 1.15
|
|
319
|
+
fx: [{ kind: circle, selector: "#revenue", delay: 2500 }]
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
**Quality recipe** (what makes the showcase videos look the way they do):
|
|
323
|
+
1. `viewport.deviceScaleFactor: 2` — retina-resolution capture (footage, type, everything)
|
|
324
|
+
2. `prepare:` — hide banners, freeze time, seed randomness, mock APIs
|
|
325
|
+
3. `.clipwise/brand.yaml` — tone preset, accent, font preset (`editorial` = Inter + Fraunces), catchphrases; line annotations + the connecting thread switch on automatically
|
|
326
|
+
4. Structure: kinetic hook → hero push-in → close-up vignettes → interstitial → split (YAML × footage) → outro
|
|
327
|
+
|
|
328
|
+
The fastest path: install the Claude Code skill (`npx clipwise install-skill`)
|
|
329
|
+
and ask `/clipwise` in natural language — it generates this YAML for you.
|
|
330
|
+
|
|
216
331
|
## Effects
|
|
217
332
|
|
|
218
333
|
All effects are optional and have sensible defaults.
|
|
@@ -284,6 +399,7 @@ deviceFrame:
|
|
|
284
399
|
enabled: true
|
|
285
400
|
type: browser # browser | iphone | ipad | android | none
|
|
286
401
|
darkMode: true
|
|
402
|
+
url: "app.example.com" # address-bar display URL (default: localhost)
|
|
287
403
|
```
|
|
288
404
|
|
|
289
405
|
| Type | Description |
|
|
@@ -297,7 +413,7 @@ deviceFrame:
|
|
|
297
413
|
|
|
298
414
|
Displays a HUD at the bottom of the screen showing what was typed. By default, only modifier+key shortcuts are shown (industry standard — same as Screen Studio, KeyCastr, ScreenFlow). Set `showTyping: true` to also show regular typed text.
|
|
299
415
|
|
|
300
|
-
When typing across multiple input fields, each field gets its own line in the HUD (up to 3 recent sessions, oldest dimmed at top, newest bright at bottom).
|
|
416
|
+
When typing across multiple input fields, each field gets its own line in the HUD (up to 3 recent sessions, oldest dimmed at top, newest bright at bottom). CJK text (Korean, Chinese, Japanese) is automatically wrapped to fit the screen width.
|
|
301
417
|
|
|
302
418
|
```yaml
|
|
303
419
|
keystroke:
|