feat: Add normalization for voice preview and improve voice resolution logic

This commit is contained in:
JB
2025-10-12 17:00:49 -07:00
parent 9ee53fc886
commit a2c08b1b4d
3 changed files with 25 additions and 3 deletions
+11 -1
View File
@@ -44,7 +44,7 @@ from abogen.constants import (
SUPPORTED_SOUND_FORMATS,
VOICES_INTERNAL,
)
from abogen.kokoro_text_normalization import normalize_roman_numeral_titles
from abogen.kokoro_text_normalization import normalize_for_pipeline, normalize_roman_numeral_titles
from abogen.utils import (
calculate_text_length,
get_user_output_path,
@@ -2488,6 +2488,11 @@ def api_preview_voice_mix() -> ResponseReturnValue:
if voice_choice is None:
abort(400, "Unable to resolve voice selection")
try:
text = normalize_for_pipeline(text)
except Exception:
current_app.logger.exception("Voice preview normalization failed; using raw text")
segments = pipeline(
text,
voice=voice_choice,
@@ -2584,6 +2589,11 @@ def api_speaker_preview() -> ResponseReturnValue:
except ValueError as exc:
abort(400, str(exc))
try:
text = normalize_for_pipeline(text)
except Exception:
current_app.logger.exception("Preview normalization failed; using raw text")
segments = pipeline(
text,
voice=voice_choice,
+11 -2
View File
@@ -1855,8 +1855,14 @@ const initPrepare = (root = document) => {
};
const resolveOverrideVoice = (data) => {
if (data.voice) {
return data.voice;
const hasVoiceProp = Boolean(data && Object.prototype.hasOwnProperty.call(data, "voice"));
const voiceValueRaw = typeof data?.voice === "string" ? data.voice : "";
const voiceValue = voiceValueRaw.trim();
if (voiceValue) {
return voiceValue;
}
if (hasVoiceProp) {
return "";
}
const normalizedKey = canonicalizeEntityKey(data.normalized || data.token || "");
let genderHint = (data.gender || "").toLowerCase();
@@ -1878,6 +1884,9 @@ const initPrepare = (root = document) => {
genderHint = "";
}
}
if (baseVoice) {
return "";
}
return pickRandomVoiceForOverride(genderHint);
};
+3
View File
@@ -1625,6 +1625,9 @@ button.step-indicator__item:focus-visible {
border: 1px solid rgba(148, 163, 184, 0.2);
box-shadow: 0 18px 38px rgba(15, 23, 42, 0.35);
backdrop-filter: blur(4px);
position: sticky;
top: max(env(safe-area-inset-top), 0.5rem);
z-index: 25;
}
.entity-tabs__tab {