@mineo71/showtime 0.2.1 → 0.4.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/CHANGELOG.md +32 -0
- package/README.md +155 -19
- package/docs/script.schema.json +395 -0
- package/package.json +1 -1
- package/skill/SKILL.md +70 -13
- package/src/audio/decode.ts +19 -0
- package/src/audio/mix.ts +72 -0
- package/src/audio/sfx.ts +55 -0
- package/src/audio/soundtrack.ts +49 -0
- package/src/audio/tts.ts +186 -0
- package/src/audio/wav.ts +96 -0
- package/src/cli/format.ts +10 -0
- package/src/cli/main.ts +125 -40
- package/src/convert.ts +48 -0
- package/src/ffmpeg.ts +21 -0
- package/src/lint.ts +128 -0
- package/src/logo.ts +20 -0
- package/src/paths.ts +19 -0
- package/src/pipeline.ts +97 -19
- package/src/render/remotion/Intro.tsx +3 -1
- package/src/render/remotion/Logo.tsx +6 -0
- package/src/render/remotion/Outro.tsx +38 -0
- package/src/render/remotion/Overlays.tsx +41 -16
- package/src/render/remotion/ShowtimeVideo.tsx +56 -18
- package/src/render/render.ts +1 -1
- package/src/runner/browser.ts +47 -6
- package/src/runner/check.ts +10 -1
- package/src/runner/events.ts +2 -0
- package/src/runner/hooks.ts +111 -0
- package/src/runner/record.ts +53 -34
- package/src/runner/steps.ts +4 -1
- package/src/script/config.ts +74 -0
- package/src/script/hash.ts +7 -1
- package/src/script/load.ts +15 -2
- package/src/script/schema.ts +115 -1
- package/src/setup.ts +13 -4
- package/src/sheet.ts +47 -0
- package/src/timeline/build.ts +113 -13
- package/src/timeline/camera.ts +34 -11
- package/src/timeline/fades.ts +3 -0
- package/src/timeline/frames.ts +15 -4
- package/src/timeline/layout.ts +70 -0
- package/src/timeline/narration.ts +160 -0
- package/src/timeline/timemap.ts +40 -5
- package/src/timeline/types.ts +44 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,37 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.4.0 — 2026-10-13
|
|
4
|
+
|
|
5
|
+
- Narration: `show.say` on any step is spoken by a TTS engine (`audio.voice`: the macOS/Linux
|
|
6
|
+
system voice, OpenAI, ElevenLabs or any command). The video holds the frame until a line ends.
|
|
7
|
+
Lines are cached; editing them needs no new take.
|
|
8
|
+
- `audio.music`: a looped music bed that ducks under the voice. `audio.sounds`: click and
|
|
9
|
+
keystroke sounds (takes now log keystrokes; older takes spread them over each `type` step).
|
|
10
|
+
- Subtitles from the narration: an `.srt` next to the video, or burned in (`audio.subtitles`).
|
|
11
|
+
- `--aspect 9:16 | 1:1` on `render`, `make` and `frames`: cropped cuts with a camera that follows
|
|
12
|
+
the action, from the same take. Stills of a crop go to `frames-9x16/` or `frames-1x1/`.
|
|
13
|
+
- `--format gif | webp` (or an `-o` with that extension) and `--width`; `--no-audio`. Silent
|
|
14
|
+
outputs skip narration (no voice needed) unless subtitles are burned in.
|
|
15
|
+
- `render --json` adds `subtitles`; the brand file accepts `audio`.
|
|
16
|
+
- `lint`: `narration-stretch` flags lines that hold the frame for long.
|
|
17
|
+
|
|
18
|
+
## 0.3.0 — 2026-10-13
|
|
19
|
+
|
|
20
|
+
- `showtime frames` also renders a contact sheet (`frames/sheet.png`) of every step.
|
|
21
|
+
- `showtime lint`: long captions, pauses that should be waits, zoom/spotlight that cannot apply,
|
|
22
|
+
and, with a take, captions too brief to read and overall length.
|
|
23
|
+
- `--json` on every command.
|
|
24
|
+
- `hooks.before` / `hooks.after`: shell commands or HTTP calls around every `check` and `record`,
|
|
25
|
+
so state can be reset between rehearsal and take.
|
|
26
|
+
- `app.mock` (canned responses for matching requests), `app.clock` (the page clock starts at a fixed date),
|
|
27
|
+
`app.dialogs` (accept or dismiss native dialogs; accepted by default).
|
|
28
|
+
- Safe re-takes: a failed `record` leaves the previous take untouched (`take.tmp` keeps the failure).
|
|
29
|
+
- Settling ignores event streams; relative `goto` URLs resolve against `app.url`.
|
|
30
|
+
- Captions never overlap, and move to the top when the action is at the bottom of the screen.
|
|
31
|
+
- `meta.outro` closing card and `meta.logo` on the intro and outro cards.
|
|
32
|
+
- `showtime.config.json` brand file with default `style` and `meta` for every script below it.
|
|
33
|
+
- Takes recorded with 0.2 stay valid.
|
|
34
|
+
|
|
3
35
|
## 0.2.1 — 2026-10-13
|
|
4
36
|
|
|
5
37
|
- Releases are automated: `npm version patch|minor|major` dates the changelog, tags and pushes;
|
package/README.md
CHANGED
|
@@ -8,7 +8,8 @@
|
|
|
8
8
|
|
|
9
9
|
Your AI agent (Claude Code or Codex) writes a short JSON script. showTime clicks through your web app, films it and edits it
|
|
10
10
|
the way a motion designer would (auto-zoom, a smooth cursor, click ripples, spotlights, captions,
|
|
11
|
-
sped-up loading) and hands you a polished 1080p MP4
|
|
11
|
+
sped-up loading, narration) and hands you a polished video: a 1080p MP4, a 9:16 cut for social or
|
|
12
|
+
a GIF for your README.<br />
|
|
12
13
|
No timeline editor. No re-take when a caption changes.
|
|
13
14
|
|
|
14
15
|
[](https://github.com/mineo71/showTime/actions/workflows/ci.yml)
|
|
@@ -26,7 +27,7 @@ No timeline editor. No re-take when a caption changes.
|
|
|
26
27
|
<div align="center">
|
|
27
28
|
<a href="docs/media/demo.mp4"><img src="docs/media/hero.webp" width="860" alt="A demo of a fictional invoicing app, filmed and edited by showTime: the camera zooms on a chart, a cursor fills in a new invoice, a spotlight lands on the total, and the sent invoice appears in the table" /></a>
|
|
28
29
|
<br />
|
|
29
|
-
<sub>Made by <a href="examples/fennel/demo.json">
|
|
30
|
+
<sub>Made by <a href="examples/fennel/demo.json">a 39-line script</a>, a <a href="examples/fennel/showtime.config.json">brand file</a> and one command, with no manual editing. <a href="docs/media/demo.mp4">▶ Full-quality MP4, with sound</a></sub>
|
|
30
31
|
</div>
|
|
31
32
|
|
|
32
33
|
---
|
|
@@ -121,7 +122,40 @@ again.
|
|
|
121
122
|
<td valign="top">
|
|
122
123
|
<img src="docs/media/intro.jpg" alt="Intro card with title and subtitle" /><br />
|
|
123
124
|
<b>🎬 Intro card and window chrome</b><br />
|
|
124
|
-
<sub>Title card, a browser frame with your URL, a gradient backdrop, rounded corners and a shadow. Each of them is a <code>style</code> field.</sub>
|
|
125
|
+
<sub>Title card with your logo, a browser frame with your URL, a gradient backdrop, rounded corners and a shadow. Each of them is a <code>style</code> or <code>meta</code> field.</sub>
|
|
126
|
+
</td>
|
|
127
|
+
</tr>
|
|
128
|
+
<tr>
|
|
129
|
+
<td valign="top">
|
|
130
|
+
<pre lang="json">
|
|
131
|
+
"show": { "say": "Send it before lunch." }
|
|
132
|
+
|
|
133
|
+
"audio": {
|
|
134
|
+
"voice": { "engine": "openai", "name": "nova" },
|
|
135
|
+
"music": { "file": "bed.mp3" },
|
|
136
|
+
"sounds": true,
|
|
137
|
+
"subtitles": "burn"
|
|
138
|
+
}
|
|
139
|
+
</pre>
|
|
140
|
+
<b>🎙️ Narration, music and clicks</b><br />
|
|
141
|
+
<sub>Give a step a line and a voice reads it: the built-in voice of macOS or Linux, OpenAI, ElevenLabs or any TTS command. The video holds the frame until the line ends, music ducks under the voice, and subtitles come as an <code>.srt</code> or burned in.</sub>
|
|
142
|
+
</td>
|
|
143
|
+
<td valign="top">
|
|
144
|
+
<img src="docs/media/formats.jpg" alt="The same moment in 16:9, 9:16 and 1:1" /><br />
|
|
145
|
+
<b>📱 Every format from one take</b><br />
|
|
146
|
+
<sub><code>--aspect 9:16</code> or <code>1:1</code> crops the window and a follow camera keeps the action in view. <code>--format gif</code> or <code>webp</code> for READMEs and docs. Nothing is re-recorded.</sub>
|
|
147
|
+
</td>
|
|
148
|
+
</tr>
|
|
149
|
+
<tr>
|
|
150
|
+
<td valign="top">
|
|
151
|
+
<img src="docs/media/outro.jpg" alt="Outro card with logo, title and URL" /><br />
|
|
152
|
+
<b>📣 Ends on your call to action</b><br />
|
|
153
|
+
<sub>An outro card with your logo, a headline and the URL to visit. Put it in a brand file once and every demo ends the same way.</sub>
|
|
154
|
+
</td>
|
|
155
|
+
<td valign="top">
|
|
156
|
+
<img src="docs/media/sheet.jpg" alt="Contact sheet of every step" /><br />
|
|
157
|
+
<b>🧪 Reviews its own work</b><br />
|
|
158
|
+
<sub><code>showtime frames</code> renders a contact sheet of every step, and <code>showtime lint</code> flags captions that are too long or too brief to read. The agent fixes them before you look.</sub>
|
|
125
159
|
</td>
|
|
126
160
|
</tr>
|
|
127
161
|
</table>
|
|
@@ -132,8 +166,16 @@ And under the hood:
|
|
|
132
166
|
When a step fails it prints an ARIA snapshot of the page, so Claude can fix its own selectors.
|
|
133
167
|
- 🔁 **Stale-take detection.** The take stores a hash of the actions. Edit a caption and `render`
|
|
134
168
|
reuses the take. Edit a click and `render` tells you to `record` again.
|
|
135
|
-
-
|
|
136
|
-
|
|
169
|
+
- 🧹 **Clean state for every take.** `hooks` run a reset command or call an endpoint before and
|
|
170
|
+
after each rehearsal and take, so a flow that creates data works twice in a row.
|
|
171
|
+
- 🎭 **Deterministic pages.** `app.mock` answers flaky or slow APIs with canned JSON, `app.clock`
|
|
172
|
+
pins the date, and `app.dialogs` answers `confirm()` the way the demo needs.
|
|
173
|
+
- 🎨 **One brand file.** `showtime.config.json` holds your colours, logo and outro; every script
|
|
174
|
+
below it inherits them.
|
|
175
|
+
- 🛟 **Safe re-takes.** A take that fails halfway leaves the last good one untouched.
|
|
176
|
+
- 🤖 **JSON everywhere.** Every command takes `--json`, so agents read results instead of parsing
|
|
177
|
+
prose. Captions also move to the top on their own when the action happens at the bottom of the
|
|
178
|
+
screen.
|
|
137
179
|
- 📐 **Typed scripts.** Point `"$schema"` at [`docs/script.schema.json`](docs/script.schema.json)
|
|
138
180
|
for autocomplete and validation in your editor.
|
|
139
181
|
- 🖥️ **Crisp at 1080p.** The app is captured at 2× device scale, so zoomed shots stay sharp.
|
|
@@ -169,7 +211,8 @@ The agent takes it from there:
|
|
|
169
211
|
3. **Rehearses** with `showtime check` until every step passes, fixing selectors from the ARIA
|
|
170
212
|
snapshot.
|
|
171
213
|
4. **Records and renders** with `showtime record` and `showtime render`.
|
|
172
|
-
5. **Reviews** the
|
|
214
|
+
5. **Reviews** the contact sheet from `showtime frames` and the warnings from `showtime lint`,
|
|
215
|
+
tightens captions and pacing, and re-renders.
|
|
173
216
|
|
|
174
217
|
The skill ([`skill/SKILL.md`](skill/SKILL.md)) is a plain-Markdown
|
|
175
218
|
[Agent Skill](https://agentskills.io). Any agent that can run shell commands can follow it, and so
|
|
@@ -185,16 +228,19 @@ flowchart LR
|
|
|
185
228
|
R --> E["events.json<br/>targets · clicks · idle"]
|
|
186
229
|
S --> T["timeline.json<br/>camera · cursor · captions · speed"]
|
|
187
230
|
E --> T
|
|
231
|
+
T --> A["mix.wav<br/>voice · music · clicks"]
|
|
188
232
|
T --> M["Remotion"]
|
|
233
|
+
A --> M
|
|
189
234
|
V --> M
|
|
190
|
-
M --> O["demo.mp4"]
|
|
235
|
+
M --> O["demo.mp4 · 9:16 · GIF"]
|
|
191
236
|
```
|
|
192
237
|
|
|
193
238
|
The core idea is to **separate capture from direction**. `record` drives a real Chromium through
|
|
194
239
|
the script and writes two things: a clean video with no cursor, and an event log of where every
|
|
195
240
|
target was, when each click landed and when the page sat idle. A pure function,
|
|
196
241
|
`buildTimeline(script, events)`, turns that log into speed segments, camera keyframes, cursor
|
|
197
|
-
paths, captions and spotlights
|
|
242
|
+
paths, captions and spotlights, and holds the frame wherever a narration line needs more time.
|
|
243
|
+
The soundtrack is mixed from the same timeline, and Remotion renders the result frame by frame.
|
|
198
244
|
|
|
199
245
|
So presentation is cheap to change and recording stays honest: the app really is clicked, typed
|
|
200
246
|
into and waited on, and everything cinematic is computed afterwards.
|
|
@@ -224,8 +270,9 @@ into and waited on, and everything cinematic is computed afterwards.
|
|
|
224
270
|
}
|
|
225
271
|
```
|
|
226
272
|
|
|
227
|
-
`meta.title` adds an intro card
|
|
228
|
-
|
|
273
|
+
`meta.title` adds an intro card, `meta.outro` a closing card and `meta.logo` puts your logo on
|
|
274
|
+
both. `setup` steps run before the camera starts (cookie banners, onboarding). Scenes group steps
|
|
275
|
+
for readability and for naming the stills.
|
|
229
276
|
|
|
230
277
|
<details>
|
|
231
278
|
<summary><b>Actions</b> (<code>do</code>)</summary>
|
|
@@ -257,6 +304,7 @@ Targets are Playwright selectors: `role=button[name='Save']`, `text=Save`, `#id`
|
|
|
257
304
|
| `spotlight` | boolean | dim everything except the target |
|
|
258
305
|
| `hold` | ms | extra real time after the step (changes the take) |
|
|
259
306
|
| `speed` | 0.25–16 | playback speed for this step |
|
|
307
|
+
| `say` | string | narration spoken from the start of the step; the next narrated step waits for it |
|
|
260
308
|
|
|
261
309
|
</details>
|
|
262
310
|
|
|
@@ -291,6 +339,83 @@ Targets are Playwright selectors: `role=button[name='Save']`, `text=Save`, `#id`
|
|
|
291
339
|
| `colorScheme` | none | `light` or `dark`; also picks the browser-bar theme |
|
|
292
340
|
| `locale`, `timezoneId` | none | passed to the browser context |
|
|
293
341
|
| `mask` | `[]` | CSS selectors to blur (plain CSS, not `text=`) |
|
|
342
|
+
| `mock` | `[]` | `[{ url, method?, status?, json? \| body?, headers?, delayMs? }]`: answer matching requests (`url` is a glob like `**/api/stats*`; the first match wins) |
|
|
343
|
+
| `clock` | none | start the page clock at this ISO date-time; it then runs normally |
|
|
344
|
+
| `dialogs` | `accept` | answer `alert`/`confirm`/`prompt` with `accept` or `dismiss` |
|
|
345
|
+
|
|
346
|
+
</details>
|
|
347
|
+
|
|
348
|
+
<details>
|
|
349
|
+
<summary><b>Sound</b> (<code>audio</code>)</summary>
|
|
350
|
+
|
|
351
|
+
```json
|
|
352
|
+
"audio": {
|
|
353
|
+
"voice": { "engine": "system", "name": "Samantha", "speed": 1 },
|
|
354
|
+
"music": { "file": "music/bed.mp3", "volume": 0.25 },
|
|
355
|
+
"sounds": true,
|
|
356
|
+
"subtitles": "file"
|
|
357
|
+
}
|
|
358
|
+
```
|
|
359
|
+
|
|
360
|
+
| field | default | |
|
|
361
|
+
|----------------------|------------|-|
|
|
362
|
+
| `voice.engine` | `system` | `system` (macOS `say`, Linux `espeak-ng`), `openai`, `elevenlabs`, or `command` |
|
|
363
|
+
| `voice.name` | engine default | voice name (`system`, `openai`), or voice id (`elevenlabs`, required) |
|
|
364
|
+
| `voice.speed` | `1` | 0.5–2 |
|
|
365
|
+
| `voice.model` | engine default | `gpt-4o-mini-tts` (OpenAI), `eleven_multilingual_v2` (ElevenLabs) |
|
|
366
|
+
| `voice.instructions` | none | OpenAI only: how to speak ("warm, confident") |
|
|
367
|
+
| `voice.command` | none | `command` only: a shell command that reads the text on stdin and writes audio to `{out}` (inserted already quoted, so write it bare; also in `$SHOWTIME_OUT`), e.g. `piper -m en_US.onnx -f {out}` |
|
|
368
|
+
| `music` | none | `{ file, volume? }`: a bed under the whole video, looped and ducked under the voice |
|
|
369
|
+
| `sounds` | `false` | click and keystroke sounds |
|
|
370
|
+
| `subtitles` | `file` | `file`: an `.srt` next to the video; `burn`: also on the video (captions move up); `off` |
|
|
371
|
+
|
|
372
|
+
`openai` and `elevenlabs` read `OPENAI_API_KEY` / `ELEVENLABS_API_KEY` from the environment
|
|
373
|
+
(`OPENAI_BASE_URL` points at any OpenAI-compatible server). Each line is synthesized once and
|
|
374
|
+
cached; edits to `say` or `audio` only need `render`. Silent outputs (GIF, WebP, `--no-audio`) skip
|
|
375
|
+
the narration and its pauses, unless subtitles are burned in.
|
|
376
|
+
|
|
377
|
+
</details>
|
|
378
|
+
|
|
379
|
+
<details>
|
|
380
|
+
<summary><b>Cards</b> (<code>meta</code>)</summary>
|
|
381
|
+
|
|
382
|
+
| field | |
|
|
383
|
+
|------------|-|
|
|
384
|
+
| `title`, `subtitle` | intro card |
|
|
385
|
+
| `logo` | SVG, PNG, JPEG or WebP (≤ 2 MB), relative to the file that names it; shown on the intro and outro |
|
|
386
|
+
| `outro` | `{ title, subtitle?, url? }`: closing card after the video |
|
|
387
|
+
|
|
388
|
+
</details>
|
|
389
|
+
|
|
390
|
+
<details>
|
|
391
|
+
<summary><b>Hooks</b> (<code>hooks</code>)</summary>
|
|
392
|
+
|
|
393
|
+
```json
|
|
394
|
+
"hooks": {
|
|
395
|
+
"before": [{ "run": "npm run db:reset" }],
|
|
396
|
+
"after": [{ "request": { "url": "http://localhost:3000/api/test/reset", "method": "POST" } }]
|
|
397
|
+
}
|
|
398
|
+
```
|
|
399
|
+
|
|
400
|
+
`before` hooks run at the start of every `check` and `record` (so `make` resets between the
|
|
401
|
+
rehearsal and the take); `after` hooks run when they end, even after a failure, and a failing
|
|
402
|
+
`after` hook is a warning that never costs you the take. `run` is a shell
|
|
403
|
+
command in the script's folder (120 s timeout); `request` is an HTTP call that must answer 2xx.
|
|
404
|
+
|
|
405
|
+
</details>
|
|
406
|
+
|
|
407
|
+
<details>
|
|
408
|
+
<summary><b>Brand file</b> (<code>showtime.config.json</code>)</summary>
|
|
409
|
+
|
|
410
|
+
Put it next to your scripts or in any folder above them; the nearest one applies. Its `style`,
|
|
411
|
+
`meta` and `audio` are defaults, and a script's own fields win key by key.
|
|
412
|
+
|
|
413
|
+
```json
|
|
414
|
+
{
|
|
415
|
+
"style": { "background": "linear-gradient(135deg, #0f172a, #312e81)", "accent": "#6366f1", "address": "app.acme.com" },
|
|
416
|
+
"meta": { "logo": "brand/logo.svg", "outro": { "title": "Try Acme free", "url": "acme.com" } }
|
|
417
|
+
}
|
|
418
|
+
```
|
|
294
419
|
|
|
295
420
|
</details>
|
|
296
421
|
|
|
@@ -299,14 +424,17 @@ Targets are Playwright selectors: `role=button[name='Save']`, `text=Save`, `#id`
|
|
|
299
424
|
| command | what it does |
|
|
300
425
|
|---|---|
|
|
301
426
|
| `showtime setup [--agent claude\|codex\|all] [--no-browsers]` | download the browsers, link the skill |
|
|
302
|
-
| `showtime make <script> [
|
|
427
|
+
| `showtime make <script> [render options]` | check → record → render |
|
|
303
428
|
| `showtime check <script> [--json] [--headed]` | rehearse; a screenshot per step; the first failure with an ARIA snapshot |
|
|
304
429
|
| `showtime record <script> [--headed] [--keep-frames]` | record a take into `.showtime/<name>/take` |
|
|
305
|
-
| `showtime render <script> [-o out
|
|
306
|
-
| `showtime frames <script
|
|
430
|
+
| `showtime render <script> [-o out] [--aspect 16:9\|9:16\|1:1] [--format mp4\|gif\|webp] [--width px] [--no-audio]` | render from the last take, without re-recording |
|
|
431
|
+
| `showtime frames <script> [--aspect …]` | QA stills (intro, one per step, outro) and a contact sheet of them |
|
|
432
|
+
| `showtime lint <script>` | warnings about captions, pauses and length; timing checks need a take |
|
|
307
433
|
| `showtime schema` | print the script's JSON Schema |
|
|
308
434
|
|
|
309
|
-
|
|
435
|
+
Every command takes `--json` and then prints exactly one JSON document. The video lands next to
|
|
436
|
+
the script (`demo/pitch.json` → `demo/pitch.mp4`, `demo/pitch-9x16.mp4`, `demo/pitch.gif`), with
|
|
437
|
+
`demo/pitch.srt` when it is narrated. Working files live in
|
|
310
438
|
`.showtime/<name>/`, which is worth adding to your `.gitignore`.
|
|
311
439
|
|
|
312
440
|
## Tips for a great demo
|
|
@@ -317,15 +445,22 @@ The video lands next to the script (`demo/pitch.json` → `demo/pitch.mp4`). Wor
|
|
|
317
445
|
`spotlight` on the one number that sells it.
|
|
318
446
|
- **Never `pause` for loading.** Use `wait` with a selector and auto-speed compresses the spinner.
|
|
319
447
|
- **Start clean.** Use `setup` for cookie banners, `app.storageState` to skip the login, `app.mask`
|
|
320
|
-
for anything personal, and
|
|
448
|
+
for anything personal, and `hooks` to reset the data between `check` and `record`.
|
|
449
|
+
- **Pin the world.** Mock slow or random APIs with `app.mock` and pin the date with `app.clock`,
|
|
450
|
+
so every take looks the same.
|
|
451
|
+
- **Narrate the why, not the clicks.** One short sentence per moment. If `showtime lint` says a
|
|
452
|
+
line holds the frame for seconds, shorten it or give the step more to show.
|
|
321
453
|
|
|
322
454
|
## FAQ
|
|
323
455
|
|
|
324
456
|
**Which apps does it work with?** Any web app Chromium can open: a localhost dev server, staging
|
|
325
457
|
or production. Logged-in flows work through `app.storageState`.
|
|
326
458
|
|
|
327
|
-
**Does showTime call an AI model?**
|
|
328
|
-
|
|
459
|
+
**Does showTime call an AI model?** Not for directing: the AI part (writing, fixing and reviewing
|
|
460
|
+
the script) happens in your agent, guided by the skill. Narration is text-to-speech. The built-in
|
|
461
|
+
voice of macOS or Linux needs no key and nothing leaves your machine; with `openai` or
|
|
462
|
+
`elevenlabs`, only the narration text is sent to that provider, with your key from the
|
|
463
|
+
environment.
|
|
329
464
|
|
|
330
465
|
**Why not just screen-record?** You can, once. A screen recording can't be re-edited when the copy
|
|
331
466
|
changes, the cursor is wherever your hand was, and the spinner plays at full length. With
|
|
@@ -336,8 +471,9 @@ needs Playwright and ffmpeg. Windows is untested.
|
|
|
336
471
|
|
|
337
472
|
## Roadmap
|
|
338
473
|
|
|
339
|
-
-
|
|
340
|
-
|
|
474
|
+
- 🧑🎨 `showtime studio`: a local page with a live player and a timeline to drag captions, zooms and
|
|
475
|
+
speed, saving back to the JSON.
|
|
476
|
+
- 🎥 `showtime record-human <url>`: click through the app yourself and get a script back.
|
|
341
477
|
- 🎞️ Deterministic frame-by-frame capture in virtual time, for a perfect 60 fps.
|
|
342
478
|
- 🧩 An MCP server for Claude Desktop, and a desktop studio for timeline tweaks.
|
|
343
479
|
- 📲 Mobile (iOS Simulator) and desktop-app drivers that produce the same `events.json`.
|