Skip to content

feat(tts): add built-in VOICEVOX-compatible TTS provider - #67808

Open
to-na wants to merge 2 commits into
NousResearch:mainfrom
to-na:feat/voicevox-tts-provider
Open

feat(tts): add built-in VOICEVOX-compatible TTS provider#67808
to-na wants to merge 2 commits into
NousResearch:mainfrom
to-na:feat/voicevox-tts-provider

Conversation

@to-na

@to-na to-na commented Jul 20, 2026

Copy link
Copy Markdown
Contributor

Summary

Add voicevox as a built-in local TTS provider that talks to any VOICEVOX-compatible HTTP engine — VOICEVOX, AivisSpeech, Sharevox, VOICEPEAK, etc.

Closes #67803

What's included

File Change
tools/tts_tool.py _generate_voicevox_tts(), _check_voicevox_available(), dispatch case, Opus conversion, check_tts_requirements()
agent/tts_registry.py "voicevox" in _BUILTIN_NAMES
hermes_cli/config.py Default config (base_url, speaker)
hermes_cli/tools_config.py hermes tools picker entry
website/docs/user-guide/features/tts.md Provider table, config example, input limits, Telegram notes, setup guide
tests/tools/test_tts_voicevox.py 14 tests (registration, dispatch, synthesis, error paths)

Design decisions

  • Zero external dependencies. Uses only urllib.request (stdlib) — no pip install, unlike Piper (piper-tts) or NeuTTS (neutts[all]).
  • Two-step HTTP API. POST /audio_queryPOST /synthesis, matching the VOICEVOX engine spec.
  • WAV → ffmpeg conversion. Same pattern as Piper/NeuTTS/KittenTTS for MP3/Opus output and Telegram voice bubbles.
  • Availability probe. GET /version with 3s timeout; clear error message when the engine is offline.
  • Speaker validation. Non-integer speaker IDs fall back to default (0); HTTP 422 surfaces a helpful "check /speakers" message.

Config

tts:
  provider: voicevox
  voicevox:
    base_url: http://127.0.0.1:50021   # any VOICEVOX-compatible engine
    speaker: 0                          # speaker ID (GET /speakers to list)

Testing

84 passed in 1.59s
  • tests/tools/test_tts_voicevox.py — 14 new tests (all mocked HTTP, no engine required)
  • tests/agent/test_tts_registry.py — registry sync check passes
  • tests/tools/test_tts_piper.py — no regressions

@to-na
to-na force-pushed the feat/voicevox-tts-provider branch from 627cc63 to 36addaf Compare July 20, 2026 02:04
@alt-glitch alt-glitch added type/feature New feature or request P3 Low — cosmetic, nice to have comp/agent Core agent runtime: loop, agent_init, prompt builder, context-compression, responses endpoint comp/cli CLI entry point, hermes_cli/, setup wizard tool/tts Text-to-speech and transcription sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades labels Jul 20, 2026

@teknium1 teknium1 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the focused local-TTS implementation. The VOICEVOX request remains unimplemented on current main, but this PR has integration gaps to resolve.

Problems

  • hermes_cli/tools_config.py:377 adds only the hermes tools row. The separate hermes setup tts flow does not list voicevox in hermes_cli/setup.py:941-977, so the setup integration requested in #67803 is incomplete.
  • #67803 asks for GET /speakers exposed through list_voices(). The proposed generator only calls /audio_query and /synthesis (tools/tts_tool.py:2266-2295 at PR head), so users still need the manual speaker lookup documented by the PR.
  • Current TTS docs identify voice-listing APIs as a Python-plugin case (website/docs/user-guide/features/tts.md:331-346), while AGENTS.md:513-516 directs custom/local-only backends to plugins. Please resolve this placement with maintainers before adding another hardcoded native provider.

Suggested changes

  • Add the setup/status wiring and tests.
  • Implement the speaker-catalog path, or narrow the feature/docs accordingly.
  • Re-scope to the TTS provider plugin surface unless maintainers explicitly choose a built-in.

Automated hermes-sweeper review.

