Skip to content

Commit

Permalink
added support for coqui local tts server
Browse files Browse the repository at this point in the history
  • Loading branch information
flukexp committed Apr 11, 2024
1 parent d9b825d commit 91a179e
Show file tree
Hide file tree
Showing 7 changed files with 117 additions and 2 deletions.
17 changes: 16 additions & 1 deletion src/components/settings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ import { OpenAITTSSettingsPage } from './settings/OpenAITTSSettingsPage';

import { PiperSettingsPage } from './settings/PiperSettingsPage';

import { CoquiLocalSettingsPage } from './settings/CoquiLocalSettingsPage';

import { STTBackendPage } from './settings/STTBackendPage';
import { STTWakeWordSettingsPage } from './settings/STTWakeWordSettingsPage';

Expand Down Expand Up @@ -101,6 +103,9 @@ export const Settings = ({

const [piperUrl, setPiperUrl] = useState(config("piper_url"));

const [coquiLocalUrl, setCoquiLocalUrl] = useState(config("coquiLocal_url"));
const [coquiLocalVoiceId, setCoquiLocalVoiceId] = useState(config("coquiLocal_voiceid"));

const [visionBackend, setVisionBackend] = useState(config("vision_backend"));
const [visionLlamaCppUrl, setVisionLlamaCppUrl] = useState(config("vision_llamacpp_url"));
const [visionOllamaUrl, setVisionOllamaUrl] = useState(config("vision_ollama_url"));
Expand Down Expand Up @@ -214,6 +219,7 @@ export const Settings = ({
coquiApiKey, coquiVoiceId,
openAITTSApiKey, openAITTSUrl, openAITTSModel, openAITTSVoice,
piperUrl,
coquiLocalUrl,coquiLocalVoiceId,
visionBackend,
visionLlamaCppUrl,
visionOllamaUrl, visionOllamaModel,
Expand Down Expand Up @@ -253,7 +259,7 @@ export const Settings = ({

case 'tts':
return <MenuPage
keys={["tts_backend", "elevenlabs_settings", "speecht5_settings", "coqui_settings", "openai_tts_settings", "piper_settings"]}
keys={["tts_backend", "elevenlabs_settings", "speecht5_settings", "coqui_settings", "openai_tts_settings", "piper_settings", "coquiLocal_settings"]}
menuClick={handleMenuClick} />;

case 'stt':
Expand Down Expand Up @@ -411,6 +417,15 @@ export const Settings = ({
setPiperUrl={setPiperUrl}
setSettingsUpdated={setSettingsUpdated}
/>

case 'coquiLocal_settings':
return <CoquiLocalSettingsPage
coquiLocalUrl={coquiLocalUrl}
coquiLocalVoiceId={coquiLocalVoiceId}
setCoquiLocalVoiceId={setCoquiLocalVoiceId}
setCoquiLocalUrl={setCoquiLocalUrl}
setSettingsUpdated={setSettingsUpdated}
/>

case'stt_backend':
return <STTBackendPage
Expand Down
61 changes: 61 additions & 0 deletions src/components/settings/CoquiLocalSettingsPage.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import { useTranslation } from 'react-i18next';

import { BasicPage, FormRow, NotUsingAlert } from './common';
import { TextInput } from "@/components/textInput";
import { config, updateConfig } from "@/utils/config";

export function CoquiLocalSettingsPage({
coquiLocalUrl,
setCoquiLocalUrl,
setSettingsUpdated,
coquiLocalVoiceId,
setCoquiLocalVoiceId
}: {
coquiLocalUrl: string;
coquiLocalVoiceId: string;
setCoquiLocalUrl: (key: string) => void;
setSettingsUpdated: (updated: boolean) => void;
setCoquiLocalVoiceId: (key: string) => void;
}) {
const { t } = useTranslation();

return (
<BasicPage
title={t("CoquiLocal") + " "+ t("Settings")}
description={t("coquiLocal_desc", "Configure CoquiLocal")}
>
{ config("tts_backend") !== "coquiLocal" && (
<NotUsingAlert>
{t("not_using_alert", "You are not currently using {{name}} as your {{what}} backend. These settings will not be used.", {name: t("CoquiLocal"), what: t("TTS")})}
</NotUsingAlert>
) }
<ul role="list" className="divide-y divide-gray-100 max-w-xs">
<li className="py-4">
<FormRow label={t("URL")}>
<TextInput
value={coquiLocalUrl}
onChange={(event: React.ChangeEvent<any>) => {
setCoquiLocalUrl(event.target.value);
updateConfig("coquiLocal_url", event.target.value);
setSettingsUpdated(true);
}}
/>
<li className="py-4">
<FormRow label={t("Voice ID")}>
<TextInput
value={coquiLocalVoiceId}
onChange={(event: React.ChangeEvent<any>) => {
event.preventDefault();
setCoquiLocalVoiceId(event.target.value);
updateConfig("coquiLocal_voiceid", event.target.value);
setSettingsUpdated(true);
}}
/>
</FormRow>
</li>
</FormRow>
</li>
</ul>
</BasicPage>
);
}
3 changes: 2 additions & 1 deletion src/components/settings/TTSBackendPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ const ttsEngines = [
{key: "openai_tts", label: "OpenAI TTS"},
{key: "localXTTS", label: "Local XTTS"}, // Our local TTS endpoint (XTTS based)
{key: "piper", label: "Piper"},
{key: "coquiLocal", label: "Coqui Local"},
];

function idToTitle(id: string): string {
Expand Down Expand Up @@ -57,7 +58,7 @@ export function TTSBackendPage({
</select>
</FormRow>
</li>
{ ["elevenlabs", "speecht5", "coqui", "openai_tts", "piper"].includes(ttsBackend) && (
{ ["elevenlabs", "speecht5", "coqui", "openai_tts", "piper", "coquiLocal"].includes(ttsBackend) && (
<li className="py-4">
<FormRow label={`${t("Configure")} ${t(idToTitle(ttsBackend))}`}>
<button
Expand Down
2 changes: 2 additions & 0 deletions src/components/settings/common.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,7 @@ export function getIconFromPage(page: string): JSX.Element {
case 'coqui_settings': return <AdjustmentsHorizontalIcon className="h-5 w-5 flex-none text-gray-800" aria-hidden="true" />;
case 'openai_tts_settings': return <AdjustmentsHorizontalIcon className="h-5 w-5 flex-none text-gray-800" aria-hidden="true" />;
case 'piper_settings': return <AdjustmentsHorizontalIcon className="h-5 w-5 flex-none text-gray-800" aria-hidden="true" />;
case 'coquiLocal_settings': return <AdjustmentsHorizontalIcon className="h-5 w-5 flex-none text-gray-800" aria-hidden="true" />;

case 'stt_backend': return <PencilSquareIcon className="h-5 w-5 flex-none text-gray-800" aria-hidden="true" />;
case 'stt_wake_word': return <MoonIcon className="h-5 w-5 flex-none text-gray-800" aria-hidden="true" />;
Expand Down Expand Up @@ -197,6 +198,7 @@ function getLabelFromPage(page: string): string {
case 'coqui_settings': return t('Coqui');
case 'openai_tts_settings': return t('OpenAI');
case 'piper_settings': return t('Piper');
case 'coquiLocal_settings': return t('coquiLocal');

case 'vision_backend': return t('Vision Backend');
case 'vision_llamacpp_settings': return t('LLama.cpp');
Expand Down
5 changes: 5 additions & 0 deletions src/features/chat/chat.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { getWindowAiChatResponseStream } from './windowAiChat';
import { getOllamaChatResponseStream, getOllamaVisionChatResponse } from './ollamaChat';
import { getKoboldAiChatResponseStream } from './koboldAiChat';

import { coquiLocal} from "@/features/coquiLocal/coquiLocal";
import { piper} from "@/features/piper/piper";
import { elevenlabs } from "@/features/elevenlabs/elevenlabs";
import { coqui } from "@/features/coqui/coqui";
Expand Down Expand Up @@ -447,6 +448,10 @@ export class Chat {
const voice = await piper(talk.message);
return voice.audio;
}
case 'coquiLocal': {
const voice = await coquiLocal(talk.message);
return voice.audio;
}
}
} catch (e: any) {
console.error(e.toString());
Expand Down
29 changes: 29 additions & 0 deletions src/features/coquiLocal/coquiLocal.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { config } from '@/utils/config';

export async function coquiLocal(
message: string,
) {

const voiceId = config("coquiLocal_voiceid");
if (!voiceId) {
throw new Error("Invalid CoquiLocal TTS Voice Id");
}

try {
const res = await fetch(config("coquiLocal_url"), {
method: 'POST',
headers: {
'text': message,
'speaker-id': config("coquiLocal_voiceid"),
}
});

const data = await res.arrayBuffer()
return { audio: data };

} catch (error) {

console.error('Error in coquiLocal:', error);
throw error;
}
}
2 changes: 2 additions & 0 deletions src/utils/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ const defaults = {
openai_tts_model: process.env.NEXT_PUBLIC_OPENAI_TTS_MODEL ?? 'tts-1',
openai_tts_voice: process.env.NEXT_PUBLIC_OPENAI_TTS_VOICE ?? 'nova',
piper_url: process.env.NEXT_PUBLIC_PIPER_URL ?? 'http://localhost:5000',
coquiLocal_url: process.env.NEXT_PUBLIC_COQUILOCAL_URL ?? 'http://localhost:5002/api/tts',
coquiLocal_voiceid: process.env.NEXT_PUBLIC_COQUILOCAL_VOICEID ?? 'p240',
elevenlabs_apikey: process.env.NEXT_PUBLIC_ELEVENLABS_APIKEY ??'',
elevenlabs_voiceid: process.env.NEXT_PUBLIC_ELEVENLABS_VOICEID ?? '21m00Tcm4TlvDq8ikWAM',
elevenlabs_model: process.env.NEXT_PUBLIC_ELEVENLABS_MODEL ?? 'eleven_monolingual_v1',
Expand Down

0 comments on commit 91a179e

Please sign in to comment.