@t3lnet/sceneforge 1.0.1 → 1.0.3

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.
Files changed (2) hide show
  1. package/README.md +478 -3
  2. package/package.json +11 -1
package/README.md CHANGED
@@ -1,5 +1,480 @@
1
- # @t3lnet/sceneforge
1
+ # SceneForge
2
2
 
3
- SceneForge runner + generation utilities for YAML-driven demos.
3
+ An open-source monorepo for recording UI interactions to YAML and turning those definitions into narrated demo videos. The system combines a Chrome extension (recording), Playwright (playback + recording), and a CLI pipeline (audio + video post-processing).
4
4
 
5
- See the repo root README for full documentation and examples.
5
+ ## What This Repo Does
6
+
7
+ - Record user interactions with a Chrome extension and export YAML.
8
+ - Replay YAML with Playwright to produce a video plus script metadata.
9
+ - Split the recording into per-step clips.
10
+ - Generate voiceover audio with ElevenLabs.
11
+ - Add audio to each clip and concatenate into a final demo video.
12
+
13
+ ## Architecture
14
+
15
+ ### Package Map
16
+
17
+ ```mermaid
18
+ flowchart LR
19
+ Extension["@t3lnet/sceneforge-extension"] -->|"records actions"| YAML["YAML demo definition"]
20
+ Shared["@t3lnet/sceneforge-shared"] --> Extension
21
+ Shared --> Playwright["@t3lnet/sceneforge-playwright"]
22
+ Shared --> CLI["@t3lnet/sceneforge-cli"]
23
+ Generation["@t3lnet/sceneforge-generation"] --> CLI
24
+ Shared --> Library["@t3lnet/sceneforge"]
25
+ Generation --> Library
26
+ Playwright --> Library
27
+ Playwright -->|"video + scripts"| Output["output/"]
28
+ CLI --> Output
29
+ ```
30
+
31
+ ### End-to-End Pipeline
32
+
33
+ ```mermaid
34
+ flowchart LR
35
+ A["Record in Extension"] --> B["YAML definition"]
36
+ B --> C["sceneforge record (Playwright)"]
37
+ C --> D["output/videos/<demo>.webm"]
38
+ C --> E["output/scripts/<demo>.json/.srt/.md/.voice.json"]
39
+ D --> F["sceneforge split"]
40
+ F --> G["output/videos/<demo>/step_XX_*.mp4"]
41
+ E --> H["sceneforge voiceover (ElevenLabs)"]
42
+ H --> I["output/audio/<demo>/manifest.json + audio files"]
43
+ G --> J["sceneforge add-audio"]
44
+ I --> J
45
+ J --> K["output/videos/<demo>/step_XX_*_with_audio.mp4"]
46
+ K --> L["sceneforge concat"]
47
+ L --> M["output/final/<demo>.mp4"]
48
+ ```
49
+
50
+ ## Requirements
51
+
52
+ - Bun (workspace + builds)
53
+ - Node.js 18+ (CLI runtime)
54
+ - FFmpeg (split/add-audio/concat)
55
+ - ElevenLabs API key (voiceover generation)
56
+
57
+ ## Install (Library)
58
+
59
+ ```bash
60
+ npm i -D @t3lnet/sceneforge @playwright/test
61
+ ```
62
+
63
+ ## Setup
64
+
65
+ ```bash
66
+ cd sceneforge
67
+ bun install
68
+ ```
69
+
70
+ ### Voiceover Environment
71
+
72
+ Create a `.env` file in `sceneforge/` (copy from `.env.example`) with your ElevenLabs credentials:
73
+
74
+ ```bash
75
+ cp .env.example .env
76
+ ```
77
+
78
+ You can also point the CLI at a specific env file with `--env-file`.
79
+
80
+ ## Recording Options
81
+
82
+ ### Chrome Extension (authoring YAML)
83
+
84
+ 1. Build and load the extension:
85
+ ```bash
86
+ bun run build
87
+ bun run chrome # Opens chrome://extensions
88
+ ```
89
+ - Enable "Developer mode" (toggle in top-right)
90
+ - Click "Load unpacked"
91
+ - Select the `dist` folder
92
+ 2. Navigate to your app and click the extension icon.
93
+ 3. Click **Record** to capture interactions.
94
+ 4. Edit steps and export as YAML.
95
+
96
+ ### Playwright (recording a demo run)
97
+
98
+ The CLI `record` command replays YAML and records video + scripts:
99
+
100
+ ```bash
101
+ bunx @t3lnet/sceneforge-cli record \
102
+ --definition examples/create-dxf-quote.yaml \
103
+ --base-url http://localhost:5173
104
+ ```
105
+
106
+ Common flags:
107
+ - `--start-path /app/quotes` to open a route before running steps
108
+ - `--storage-state path/to/user.json` to reuse auth
109
+ - `--asset-root path/to/files` for upload resolution
110
+ - `--output-dir output` or `--root /path/to/repo`
111
+ - `--locale en-US` or `DEMO_LOCALE=en-US` to control request locale (default: `en-US`)
112
+
113
+ ## YAML Format
114
+
115
+ ```yaml
116
+ version: 1
117
+ name: demo-name
118
+ title: "Demo Title"
119
+ description: |
120
+ Optional description
121
+
122
+ # Optional media configuration for final video
123
+ media:
124
+ intro:
125
+ file: "assets/intro.mp4"
126
+ fade: true
127
+ fadeDuration: 0.5
128
+ outro:
129
+ file: "assets/outro.mp4"
130
+ fade: true
131
+ backgroundMusic:
132
+ file: "assets/background-music.mp3"
133
+ volume: 0.15
134
+ loop: true
135
+ fadeIn: 1.5
136
+ fadeOut: 2.0
137
+ startAt:
138
+ type: "afterIntro"
139
+ endAt:
140
+ type: "beforeOutro"
141
+
142
+ steps:
143
+ - id: step-id
144
+ script: "Voiceover text for this step"
145
+ actions:
146
+ - action: click
147
+ target:
148
+ type: selector
149
+ selector: "button:has-text('Save')"
150
+ highlight: true
151
+ - action: wait
152
+ waitFor:
153
+ type: text
154
+ value: "Success"
155
+ timeout: 15000
156
+ ```
157
+
158
+ Supported `waitFor.type` values:
159
+ - `text`
160
+ - `selector`
161
+ - `navigation`
162
+ - `idle`
163
+ - `selectorHidden`
164
+ - `textHidden`
165
+
166
+ `version` defaults to `1` if omitted, but including it is recommended for forward compatibility.
167
+
168
+ ## Secrets in YAML
169
+
170
+ Use `${SECRET:VAR_NAME}` (or `${ENV:VAR_NAME}`) placeholders to avoid committing credentials:
171
+
172
+ ```yaml
173
+ actions:
174
+ - action: type
175
+ target:
176
+ type: selector
177
+ selector: "input[name=\"email\"]"
178
+ text: "${SECRET:NANOQUOTE_USER_EMAIL}"
179
+ ```
180
+
181
+ The CLI will load `.env` or `.local/.env` automatically (or use `--env-file`) when running `record`, `setup`, or `pipeline`. Missing secrets will error during parsing.
182
+
183
+ ## Supported Actions
184
+
185
+ | Action | Parameters | Description |
186
+ |--------|-----------|-------------|
187
+ | `navigate` | `path` | Go to URL (supports `{baseURL}` template) |
188
+ | `click` | `target`, `highlight?` | Click element |
189
+ | `type` | `target`, `text` | Type into input field |
190
+ | `upload` | `file`, `target?` | Upload file (auto-finds file input if no target) |
191
+ | `wait` | `duration` OR `waitFor` | Wait for time or condition |
192
+ | `hover` | `target` | Hover over element |
193
+ | `scroll` | `duration` | Scroll page |
194
+ | `scrollTo` | `target` | Scroll element into view |
195
+ | `drag` | `target`, `drag{deltaX,deltaY,steps}` | Drag element by offset |
196
+
197
+ ## CLI Pipeline
198
+
199
+ The CLI packages the post-processing pipeline for voiceover, video splits, and final concatenation.
200
+
201
+ ### Setup/Login (Storage State)
202
+
203
+ Run a setup YAML to log in once and save Playwright storage state for later sessions:
204
+
205
+ ```bash
206
+ bunx @t3lnet/sceneforge-cli setup \
207
+ --definition examples/setup-login.yaml \
208
+ --base-url http://localhost:5173 \
209
+ --start-path /app \
210
+ --headed \
211
+ --storage-state output/storage/login.json
212
+ ```
213
+
214
+ Then reuse the cached session during recording or pipeline runs:
215
+
216
+ ```bash
217
+ bunx @t3lnet/sceneforge-cli record \
218
+ --definition examples/create-dxf-quote.yaml \
219
+ --base-url http://localhost:5173 \
220
+ --storage-state output/storage/login.json
221
+ ```
222
+
223
+ ```bash
224
+ # Record a demo with Playwright and generate script JSON
225
+ bunx @t3lnet/sceneforge-cli record \
226
+ --definition examples/create-dxf-quote.yaml \
227
+ --base-url http://localhost:5173
228
+
229
+ # Run the full pipeline in one command
230
+ bunx @t3lnet/sceneforge-cli pipeline \
231
+ --definition examples/create-dxf-quote.yaml \
232
+ --base-url http://localhost:5173 \
233
+ --clean
234
+
235
+ # Preview pipeline steps and skip existing artifacts
236
+ bunx @t3lnet/sceneforge-cli pipeline \
237
+ --definition examples/create-dxf-quote.yaml \
238
+ --resume \
239
+ --progress \
240
+ --dry-run
241
+
242
+ # Split, voiceover, add-audio, concat
243
+ # (The sample YAML uses name: "new-demo", so downstream commands use that demo name.)
244
+ bunx @t3lnet/sceneforge-cli split --demo new-demo
245
+ bunx @t3lnet/sceneforge-cli voiceover --demo new-demo
246
+ bunx @t3lnet/sceneforge-cli add-audio --demo new-demo
247
+ bunx @t3lnet/sceneforge-cli concat --demo new-demo
248
+
249
+ # Concat with intro/outro and background music (CLI overrides)
250
+ bunx @t3lnet/sceneforge-cli concat --demo new-demo \
251
+ --intro assets/intro.mp4 \
252
+ --outro assets/outro.mp4 \
253
+ --music assets/background.mp3 \
254
+ --music-volume 0.15 \
255
+ --music-loop
256
+ ```
257
+
258
+ ### Media Options (Intro/Outro/Background Music)
259
+
260
+ You can add intro/outro videos and background music to the final demo either via YAML configuration or CLI flags:
261
+
262
+ **YAML Configuration (recommended for project defaults):**
263
+ ```yaml
264
+ media:
265
+ intro:
266
+ file: "assets/intro.mp4" # Prepended to demo
267
+ fade: true # Enable fade transition
268
+ fadeDuration: 0.5 # Fade duration in seconds
269
+ outro:
270
+ file: "assets/outro.mp4" # Appended to demo
271
+ backgroundMusic:
272
+ file: "assets/music.mp3"
273
+ volume: 0.15 # 0.0 to 1.0 (15% is typical for background)
274
+ loop: true # Repeat if shorter than video
275
+ fadeIn: 1.5 # Fade in duration
276
+ fadeOut: 2.0 # Fade out duration
277
+ startAt:
278
+ type: "afterIntro" # Options: beginning, afterIntro, step, time
279
+ endAt:
280
+ type: "beforeOutro" # Options: end, beforeOutro, step, time
281
+ ```
282
+
283
+ **CLI Flags (override YAML config):**
284
+ - `--intro <path>` - Intro video to prepend
285
+ - `--outro <path>` - Outro video to append
286
+ - `--music <path>` - Background music file
287
+ - `--music-volume <0-1>` - Music volume (default: 0.15)
288
+ - `--music-loop` - Loop music if shorter than video
289
+ - `--music-fade-in <s>` - Fade in duration (default: 1)
290
+ - `--music-fade-out <s>` - Fade out duration (default: 2)
291
+
292
+ Notes:
293
+ - `split` reads `output/scripts/<demo>.json` and `output/videos/<demo>.webm`.
294
+ - `voiceover` uses `ELEVENLABS_API_KEY` and `ELEVENLABS_VOICE_ID`.
295
+ - `add-audio` pads or extends clips to align audio with video.
296
+ - `concat` re-encodes to avoid audio dropouts at clip boundaries.
297
+ - `pipeline --resume` skips steps with existing artifacts; `--clean` overrides resume.
298
+ - `setup` saves Playwright storage state to reuse login sessions.
299
+
300
+ By default, the CLI writes to `output/` in the project root (or `e2e/output` if it already exists). You can override with `--root` and `--output-dir`.
301
+
302
+ ## Output Layout
303
+
304
+ ```
305
+ output/
306
+ ├── scripts/
307
+ │ ├── <demo>.json
308
+ │ ├── <demo>.srt
309
+ │ ├── <demo>.md
310
+ │ └── <demo>.voice.json
311
+ ├── videos/
312
+ │ ├── <demo>.webm
313
+ │ └── <demo>/
314
+ │ ├── step_01_<stepId>.mp4
315
+ │ ├── step_01_<stepId>_with_audio.mp4
316
+ │ └── steps-manifest.json
317
+ ├── audio/
318
+ │ └── <demo>/
319
+ │ ├── manifest.json
320
+ │ └── segment_*.mp3
321
+ └── final/
322
+ └── <demo>.mp4
323
+ ```
324
+
325
+ ## Programmatic Playback
326
+
327
+ Install the single-package API:
328
+
329
+ ```bash
330
+ npm i -D @t3lnet/sceneforge @playwright/test
331
+ ```
332
+
333
+ ```typescript
334
+ import { chromium } from "@playwright/test";
335
+ import { runDemoFromFile } from "@t3lnet/sceneforge";
336
+
337
+ const browser = await chromium.launch();
338
+ const context = await browser.newContext();
339
+ const page = await context.newPage();
340
+
341
+ await runDemoFromFile("./examples/create-dxf-quote.yaml", {
342
+ page,
343
+ baseURL: "http://localhost:5173",
344
+ outputDir: "./output",
345
+ });
346
+ ```
347
+
348
+ ## Project Structure
349
+
350
+ ```
351
+ sceneforge/
352
+ ├── packages/
353
+ │ ├── shared/ # Shared types and utilities
354
+ │ │ └── src/
355
+ │ │ ├── types.ts # TypeScript interfaces
356
+ │ │ ├── yaml-parser.ts # YAML parsing/serialization
357
+ │ │ ├── target-resolver.ts # Selector resolution
358
+ │ │ └── action-helpers.ts # Action factory functions
359
+ │ │
360
+ │ ├── playwright/ # Playwright demo runner
361
+ │ │ └── src/
362
+ │ │ ├── demo-runner.ts # Main runner
363
+ │ │ └── cursor-overlay.ts # Visual cursor effects
364
+ │ │
365
+ │ ├── generation/ # Script + audio generation utilities
366
+ │ │ └── src/
367
+ │ │ ├── script-generator.ts
368
+ │ │ └── voice-synthesis.ts
369
+ │ │
370
+ │ ├── sceneforge/ # Public runner + generation API (npm)
371
+ │ │ └── src/
372
+ │ │
373
+ │ ├── cli/ # CLI for generation pipeline
374
+ │ │ └── src/
375
+ │ │ ├── cli.js
376
+ │ │ └── commands/
377
+ │ │
378
+ │ └── extension/ # Chrome extension
379
+ │ ├── manifest.json
380
+ │ └── src/
381
+ │ ├── background/ # Service worker
382
+ │ ├── content/ # Content scripts
383
+ │ ├── sidepanel/ # React UI
384
+ │ └── shared/ # Re-exports from @t3lnet/sceneforge-shared
385
+
386
+ ├── examples/ # Example demo definitions
387
+ │ ├── create-dxf-quote.yaml
388
+ │ └── setup-login.yaml
389
+
390
+ ├── package.json # Workspace root
391
+ └── tsconfig.json
392
+ ```
393
+
394
+ ## Development
395
+
396
+ ```bash
397
+ # Development mode (watch + rebuild)
398
+ bun run dev
399
+
400
+ # Build all packages
401
+ bun run build
402
+
403
+ # Build just the extension
404
+ bun run build:extension
405
+
406
+ # Type check
407
+ bun run typecheck
408
+
409
+ # Open Chrome extensions page
410
+ bun run chrome
411
+ ```
412
+
413
+ ## Manual Release (Library)
414
+
415
+ ```bash
416
+ ./scripts/release.sh <version> [tag]
417
+ # example:
418
+ ./scripts/release.sh 0.2.0 next
419
+ ```
420
+
421
+ Notes:
422
+ - Requires an npm automation token with publish access to @t3lnet.
423
+ - Builds are manual (no CI/CD publish).
424
+
425
+ ## Chrome Extension Features
426
+
427
+ ### Recording Mode
428
+ - Click **Record** to capture clicks and form inputs
429
+ - Actions are grouped into steps with editable voiceover scripts
430
+ - Click **Stop** when done
431
+ - Use **Pause** / **Resume** or press `Ctrl+Shift+P` to toggle recording
432
+
433
+ ### Element Picker
434
+ - Click **Pick Element** to enter visual selection mode
435
+ - Hover over elements to see selector preview
436
+ - Click to add as a click action
437
+ - Press **Esc** to cancel
438
+
439
+ ### Selector Strategies (Configurable)
440
+ Choose which strategies are enabled in the sidepanel:
441
+ 1. `data-testid` - Most stable
442
+ 2. `aria-label` - Accessible and stable
443
+ 3. `role + text` - e.g., `button:has-text("Save")`
444
+ 4. `placeholder` - For input fields
445
+ 5. `name` - Form controls with name attributes
446
+ 6. `id` - Stable IDs only
447
+ 7. `css-class` - Semantic class names
448
+ 8. `role + class` - Role-scoped class selectors
449
+ 9. `title` - Title attribute selectors
450
+ 10. `text` - Generic text fallback
451
+ 11. `css-path` - CSS path fallback
452
+
453
+ ### Suggested Waits
454
+ - The extension detects DOM changes after interactions and suggests waits.
455
+ - Use **Add** to insert a wait action into the current step.
456
+
457
+ ### YAML Preview & Export
458
+ - **YAML Preview** tab shows live output
459
+ - **Copy** to clipboard or **Download** as file
460
+ - **Edit YAML** mode for direct editing with validation
461
+
462
+ ### Playback
463
+ - **Play Step** to test individual steps
464
+ - **Play All** to run the complete demo
465
+ - Requires content script to be active on page
466
+
467
+ ### Diagnostics
468
+ - `sceneforge doctor` checks for ffmpeg/ffprobe and ElevenLabs env setup.
469
+
470
+ ## Troubleshooting
471
+
472
+ - `FFmpeg is not installed`: install FFmpeg and re-run `split`, `add-audio`, or `concat`.
473
+ - `ELEVENLABS_API_KEY environment variable is required`: add it to `sceneforge/.env` or pass `--env-file`.
474
+ - `Uploads fail`: use `--asset-root` or provide absolute file paths.
475
+ - `Selectors miss portal content`: prefer portal-scoped selectors (the recorder detects Radix/Headless UI portals).
476
+ - `Audio cuts between steps`: re-run `add-audio` (pads silence) and `concat` (re-encodes).
477
+
478
+ ## License
479
+
480
+ MIT
package/package.json CHANGED
@@ -1,7 +1,17 @@
1
1
  {
2
2
  "name": "@t3lnet/sceneforge",
3
- "version": "1.0.1",
3
+ "version": "1.0.3",
4
4
  "description": "SceneForge runner and generation utilities for YAML-driven demos",
5
+ "license": "MIT",
6
+ "author": "T3LNET",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "git+https://github.com/jhandel/sceneforge.git"
10
+ },
11
+ "bugs": {
12
+ "url": "https://github.com/jhandel/sceneforge/issues"
13
+ },
14
+ "homepage": "https://github.com/jhandel/sceneforge#readme",
5
15
  "type": "module",
6
16
  "main": "./dist/index.cjs",
7
17
  "module": "./dist/index.js",