@@ -373,6 +373,12 @@ def _checklist_toolset_keys(platform: str) -> Set[str]:
"tts_provider": "piper",
"post_setup": "piper",
},
{
"name": "VOICEVOX (local, Japanese)",

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This makes VOICEVOX selectable in hermes tools, but the separate hermes setup tts flow still omits it from provider_labels and providers (hermes_cli/setup.py:941-977). Please wire the provider into that flow as well; #67803 explicitly requests setup integration.

Comment thread tools/tts_tool.py
# Provider: VOICEVOX (local, Japanese TTS, zero dependencies)
# ===========================================================================

def _generate_voicevox_tts(text: str, output_path: str, tts_config: Dict[str, Any]) -> str:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The feature spec in #67803 calls for GET /speakers exposed through voice listing, but this implementation only performs /audio_query and /synthesis. Please add the catalog path and connect it to the supported TTS provider selection/listing surface, or narrow the feature claim.

to-na added 2 commits July 26, 2026 00:07
Add voicevox as a first-class local TTS provider that talks to any
VOICEVOX-compatible HTTP engine (VOICEVOX, AivisSpeech, Sharevox,
VOICEPEAK) via the standard two-step API (audio_query → synthesis).

- Zero external dependencies: uses only stdlib urllib.request
- Configurable base_url and speaker ID via tts.voicevox.*
- Availability probe via GET /version
- Clear error messages for engine-offline and invalid-speaker cases
- WAV output with ffmpeg conversion for MP3/Opus (Telegram voice bubbles)
- Registered in BUILTIN_TTS_PROVIDERS, tts_registry, config defaults,
  hermes tools picker, and documentation
- 14 new tests covering registration, dispatch, synthesis, error paths

Fixes NousResearch#67803
@to-na
to-na force-pushed the feat/voicevox-tts-provider branch from 36addaf to cf2d5c2 Compare July 25, 2026 15:14
@to-na

to-na commented Jul 25, 2026

Copy link
Copy Markdown
Contributor Author

Thanks for the detailed review. I have pushed the completed integration in cf2d5c2a0, rebased onto the current main.

The updated branch now:

  • Adds VOICEVOX to the separate hermes setup tts flow, including provider labels, engine URL configuration, readiness/status reporting, and setup-summary output.
  • Adds speaker/style selection to both hermes setup tts and hermes tools.
  • Implements GET /speakers through the shared list_voices() surface, flattening talk-compatible speaker styles into picker entries.
  • Preserves the configured engine URL for readiness checks and synthesis.
  • Handles offline engines, HTTP errors, malformed catalog responses, invalid style IDs, and the no-ffmpeg output path without mislabeling WAV data as MP3.
  • Adds regression coverage for setup/status, catalog parsing, picker behavior, synthesis errors, plugin voice-listing compatibility, and a real local HTTP contract test covering /version, /speakers, /audio_query, and /synthesis.

Local verification after rebasing:

  • 22 related test files: 501 passed
  • Gateway TTS media routing: 7 passed
  • Ruff and git diff --check: passed

Regarding placement: I am the author of #67803. I initially proposed a built-in provider because VOICEVOX is a widely used local TTS engine in Japan, requires no API key or additional Python SDK, and extends the existing TTS provider surface without adding a new model tool.

That said, I am not attached to the built-in placement. I would be happy to re-scope this as a standalone TTS provider plugin if that is the preferred maintenance direction. Could a maintainer confirm whether VOICEVOX should remain built in or move to the plugin surface? I have kept the completed built-in implementation in the branch so the integration can be reviewed concretely.

@to-na
to-na requested a review from teknium1 July 25, 2026 15:24
@teknium1 teknium1 added the sweeper:blast-moderate Sweeper blast radius: moderate — a subsystem or single platform label Jul 30, 2026
@GottZ

GottZ commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

This was generated by AI during triage.

Summary

Four PRs are associated with this complex. #7815, #17092, and #17885 concern Piper support for #8508, while #67808 addresses #67803 with a VOICEVOX-compatible provider, speaker discovery, setup integration, configuration, documentation, and tests.

Related pull requests

Duplicates

#7815 and #17885 substantially overlap as native Piper implementations for #8508, with #7815 closed as superseded after #17885 landed; #17092 is related Piper work but uses a distinct external HTTP transport. None duplicates #67808’s VOICEVOX implementation.

Suggested consolidation

Keep #67808 open with a salvage path: preserve its complete VOICEVOX protocol, speaker-catalog, setup, error-handling, and test work while obtaining maintainer re-review on the contributor-raised native-provider-versus-plugin placement decision, re-scoping or splitting only if that decision requires it. Leave #7815 and #17092 closed, treat #7815 as superseded by merged #17885 for the Piper path, and retain #17885 as the merged Piper reference implementation.

Complex graph

flowchart LR
    classDef open fill:#dbeafe,stroke:#1d4ed8,color:#1e3a8a
    classDef merged fill:#dcfce7,stroke:#15803d,color:#14532d
    classDef closed fill:#e5e7eb,stroke:#6b7280,color:#1f2937
    classDef unverified fill:#f3f4f6,stroke:#9ca3af,color:#374151
    classDef best stroke-width:3px,stroke:#b45309
    classDef target stroke-width:3px,stroke:#4338ca
    I67803(["issue #67803 (open)"])
    P67808["PR #67808 (open)"]
    P67808 -->|best fix| I67803
    class I67803 open
    class P67808 open
    class P67808 best
    class P67808 target
    click I67803 "https://github.com/NousResearch/hermes-agent/issues/67803"
    click P67808 "https://github.com/NousResearch/hermes-agent/pull/67808"
Loading

Graph: solid arrow = fixes / best fix, dashed arrow = partial or unverified (see edge label); boxed group = PRs duplicating each other; amber border = best fix; indigo border = target; gray node = closed (state tag in the node label).

Cross-PR triage: Reviewed 4 pull requests and 2 issues in this complex. Diffs were read for 3 of 4 PRs (rest unavailable); Assessment working set: 107 kB of PR diffs, 20 kB of issue/PR text, 8 kB of discussion (11 comments), 6 verify verdicts. verdicts reflect diff content, not PR titles. Part of an automated triage batch.

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

Labels

comp/agent Core agent runtime: loop, agent_init, prompt builder, context-compression, responses endpoint comp/cli CLI entry point, hermes_cli/, setup wizard P3 Low — cosmetic, nice to have sweeper:blast-moderate Sweeper blast radius: moderate — a subsystem or single platform sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades tool/tts Text-to-speech and transcription type/feature New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature]: Add VOICEVOX-compatible engine as a built-in TTS provider

4 participants