Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ jobs:
# rest (sounddevice, protobuf, sentencepiece, pyyaml, jinja2) are
# pulled in by other engines.
pip install --no-deps mlx-lm==0.31.1
pip install --no-deps mlx-audio==0.4.1
pip install --no-deps mlx-audio==0.5.9

- name: Build Python server (Linux/macOS)
if: matrix.platform != 'windows-latest'
Expand Down
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
### Engines

- **OmniVoice TTS engine (non-commercial).** Adds k2-fsa/OmniVoice as an opt-in eighth engine: zero-shot cloning and attribute-based voice design (gender, age, pitch, accent) across the 23 languages Voicebox already lists, 24 kHz output. Its `HiggsAudioV2` codec only exists in transformers 5.x, so the modelling code is vendored under `backend/vendor/` and grafted onto the pinned 4.57 at load time; `omnivoice` installs `--no-deps` like Chatterbox and TADA. The weights are CC-BY-NC, so the engine is labelled non-commercial in the engine picker and model manager and is never a default. — @pippo73 ([#1062](https://github.com/jamiepine/voicebox/pull/1062); fixes [#380](https://github.com/jamiepine/voicebox/issues/380), [#517](https://github.com/jamiepine/voicebox/issues/517), [#791](https://github.com/jamiepine/voicebox/issues/791))
- **Higgs Audio v3 TTS engine on Apple Silicon (non-commercial).** Adds Boson AI's Higgs Audio v3 4B (`bosonai/higgs-tts-3-4b`) as the `higgs` engine, MLX only: zero-shot cloning across the 23 languages Voicebox lists, inline control tags such as `<|emotion:amusement|>`, 24 kHz output, about 0.9x realtime on an M4 Max. It runs on mlx-audio's port, so mlx-audio moves from 0.4.1 to 0.5.9 (still `--no-deps`; mlx now needs 0.31.1+). The bump changed Whisper's temperature fallback into multilingual gibberish on short clips, so MLX transcription now decodes greedily. The community 4-bit MLX artifact (`Reza2kn/Higgs-Audio-v3-TTS-4bit-MLX`) holds only the quantized transformer layers, without the audio codec, so it cannot be loaded; the engine downloads the 9.3 GB bf16 checkpoint instead. The weights are under Boson's research and non-commercial licence, so the engine is labelled non-commercial and is never a default.

## [0.6.0] - 2026-10-04

Expand Down
2 changes: 1 addition & 1 deletion app/src/components/CapturesTab/CapturesTab.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -269,7 +269,7 @@ export function CapturesTab() {
// override fall through to whatever the backend picks.
const engine = voice.default_engine as
| 'qwen' | 'qwen_custom_voice' | 'qwen_voice_design' | 'luxtts' | 'chatterbox'
| 'chatterbox_turbo' | 'tada' | 'kokoro' | 'omnivoice'
| 'chatterbox_turbo' | 'tada' | 'kokoro' | 'omnivoice' | 'higgs'
| undefined;
return apiClient.generateSpeech({
profile_id: voice.id,
Expand Down
3 changes: 3 additions & 0 deletions app/src/components/Generation/EngineModelSelector.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ const ENGINE_OPTIONS = [
{ value: 'tada:3B', label: 'TADA 3B Multilingual', engine: 'tada' },
{ value: 'kokoro', label: 'Kokoro 82M', engine: 'kokoro' },
{ value: 'omnivoice', label: 'OmniVoice (non-commercial)', engine: 'omnivoice' },
{ value: 'higgs', label: 'Higgs Audio v3 (non-commercial)', engine: 'higgs' },
] as const;

const ENGINE_DESCRIPTIONS: Record<string, string> = {
Expand All @@ -41,6 +42,7 @@ const ENGINE_DESCRIPTIONS: Record<string, string> = {
tada: 'HumeAI, 700s+ coherent audio',
kokoro: '82M params, CPU realtime, 8 langs',
omnivoice: '23 languages, voice design. CC-BY-NC weights: non-commercial use only',
higgs: 'Apple Silicon only, 23 languages, <|emotion:...|> tags. Non-commercial licence',
};

/** Engines that only support English and should force language to 'en' on select. */
Expand All @@ -54,6 +56,7 @@ const CLONING_ENGINES = new Set([
'chatterbox_turbo',
'tada',
'omnivoice',
'higgs',
]);

/** Engines that synthesise a voice from a written description. */
Expand Down
3 changes: 2 additions & 1 deletion app/src/components/Generation/FloatingGenerateBox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,8 @@ export function FloatingGenerateBox({
| 'kokoro'
| 'qwen_custom_voice'
| 'qwen_voice_design'
| 'omnivoice';
| 'omnivoice'
| 'higgs';
useEffect(() => {
if (selectedProfile?.language) {
form.setValue('language', selectedProfile.language as LanguageCode);
Expand Down
5 changes: 4 additions & 1 deletion app/src/components/ServerSettings/ModelManagement.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,8 @@ const MODEL_DESCRIPTIONS: Record<string, string> = {
'Kokoro 82M by hexgrad. Tiny 82M-parameter TTS that runs at CPU realtime. Supports 8 languages with pre-built voice styles. Apache 2.0 licensed.',
omnivoice:
'OmniVoice by k2-fsa. Zero-shot voice cloning via a diffusion language model, plus attribute-based voice design (gender, age, pitch, accent). The model covers 600+ languages; Voicebox exposes the 23 in its own language list. 24kHz output. NON-COMMERCIAL: the weights are CC-BY-NC (code is Apache 2.0; the bundled Higgs Audio V2 codec is under the Boson community licence), so do not use output commercially.',
'higgs-audio-v3':
'Higgs Audio v3 4B by Boson AI, on Apple Silicon (MLX). Qwen3-based conversational TTS with zero-shot voice cloning, 100+ languages (Voicebox exposes 23) and inline control tags such as <|emotion:amusement|> or <|sfx:laughter|>. 24kHz output, ~9.3 GB download. NON-COMMERCIAL: Boson Higgs Audio v3 research and non-commercial licence.',
'qwen-custom-voice-1.7B':
'Qwen3-TTS CustomVoice 1.7B by Alibaba. 9 premium preset voices with instruct-based style control for tone, emotion, and prosody. Supports 10 languages.',
'qwen-custom-voice-0.6B':
Expand Down Expand Up @@ -420,7 +422,8 @@ export function ModelManagement() {
m.model_name.startsWith('chatterbox') ||
m.model_name.startsWith('tada') ||
m.model_name.startsWith('kokoro') ||
m.model_name.startsWith('omnivoice'),
m.model_name.startsWith('omnivoice') ||
m.model_name.startsWith('higgs'),
) ?? [];
const whisperModels = modelStatus?.models.filter((m) => m.model_name.startsWith('whisper')) ?? [];
const llmModels = modelStatus?.models.filter((m) => m.model_name.startsWith('qwen3-')) ?? [];
Expand Down
1 change: 1 addition & 0 deletions app/src/components/VoiceProfiles/ProfileForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ const DEFAULT_ENGINE_OPTIONS = [
{ value: 'tada', label: 'TADA' },
{ value: 'kokoro', label: 'Kokoro 82M' },
{ value: 'omnivoice', label: 'OmniVoice (non-commercial)' },
{ value: 'higgs', label: 'Higgs Audio v3 (non-commercial)' },
] as const;

function makeProfileSchema(t: (key: string) => string) {
Expand Down
3 changes: 2 additions & 1 deletion app/src/lib/api/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,8 @@ export interface GenerationRequest {
| 'chatterbox_turbo'
| 'tada'
| 'kokoro'
| 'omnivoice';
| 'omnivoice'
| 'higgs';
instruct?: string;
/** When true and the profile has a personality prompt, input text is rewritten in-character before TTS. */
personality?: boolean;
Expand Down
26 changes: 26 additions & 0 deletions app/src/lib/constants/languages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,32 @@ export const ENGINE_LANGUAGES: Record<string, readonly LanguageCode[]> = {
'tr',
'zh',
],
// Higgs Audio v3 covers 100+ languages; same ALL_LANGUAGES subset as OmniVoice.
higgs: [
'ar',
'da',
'de',
'el',
'en',
'es',
'fi',
'fr',
'he',
'hi',
'it',
'ja',
'ko',
'ms',
'nl',
'no',
'pl',
'pt',
'ru',
'sv',
'sw',
'tr',
'zh',
],
} as const;

/** Helper: get language options for a given engine. */
Expand Down
25 changes: 15 additions & 10 deletions app/src/lib/hooks/useGenerationForm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ const generationSchema = z.object({
'tada',
'kokoro',
'omnivoice',
'higgs',
])
.optional(),
personality: z.boolean().optional(),
Expand Down Expand Up @@ -107,9 +108,11 @@ export function useGenerationForm(options: UseGenerationFormOptions = {}) {
? 'qwen-voice-design-1.7B'
: engine === 'omnivoice'
? 'omnivoice'
: engine === 'qwen_custom_voice'
? `qwen-custom-voice-${data.modelSize}`
: `qwen-tts-${data.modelSize}`;
: engine === 'higgs'
? 'higgs-audio-v3'
: engine === 'qwen_custom_voice'
? `qwen-custom-voice-${data.modelSize}`
: `qwen-tts-${data.modelSize}`;
const displayName =
engine === 'luxtts'
? 'LuxTTS'
Expand All @@ -127,13 +130,15 @@ export function useGenerationForm(options: UseGenerationFormOptions = {}) {
? 'Qwen VoiceDesign 1.7B'
: engine === 'omnivoice'
? 'OmniVoice'
: engine === 'qwen_custom_voice'
? data.modelSize === '1.7B'
? 'Qwen CustomVoice 1.7B'
: 'Qwen CustomVoice 0.6B'
: data.modelSize === '1.7B'
? 'Qwen TTS 1.7B'
: 'Qwen TTS 0.6B';
: engine === 'higgs'
? 'Higgs Audio v3'
: engine === 'qwen_custom_voice'
? data.modelSize === '1.7B'
? 'Qwen CustomVoice 1.7B'
: 'Qwen CustomVoice 0.6B'
: data.modelSize === '1.7B'
? 'Qwen TTS 1.7B'
: 'Qwen TTS 0.6B';

// Check if model needs downloading
try {
Expand Down
1 change: 1 addition & 0 deletions app/src/lib/utils/format.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ const ENGINE_DISPLAY_NAMES: Record<string, string> = {
chatterbox_turbo: 'Chatterbox Turbo',
tada: 'TADA',
kokoro: 'Kokoro 82M',
higgs: 'Higgs Audio v3',
};

export function formatEngineName(engine?: string, modelSize?: string): string {
Expand Down
51 changes: 50 additions & 1 deletion backend/backends/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,7 @@ def is_loaded(self) -> bool:
"tada": "TADA",
"kokoro": "Kokoro",
"omnivoice": "OmniVoice",
"higgs": "Higgs Audio v3",
}

LLM_ENGINES = {
Expand Down Expand Up @@ -347,7 +348,49 @@ def _get_non_qwen_tts_configs() -> list[ModelConfig]:
chatterbox_size_mb = 3200
chatterbox_aux_repos = ()

return [
# Higgs Audio v3 only has an MLX implementation (mlx-audio), so it is offered on Apple Silicon only.
higgs_configs = (
[
ModelConfig(
model_name="higgs-audio-v3",
# Non-commercial: Boson Higgs Audio v3 research and non-commercial licence.
display_name="Higgs Audio v3 4B (Multilingual, non-commercial)",
engine="higgs",
hf_repo_id="bosonai/higgs-tts-3-4b",
size_mb=9300,
# Same 23 languages Voicebox already exposes; upstream covers 100+.
languages=[
"zh",
"en",
"ja",
"ko",
"de",
"fr",
"ru",
"pt",
"es",
"it",
"he",
"ar",
"da",
"el",
"fi",
"hi",
"ms",
"nl",
"no",
"pl",
"sv",
"sw",
"tr",
],
)
]
if on_mlx
else []
)

return higgs_configs + [
ModelConfig(
model_name="luxtts",
display_name="LuxTTS (Fast, CPU-friendly)",
Expand Down Expand Up @@ -842,6 +885,12 @@ def get_tts_backend_for_engine(engine: str) -> TTSBackend:
from .omnivoice_backend import OmniVoiceBackend

backend = OmniVoiceBackend()
elif engine == "higgs":
if get_backend_type() != "mlx":
raise ValueError("Higgs Audio v3 requires Apple Silicon (MLX backend)")
from .higgs_mlx_backend import HiggsMLXTTSBackend

backend = HiggsMLXTTSBackend()
elif engine == "qwen_custom_voice":
from .qwen_custom_voice_backend import QwenCustomVoiceBackend

Expand Down
Loading