From dcda11a9248e1d24a67bdd9f6fd34fe112fb4a4b Mon Sep 17 00:00:00 2001 From: codeonym Date: Tue, 10 Nov 2026 17:37:00 +0000 Subject: [PATCH 1/2] feat: generate offline Qwen narration clips (#4) --- .github/workflows/ci.yml | 2 +- README.md | 28 +++- docker/Dockerfile | 9 +- docker/tts/assets.json | 72 +++++++++ docker/tts/download.py | 28 ++++ docker/tts/requirements.in | 5 + docker/tts/requirements.txt | 92 +++++++++++ docker/tts/worker.py | 67 ++++++++ package.json | 2 +- .../004-pluggable-tts-local-default.md | 2 + .../decisions/011-transcript-json-schema.md | 2 + ...26-11-10_1716_odd-viewport-encoder-hang.md | 17 ++ .../history/CHANGES.md | 1 + .../001-clips-and-metadata-in-gh4.md | 16 ++ .../002-qwen3-tts-06b-local-default.md | 21 +++ .../decisions/003-customvoice-ryan-english.md | 14 ++ .../decisions/004-local-adapter-only.md | 14 ++ .../005-official-python-cpu-runtime.md | 23 +++ .../006-skip-blank-narration-audio.md | 14 ++ ...007-demo-specific-portable-audio-folder.md | 13 ++ .../GH-4-tts-adapter-local-voice/draft.md | 48 ++++-- .../history/2026-11-10_1353_draft.md | 27 ++++ .../history/2026-11-10_1353_meta.md | 12 ++ .../history/2026-11-10_1358_meta.md | 12 ++ .../history/2026-11-10_1423_impl.md | 110 +++++++++++++ .../history/2026-11-10_1735_impl.md | 126 +++++++++++++++ .../history/CHANGES.md | 13 ++ .../GH-4-tts-adapter-local-voice/impl.md | 146 ++++++++++++++++++ .../GH-4-tts-adapter-local-voice/meta.md | 6 +- src/runner/run.ts | 32 ++-- src/runner/tts.ts | 79 ++++++++++ test/e2e/record.test.ts | 67 ++++++-- test/e2e/tts.test.ts | 55 +++++++ test/unit/tts.test.ts | 97 ++++++++++++ 34 files changed, 1223 insertions(+), 49 deletions(-) create mode 100644 docker/tts/assets.json create mode 100644 docker/tts/download.py create mode 100644 docker/tts/requirements.in create mode 100644 docker/tts/requirements.txt create mode 100644 docker/tts/worker.py create mode 100644 planning/GH-1-narrated-reproducible-feature-demos/tickets/GH-2-silent-replay-recording-sandbox/follow-ups/2026-11-10_1716_odd-viewport-encoder-hang.md create mode 100644 planning/GH-1-narrated-reproducible-feature-demos/tickets/GH-4-tts-adapter-local-voice/decisions/001-clips-and-metadata-in-gh4.md create mode 100644 planning/GH-1-narrated-reproducible-feature-demos/tickets/GH-4-tts-adapter-local-voice/decisions/002-qwen3-tts-06b-local-default.md create mode 100644 planning/GH-1-narrated-reproducible-feature-demos/tickets/GH-4-tts-adapter-local-voice/decisions/003-customvoice-ryan-english.md create mode 100644 planning/GH-1-narrated-reproducible-feature-demos/tickets/GH-4-tts-adapter-local-voice/decisions/004-local-adapter-only.md create mode 100644 planning/GH-1-narrated-reproducible-feature-demos/tickets/GH-4-tts-adapter-local-voice/decisions/005-official-python-cpu-runtime.md create mode 100644 planning/GH-1-narrated-reproducible-feature-demos/tickets/GH-4-tts-adapter-local-voice/decisions/006-skip-blank-narration-audio.md create mode 100644 planning/GH-1-narrated-reproducible-feature-demos/tickets/GH-4-tts-adapter-local-voice/decisions/007-demo-specific-portable-audio-folder.md create mode 100644 planning/GH-1-narrated-reproducible-feature-demos/tickets/GH-4-tts-adapter-local-voice/history/2026-11-10_1353_draft.md create mode 100644 planning/GH-1-narrated-reproducible-feature-demos/tickets/GH-4-tts-adapter-local-voice/history/2026-11-10_1353_meta.md create mode 100644 planning/GH-1-narrated-reproducible-feature-demos/tickets/GH-4-tts-adapter-local-voice/history/2026-11-10_1358_meta.md create mode 100644 planning/GH-1-narrated-reproducible-feature-demos/tickets/GH-4-tts-adapter-local-voice/history/2026-11-10_1423_impl.md create mode 100644 planning/GH-1-narrated-reproducible-feature-demos/tickets/GH-4-tts-adapter-local-voice/history/2026-11-10_1735_impl.md create mode 100644 planning/GH-1-narrated-reproducible-feature-demos/tickets/GH-4-tts-adapter-local-voice/impl.md create mode 100644 src/runner/tts.ts create mode 100644 test/e2e/tts.test.ts create mode 100644 test/unit/tts.test.ts diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b272516..e395f4b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -8,7 +8,7 @@ on: jobs: test: runs-on: ubuntu-latest - timeout-minutes: 30 + timeout-minutes: 45 steps: - uses: actions/checkout@v5 - uses: actions/setup-node@v5 diff --git a/README.md b/README.md index eb93935..116cefc 100644 --- a/README.md +++ b/README.md @@ -4,8 +4,8 @@ Record reproducible feature demos from a short Playwright script. A coding agent writes the script, and `flow-reel` replays it in a sandbox on a virtual display while recording the screen. The same script gives the same video, step for step. -This release records **silent** video with narration text, captions and step timings. Voice, cursor and zoom polish, -and sound effects come in later releases. +This release records **silent** video with narration text, captions, step timings and separate speech clips. +Fitting and mixing the speech into the MP4, cursor and zoom polish, and sound effects come in later releases. ## Requirements @@ -14,6 +14,8 @@ and sound effects come in later releases. pulled, `flow-reel` builds it locally once (a few minutes). - About 2.5 free CPU cores while recording. On an overloaded machine the recording stops with an error rather than save a video whose timing is off. +- The image is about 7 GB unpacked; its build downloads about 2.5 GB of model weights. Local speech synthesis uses + four CPU threads after capture and can require more than 5 GiB of process memory, in addition to your app and OS. ## Install @@ -62,12 +64,30 @@ Next to the script: | `settings.events.json` | Every move, click, keystroke run and scroll the runner made, timed the same way (schema version 1). | | `settings.srt` | Captions for a subtitle-capable video player. | | `settings.vtt` | WebVTT captions for a browser's `