@kadj-amoah/showrunner 1.1.7 → 1.1.8
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/CHANGELOG.md +187 -211
- package/README.md +213 -191
- package/dist/cli.js +88 -13
- package/dist/cli.js.map +1 -1
- package/dist/index.js.map +1 -1
- package/package.json +85 -85
package/README.md
CHANGED
|
@@ -1,191 +1,213 @@
|
|
|
1
|
-
# Showrunner
|
|
2
|
-
|
|
3
|
-
Automated product demo recording & production tool.
|
|
4
|
-
|
|
5
|
-
Showrunner collapses the demo-video pipeline into a single, repeatable, automatable command. Point it at a running web product, give it a one-page brief, and it produces a finished, captioned MP4 — comprehension, script, recording, voiceover, and mux in one pass.
|
|
6
|
-
|
|
7
|
-
## Status
|
|
8
|
-
|
|
9
|
-
v1.1 — usable end-to-end for short demos. The LLM and TTS layers are provider-agnostic so you can bring your own keys or wire in an in-house pipeline. See `prd_showrunner.md` for the full product spec.
|
|
10
|
-
|
|
11
|
-
## What you need on your machine
|
|
12
|
-
|
|
13
|
-
- **Node ≥ 20.6** (`process.loadEnvFile` is required)
|
|
14
|
-
- **ffmpeg + ffprobe on PATH** (`apt install ffmpeg` on Debian/Ubuntu, `brew install ffmpeg` on macOS, gyan.dev build on Windows)
|
|
15
|
-
- **A Chromium binary** — Playwright installs one for you (`npx playwright install chromium`)
|
|
16
|
-
- **API keys for the providers you pick**, OR a headless CLI agent like `claude -p` (see _Provider choices_ below)
|
|
17
|
-
|
|
18
|
-
Showrunner is built to deploy on Linux but develops fine on WSL2 or macOS.
|
|
19
|
-
|
|
20
|
-
## Install
|
|
21
|
-
|
|
22
|
-
Published to both npmjs.org (zero-friction install) and GitHub Packages (mirrors the GitHub Releases timeline). Pick whichever matches your workflow.
|
|
23
|
-
|
|
24
|
-
Showrunner ships with `playwright-core`, which means **no browsers are downloaded during `npm install`**. You must run the browser-bootstrap step (`npx playwright install chromium`) after install — otherwise the first recording attempt will fail with a "browser binary missing" error from `doctor`.
|
|
25
|
-
|
|
26
|
-
### npx (no install, recommended for first-time use)
|
|
27
|
-
|
|
28
|
-
```bash
|
|
29
|
-
npx @kadj-amoah/showrunner --version # → 1.1.1
|
|
30
|
-
npx playwright install chromium # required: bootstraps the browser
|
|
31
|
-
```
|
|
32
|
-
|
|
33
|
-
Running `showrunner` with no arguments prints a context-aware welcome with the next command to run — from outside a project it suggests `showrunner init`; inside a project root it suggests `showrunner doctor -c demo.yaml`.
|
|
34
|
-
|
|
35
|
-
### Global install (`npm i -g`)
|
|
36
|
-
|
|
37
|
-
```bash
|
|
38
|
-
npm install -g @kadj-amoah/showrunner
|
|
39
|
-
npx playwright install chromium # required: bootstraps the browser
|
|
40
|
-
showrunner --version # → 1.1.1
|
|
41
|
-
```
|
|
42
|
-
|
|
43
|
-
> **Linux note:** if `npm i -g` needs `sudo`, **do not** run `sudo npx playwright install` afterwards — the browser will land in `/root/.cache/ms-playwright` where your user-mode `showrunner` process can't find it. Run `npx playwright install chromium` as your normal user. (`showrunner doctor` will detect and warn about this case.)
|
|
44
|
-
|
|
45
|
-
### GitHub Packages
|
|
46
|
-
|
|
47
|
-
Requires a one-time `~/.npmrc` setup since GitHub Packages requires auth even for public packages:
|
|
48
|
-
|
|
49
|
-
```bash
|
|
50
|
-
# Generate a Personal Access Token at github.com/settings/tokens
|
|
51
|
-
# Scope needed: read:packages
|
|
52
|
-
echo "@kadj-amoah:registry=https://npm.pkg.github.com" >> ~/.npmrc
|
|
53
|
-
echo "//npm.pkg.github.com/:_authToken=YOUR_TOKEN_HERE" >> ~/.npmrc
|
|
54
|
-
|
|
55
|
-
npm install -g @kadj-amoah/showrunner
|
|
56
|
-
npx playwright install chromium
|
|
57
|
-
```
|
|
58
|
-
|
|
59
|
-
### Directly from a git tag (no registry at all)
|
|
60
|
-
|
|
61
|
-
```bash
|
|
62
|
-
npm install -g github:kadj-amoah/showrunner#v1.1.1
|
|
63
|
-
npx playwright install chromium
|
|
64
|
-
```
|
|
65
|
-
|
|
66
|
-
### From source
|
|
67
|
-
|
|
68
|
-
```bash
|
|
69
|
-
git clone https://github.com/kadj-amoah/showrunner.git
|
|
70
|
-
cd showrunner
|
|
71
|
-
npm install
|
|
72
|
-
npm run build
|
|
73
|
-
npm link # makes `showrunner` available globally
|
|
74
|
-
npx playwright install chromium
|
|
75
|
-
```
|
|
76
|
-
|
|
77
|
-
Verify any of the above with `showrunner --help`.
|
|
78
|
-
|
|
79
|
-
##
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
|
125
|
-
|
|
126
|
-
| `
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
1
|
+
# Showrunner
|
|
2
|
+
|
|
3
|
+
Automated product demo recording & production tool.
|
|
4
|
+
|
|
5
|
+
Showrunner collapses the demo-video pipeline into a single, repeatable, automatable command. Point it at a running web product, give it a one-page brief, and it produces a finished, captioned MP4 — comprehension, script, recording, voiceover, and mux in one pass.
|
|
6
|
+
|
|
7
|
+
## Status
|
|
8
|
+
|
|
9
|
+
v1.1 — usable end-to-end for short demos. The LLM and TTS layers are provider-agnostic so you can bring your own keys or wire in an in-house pipeline. See `prd_showrunner.md` for the full product spec.
|
|
10
|
+
|
|
11
|
+
## What you need on your machine
|
|
12
|
+
|
|
13
|
+
- **Node ≥ 20.6** (`process.loadEnvFile` is required)
|
|
14
|
+
- **ffmpeg + ffprobe on PATH** (`apt install ffmpeg` on Debian/Ubuntu, `brew install ffmpeg` on macOS, gyan.dev build on Windows)
|
|
15
|
+
- **A Chromium binary** — Playwright installs one for you (`npx playwright install chromium`)
|
|
16
|
+
- **API keys for the providers you pick**, OR a headless CLI agent like `claude -p` (see _Provider choices_ below)
|
|
17
|
+
|
|
18
|
+
Showrunner is built to deploy on Linux but develops fine on WSL2 or macOS.
|
|
19
|
+
|
|
20
|
+
## Install
|
|
21
|
+
|
|
22
|
+
Published to both npmjs.org (zero-friction install) and GitHub Packages (mirrors the GitHub Releases timeline). Pick whichever matches your workflow.
|
|
23
|
+
|
|
24
|
+
Showrunner ships with `playwright-core`, which means **no browsers are downloaded during `npm install`**. You must run the browser-bootstrap step (`npx playwright install chromium`) after install — otherwise the first recording attempt will fail with a "browser binary missing" error from `doctor`.
|
|
25
|
+
|
|
26
|
+
### npx (no install, recommended for first-time use)
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
npx @kadj-amoah/showrunner --version # → 1.1.1
|
|
30
|
+
npx playwright install chromium # required: bootstraps the browser
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Running `showrunner` with no arguments prints a context-aware welcome with the next command to run — from outside a project it suggests `showrunner init`; inside a project root it suggests `showrunner doctor -c demo.yaml`.
|
|
34
|
+
|
|
35
|
+
### Global install (`npm i -g`)
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
npm install -g @kadj-amoah/showrunner
|
|
39
|
+
npx playwright install chromium # required: bootstraps the browser
|
|
40
|
+
showrunner --version # → 1.1.1
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
> **Linux note:** if `npm i -g` needs `sudo`, **do not** run `sudo npx playwright install` afterwards — the browser will land in `/root/.cache/ms-playwright` where your user-mode `showrunner` process can't find it. Run `npx playwright install chromium` as your normal user. (`showrunner doctor` will detect and warn about this case.)
|
|
44
|
+
|
|
45
|
+
### GitHub Packages
|
|
46
|
+
|
|
47
|
+
Requires a one-time `~/.npmrc` setup since GitHub Packages requires auth even for public packages:
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
# Generate a Personal Access Token at github.com/settings/tokens
|
|
51
|
+
# Scope needed: read:packages
|
|
52
|
+
echo "@kadj-amoah:registry=https://npm.pkg.github.com" >> ~/.npmrc
|
|
53
|
+
echo "//npm.pkg.github.com/:_authToken=YOUR_TOKEN_HERE" >> ~/.npmrc
|
|
54
|
+
|
|
55
|
+
npm install -g @kadj-amoah/showrunner
|
|
56
|
+
npx playwright install chromium
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
### Directly from a git tag (no registry at all)
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
npm install -g github:kadj-amoah/showrunner#v1.1.1
|
|
63
|
+
npx playwright install chromium
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
### From source
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
git clone https://github.com/kadj-amoah/showrunner.git
|
|
70
|
+
cd showrunner
|
|
71
|
+
npm install
|
|
72
|
+
npm run build
|
|
73
|
+
npm link # makes `showrunner` available globally
|
|
74
|
+
npx playwright install chromium
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
Verify any of the above with `showrunner --help`.
|
|
78
|
+
|
|
79
|
+
## After installing: run the doctor first
|
|
80
|
+
|
|
81
|
+
Before doing anything else, run a system check. This catches missing prerequisites (ffmpeg, ffprobe, the recording browser) before they bite you mid-pipeline:
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
showrunner doctor # no -c flag yet — this is the system-only pass
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
If it flags anything missing, fix it now. The most common gaps are `ffmpeg` (install via your OS package manager: `apt`, `pacman`, `dnf`, `brew`, or `winget`) and the recording browser (`showrunner install-browser`).
|
|
88
|
+
|
|
89
|
+
## First demo in six commands
|
|
90
|
+
|
|
91
|
+
**Step 1 is the one most people get wrong: `cd` into the root of the product you want to demo *before* running `init`.** The scaffold creates a `showrunner-demo/` directory inside your current location, and several things in `demo.yaml` (`recording.target_url`, `project.codebase_root`, lifecycle scripts) are wired up assuming the parent directory is your product's root. If you run `init` from a random location (your home directory, `~/Downloads`, etc.), the resulting project will target nothing and you'll get a reel about an empty directory.
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
# 1. Navigate to your product's root directory — the same place your package.json / pyproject.toml / etc. lives.
|
|
95
|
+
cd ~/my-product
|
|
96
|
+
|
|
97
|
+
# 2. Scaffold the demo project (creates ./showrunner-demo/ inside your product).
|
|
98
|
+
# `init` is interactive by default — it'll prompt for provider keys, target URL, etc.
|
|
99
|
+
showrunner init
|
|
100
|
+
|
|
101
|
+
# 3. Move into the scaffold and finish setup. The wizard already wrote .env if you pasted keys.
|
|
102
|
+
cd showrunner-demo
|
|
103
|
+
$EDITOR docs/PRD.md # replace the stub with your product brief
|
|
104
|
+
|
|
105
|
+
# 4. Full preflight (now with project context — ~11–12 PASS/FAIL rows).
|
|
106
|
+
showrunner doctor -c demo.yaml
|
|
107
|
+
|
|
108
|
+
# 5. Run the pipeline.
|
|
109
|
+
showrunner run -c demo.yaml
|
|
110
|
+
open output/demo_final.mp4
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
If you'd rather not write a PRD upfront, swap the `$EDITOR` step for `showrunner understand -c demo.yaml --interactive` — it asks five questions and produces the product model on the spot.
|
|
114
|
+
|
|
115
|
+
## Provider choices
|
|
116
|
+
|
|
117
|
+
The two generative stages (LLM for comprehension + script, TTS for voiceover) are pluggable. Pick them at scaffold time with `--llm-provider` and `--tts-provider`, or edit the `llm` and `voiceover.provider` blocks in `demo.yaml` later.
|
|
118
|
+
|
|
119
|
+
### LLM (`llm.default.provider`)
|
|
120
|
+
|
|
121
|
+
| Provider | Needs | Notes |
|
|
122
|
+
|----------------|--------------------------------------------|-----------------------------------------------------------------------------|
|
|
123
|
+
| `anthropic` | `ANTHROPIC_API_KEY` | Default. Uses Claude with structured outputs. |
|
|
124
|
+
| `openai` | `OPENAI_API_KEY` | Uses `response_format: json_schema`, falls back to `json_object` if needed. |
|
|
125
|
+
| `agent_bridge` | A headless CLI agent on PATH (default `claude -p --output-format json`) | No API key on file — Showrunner spawns the agent per request. |
|
|
126
|
+
| `custom` | A dynamic-importable module | Implement the `LLMProvider` interface. |
|
|
127
|
+
|
|
128
|
+
Per-stage overrides are supported under `llm.overrides.{comprehension,script,instrument}` so you can, e.g., use `agent_bridge` for the heavy script generation and `anthropic` for the small `instrument` calls.
|
|
129
|
+
|
|
130
|
+
### TTS (`voiceover.provider.name`)
|
|
131
|
+
|
|
132
|
+
| Provider | Needs | Alignment? | Default `alignment_strategy` |
|
|
133
|
+
|--------------|------------------------|------------|------------------------------|
|
|
134
|
+
| `elevenlabs` | `ELEVENLABS_API_KEY` | ✅ | `required` |
|
|
135
|
+
| `openai` | `OPENAI_API_KEY` | ❌ | `best_effort` |
|
|
136
|
+
| `custom` | A dynamic-import module| Your call | `best_effort` |
|
|
137
|
+
|
|
138
|
+
Only ElevenLabs returns per-character alignment. With other providers, Showrunner takes the **best-effort path**: one synthesis call per segment (no slicing), captions collapse to whole-segment cues, and `at_word` action timing degrades to `at`. Set `voiceover.alignment_strategy: required` if you want it to fail loudly instead.
|
|
139
|
+
|
|
140
|
+
## Pipeline
|
|
141
|
+
|
|
142
|
+
```
|
|
143
|
+
comprehension → script → record + voiceover → mux → demo_final.mp4
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
| Stage | What it does | Inputs | Outputs |
|
|
147
|
+
|-----------------|----------------------------------------------------------------------------------------------------|-----------------------------------------|---------------------------------------------------------|
|
|
148
|
+
| `comprehension` | Reads `docs/`, an optional codebase, or runs the interactive Q&A. Emits `product_model.json`. | `docs/PRD.md` (or `--interactive`) | `product_model.json` |
|
|
149
|
+
| `script` | Scrapes the live target's actionable DOM, then asks the LLM for a manifest using only those selectors. | `product_model.json` + live target URL | `scripts/manifest.json`, `vo_script.txt`, Playwright spec |
|
|
150
|
+
| `record` | Drives Playwright through the manifest, captures `master.webm` + a slice plan. | manifest, dev server | `segments/video/master.webm`, `slice_plan.json` |
|
|
151
|
+
| `voiceover` | TTS for the whole script, slices per segment, writes alignment files (when supported). | manifest | `segments/audio/*.mp3`, `segments/alignment/*.json` |
|
|
152
|
+
| `mux` | Normalizes, slices, branding cards, background music, captions. Outputs the MP4. | video + audio + alignment | `output/demo_final.mp4` (+ `.srt`/`.vtt` if enabled) |
|
|
153
|
+
|
|
154
|
+
Stages are independently runnable, checkpointed, and idempotent. Existing artifacts are never silently overwritten — use `--force <stage>[,<stage>]` to regenerate.
|
|
155
|
+
|
|
156
|
+
## Daily commands
|
|
157
|
+
|
|
158
|
+
```bash
|
|
159
|
+
# preflight — catches missing keys, ffmpeg, dev server down, free disk, RAM cap
|
|
160
|
+
showrunner doctor -c demo.yaml
|
|
161
|
+
|
|
162
|
+
# generate (or refresh) product_model.json from docs/PRD.md
|
|
163
|
+
showrunner understand -c demo.yaml
|
|
164
|
+
showrunner understand -c demo.yaml --interactive # 5-question fallback
|
|
165
|
+
|
|
166
|
+
# full pipeline (`--skip-doctor` to bypass the implicit preflight)
|
|
167
|
+
showrunner run -c demo.yaml
|
|
168
|
+
|
|
169
|
+
# re-run just one stage
|
|
170
|
+
showrunner run -c demo.yaml --stages script
|
|
171
|
+
showrunner run -c demo.yaml --force voiceover,mux # regen, don't reuse
|
|
172
|
+
|
|
173
|
+
# the LLM's selectors are wrong for one segment — demo it yourself
|
|
174
|
+
showrunner record-actions -c demo.yaml --segment fill-form
|
|
175
|
+
|
|
176
|
+
# preview the manifest in Playwright UI Mode (no recording)
|
|
177
|
+
showrunner preview -c demo.yaml
|
|
178
|
+
|
|
179
|
+
# inspect a failed take
|
|
180
|
+
showrunner trace -c demo.yaml --segment <id>
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
## When things go wrong
|
|
184
|
+
|
|
185
|
+
- **`x264 malloc failed` during mux** — out of RAM. The `doctor` row "free memory: … (ffmpeg thread cap: N)" shows what was budgeted. Drop resolution to 1280x720 (or 854x480 for draft), set `SHOWRUNNER_FFMPEG_THREADS=1`, or close Docker / browsers.
|
|
186
|
+
- **Recording fails because a selector doesn't resolve** — usually the LLM picked something fragile. The `script` stage's DOM preflight is supposed to prevent this; if it does happen, run `showrunner record-actions -c demo.yaml --segment <id>` and demonstrate the interaction yourself.
|
|
187
|
+
- **`vo_review_gate` halted the pipeline** — by design. Edit `scripts/vo_script.txt`, then `showrunner approve-vo -c demo.yaml`. (The init scaffold ships with this off — you have to opt in via `script.vo_review_gate: true`.)
|
|
188
|
+
- **Output file is locked by a media player** — close VLC/QuickTime/your-browser-tab. Showrunner falls back to writing a timestamped sibling MP4 with a warning, but the canonical path needs the lock released.
|
|
189
|
+
- **DOM preflight failed** — your dev server isn't on the URL in `demo.yaml`, or it's behind auth. Bring the server up, configure `recording.auth` for session/form/setup-script flows.
|
|
190
|
+
- **Playwright warns "your OS is not officially supported"** — on Arch / CachyOS / Fedora during `npx playwright install`. Safe to ignore; Playwright falls back to the Ubuntu 24.04 build, which works fine.
|
|
191
|
+
- **`browser binary missing` even though I ran `npx playwright install`** — you likely ran the install under `sudo`, so the browser is in the root cache. Re-run as your normal user: `npx playwright install chromium`. `showrunner doctor` detects this and prints the specific cache it found the browser in.
|
|
192
|
+
|
|
193
|
+
## Configuration reference
|
|
194
|
+
|
|
195
|
+
`demo.yaml` is the single source of truth. Sections:
|
|
196
|
+
|
|
197
|
+
- `project` — name and optional `product_model` path
|
|
198
|
+
- `comprehension` — `mode` + `sources` (PRD, README, codebase, OpenAPI, etc.)
|
|
199
|
+
- `script` — `style`, `duration_target_seconds`, `highlight_features`, `vo_review_gate`
|
|
200
|
+
- `recording` — `target_url`, viewport, browser, cursor + segment timing knobs, auth, lifecycle scripts
|
|
201
|
+
- `voiceover` — `provider` (discriminated by `name`), `alignment_strategy`, output dirs, drift behavior, pause placement
|
|
202
|
+
- `llm` — `default` provider + per-stage `overrides` (comprehension, script, instrument)
|
|
203
|
+
- `output` — resolution, fps, branding cards, background music, captions, output path
|
|
204
|
+
|
|
205
|
+
Legacy v1.0 configs (flat `voiceover.voice_id`, no `llm` block) are auto-migrated by the loader — your existing demos keep working without edits.
|
|
206
|
+
|
|
207
|
+
## Deployment target
|
|
208
|
+
|
|
209
|
+
Linux. Local dev runs on WSL2/Docker on Windows or macOS hosts. A Docker image bundling Node 20, Playwright (Chromium), FFmpeg, and `xvfb` is on the roadmap.
|
|
210
|
+
|
|
211
|
+
## License
|
|
212
|
+
|
|
213
|
+
MIT
|
package/dist/cli.js
CHANGED
|
@@ -5935,6 +5935,29 @@ function sleep3(ms) {
|
|
|
5935
5935
|
var SLUG_RE = /^[a-z0-9](?:[a-z0-9._-]*[a-z0-9])?$/i;
|
|
5936
5936
|
async function runWizard(env) {
|
|
5937
5937
|
intro("Showrunner setup");
|
|
5938
|
+
note(
|
|
5939
|
+
[
|
|
5940
|
+
`Showrunner will scaffold a new project inside:`,
|
|
5941
|
+
``,
|
|
5942
|
+
` ${process.cwd()}`,
|
|
5943
|
+
``,
|
|
5944
|
+
`That directory should be the root of the product you want to demo (the dir`,
|
|
5945
|
+
`where your package.json / pyproject.toml / etc. lives). If you're somewhere`,
|
|
5946
|
+
`else, cancel with Ctrl+C, \`cd\` to your product's root, and re-run`,
|
|
5947
|
+
`\`showrunner init\` from there.`
|
|
5948
|
+
].join("\n"),
|
|
5949
|
+
"Heads up \u2014 confirm your starting directory"
|
|
5950
|
+
);
|
|
5951
|
+
const proceedFromCwd = await ask(
|
|
5952
|
+
confirm({
|
|
5953
|
+
message: "Continue scaffolding from this directory?",
|
|
5954
|
+
initialValue: true
|
|
5955
|
+
})
|
|
5956
|
+
);
|
|
5957
|
+
if (proceedFromCwd === null || proceedFromCwd === false) {
|
|
5958
|
+
cancel("Setup cancelled. Re-run `showrunner init` from your product root.");
|
|
5959
|
+
return null;
|
|
5960
|
+
}
|
|
5938
5961
|
note(formatDetection(env), "Detected on this machine");
|
|
5939
5962
|
const projectName = await ask(
|
|
5940
5963
|
text({
|
|
@@ -8494,7 +8517,7 @@ async function fileExists10(path) {
|
|
|
8494
8517
|
|
|
8495
8518
|
// src/cli.ts
|
|
8496
8519
|
var program = new Command();
|
|
8497
|
-
program.name("showrunner").description("Automated product demo recording & production tool").version("1.1.
|
|
8520
|
+
program.name("showrunner").description("Automated product demo recording & production tool").version("1.1.8").option("--json", "emit structured JSON logs to stdout").option("--log-level <level>", "log level (debug|info|warn|error)").hook("preAction", (thisCmd) => {
|
|
8498
8521
|
const opts = thisCmd.opts();
|
|
8499
8522
|
if (opts.json) logger.setJson(true);
|
|
8500
8523
|
if (opts.logLevel) logger.setLevel(opts.logLevel);
|
|
@@ -8561,14 +8584,28 @@ async function printWelcome() {
|
|
|
8561
8584
|
inProject = true;
|
|
8562
8585
|
} catch {
|
|
8563
8586
|
}
|
|
8564
|
-
const
|
|
8565
|
-
const
|
|
8566
|
-
|
|
8567
|
-
|
|
8587
|
+
const missing = await detectMissingPrereqs();
|
|
8588
|
+
const anyMissing = missing.ffmpeg || missing.ffprobe || missing.chromium;
|
|
8589
|
+
const lines = ["", `Showrunner v1.1.8`, ""];
|
|
8590
|
+
if (anyMissing) {
|
|
8591
|
+
lines.push(`First-time setup. Showrunner needs these system tools:`);
|
|
8568
8592
|
lines.push(``);
|
|
8569
|
-
|
|
8570
|
-
|
|
8571
|
-
|
|
8593
|
+
if (missing.ffmpeg || missing.ffprobe) {
|
|
8594
|
+
const which = missing.ffmpeg && missing.ffprobe ? "ffmpeg / ffprobe" : missing.ffmpeg ? "ffmpeg" : "ffprobe";
|
|
8595
|
+
lines.push(` ${which} \u2014 install via your OS package manager:`);
|
|
8596
|
+
lines.push(` Linux (apt): sudo apt install ffmpeg`);
|
|
8597
|
+
lines.push(` Linux (pacman): sudo pacman -S ffmpeg`);
|
|
8598
|
+
lines.push(` Linux (dnf): sudo dnf install ffmpeg`);
|
|
8599
|
+
lines.push(` macOS: brew install ffmpeg`);
|
|
8600
|
+
lines.push(` Windows: winget install Gyan.FFmpeg`);
|
|
8601
|
+
lines.push(``);
|
|
8602
|
+
}
|
|
8603
|
+
if (missing.chromium) {
|
|
8604
|
+
lines.push(` chromium recording browser \u2014 install via:`);
|
|
8605
|
+
lines.push(` showrunner install-browser`);
|
|
8606
|
+
lines.push(``);
|
|
8607
|
+
}
|
|
8608
|
+
lines.push(`Re-run \`showrunner\` once those are in place.`);
|
|
8572
8609
|
} else if (inProject) {
|
|
8573
8610
|
lines.push(`This is a Showrunner project (found demo.yaml).`);
|
|
8574
8611
|
lines.push(``);
|
|
@@ -8579,22 +8616,60 @@ async function printWelcome() {
|
|
|
8579
8616
|
} else {
|
|
8580
8617
|
lines.push(`No Showrunner project in this directory. To create one:`);
|
|
8581
8618
|
lines.push(``);
|
|
8582
|
-
lines.push(`
|
|
8619
|
+
lines.push(` cd <your-product's-root-directory> # the dir with package.json / etc.`);
|
|
8620
|
+
lines.push(` showrunner init # then run init from THERE`);
|
|
8583
8621
|
lines.push(``);
|
|
8584
|
-
lines.push(`\`init\` scaffolds
|
|
8622
|
+
lines.push(`\`init\` scaffolds inside cwd, so cwd must be your product. The wizard will`);
|
|
8623
|
+
lines.push(`confirm the path before doing anything destructive.`);
|
|
8585
8624
|
}
|
|
8586
8625
|
lines.push("");
|
|
8587
8626
|
process.stdout.write(lines.join("\n"));
|
|
8588
8627
|
}
|
|
8589
|
-
async function
|
|
8628
|
+
async function detectMissingPrereqs() {
|
|
8629
|
+
const [ffmpegOk, ffprobeOk, chromiumOk] = await Promise.all([
|
|
8630
|
+
binaryOnPath("ffmpeg"),
|
|
8631
|
+
binaryOnPath("ffprobe"),
|
|
8632
|
+
chromiumInstalled2()
|
|
8633
|
+
]);
|
|
8634
|
+
return {
|
|
8635
|
+
ffmpeg: !ffmpegOk,
|
|
8636
|
+
ffprobe: !ffprobeOk,
|
|
8637
|
+
chromium: !chromiumOk
|
|
8638
|
+
};
|
|
8639
|
+
}
|
|
8640
|
+
async function binaryOnPath(name) {
|
|
8641
|
+
const { spawn: spawn7 } = await import("child_process");
|
|
8642
|
+
return new Promise((resolve28) => {
|
|
8643
|
+
const useShell = process.platform === "win32";
|
|
8644
|
+
const child = spawn7(name, ["-version"], {
|
|
8645
|
+
stdio: ["ignore", "ignore", "ignore"],
|
|
8646
|
+
shell: useShell
|
|
8647
|
+
});
|
|
8648
|
+
let settled = false;
|
|
8649
|
+
const finish = (ok) => {
|
|
8650
|
+
if (settled) return;
|
|
8651
|
+
settled = true;
|
|
8652
|
+
resolve28(ok);
|
|
8653
|
+
};
|
|
8654
|
+
child.on("error", () => finish(false));
|
|
8655
|
+
child.on("exit", (code) => finish(code === 0));
|
|
8656
|
+
setTimeout(() => {
|
|
8657
|
+
if (!settled) {
|
|
8658
|
+
child.kill("SIGKILL");
|
|
8659
|
+
finish(false);
|
|
8660
|
+
}
|
|
8661
|
+
}, 3e3);
|
|
8662
|
+
});
|
|
8663
|
+
}
|
|
8664
|
+
async function chromiumInstalled2() {
|
|
8590
8665
|
try {
|
|
8591
8666
|
const { chromium: chromium6 } = await import("playwright-core");
|
|
8592
8667
|
const exec = chromium6.executablePath();
|
|
8593
8668
|
const { stat: stat17 } = await import("fs/promises");
|
|
8594
8669
|
await stat17(exec);
|
|
8595
|
-
return false;
|
|
8596
|
-
} catch {
|
|
8597
8670
|
return true;
|
|
8671
|
+
} catch {
|
|
8672
|
+
return false;
|
|
8598
8673
|
}
|
|
8599
8674
|
}
|
|
8600
8675
|
function parseStages(value) {
|