Skip to content

feat(cli): generate complete local speech WAV files - #5012

Closed
tang-vu wants to merge 3 commits into
Osmantic:public-betafrom
tang-vu:feat/beta-cli-local-speech-output-20260914
Closed

tang-vu wants to merge 3 commits into
Osmantic:public-betafrom
tang-vu:feat/beta-cli-local-speech-output-20260914

Conversation

@tang-vu

@tang-vu tang-vu commented Sep 14, 2026 •

Copy link
Copy Markdown
Contributor

Ready for independent review (2026-09-15). Candidate d156f21a16152cb48056dd86680a799b8995b344 has a successful GitHub check rollup and no base-branch conflict at this review snapshot. This supersedes earlier draft-status wording only. All validation gaps, migration requirements, live gates and independent human review requirements below remain in force; this is not a merge-ready approval.

Why this matters

Scripts can list local Kokoro voices and turn text or standard input into a complete WAV using the installed ods CLI, without an SDK or hand-written JSON. The shared Linux/WSL CLI gains ods tts voices and ods tts speak TEXT OUTPUT.wav [--voice VOICE], help, completion and concrete usage documentation.

Contract and design

  • Read the installed quoted TTS_PORT through the existing safe environment loader. Send literal Unicode/text only to 127.0.0.1; preserve output paths relative to the caller. No redirects, automatic service start or audio playback.
  • The exact shipped Kokoro v0.2.4 writer reads its buffer before closing the WAV container, leaving incomplete header lengths even with stream=false. The real-image test caught this. Request documented 24 kHz mono signed 16-bit PCM and create a finalized WAV header locally with Python's standard library.
  • Bound text to 10,000 characters, response bytes to 64 MiB and socket operations to five minutes. Require successful HTTP and PCM content type, a complete declared HTTP body, nonempty audio and complete samples. Errors publish no output.
  • Write/fsync a private temporary file and publish it via a same-directory hard link, which atomically refuses to overwrite a pre-existing file or a concurrent writer's file. The output filesystem must support hard links. This requires Python 3; the separately generated native macOS CLI is unchanged.
  • Handoff: CLI arguments/stdin + installed .env -> loopback Kokoro request -> complete PCM response -> finalized WAV -> private atomic file publication. Rollback removes the subcommands/helper; previously generated WAVs remain ordinary files.

Overlap check

Searched open/closed PRs for TTS CLI, speech CLI, synthesis and voice discovery, plus the changed CLI/completion paths and new helper/test filenames. #2499 is an n8n voice workflow; #4976 adds the complementary STT transcription command. #2832 owns TTS server memory/temp-storage tuning and the existing README voice-route correction; those hunks are intentionally excluded here. #2183 owns broader completion parity, and integration must preserve both its existing commands and this new tts command. No existing CLI speech-file client was found.

Validation

  • Candidate d156f21a: real CPU synthesis 1 passed in 509.14 seconds (25-live-pcm) on Linux amd64 under WSL; generated WAV has complete 24 kHz mono 16-bit frames, a nonzero signal and mode 0600.
  • Red public-CLI regression before implementation: command dispatch did not exist. Final HTTP/filesystem boundary suite: 10 passed, including literal special characters, quoted CRLF configuration, relative paths, standard input/default/custom voices, existing/concurrently created outputs, HTTP errors/redirect refusal, wrong media type, incomplete HTTP body, empty/partial PCM, invalid ports/arguments and registered completion.
  • The opt-in exact-image test uses ghcr.io/remsky/kokoro-fastapi-cpu:v0.2.4@sha256:c8812546d358cbfd6a5c4087a28795b2b001d8e32d7a322eedd246e6bc13cb55, retaining the production two workers, 1 CPU and 4 GiB recipe. It checks actual voice discovery, synthesis through the CLI, WAV framing/sample rate/nonzero signal, file mode and cleanup.
  • Initial default-health run failed during cold worker initialization. The client fixture now grants a 300-second startup grace; it does not validate the shipped 30-second grace. The next live run exposed the upstream WAV header defect, which led to the PCM implementation above. No success is claimed for either failed run.
  • ShellCheck, scoped hooks and git diff --check passed. Full local make gate still fails the pre-existing no-sudo Docker promotion/raw-sudo contract covered by fix(installer): honor unavailable sudo in Docker fallback #3158; no full local gate pass is claimed. A path-filtered workflow runs both boundary and real-image synthesis tests.

Review and limits

Latest-head CI: 33 successful checks, 4 conditionally skipped, including real CPU synthesis. Awaiting independent review. No GPU, native macOS/Windows, every voice/language, audio listening assessment, concurrent load or non-hard-link filesystem was tested. Valid PCM samples prove a structurally complete file, not speech quality or the semantic completeness of the server's spoken text.

Final candidate d156f21a16152cb48056dd86680a799b8995b344: 33 successful CI checks, 4 conditionally skipped; no pending or failed checks.

Batch integration receipt

This is one of 30 independently branched public-beta PRs. The published synthetic integration head is 61f4c6fccc81bea697f4941683fefb5089ba77f4, built from baseline d49ad4bbc760be319de7f4c9b9a93b1f18fe3922 in this reproducible order:

#4946 → #4948 → #4951 → #4954 → #4972 → #4960 → #4961 → #4957 → #4964 → #4967 → #4968 → #4971 → #4975 → #4976 → #4984 → #4982 → #4990 → #4988 → #4989 → #4997 → #5003 → #5006 → #5007 → #5009 → #5012 → #5011 → #5013 → #5014 → #5020 → #5021

Reconciliation preserved all 146 files owned by a single PR byte-for-byte against their exact candidate heads. The eight shared paths preserve both CLI STT/TTS commands and help, every added Makefile test, both environment schema additions and all Extensions UI behavior. LanguageTool and Kroki both remain headless API entries. Canonical regeneration yields 76 catalog entries and 47 library manifests; all README rows are retained. Shared-file changes need these additive resolutions when merged independently.

Combined validation: 2,852 API tests passed / 1 skipped; 1,082 UI tests passed; 47 manifests passed; all 12 added Makefile commands passed; 12 catalog boundary tests passed / 12 opt-in runtime tests skipped in this combined run. Individual exact-image results remain documented above. UI lint/build, scoped secret hooks, diff checks, four platform smoke tests and installer simulation passed. Compose plans for NVIDIA/AMD/Apple each contain 20 services and no duplicate published bindings across the core plus 12 new recipes; this is static plan evidence, not simultaneous startup or GPU inference.

The first unrestricted UI run timed out in two tests under concurrent load; the complete rerun used --maxWorkers=2 with unchanged assertions and timeouts and passed. ESLint reports zero errors and 603 warnings, including the existing JSX usage-detection pattern. Full local make gate still fails the no-sudo Docker baseline covered by #3158. BATS records 416 passed / 5 failed on this root/WSL host (platform detection, root preflight and a 15 GiB versus 20 GiB free-space expectation). Neither full local gate nor BATS is described as green.

This integration receipt supplements each PR's own regression and does not waive its independent review, live hardware/browser/upgrade gates or rollback requirements. The PRs remain drafts; none was merged upstream.

This was referenced Sep 14, 2026
@tang-vu
tang-vu marked this pull request as ready for review September 15, 2026 01:31
@Lightheartdevs

Copy link
Copy Markdown
Collaborator

Thanks for this contribution. public-beta was promoted into main on 2026-09-24 and no longer receives changes, so we're closing pull requests that target it. This isn't a judgment on the change itself. If it's still needed, please rebase onto main and open a focused PR. See #7253 for details and the contribution policy.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants