feat: Add ElevenLabs TTS provider and response splitting options

This commit is contained in:
n4ze3m
2024-12-28 20:10:50 +05:30
parent aa49f03f63
commit 3ddb7f1ad8
7 changed files with 454 additions and 57 deletions

View File

@@ -0,0 +1,49 @@
import axios from 'axios';
export interface Voice {
voice_id: string;
name: string;
}
export interface Model {
model_id: string;
name: string;
}
const BASE_URL = 'https://api.elevenlabs.io/v1';
export const getVoices = async (apiKey: string): Promise<Voice[]> => {
const response = await axios.get(`${BASE_URL}/voices`, {
headers: { 'xi-api-key': apiKey }
});
return response.data.voices;
};
export const getModels = async (apiKey: string): Promise<Model[]> => {
const response = await axios.get(`${BASE_URL}/models`, {
headers: { 'xi-api-key': apiKey }
});
return response.data;
};
export const generateSpeech = async (
apiKey: string,
text: string,
voiceId: string,
modelId: string
): Promise<ArrayBuffer> => {
const response = await axios.post(
`${BASE_URL}/text-to-speech/${voiceId}`,
{
text,
model_id: modelId,
},
{
headers: {
'xi-api-key': apiKey,
'Content-Type': 'application/json',
},
responseType: 'arraybuffer',
}
);
return response.data;
};

View File

@@ -4,7 +4,7 @@ const storage = new Storage()
const DEFAULT_TTS_PROVIDER = "browser"
const AVAILABLE_TTS_PROVIDERS = ["browser"] as const
const AVAILABLE_TTS_PROVIDERS = ["browser", "elevenlabs"] as const
export const getTTSProvider = async (): Promise<
(typeof AVAILABLE_TTS_PROVIDERS)[number]
@@ -63,22 +63,78 @@ export const setSSMLEnabled = async (isSSMLEnabled: boolean) => {
await storage.set("isSSMLEnabled", isSSMLEnabled.toString())
}
export const getElevenLabsApiKey = async () => {
const data = await storage.get("elevenLabsApiKey")
return data
}
export const setElevenLabsApiKey = async (elevenLabsApiKey: string) => {
await storage.set("elevenLabsApiKey", elevenLabsApiKey)
}
export const getElevenLabsVoiceId = async () => {
const data = await storage.get("elevenLabsVoiceId")
return data
}
export const setElevenLabsVoiceId = async (elevenLabsVoiceId: string) => {
await storage.set("elevenLabsVoiceId", elevenLabsVoiceId)
}
export const getElevenLabsModel = async () => {
const data = await storage.get("elevenLabsModel")
return data
}
export const setElevenLabsModel = async (elevenLabsModel: string) => {
await storage.set("elevenLabsModel", elevenLabsModel)
}
export const getResponseSplitting = async () => {
const data = await storage.get("ttsResponseSplitting")
if (!data || data.length === 0 || data === "") {
return "punctuation"
}
return data
}
export const setResponseSplitting = async (responseSplitting: string) => {
await storage.set("ttsResponseSplitting", responseSplitting)
}
export const getTTSSettings = async () => {
const [ttsEnabled, ttsProvider, browserTTSVoices, voice, ssmlEnabled] =
await Promise.all([
isTTSEnabled(),
getTTSProvider(),
getBrowserTTSVoices(),
getVoice(),
isSSMLEnabled()
])
const [
ttsEnabled,
ttsProvider,
browserTTSVoices,
voice,
ssmlEnabled,
elevenLabsApiKey,
elevenLabsVoiceId,
elevenLabsModel,
responseSplitting
] = await Promise.all([
isTTSEnabled(),
getTTSProvider(),
getBrowserTTSVoices(),
getVoice(),
isSSMLEnabled(),
getElevenLabsApiKey(),
getElevenLabsVoiceId(),
getElevenLabsModel(),
getResponseSplitting()
])
return {
ttsEnabled,
ttsProvider,
browserTTSVoices,
voice,
ssmlEnabled
ssmlEnabled,
elevenLabsApiKey,
elevenLabsVoiceId,
elevenLabsModel,
responseSplitting
}
}
@@ -86,17 +142,29 @@ export const setTTSSettings = async ({
ttsEnabled,
ttsProvider,
voice,
ssmlEnabled
ssmlEnabled,
elevenLabsApiKey,
elevenLabsVoiceId,
elevenLabsModel,
responseSplitting
}: {
ttsEnabled: boolean
ttsProvider: string
voice: string
ssmlEnabled: boolean
elevenLabsApiKey: string
elevenLabsVoiceId: string
elevenLabsModel: string
responseSplitting: string
}) => {
await Promise.all([
setTTSEnabled(ttsEnabled),
setTTSProvider(ttsProvider),
setVoice(voice),
setSSMLEnabled(ssmlEnabled)
setSSMLEnabled(ssmlEnabled),
setElevenLabsApiKey(elevenLabsApiKey),
setElevenLabsVoiceId(elevenLabsVoiceId),
setElevenLabsModel(elevenLabsModel),
setResponseSplitting(responseSplitting)
])
}