@t3lnet/sceneforge 1.0.8 → 1.0.10
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.md +57 -0
- package/cli/cli.js +6 -0
- package/cli/commands/context.js +791 -0
- package/context/context-builder.ts +318 -0
- package/context/index.ts +52 -0
- package/context/template-loader.ts +161 -0
- package/context/templates/base/actions-reference.md +299 -0
- package/context/templates/base/cli-reference.md +236 -0
- package/context/templates/base/project-overview.md +58 -0
- package/context/templates/base/selectors-guide.md +233 -0
- package/context/templates/base/yaml-schema.md +210 -0
- package/context/templates/skills/balance-timing.md +136 -0
- package/context/templates/skills/debug-selector.md +193 -0
- package/context/templates/skills/generate-actions.md +94 -0
- package/context/templates/skills/optimize-demo.md +218 -0
- package/context/templates/skills/review-demo-yaml.md +164 -0
- package/context/templates/skills/write-step-script.md +136 -0
- package/context/templates/stages/stage1-actions.md +236 -0
- package/context/templates/stages/stage2-scripts.md +197 -0
- package/context/templates/stages/stage3-balancing.md +229 -0
- package/context/templates/stages/stage4-rebalancing.md +228 -0
- package/context/tests/context-builder.test.ts +237 -0
- package/context/tests/template-loader.test.ts +181 -0
- package/context/tests/tool-formatter.test.ts +198 -0
- package/context/tool-formatter.ts +189 -0
- package/dist/index.cjs +416 -11
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +182 -1
- package/dist/index.d.ts +182 -1
- package/dist/index.js +391 -11
- package/dist/index.js.map +1 -1
- package/package.json +2 -1
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
# SceneForge Selectors Guide
|
|
2
|
+
|
|
3
|
+
## Selector Priority
|
|
4
|
+
|
|
5
|
+
When targeting elements, use this priority order for reliability:
|
|
6
|
+
|
|
7
|
+
1. **data-testid** - Most reliable, designed for testing
|
|
8
|
+
2. **aria-label** - Good for accessibility-labeled elements
|
|
9
|
+
3. **role + text** - Semantic matching for buttons, links
|
|
10
|
+
4. **name attribute** - Form inputs
|
|
11
|
+
5. **placeholder** - Input placeholders
|
|
12
|
+
6. **text content** - Visible text (least stable)
|
|
13
|
+
7. **CSS selector** - Last resort, most brittle
|
|
14
|
+
|
|
15
|
+
## Target Types in SceneForge
|
|
16
|
+
|
|
17
|
+
### Using `type: selector`
|
|
18
|
+
|
|
19
|
+
Direct CSS selector - most flexible but requires maintenance.
|
|
20
|
+
|
|
21
|
+
```yaml
|
|
22
|
+
target:
|
|
23
|
+
type: selector
|
|
24
|
+
selector: "[data-testid='submit-button']"
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
**Good selectors:**
|
|
28
|
+
```yaml
|
|
29
|
+
# data-testid (best)
|
|
30
|
+
selector: "[data-testid='save-btn']"
|
|
31
|
+
|
|
32
|
+
# aria-label
|
|
33
|
+
selector: "[aria-label='Close dialog']"
|
|
34
|
+
|
|
35
|
+
# role with name
|
|
36
|
+
selector: "button[name='submit']"
|
|
37
|
+
|
|
38
|
+
# Unique ID
|
|
39
|
+
selector: "#main-header"
|
|
40
|
+
|
|
41
|
+
# Playwright-specific role selector
|
|
42
|
+
selector: "button:has-text('Save')"
|
|
43
|
+
selector: "role=button[name='Submit']"
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
**Avoid:**
|
|
47
|
+
```yaml
|
|
48
|
+
# Fragile class-based selectors
|
|
49
|
+
selector: ".btn.btn-primary.mt-4"
|
|
50
|
+
|
|
51
|
+
# Position-based
|
|
52
|
+
selector: "div > div > button:first-child"
|
|
53
|
+
|
|
54
|
+
# Generated class names
|
|
55
|
+
selector: ".css-1a2b3c"
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
### Using `type: button`
|
|
59
|
+
|
|
60
|
+
Match button elements by text, name, or selector.
|
|
61
|
+
|
|
62
|
+
```yaml
|
|
63
|
+
# By visible text
|
|
64
|
+
target:
|
|
65
|
+
type: button
|
|
66
|
+
text: "Save Changes"
|
|
67
|
+
|
|
68
|
+
# By name attribute
|
|
69
|
+
target:
|
|
70
|
+
type: button
|
|
71
|
+
name: "submit"
|
|
72
|
+
|
|
73
|
+
# By selector (fallback)
|
|
74
|
+
target:
|
|
75
|
+
type: button
|
|
76
|
+
selector: "[data-testid='save']"
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### Using `type: link`
|
|
80
|
+
|
|
81
|
+
Match anchor elements.
|
|
82
|
+
|
|
83
|
+
```yaml
|
|
84
|
+
target:
|
|
85
|
+
type: link
|
|
86
|
+
text: "Learn More"
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### Using `type: input`
|
|
90
|
+
|
|
91
|
+
Match form input elements.
|
|
92
|
+
|
|
93
|
+
```yaml
|
|
94
|
+
# By name (most common)
|
|
95
|
+
target:
|
|
96
|
+
type: input
|
|
97
|
+
name: "email"
|
|
98
|
+
|
|
99
|
+
# By placeholder text
|
|
100
|
+
target:
|
|
101
|
+
type: input
|
|
102
|
+
text: "Enter your email"
|
|
103
|
+
|
|
104
|
+
# By selector
|
|
105
|
+
target:
|
|
106
|
+
type: input
|
|
107
|
+
selector: "[data-testid='email-input']"
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
### Using `type: text`
|
|
111
|
+
|
|
112
|
+
Match any element containing specific text.
|
|
113
|
+
|
|
114
|
+
```yaml
|
|
115
|
+
target:
|
|
116
|
+
type: text
|
|
117
|
+
text: "Welcome back!"
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
**Use for:**
|
|
121
|
+
- Headings and labels
|
|
122
|
+
- Menu items
|
|
123
|
+
- Any element identified by its text content
|
|
124
|
+
|
|
125
|
+
## Playwright Selector Syntax
|
|
126
|
+
|
|
127
|
+
SceneForge uses Playwright under the hood. You can use Playwright's selector syntax:
|
|
128
|
+
|
|
129
|
+
### Role Selectors
|
|
130
|
+
```yaml
|
|
131
|
+
selector: "role=button[name='Submit']"
|
|
132
|
+
selector: "role=link[name='Dashboard']"
|
|
133
|
+
selector: "role=textbox[name='Email']"
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
### Text Selectors
|
|
137
|
+
```yaml
|
|
138
|
+
selector: "text=Click here"
|
|
139
|
+
selector: "text=/welcome/i" # Regex, case-insensitive
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
### Has-text Selectors
|
|
143
|
+
```yaml
|
|
144
|
+
selector: "button:has-text('Save')"
|
|
145
|
+
selector: "div:has-text('Loading')"
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
### Combining Selectors
|
|
149
|
+
```yaml
|
|
150
|
+
selector: ".modal >> button:has-text('Confirm')"
|
|
151
|
+
selector: "[data-testid='form'] >> input[name='email']"
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
## Common Patterns
|
|
155
|
+
|
|
156
|
+
### Dropdown/Select
|
|
157
|
+
```yaml
|
|
158
|
+
# Click to open dropdown
|
|
159
|
+
- action: click
|
|
160
|
+
target:
|
|
161
|
+
type: selector
|
|
162
|
+
selector: "[data-testid='country-select']"
|
|
163
|
+
|
|
164
|
+
# Click option
|
|
165
|
+
- action: click
|
|
166
|
+
target:
|
|
167
|
+
type: text
|
|
168
|
+
text: "United States"
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
### Modal Dialog
|
|
172
|
+
```yaml
|
|
173
|
+
# Wait for modal
|
|
174
|
+
- action: wait
|
|
175
|
+
waitFor:
|
|
176
|
+
type: selector
|
|
177
|
+
value: ".modal-content"
|
|
178
|
+
|
|
179
|
+
# Click modal button
|
|
180
|
+
- action: click
|
|
181
|
+
target:
|
|
182
|
+
type: selector
|
|
183
|
+
selector: ".modal-content >> button:has-text('Confirm')"
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
### Dynamic Content
|
|
187
|
+
```yaml
|
|
188
|
+
# Wait for async content
|
|
189
|
+
- action: wait
|
|
190
|
+
waitFor:
|
|
191
|
+
type: selectorHidden
|
|
192
|
+
value: ".skeleton-loader"
|
|
193
|
+
|
|
194
|
+
# Now interact with loaded content
|
|
195
|
+
- action: click
|
|
196
|
+
target:
|
|
197
|
+
type: selector
|
|
198
|
+
selector: "[data-testid='data-row-1']"
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
### Form Inputs
|
|
202
|
+
```yaml
|
|
203
|
+
# Input with label
|
|
204
|
+
target:
|
|
205
|
+
type: selector
|
|
206
|
+
selector: "label:has-text('Email') >> input"
|
|
207
|
+
|
|
208
|
+
# Input by placeholder
|
|
209
|
+
target:
|
|
210
|
+
type: selector
|
|
211
|
+
selector: "[placeholder='Enter email address']"
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
## Debugging Selectors
|
|
215
|
+
|
|
216
|
+
Run the demo in headed mode to verify selectors:
|
|
217
|
+
|
|
218
|
+
```bash
|
|
219
|
+
sceneforge record --definition demo.yaml --headed
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
Use browser DevTools to:
|
|
223
|
+
1. Inspect element attributes
|
|
224
|
+
2. Test selectors in console: `document.querySelector('[data-testid="x"]')`
|
|
225
|
+
3. Check for unique identifiers
|
|
226
|
+
|
|
227
|
+
## Selector Stability Tips
|
|
228
|
+
|
|
229
|
+
1. **Request data-testid**: Ask developers to add test IDs
|
|
230
|
+
2. **Use aria-labels**: Good for accessibility anyway
|
|
231
|
+
3. **Avoid CSS classes**: Often change with styling updates
|
|
232
|
+
4. **Avoid deep nesting**: Use direct selectors when possible
|
|
233
|
+
5. **Test after UI changes**: Re-verify selectors periodically
|
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
# SceneForge YAML Schema Reference
|
|
2
|
+
|
|
3
|
+
## Demo Definition Structure
|
|
4
|
+
|
|
5
|
+
```yaml
|
|
6
|
+
version: 1
|
|
7
|
+
name: demo-name # Identifier (used for output folders)
|
|
8
|
+
title: "Demo Title" # Display title
|
|
9
|
+
description: "Optional description"
|
|
10
|
+
steps:
|
|
11
|
+
- id: step-1
|
|
12
|
+
script: "Voiceover text for this step"
|
|
13
|
+
actions:
|
|
14
|
+
- action: navigate
|
|
15
|
+
path: /page-path
|
|
16
|
+
- action: click
|
|
17
|
+
target:
|
|
18
|
+
type: button
|
|
19
|
+
text: "Click Me"
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Root Properties
|
|
23
|
+
|
|
24
|
+
| Property | Type | Required | Description |
|
|
25
|
+
|----------|------|----------|-------------|
|
|
26
|
+
| `version` | number | No | Schema version (default: 1) |
|
|
27
|
+
| `name` | string | Yes | Demo identifier for output folders |
|
|
28
|
+
| `title` | string | Yes | Display title for the demo |
|
|
29
|
+
| `description` | string | No | Optional description |
|
|
30
|
+
| `steps` | DemoStep[] | Yes | Array of demo steps |
|
|
31
|
+
| `media` | MediaConfig | No | Intro/outro and music config |
|
|
32
|
+
|
|
33
|
+
## DemoStep
|
|
34
|
+
|
|
35
|
+
| Property | Type | Required | Description |
|
|
36
|
+
|----------|------|----------|-------------|
|
|
37
|
+
| `id` | string | Yes | Unique step identifier |
|
|
38
|
+
| `script` | string | Yes | Voiceover text (can be empty string) |
|
|
39
|
+
| `actions` | DemoAction[] | Yes | Array of actions to execute |
|
|
40
|
+
|
|
41
|
+
## DemoAction Types
|
|
42
|
+
|
|
43
|
+
### navigate
|
|
44
|
+
Navigate to a URL path.
|
|
45
|
+
```yaml
|
|
46
|
+
- action: navigate
|
|
47
|
+
path: /dashboard
|
|
48
|
+
waitFor: # Optional
|
|
49
|
+
type: idle
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
### click
|
|
53
|
+
Click on an element.
|
|
54
|
+
```yaml
|
|
55
|
+
- action: click
|
|
56
|
+
target:
|
|
57
|
+
type: button
|
|
58
|
+
text: "Submit"
|
|
59
|
+
highlight: true # Optional: visual highlight
|
|
60
|
+
waitFor: # Optional
|
|
61
|
+
type: selector
|
|
62
|
+
value: ".success-message"
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
### type
|
|
66
|
+
Type text into an input.
|
|
67
|
+
```yaml
|
|
68
|
+
- action: type
|
|
69
|
+
target:
|
|
70
|
+
type: input
|
|
71
|
+
name: email
|
|
72
|
+
text: "user@example.com"
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
### hover
|
|
76
|
+
Hover over an element.
|
|
77
|
+
```yaml
|
|
78
|
+
- action: hover
|
|
79
|
+
target:
|
|
80
|
+
type: selector
|
|
81
|
+
selector: "[data-testid='menu']"
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
### scroll
|
|
85
|
+
Scroll the page by duration.
|
|
86
|
+
```yaml
|
|
87
|
+
- action: scroll
|
|
88
|
+
duration: 1000 # Scroll for 1 second
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
### scrollTo
|
|
92
|
+
Scroll to bring an element into view.
|
|
93
|
+
```yaml
|
|
94
|
+
- action: scrollTo
|
|
95
|
+
target:
|
|
96
|
+
type: text
|
|
97
|
+
text: "Section Title"
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
### wait
|
|
101
|
+
Wait for duration or condition.
|
|
102
|
+
```yaml
|
|
103
|
+
# Wait for fixed duration
|
|
104
|
+
- action: wait
|
|
105
|
+
duration: 2000 # 2 seconds
|
|
106
|
+
|
|
107
|
+
# Wait for condition
|
|
108
|
+
- action: wait
|
|
109
|
+
waitFor:
|
|
110
|
+
type: selector
|
|
111
|
+
value: ".loaded"
|
|
112
|
+
timeout: 10000 # Optional timeout
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
### upload
|
|
116
|
+
Upload a file.
|
|
117
|
+
```yaml
|
|
118
|
+
- action: upload
|
|
119
|
+
file: ./assets/document.pdf
|
|
120
|
+
target: # Optional: specific file input
|
|
121
|
+
type: selector
|
|
122
|
+
selector: "input[type='file']"
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
### drag
|
|
126
|
+
Drag an element.
|
|
127
|
+
```yaml
|
|
128
|
+
- action: drag
|
|
129
|
+
target:
|
|
130
|
+
type: selector
|
|
131
|
+
selector: ".draggable"
|
|
132
|
+
drag:
|
|
133
|
+
deltaX: 100
|
|
134
|
+
deltaY: 50
|
|
135
|
+
steps: 10 # Optional: smoothness
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
## StepTarget Types
|
|
139
|
+
|
|
140
|
+
| Type | Required Fields | Description |
|
|
141
|
+
|------|-----------------|-------------|
|
|
142
|
+
| `button` | `text`, `name`, or `selector` | Match a button element |
|
|
143
|
+
| `link` | `text`, `name`, or `selector` | Match a link element |
|
|
144
|
+
| `input` | `text`, `name`, or `selector` | Match an input element |
|
|
145
|
+
| `text` | `text` | Match element containing text |
|
|
146
|
+
| `selector` | `selector` | Match by CSS selector |
|
|
147
|
+
|
|
148
|
+
### Target Examples
|
|
149
|
+
```yaml
|
|
150
|
+
# By visible text
|
|
151
|
+
target:
|
|
152
|
+
type: button
|
|
153
|
+
text: "Save Changes"
|
|
154
|
+
|
|
155
|
+
# By name attribute
|
|
156
|
+
target:
|
|
157
|
+
type: input
|
|
158
|
+
name: "username"
|
|
159
|
+
|
|
160
|
+
# By CSS selector
|
|
161
|
+
target:
|
|
162
|
+
type: selector
|
|
163
|
+
selector: "[data-testid='submit-btn']"
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
## WaitCondition Types
|
|
167
|
+
|
|
168
|
+
| Type | Requires Value | Description |
|
|
169
|
+
|------|----------------|-------------|
|
|
170
|
+
| `text` | Yes | Wait for text to appear |
|
|
171
|
+
| `selector` | Yes | Wait for selector to match |
|
|
172
|
+
| `textHidden` | Yes | Wait for text to disappear |
|
|
173
|
+
| `selectorHidden` | Yes | Wait for selector to disappear |
|
|
174
|
+
| `navigation` | No | Wait for page navigation |
|
|
175
|
+
| `idle` | No | Wait for network idle |
|
|
176
|
+
|
|
177
|
+
### WaitCondition Examples
|
|
178
|
+
```yaml
|
|
179
|
+
waitFor:
|
|
180
|
+
type: text
|
|
181
|
+
value: "Success!"
|
|
182
|
+
timeout: 5000
|
|
183
|
+
|
|
184
|
+
waitFor:
|
|
185
|
+
type: selectorHidden
|
|
186
|
+
value: ".loading-spinner"
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
## Media Configuration
|
|
190
|
+
|
|
191
|
+
```yaml
|
|
192
|
+
media:
|
|
193
|
+
intro:
|
|
194
|
+
file: ./assets/intro.mp4
|
|
195
|
+
duration: 5 # Optional: trim to seconds
|
|
196
|
+
fade: true
|
|
197
|
+
fadeDuration: 0.5
|
|
198
|
+
outro:
|
|
199
|
+
file: ./assets/outro.mp4
|
|
200
|
+
backgroundMusic:
|
|
201
|
+
file: ./assets/music.mp3
|
|
202
|
+
volume: 0.15
|
|
203
|
+
loop: true
|
|
204
|
+
fadeIn: 2
|
|
205
|
+
fadeOut: 2
|
|
206
|
+
startAt:
|
|
207
|
+
type: afterIntro
|
|
208
|
+
endAt:
|
|
209
|
+
type: beforeOutro
|
|
210
|
+
```
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
# Skill: Balance Timing
|
|
2
|
+
|
|
3
|
+
Analyze and balance the timing between script duration and action duration in a SceneForge demo.
|
|
4
|
+
|
|
5
|
+
## Task
|
|
6
|
+
|
|
7
|
+
Review timing data from the scripts JSON and suggest adjustments to achieve better synchronization.
|
|
8
|
+
|
|
9
|
+
## Input Required
|
|
10
|
+
|
|
11
|
+
Provide the following:
|
|
12
|
+
- **Scripts JSON data**: Content from `output/<demo>/scripts/<demo>-scripts.json`
|
|
13
|
+
- **Problem steps**: Steps with timing issues (optional)
|
|
14
|
+
- **Constraints**: Any timing requirements (optional)
|
|
15
|
+
|
|
16
|
+
## Analysis Process
|
|
17
|
+
|
|
18
|
+
### Step 1: Calculate Timing Difference
|
|
19
|
+
|
|
20
|
+
For each step:
|
|
21
|
+
```
|
|
22
|
+
difference = stepTimingMs - estimatedDurationMs
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
- **Positive**: Actions take longer than voiceover
|
|
26
|
+
- **Negative**: Voiceover takes longer than actions
|
|
27
|
+
|
|
28
|
+
### Step 2: Categorize Issues
|
|
29
|
+
|
|
30
|
+
| Difference | Severity | Action Needed |
|
|
31
|
+
|------------|----------|---------------|
|
|
32
|
+
| ±500ms | Minor | Usually acceptable |
|
|
33
|
+
| 500-1500ms | Moderate | Consider adjustment |
|
|
34
|
+
| >1500ms | Significant | Must adjust |
|
|
35
|
+
|
|
36
|
+
### Step 3: Recommend Solutions
|
|
37
|
+
|
|
38
|
+
## Output Format
|
|
39
|
+
|
|
40
|
+
Provide a timing analysis report with:
|
|
41
|
+
1. Summary of all steps with issues
|
|
42
|
+
2. Recommended adjustments per step
|
|
43
|
+
3. Updated YAML snippets
|
|
44
|
+
|
|
45
|
+
## Example Analysis
|
|
46
|
+
|
|
47
|
+
### Input Data
|
|
48
|
+
```json
|
|
49
|
+
{
|
|
50
|
+
"steps": [
|
|
51
|
+
{
|
|
52
|
+
"stepId": "intro",
|
|
53
|
+
"estimatedDurationMs": 4800,
|
|
54
|
+
"stepTimingMs": 2000,
|
|
55
|
+
"wordCount": 12
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
"stepId": "fill-form",
|
|
59
|
+
"estimatedDurationMs": 3600,
|
|
60
|
+
"stepTimingMs": 6000,
|
|
61
|
+
"wordCount": 9
|
|
62
|
+
}
|
|
63
|
+
]
|
|
64
|
+
}
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
### Analysis Output
|
|
68
|
+
|
|
69
|
+
```
|
|
70
|
+
## Timing Analysis Report
|
|
71
|
+
|
|
72
|
+
### Step: intro
|
|
73
|
+
- Script duration: 4800ms (12 words)
|
|
74
|
+
- Video duration: 2000ms
|
|
75
|
+
- Difference: -2800ms (voiceover too long)
|
|
76
|
+
|
|
77
|
+
**Recommendation:** Add wait action to extend step duration
|
|
78
|
+
|
|
79
|
+
```yaml
|
|
80
|
+
- id: intro
|
|
81
|
+
script: "Welcome to this demo..."
|
|
82
|
+
actions:
|
|
83
|
+
- action: wait
|
|
84
|
+
duration: 5000 # Extended from 2000ms
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
### Step: fill-form
|
|
88
|
+
- Script duration: 3600ms (9 words)
|
|
89
|
+
- Video duration: 6000ms
|
|
90
|
+
- Difference: +2400ms (video has dead air)
|
|
91
|
+
|
|
92
|
+
**Recommendation:** Expand script to fill time
|
|
93
|
+
|
|
94
|
+
**Current script (9 words):**
|
|
95
|
+
"Enter your details in the form below."
|
|
96
|
+
|
|
97
|
+
**Suggested script (15 words):**
|
|
98
|
+
"Enter your details in the form below. We'll add your name, email, and message."
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
## Adjustment Strategies
|
|
102
|
+
|
|
103
|
+
### When Video > Script (Dead Air)
|
|
104
|
+
|
|
105
|
+
**Option 1: Expand script**
|
|
106
|
+
- Add more context or explanation
|
|
107
|
+
- Describe what user should notice
|
|
108
|
+
- Preview next step
|
|
109
|
+
|
|
110
|
+
**Option 2: Split into multiple steps**
|
|
111
|
+
- If step has distinct phases
|
|
112
|
+
- Each gets focused narration
|
|
113
|
+
|
|
114
|
+
### When Script > Video (Overlap Risk)
|
|
115
|
+
|
|
116
|
+
**Option 1: Add wait action**
|
|
117
|
+
```yaml
|
|
118
|
+
actions:
|
|
119
|
+
- action: click
|
|
120
|
+
target: ...
|
|
121
|
+
- action: wait
|
|
122
|
+
duration: 2000 # Added padding
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
**Option 2: Shorten script**
|
|
126
|
+
- Remove redundant words
|
|
127
|
+
- Focus on essential information
|
|
128
|
+
- Split long sentences
|
|
129
|
+
|
|
130
|
+
## Checklist
|
|
131
|
+
|
|
132
|
+
- [ ] All steps analyzed for timing variance
|
|
133
|
+
- [ ] Significant issues identified
|
|
134
|
+
- [ ] Solutions provided for each issue
|
|
135
|
+
- [ ] Updated YAML snippets included
|
|
136
|
+
- [ ] Total runtime remains reasonable
|