[feat] oai tts
This commit is contained in:
@@ -15,7 +15,7 @@
|
|||||||
import Help from "../Others/Help.svelte";
|
import Help from "../Others/Help.svelte";
|
||||||
import RegexData from "./Scripts/RegexData.svelte";
|
import RegexData from "./Scripts/RegexData.svelte";
|
||||||
import { exportChar, shareRisuHub } from "src/ts/characterCards";
|
import { exportChar, shareRisuHub } from "src/ts/characterCards";
|
||||||
import { getElevenTTSVoices, getWebSpeechTTSVoices, getVOICEVOXVoices } from "src/ts/process/tts";
|
import { getElevenTTSVoices, getWebSpeechTTSVoices, getVOICEVOXVoices, oaiVoices } from "src/ts/process/tts";
|
||||||
import { checkCharOrder, getFileSrc } from "src/ts/storage/globalApi";
|
import { checkCharOrder, getFileSrc } from "src/ts/storage/globalApi";
|
||||||
import { addGroupChar, rmCharFromGroup } from "src/ts/process/group";
|
import { addGroupChar, rmCharFromGroup } from "src/ts/process/group";
|
||||||
import RealmUpload from "../UI/Realm/RealmUpload.svelte";
|
import RealmUpload from "../UI/Realm/RealmUpload.svelte";
|
||||||
@@ -529,6 +529,7 @@
|
|||||||
<OptionInput value="elevenlab">ElevenLabs</OptionInput>
|
<OptionInput value="elevenlab">ElevenLabs</OptionInput>
|
||||||
<OptionInput value="webspeech">Web Speech</OptionInput>
|
<OptionInput value="webspeech">Web Speech</OptionInput>
|
||||||
<OptionInput value="VOICEVOX">VOICEVOX</OptionInput>
|
<OptionInput value="VOICEVOX">VOICEVOX</OptionInput>
|
||||||
|
<OptionInput value="openai">OpenAI</OptionInput>
|
||||||
</SelectInput>
|
</SelectInput>
|
||||||
|
|
||||||
|
|
||||||
@@ -588,6 +589,15 @@
|
|||||||
<NumberInput size={"sm"} marginBottom bind:value={currentChar.data.voicevoxConfig.INTONATION_SCALE}/>
|
<NumberInput size={"sm"} marginBottom bind:value={currentChar.data.voicevoxConfig.INTONATION_SCALE}/>
|
||||||
<span class="text-sm mb-2 text-textcolor2">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</span>
|
<span class="text-sm mb-2 text-textcolor2">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</span>
|
||||||
{/if}
|
{/if}
|
||||||
|
{#if currentChar.data.ttsMode === 'openai'}
|
||||||
|
<span class="text-textcolor">OpenAI TTS uses your OpenAI key on the chat model section</span>
|
||||||
|
<SelectInput className="mb-4 mt-2" bind:value={currentChar.data.oaiVoice}>
|
||||||
|
<OptionInput value="">Unset</OptionInput>
|
||||||
|
{#each oaiVoices as voice}
|
||||||
|
<OptionInput value={voice}>{voice}</OptionInput>
|
||||||
|
{/each}
|
||||||
|
</SelectInput>
|
||||||
|
{/if}
|
||||||
{#if currentChar.data.ttsMode === 'webspeech' || currentChar.data.ttsMode === 'elevenlab' || currentChar.data.ttsMode === 'VOICEVOX'}
|
{#if currentChar.data.ttsMode === 'webspeech' || currentChar.data.ttsMode === 'elevenlab' || currentChar.data.ttsMode === 'VOICEVOX'}
|
||||||
<div class="flex items-center mt-2">
|
<div class="flex items-center mt-2">
|
||||||
<Check bind:check={currentChar.data.ttsReadOnlyQuoted} name={language.ttsReadOnlyQuoted}/>
|
<Check bind:check={currentChar.data.ttsReadOnlyQuoted} name={language.ttsReadOnlyQuoted}/>
|
||||||
|
|||||||
@@ -2,6 +2,8 @@ import { get } from "svelte/store";
|
|||||||
import { alertError } from "../alert";
|
import { alertError } from "../alert";
|
||||||
import { DataBase, type character } from "../storage/database";
|
import { DataBase, type character } from "../storage/database";
|
||||||
import { translateVox } from "../translator/translator";
|
import { translateVox } from "../translator/translator";
|
||||||
|
import { globalFetch } from "../storage/globalApi";
|
||||||
|
import { language } from "src/lang";
|
||||||
|
|
||||||
let sourceNode:AudioBufferSourceNode = null
|
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(){
|
export function stopTTS(){
|
||||||
if(sourceNode){
|
if(sourceNode){
|
||||||
sourceNode.stop()
|
sourceNode.stop()
|
||||||
|
|||||||
@@ -574,6 +574,7 @@ export interface character{
|
|||||||
license?:string
|
license?:string
|
||||||
private?:boolean
|
private?:boolean
|
||||||
additionalText:string
|
additionalText:string
|
||||||
|
oaiVoice?:string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -155,8 +155,5 @@ export async function translateVox(text:string) {
|
|||||||
|
|
||||||
|
|
||||||
async function jaTrans(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')
|
return await runTranslator(text,false, 'en','ja')
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user