mirror of
https://github.com/mudler/LocalAI.git
synced 2026-06-14 11:49:33 -04:00
* feat(omnivoice-cpp): add C wrapper + CMake/Makefile build over OmniVoice ov_* ABI Assisted-by: claude:claude-opus-4-8 [Claude Code] Signed-off-by: Ettore Di Giacinto <mudler@localai.io> * feat(omnivoice-cpp): add option/language parsing + WAV framing helpers with tests Assisted-by: claude:claude-opus-4-8 [Claude Code] Signed-off-by: Ettore Di Giacinto <mudler@localai.io> * feat(omnivoice-cpp): wire purego binding with TTS + streaming TTSStream Assisted-by: claude:claude-opus-4-8 [Claude Code] Signed-off-by: Ettore Di Giacinto <mudler@localai.io> * build(omnivoice-cpp): wire backend into root Makefile Assisted-by: claude:claude-opus-4-8 [Claude Code] Signed-off-by: Ettore Di Giacinto <mudler@localai.io> * ci(omnivoice-cpp): add build matrix entries + dep-bump registration Assisted-by: claude:claude-opus-4-8 [Claude Code] Signed-off-by: Ettore Di Giacinto <mudler@localai.io> * feat(omnivoice-cpp): register backend meta + image entries Assisted-by: claude:claude-opus-4-8 [Claude Code] Signed-off-by: Ettore Di Giacinto <mudler@localai.io> * feat(omnivoice-cpp): expose as preference-only importable backend Assisted-by: claude:claude-opus-4-8 [Claude Code] Signed-off-by: Ettore Di Giacinto <mudler@localai.io> * feat(gallery): add omnivoice-cpp TTS models (Q8_0 default + BF16 HQ) Assisted-by: claude:claude-opus-4-8 [Claude Code] Signed-off-by: Ettore Di Giacinto <mudler@localai.io> * docs(omnivoice-cpp): document the OmniVoice TTS backend Assisted-by: claude:claude-opus-4-8 [Claude Code] Signed-off-by: Ettore Di Giacinto <mudler@localai.io> * test(omnivoice-cpp): add env-gated e2e for TTS + streaming Assisted-by: claude:claude-opus-4-8 [Claude Code] Signed-off-by: Ettore Di Giacinto <mudler@localai.io> * feat(omnivoice-cpp): honor tts.audio_path/tts.voice config as default cloning reference The model config tts.audio_path (ModelOptions.AudioPath) and tts.voice now provide a default voice-cloning reference used when a request omits Voice, so a cloned voice can be pinned in the model YAML instead of passed per request. A per-request voice still overrides. Paths resolve relative to the model dir. Assisted-by: claude:claude-opus-4-8 [Claude Code] Signed-off-by: Ettore Di Giacinto <mudler@localai.io> * fix(omnivoice-cpp): add missing omnivoice-cpp-development backend meta Mirrors the whisper/vibevoice convention: a -development meta aggregating the master-tagged image variants (the production meta and per-variant prod+dev image entries already existed; only the development meta aggregator was missing). Assisted-by: claude:claude-opus-4-8 [Claude Code] Signed-off-by: Ettore Di Giacinto <mudler@localai.io> --------- Signed-off-by: Ettore Di Giacinto <mudler@localai.io> Co-authored-by: Ettore Di Giacinto <mudler@localai.io>
75 lines
1.8 KiB
Go
75 lines
1.8 KiB
Go
package main
|
|
|
|
import (
|
|
"strconv"
|
|
"strings"
|
|
)
|
|
|
|
// loadOptions holds the parsed model-level options for OmniVoice.
|
|
type loadOptions struct {
|
|
codecPath string
|
|
useFA bool
|
|
clampFP16 bool
|
|
seed int64
|
|
denoise bool
|
|
}
|
|
|
|
func splitOption(o string) (key, value string, ok bool) {
|
|
i := strings.Index(o, ":")
|
|
if i < 0 {
|
|
return "", "", false
|
|
}
|
|
return strings.TrimSpace(o[:i]), strings.TrimSpace(o[i+1:]), true
|
|
}
|
|
|
|
// parseOptions reads the backend "key:value" option slice. Unknown keys are
|
|
// ignored. Defaults: seed -1 (engine default), denoise true.
|
|
func parseOptions(opts []string) loadOptions {
|
|
o := loadOptions{seed: -1, denoise: true}
|
|
for _, oo := range opts {
|
|
key, value, ok := splitOption(oo)
|
|
if !ok {
|
|
continue
|
|
}
|
|
switch key {
|
|
case "tokenizer", "codec":
|
|
o.codecPath = value
|
|
case "use_fa":
|
|
o.useFA = value == "true" || value == "1"
|
|
case "clamp_fp16":
|
|
o.clampFP16 = value == "true" || value == "1"
|
|
case "seed":
|
|
if n, err := strconv.ParseInt(value, 10, 64); err == nil {
|
|
o.seed = n
|
|
}
|
|
case "denoise":
|
|
o.denoise = value == "true" || value == "1"
|
|
}
|
|
}
|
|
return o
|
|
}
|
|
|
|
// languageNameAliases maps full language names to OmniVoice codes. OmniVoice's
|
|
// lang hint accepts "" (auto), "en", "zh" per the upstream convention; other
|
|
// codes pass through and the engine treats unknown hints as auto.
|
|
var languageNameAliases = map[string]string{
|
|
"english": "en",
|
|
"chinese": "zh",
|
|
}
|
|
|
|
// normalizeLanguage lowercases, trims, strips a region/locale suffix, and
|
|
// resolves common full names. Empty stays empty so the engine auto-detects.
|
|
func normalizeLanguage(lang string) string {
|
|
lang = strings.ToLower(strings.TrimSpace(lang))
|
|
if lang == "" {
|
|
return ""
|
|
}
|
|
if i := strings.IndexAny(lang, "-_."); i >= 0 {
|
|
lang = lang[:i]
|
|
}
|
|
if code, ok := languageNameAliases[lang]; ok {
|
|
return code
|
|
}
|
|
return lang
|
|
}
|