mirror of
https://github.com/heygen-com/hyperframes.git
synced 2026-09-04 07:19:52 +00:00
2ceb0683a8c1e515867cc159621b1d32510f2230
7
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
995db68ad0 |
fix(cli): map zh to espeak-ng's cmn for Kokoro TTS synthesis (#2094)
* fix(cli): map zh to espeak-ng's cmn for Kokoro TTS synthesis espeak-ng 1.52.0 recognizes Mandarin Chinese as the ISO 639-3 code "cmn", not Kokoro's own voice-prefix convention "zh". `hyperframes tts --lang zh` was forwarding "zh" straight through to kokoro_onnx.Kokoro.create(), which failed with "language zh is not supported by espeak backend". Translate only at the Python/espeak boundary; the public --lang value stays "zh" since that matches Kokoro's own docs and voice-ID prefixes. * test(cli): cover Kokoro zh language override |
||
|
|
8c3590a90e | feat(cli): parakeet ASR engine for transcribe (--engine) + HYPERFRAMES_PYTHON override | ||
|
|
54cab331d0 |
feat(cli): shared TTS/BGM auth preflight + caption and skill-workflow fixes (#1697)
* fix: handle caption skin workflow * docs(skills): simplify the finalize step across video workflows - Drop --strict-layout; all skills use plain `hyperframes inspect` - Add the caption text_box_overflow false-positive note to faceless-explainer - On a failed check, the orchestrator makes the cheapest safe edit itself (no worker re-dispatch / Step 3 backtrack language) - Snapshot: glance at the stitched contact-sheet.jpg and move on Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * feat(auth): onboarding-first `auth status` + shared TTS/BGM preflight When no HeyGen credential is configured, `hyperframes auth status` now prints registration-first guidance instead of a terse error: - Interactive / agent-driven sessions get sign-in guidance led by `hyperframes auth login` (the OAuth step that also creates an account and is shared with heygen-cli), and never steer users to a per-repo `.env`. CI / non-interactive runs get a terse note. Exit 1 is kept so the "am I logged in?" `$?` contract still holds. - It probes which local engine voice/music will fall back to (Kokoro / MusicGen, mirroring the skill resolution order) and whether their Python deps are installed, with a pip hint when missing. `--json` exposes `recommended_action` + `offline_engines` for skills to branch. - `doctor` gains matching "TTS (Kokoro)" / "BGM (MusicGen)" checks via the same shared probe (findPython/hasPythonModules extracted to tts/python.ts; provider resolution in audio/providers.ts). Every TTS/BGM workflow now relays this at Step 0 (setup) instead of improvising its own "missing key" prompt: pr-to-video, product-launch- video, faceless-explainer, website-to-video, music-to-video. The canonical behavior + key-priority table live once in hyperframes-media. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * feat(pr-to-video): scale recommended video length to PR change size Step 0 led with a fixed ~60-90s length default. Now the recommended length is derived from the PR's diff stat (lines added+deleted, nudged by file count) on a tier scale (trivial ~20-40s → large ~110-180s, hard cap ~3 min), reusing the same PR peek already done to infer the angle. The agent states the basis when proposing it, and a huge PR with one headline change still stays tight. User can always override. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(captions): embed brand fonts whose files use separators brandFontFaces() matched font files by stripping only whitespace, so an underscore/hyphen-named file (TT_Norms_Pro_Bold.woff2) never matched the family key "ttnormspro" — captions shipped with no @font-face, the font_family_without_font_face bug. Now both family and filename normalize away all non-alphanumerics; families match longest-key-first so a parent family can't swallow a more specific one's files (TT Norms Pro vs Mono); each file is claimed once; "demibold" ranks before "bold"; and when nothing matches it warns loudly at build time instead of returning "". Also: parseFonts() falls back to h1/h2/title/hero display roles, and the frame-worker + caption authoring docs spell out that only shipped font files render — no system CJK/Devanagari families on the headless renderer. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(hyperframes-media): enforce sign-in preflight on standalone BGM/TTS A one-off "generate me a BGM" request went straight to local MusicGen without recommending sign-in: bgm.md/tts.md framed the no-credential path as an automatic fallback, so the generation path bypassed the Preflight stop, and the preflight used a bare `hyperframes auth status` that isn't on PATH in a fresh `npx skills` project. - Preflight now applies to one-off generation as well as workflows, uses `npx hyperframes auth status`, and says: if the CLI can't run, still recommend signing in and STOP — never treat "no credential" as a silent green light for local generation. - bgm.md and tts.md point at the Preflight before generating, reframing local generation as the fallback the user opts into, not a default. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs(auth): add Authentication & API keys guide Document signing in, the keys each capability (voice, music, capture) uses, their resolution priority, and the fully local fallback. Add the guide to the nav and cross-link it from the cloud deploy note and the CLI env-var reference. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(lint): strip HTML comments in a fixpoint loop (CodeQL) Single-pass <!-- --> removal can re-form a complete comment from adjacent markers (e.g. `<<!-- -->!-- ... -->`), letting a decoy <template> survive and hijack the template-boundary match. Loop to a fixpoint, mirroring the captions.mjs precedent; add a regression test that fails on single-pass (2 root findings) and passes on the loop. Also wrap the build-frame.mjs node:fs imports to satisfy oxfmt — the new copyFileSync import pushed the line past the width limit, which was the sole cause of the Format / Preflight CI failures. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(lint): strip HTML comments with a linear scan (CodeQL ReDoS) The fixpoint loop still ran a /<!--[\s\S]*?-->/ regex per pass, which backtracks O(n^2) on inputs with many unterminated "<!--" — CodeQL js/polynomial-redos (high). Looping the same regex (the prescribed fix) never addressed this; only the regex itself does. Replace it with an indexOf-based linear strip in utils.ts (stripHtmlComments), kept in a fixpoint loop so markers that re-form when a comment is removed are still stripped. 200k unterminated "<!--" now strips in ~3ms instead of quadratic time; behavior is otherwise unchanged — unterminated comments are kept verbatim, as the old regex left them. The re-forming regression test still guards it. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(auth): make TTS/BGM sign-in guidance accurate and runnable From team review of the not-signed-in onboarding: - OAuth is a `hyperframes auth login` feature only. The separate `heygen` CLI is API-key-only — `heygen auth login` stores a pasted key, it is not OAuth and does not create an account. Stop presenting the two CLIs as the same OAuth/sign-up step. - Use `npx hyperframes` in every imperative and runtime hint. Bare `hyperframes` is not on PATH on a fresh machine (command not found); only `npx hyperframes` is guaranteed. Also updates the JSON recommended_action. - Drop `heygen auth login` from the terminal/skill onboarding: it needs its own install and there is no `npx heygen`, so it was a command-not-found trap. The shared-credential fact stays in the reference docs. Covers the `auth status` guidance + tests, the Authentication docs, the shared hyperframes-media preflight (SKILL, requirements, tts, error hints), and the `npx hyperframes auth status` preflight in every TTS/BGM workflow (pr-to-video, product-launch-video, faceless-explainer, website-to-video, music-to-video). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
7e0a447325 |
refactor: drop unused exports detected by fallow auto-fix
Run `fallow fix --auto-fixable` to remove `export` keywords from symbols fallow's reachability analysis identifies as unused. Keeps only the cases where the symbol is still referenced internally in its own file (so removing `export` doesn't surface a new oxlint `no-unused-vars` error). Result: fallow dead-code findings drop from 276 → 208 (68 fewer unused exports), with no behavior change — each symbol is still defined and used exactly the same way within its file. Reverted ~20 files where fallow's auto-fix would have created cascading "declared but never used" lint errors — those are cases where the symbol isn't used at all, and properly cleaning them up means deleting the declaration, not just dropping `export`. Better to land that as a separate, narrower PR rather than mixing it into a mechanical de-export. Also reverted four false positives where fallow missed real consumers: - `captureCost.ts` (renderOrchestrator has two separate import blocks from the same module; fallow only saw the first) - `propertyPanelHelpers.ts`, `domEditingLayers.ts` (real internal uses fallow's reachability missed) - `render.ts` (functions imported via `await import()` dynamic import, which fallow's static analysis doesn't follow) Test plan: bun run --filter '*' typecheck (clean), oxlint + oxfmt clean, cli/core/studio/engine vitest suites pass (335 + 917 + 576 + 605 tests). |
||
|
|
4a55bc8673 |
feat(cli): add --lang and auto-infer phonemizer locale from voice prefix (#351)
* feat(cli): add --lang and auto-infer phonemizer locale from voice prefix `hyperframes tts` was calling Kokoro's `model.create(text, voice=, speed=)` with no language argument, so Kokoro's default phonemizer (en-us) was applied regardless of the voice selected. Picking `ef_dora` or `jf_alpha` and feeding it Spanish or Japanese text produced English-phonemized output. Closes #349. - `manager.ts`: add `SUPPORTED_LANGS`, `inferLangFromVoiceId`, and `isSupportedLang`. Attach a `defaultLang` field to every bundled voice and expand the bundled list with `ef_dora`, `ff_siwis`, `jf_alpha`, `zf_xiaobei` so `--list` surfaces multilingual options. - `synthesize.ts`: accept optional `lang: SupportedLang` in `SynthesizeOptions`, forward it to the Python worker as `argv[7]`. The worker introspects `Kokoro.create`'s signature and only passes `lang=` when the installed kokoro-onnx version supports it. Returned metadata now includes `lang` and `langApplied` so callers can detect silent no-ops. Bump the cached script filename to `synth-v2.py` so existing installs pick up the new script automatically. - `commands/tts.ts`: add `--lang, -l` with validation against `SUPPORTED_LANGS`. Resolution order is explicit `--lang` > inferred from voice prefix > `en-us`. When explicit lang disagrees with the voice-implied lang (legitimate for stylized accents), emit a dim-level hint; suppress under `--json`. When kokoro-onnx silently ignores the kwarg, log that too. Update `--list` with a new "Lang code" column and add multilingual examples. - Tests: new `manager.test.ts` covering every supported prefix, the unknown-prefix fallback, case-insensitivity, `isSupportedLang` validation, and a regression guard that every bundled voice has a valid `defaultLang` matching its ID. - Docs: `docs/packages/cli.mdx` and `skills/hyperframes/references/tts.md` updated with the flag, examples, the espeak-ng dependency note for non-English phonemization, and the voice-prefix → lang table. Backward compatibility: - English voices (a*/b* prefixes) continue to phonemize as en-us / en-gb — no change. - Non-English voices now phonemize correctly by default (bug fix, not a regression). - Older kokoro-onnx versions that don't know the `lang` kwarg keep working via signature introspection; the CLI logs a dim note if `--lang` was requested but ignored. Verification: - `bun --cwd packages/cli test` — 128 tests pass (incl. 17 new). - `bunx oxlint` and `bunx oxfmt --check` clean on changed files. - `bun run build` succeeds. - `npx tsx packages/cli/src/cli.ts tts --help` / `--list` render cleanly; invalid `--lang` produces a clean error with the valid-codes list. * refactor(cli): simplify tts --lang implementation Post-review cleanup on #351. Net -21 lines. - Drop `defaultLang` field + `makeVoice()` helper from VoiceInfo — compute via `inferLangFromVoiceId(v.id)` at read time in listVoices. The only reader was the --list table; caching the derived value on every voice added a self-consistency invariant we had to test. - Drop redundant `lang` field from SynthesizeResult — caller already knows the requested lang since it passed it in; only `langApplied` carries information the caller can't derive. - Use `errorBox` for --lang validation to match the house style in render.ts (other validation errors already use errorBox). - Reuse existing `langList` module constant in the validation error instead of re-joining SUPPORTED_LANGS. - Inline `DEFAULT_LANG` — used once in inferLangFromVoiceId. - Trim WHAT-restating comments and the duplicate prefix-enumeration JSDoc on inferLangFromVoiceId (VOICE_PREFIX_LANG already carries per-row comments). - Clean up orphaned `synth*.py` files in ~/.cache/hyperframes/tts when writing the current versioned script, so repeated upgrades don't leak files. - Drop the `EN-US` case-sensitive-rejection test assertion — the CLI lowercases input before validation, so accepting mixed case is a feature, not a bug. Tests: 16/16 in `manager.test.ts`, 127/127 full CLI suite pass. Lint + format + typecheck clean. |
||
|
|
d1f992570a |
fix(cli): use 'where' instead of 'which' on Windows for FFmpeg and br… (#336)
* fix(cli): use 'where' instead of 'which' on Windows for FFmpeg and browser detection - findFFmpeg() now uses 'where ffmpeg' on Windows, 'which ffmpeg' on Unix - whichBinary() now uses 'where' on Windows, 'which' on Unix Fixes FFmpeg detection failure on Windows where 'which' command doesn't exist. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * fix(cli): handle multi-line output from Windows 'where' command Windows 'where' can return multiple paths (one per line) when there are multiple matches on PATH. Take only the first non-empty line. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * fix(cli): extend Windows 'where' fix to whisper, tts, and clipboard modules - whisper/manager.ts: whichBinary() now uses 'where' on Windows - tts/synthesize.ts: findPython() now uses 'where' on Windows - utils/clipboard.ts: detectProvider() now uses 'where' on Windows All functions handle multi-line output from 'where' command. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com> |
||
|
|
7389c0c89b |
feat(cli): add tts command for local text-to-speech via Kokoro-82M (#201)
* feat(cli): add `tts` command for local text-to-speech via Kokoro-82M Adds `hyperframes tts` — generate speech audio locally using Kokoro-82M (ONNX), no API key needed. Mirrors the transcribe command architecture. - New command: `hyperframes tts "text" --voice af_heart --output speech.wav` - 54 voices across 8 languages, ~5x realtime on CPU - Auto-downloads model (~311 MB) + voices (~27 MB) to ~/.cache/hyperframes/tts/ - Requires Python 3.8+ with kokoro-onnx installed - Extracted shared `downloadFile` utility from whisper/manager.ts with atomic .tmp→rename to prevent partial download corruption - Added hyperframes-tts skill with voice selection guide - Updated CLAUDE.md with TTS docs, voice table, and skill reference Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * docs(tts): improve skill per skill-creator guidelines - Move trigger info from body to frontmatter description - Remove `trigger` field (not a valid frontmatter field) - Remove CLI flag docs Claude can derive from --help - Remove redundant voice tables (keep content-to-voice mapping) - Fix composition audio example to use actual <audio> element pattern - Keep non-obvious workflows: TTS+transcribe for captions, long scripts Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * docs(tts): add guidance for using external TTS sources Help users understand when to use cloud TTS (voice cloning, broader languages, higher quality) vs the built-in Kokoro model, and how external audio integrates into the same composition workflow. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * docs(tts): prioritize HeyGen API as recommended cloud TTS Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * docs(tts): remove external TTS section for now Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix(tts): set required: false on input arg so --list works standalone Citty treats positional args as required by default unless explicitly set to required: false. Without this, `hyperframes tts --list` fails with "Missing required positional argument". Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * feat(tts): add --help examples and fix required:false for --list Add examples section to `tts --help` matching the pattern from other commands (transcribe, render, etc.). Fix citty positional arg requiring explicit `required: false` for --list to work standalone. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * docs: add CLI command checklist to CLAUDE.md Ensure new commands always get --help examples in help.ts. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> |