feat: per model tts voice

This commit is contained in:
Timothy Jaeryang Baek committed 2026-01-09 19:05:09 +04:00
1 parent 401c1949a0
commit bb6188abf0
3 files changed
+66 -15

No files matched your search

@@ -363,6 +363,19 @@
let currentMessageId = null;
let currentUtterance = null;
// Get voice: model-specific > user settings > config default
const getVoiceId = () => {
// Check for model-specific TTS voice first
if (model?.info?.meta?.tts?.voice) {
return model.info.meta.tts.voice;
}
// Fall back to user settings or config default
if ($settings?.audio?.tts?.defaultVoice === $config.audio.tts.voice) {
return $settings?.audio?.tts?.voice ?? $config?.audio?.tts?.voice;
}
return $config?.audio?.tts?.voice;
};
const speakSpeechSynthesisHandler = (content) => {
if ($showCallOverlay) {
return new Promise((resolve) => {
@@ -372,11 +385,10 @@
if (voices.length > 0) {
clearInterval(getVoicesLoop);
const voiceId = getVoiceId();
const voice =
voices
?.filter(
(v) => v.voiceURI === ($settings?.audio?.tts?.voice ?? $config?.audio?.tts?.voice)
)
?.filter((v) => v.voiceURI === voiceId)
?.at(0) ?? undefined;
currentUtterance = new SpeechSynthesisUtterance(content);
@@ -471,7 +483,7 @@
const url = await $TTSWorker
.generate({
text: content,
voice: $settings?.audio?.tts?.voice ?? $config?.audio?.tts?.voice
voice: getVoiceId()
})
.catch((error) => {
console.error(error);
@@ -484,9 +496,7 @@
} else if ($config.audio.tts.engine !== '') {
const res = await synthesizeOpenAISpeech(
localStorage.token,
$settings?.audio?.tts?.defaultVoice === $config.audio.tts.voice
? ($settings?.audio?.tts?.voice ?? $config?.audio?.tts?.voice)
: $config?.audio?.tts?.voice,
getVoiceId(),
content
).catch((error) => {
console.error(error);
@@ -207,6 +207,19 @@
speaking = true;
const content = removeAllDetails(message.content);
// Get voice: model-specific > user settings > config default
const getVoiceId = () => {
// Check for model-specific TTS voice first
if (model?.info?.meta?.tts?.voice) {
return model.info.meta.tts.voice;
}
// Fall back to user settings or config default
if ($settings?.audio?.tts?.defaultVoice === $config.audio.tts.voice) {
return $settings?.audio?.tts?.voice ?? $config?.audio?.tts?.voice;
}
return $config?.audio?.tts?.voice;
};
if ($config.audio.tts.engine === '') {
let voices = [];
const getVoicesLoop = setInterval(() => {
@@ -214,11 +227,10 @@
if (voices.length > 0) {
clearInterval(getVoicesLoop);
const voiceId = getVoiceId();
const voice =
voices
?.filter(
(v) => v.voiceURI === ($settings?.audio?.tts?.voice ?? $config?.audio?.tts?.voice)
)
?.filter((v) => v.voiceURI === voiceId)
?.at(0) ?? undefined;
console.log(voice);
@@ -265,7 +277,9 @@
return;
}
console.debug('Prepared message content for TTS', messageContentParts);
const voiceId = getVoiceId();
console.debug('Prepared message content for TTS', messageContentParts, 'voice:', voiceId);
if ($settings.audio?.tts?.engine === 'browser-kokoro') {
if (!$TTSWorker) {
await TTSWorker.set(
@@ -281,7 +295,7 @@
const url = await $TTSWorker
.generate({
text: sentence,
voice: $settings?.audio?.tts?.voice ?? $config?.audio?.tts?.voice
voice: voiceId
})
.catch((error) => {
console.error(error);
@@ -300,9 +314,7 @@
for (const [idx, sentence] of messageContentParts.entries()) {
const res = await synthesizeOpenAISpeech(
localStorage.token,
$settings?.audio?.tts?.defaultVoice === $config.audio.tts.voice
? ($settings?.audio?.tts?.voice ?? $config?.audio?.tts?.voice)
: $config?.audio?.tts?.voice,
voiceId,
sentence
).catch((error) => {
console.error(error);
@@ -324,6 +336,7 @@
}
};
let preprocessedDetailsCache = [];
function preprocessForEditing(content: string): string {