diff --git a/packages/cli/src/commands/coreSkillContent.test.ts b/packages/cli/src/commands/coreSkillContent.test.ts index 001eecb1c0..b283199a5e 100644 --- a/packages/cli/src/commands/coreSkillContent.test.ts +++ b/packages/cli/src/commands/coreSkillContent.test.ts @@ -24,3 +24,15 @@ describe("hyperframes-core contract docs", () => { expect(brief).not.toContain("`lint` / `validate` / `inspect`"); }); }); + +describe("media-use TTS documentation", () => { + it("does not advertise flags unsupported by the published tts command", () => { + const tts = read("skills", "media-use", "audio", "references", "tts.md"); + const captions = read("skills", "media-use", "audio", "references", "tts-to-captions.md"); + + expect(tts).not.toMatch(/hyperframes tts[^\n]*--provider/); + expect(tts).not.toMatch(/hyperframes tts[^\n]*--words/); + expect(captions).not.toMatch(/hyperframes tts[^\n]*--provider/); + expect(captions).toContain("heygen-tts.mjs"); + }); +}); diff --git a/skills-manifest.json b/skills-manifest.json index 4868c30dd2..15f3533d07 100644 --- a/skills-manifest.json +++ b/skills-manifest.json @@ -30,7 +30,7 @@ "files": 11 }, "hyperframes-core": { - "hash": "cf6e9f7827bc86d1", + "hash": "627ad77d778ec13d", "files": 17 }, "hyperframes-creative": { @@ -46,7 +46,7 @@ "files": 10 }, "media-use": { - "hash": "316e9a260f56b9df", + "hash": "675a735177b23d1b", "files": 133 }, "motion-graphics": { diff --git a/skills/hyperframes-core/references/script-format.md b/skills/hyperframes-core/references/script-format.md index 1946bf9a37..ad2b8ba470 100644 --- a/skills/hyperframes-core/references/script-format.md +++ b/skills/hyperframes-core/references/script-format.md @@ -46,4 +46,7 @@ A header block, then one section per spoken line. ## To TTS -Feed each line's spoken text to `npx hyperframes tts` (pin `--voice` / `--provider` from the header; capture word timestamps for captions). Real per-word timing replaces the `**Time:**` guides. CLI contract → `media-use/audio/references/tts.md`. +Feed each line's spoken text to the provider documented in +`media-use/audio/references/tts.md`. The `hyperframes tts` command is +Kokoro-only; use its `--voice` flag, or use the bundled HeyGen helper when word +timestamps are required. Real per-word timing replaces the `**Time:**` guides. diff --git a/skills/media-use/audio/references/tts-to-captions.md b/skills/media-use/audio/references/tts-to-captions.md index bad5f86eae..e11262cae2 100644 --- a/skills/media-use/audio/references/tts-to-captions.md +++ b/skills/media-use/audio/references/tts-to-captions.md @@ -4,10 +4,12 @@ When no recorded voiceover exists, generate one and obtain word-level caption ti ## Path A — HeyGen (single call, no Whisper) -HeyGen returns word timestamps in the same response as the audio. Pass `--words` and you're done: +HeyGen returns word timestamps in the same response as the audio. Use the +bundled REST helper (the `hyperframes tts` command is Kokoro-only): ```bash -npx hyperframes tts script.txt --provider heygen --output narration.wav --words narration.words.json +node skills/media-use/audio/scripts/heygen-tts.mjs \ + script.txt --output narration.wav --words narration.words.json ``` `narration.words.json` is already in the `[{ id, text, start, end }]` shape the captions pipeline consumes — no separate transcribe pass. diff --git a/skills/media-use/audio/references/tts.md b/skills/media-use/audio/references/tts.md index 8763d1b875..98f2878272 100644 --- a/skills/media-use/audio/references/tts.md +++ b/skills/media-use/audio/references/tts.md @@ -1,10 +1,12 @@ # Text To Speech -`npx hyperframes tts` auto-detects a provider from env vars; explicit override via `--provider`. +`npx hyperframes tts` synthesizes locally with Kokoro. It does not accept a +`--provider` or `--words` flag. For HeyGen audio plus word timestamps, use the +bundled `heygen-tts.mjs` script below. > **Run the Preflight first — no credential is not a green light to silently use the local voice.** Before generating a voiceover, complete the sign-in **Preflight** (see `../SKILL.md` → Preflight): run `npx hyperframes auth status`, recommend signing in, and **STOP for the user's choice** (sign in for HeyGen voices, or continue offline with local Kokoro). This applies to a one-off "generate a voiceover" request just as much as inside a full workflow. -## Provider chain +## Available routes | Order | Provider | Env trigger | Voice IDs | Word timestamps | Audio format | | ----- | ----------------- | ------------------------------------------- | ------------------------------------------- | ----------------------------------------- | -------------------- | @@ -13,16 +15,8 @@ | 3 | Kokoro-82M | always (local fallback) | `am_michael`, `af_heart`, … (54 voices) | No | wav direct | ```bash -# Auto-detect (HeyGen if key set, else ElevenLabs, else Kokoro) +# Local Kokoro CLI npx hyperframes tts "Welcome to HyperFrames" -o narration.wav - -# Pin the provider explicitly -npx hyperframes tts "Hello" --provider kokoro -npx hyperframes tts "Hello" --provider heygen --voice -npx hyperframes tts "Hello" --provider elevenlabs --voice 21m00Tcm4TlvDq8ikWAM - -# HeyGen path: capture word timestamps in one call (skips a Whisper pass) -npx hyperframes tts "Hi there" --words narration.words.json ``` ## Self-contained HeyGen (no CLI) — `scripts/heygen-tts.mjs` @@ -70,7 +64,11 @@ node skills/media-use/audio/scripts/heygen-tts.mjs --list # public starfish vo ## ffmpeg requirement -HeyGen + ElevenLabs return mp3. The CLI transcodes to wav when `--output` ends in `.wav` (the default and what downstream `ffprobe` + Whisper expect). If you'd rather skip the transcode, pass `-o file.mp3`. Without `ffmpeg` on PATH, `.wav` output from the cloud providers fails — install ffmpeg or use `.mp3`. +HeyGen + ElevenLabs return mp3. The bundled HeyGen helper transcodes to wav +when `--output` ends in `.wav` (the default and what downstream `ffprobe` + +Whisper expect). If you'd rather skip the transcode, pass `-o file.mp3`. +Without `ffmpeg` on PATH, wav output from cloud providers fails; the local +Kokoro CLI writes wav directly. ## Voice selection (Kokoro) @@ -103,8 +101,8 @@ The first letter of a Kokoro voice ID picks the phonemizer language; `--lang` ov | `z` | Mandarin | ```bash -npx hyperframes tts "La reunión empieza a las nueve" --voice ef_dora --provider kokoro -npx hyperframes tts "Today is a nice day" --voice af_heart --provider kokoro +npx hyperframes tts "La reunión empieza a las nueve" --voice ef_dora +npx hyperframes tts "Today is a nice day" --voice af_heart ``` Valid `--lang` codes (only needed to override the voice's auto-detected language): `en-us`, `en-gb`, `es`, `fr-fr`, `hi`, `it`, `pt-br`, `ja`, `zh`. @@ -118,7 +116,8 @@ Non-English phonemization requires `espeak-ng` system-wide (`brew install espeak - `1.1-1.2` — intros, transitions, upbeat content - `1.5+` — rarely appropriate, test carefully -Honored by Kokoro + HeyGen; ElevenLabs ignores `--speed` (use voice settings on their dashboard). +The `hyperframes tts` command honors `--speed` for Kokoro. Provider-specific +helpers document their own pacing controls. ## Long scripts