To use VOICEVOX, you need to run a colab and put the localtunnel URL in "Settings → Other Bots". https://colab.research.google.com/drive/1tyeXJSklNfjW-aZJAib1JfgOMFarAwze
{/if}
+ {#if currentChar.data.ttsMode === 'openai'}
+ OpenAI TTS uses your OpenAI key on the chat model section
+
+ Unset
+ {#each oaiVoices as voice}
+ {voice}
+ {/each}
+
+ {/if}
{#if currentChar.data.ttsMode === 'webspeech' || currentChar.data.ttsMode === 'elevenlab' || currentChar.data.ttsMode === 'VOICEVOX'}
diff --git a/src/ts/process/tts.ts b/src/ts/process/tts.ts
index 2c17908d..883e5b8f 100644
--- a/src/ts/process/tts.ts
+++ b/src/ts/process/tts.ts
@@ -2,6 +2,8 @@ import { get } from "svelte/store";
import { alertError } from "../alert";
import { DataBase, type character } from "../storage/database";
import { translateVox } from "../translator/translator";
+import { globalFetch } from "../storage/globalApi";
+import { language } from "src/lang";
let sourceNode:AudioBufferSourceNode = null
@@ -94,10 +96,55 @@ export async function sayTTS(character:character,text:string) {
}
}
}
+ case 'openai':{
+ const key = db.openAIKey
+ const res = await globalFetch('https://api.openai.com/v1/audio/speech', {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json',
+ 'Authorization': 'Bearer ' + key,
+ },
+ body: {
+ model: 'tts-1',
+ input: text,
+ voice: character.oaiVoice,
+
+ },
+ rawResponse: true,
+ })
+ const dat = res.data
+
+ if(res.ok){
+ try {
+ const audio = Buffer.from(dat).buffer
+ const audioContext = new AudioContext();
+ const audioBuffer = await audioContext.decodeAudioData(audio)
+ sourceNode = audioContext.createBufferSource();
+ sourceNode.buffer = audioBuffer;
+ sourceNode.connect(audioContext.destination);
+ sourceNode.start();
+ } catch (error) {
+ alertError(language.errors.httpError + `${error}`)
+ }
+ }
+ else{
+ if(dat.error && dat.error.message){
+ alertError((language.errors.httpError + `${dat.error.message}`))
+ }
+ else{
+ alertError((language.errors.httpError + `${JSON.stringify(res.data)}`))
+ }
+ }
+
+ }
}
}
+export const oaiVoices = [
+ 'alloy', 'echo', 'fable', 'onyx', 'nova', 'shimmer'
+]
+
export function stopTTS(){
if(sourceNode){
sourceNode.stop()
diff --git a/src/ts/storage/database.ts b/src/ts/storage/database.ts
index 9d0e7825..455c3397 100644
--- a/src/ts/storage/database.ts
+++ b/src/ts/storage/database.ts
@@ -574,6 +574,7 @@ export interface character{
license?:string
private?:boolean
additionalText:string
+ oaiVoice?:string
}
diff --git a/src/ts/translator/translator.ts b/src/ts/translator/translator.ts
index 9e1b71b4..5c60bc45 100644
--- a/src/ts/translator/translator.ts
+++ b/src/ts/translator/translator.ts
@@ -155,8 +155,5 @@ export async function translateVox(text:string) {
async function jaTrans(text:string) {
- if(/[\u3000-\u303f\u3040-\u309f\u30a0-\u30ff\uff00-\uff9f\u4e00-\u9faf\u3400-\u4dbf]/.test(text)){
- return text
- }
return await runTranslator(text,false, 'en','ja')
}
\ No newline at end of file