[feat] hf tts translation
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { ArrowLeft, ArrowRight, PencilIcon, LanguagesIcon, RefreshCcwIcon, TrashIcon, CopyIcon } from "lucide-svelte";
|
import { ArrowLeft, ArrowRight, PencilIcon, LanguagesIcon, RefreshCcwIcon, TrashIcon, CopyIcon, Volume2Icon } from "lucide-svelte";
|
||||||
import { ParseMarkdown, type simpleCharacterArgument } from "../../ts/parser";
|
import { ParseMarkdown, type simpleCharacterArgument } from "../../ts/parser";
|
||||||
import AutoresizeArea from "../UI/GUI/TextAreaResizable.svelte";
|
import AutoresizeArea from "../UI/GUI/TextAreaResizable.svelte";
|
||||||
import { alertConfirm, alertError } from "../../ts/alert";
|
import { alertConfirm, alertError } from "../../ts/alert";
|
||||||
@@ -10,6 +10,7 @@
|
|||||||
import { risuChatParser } from "src/ts/process/scripts";
|
import { risuChatParser } from "src/ts/process/scripts";
|
||||||
import { get } from "svelte/store";
|
import { get } from "svelte/store";
|
||||||
import { isEqual } from "lodash";
|
import { isEqual } from "lodash";
|
||||||
|
import { sayTTS } from "src/ts/process/tts";
|
||||||
export let message = ''
|
export let message = ''
|
||||||
export let name = ''
|
export let name = ''
|
||||||
export let largePortrait = false
|
export let largePortrait = false
|
||||||
@@ -145,6 +146,12 @@
|
|||||||
</button>
|
</button>
|
||||||
{/if}
|
{/if}
|
||||||
{#if idx > -1}
|
{#if idx > -1}
|
||||||
|
<button class="ml-2 hover:text-green-500 transition-colors" on:click={()=>{
|
||||||
|
return sayTTS(null, message)
|
||||||
|
}}>
|
||||||
|
<Volume2Icon size={20}/>
|
||||||
|
</button>
|
||||||
|
|
||||||
<button class={"ml-2 hover:text-green-500 transition-colors "+(editMode?'text-green-400':'')} on:click={() => {
|
<button class={"ml-2 hover:text-green-500 transition-colors "+(editMode?'text-green-400':'')} on:click={() => {
|
||||||
if(!editMode){
|
if(!editMode){
|
||||||
editMode = true
|
editMode = true
|
||||||
|
|||||||
@@ -301,7 +301,7 @@ export function characterFormatUpdate(index:number|character){
|
|||||||
depth: 0,
|
depth: 0,
|
||||||
prompt: ''
|
prompt: ''
|
||||||
}
|
}
|
||||||
cha.hfTTS = {
|
cha.hfTTS ??= {
|
||||||
model: '',
|
model: '',
|
||||||
language: 'en'
|
language: 'en'
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { get } from 'svelte/store'
|
import { get } from 'svelte/store'
|
||||||
import type { ScriptMode } from '../process/scripts'
|
import type { ScriptMode } from '../process/scripts'
|
||||||
|
//@ts-ignore
|
||||||
import WorkerUrl from './embedworker?worker&url'
|
import WorkerUrl from './embedworker?worker&url'
|
||||||
import { DataBase, type Chat, type character, type Message } from '../storage/database'
|
import { DataBase, type Chat, type character, type Message } from '../storage/database'
|
||||||
import { selectedCharID } from '../stores'
|
import { selectedCharID } from '../stores'
|
||||||
|
|||||||
@@ -53,3 +53,10 @@ export const runEmbedding = async (text: string):Promise<Float32Array> => {
|
|||||||
let result = await extractor(text, { pooling: 'mean', normalize: true });
|
let result = await extractor(text, { pooling: 'mean', normalize: true });
|
||||||
return result?.data ?? null;
|
return result?.data ?? null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const runTTS = async (text: string) => {
|
||||||
|
let speaker_embeddings = 'https://huggingface.co/datasets/Xenova/transformers.js-docs/resolve/main/speaker_embeddings.bin';
|
||||||
|
let synthesizer = await pipeline('text-to-speech', 'Xenova/speecht5_tts', { local_files_only: true });
|
||||||
|
let out = await synthesizer(text, { speaker_embeddings });
|
||||||
|
return out
|
||||||
|
}
|
||||||
@@ -1,14 +1,21 @@
|
|||||||
import { get } from "svelte/store";
|
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 { runTranslator, translateVox } from "../translator/translator";
|
||||||
import { globalFetch } from "../storage/globalApi";
|
import { globalFetch } from "../storage/globalApi";
|
||||||
import { language } from "src/lang";
|
import { language } from "src/lang";
|
||||||
import { sleep } from "../util";
|
import { getCurrentCharacter, sleep } from "../util";
|
||||||
|
|
||||||
let sourceNode:AudioBufferSourceNode = null
|
let sourceNode:AudioBufferSourceNode = null
|
||||||
|
|
||||||
export async function sayTTS(character:character,text:string) {
|
export async function sayTTS(character:character,text:string) {
|
||||||
|
if(!character){
|
||||||
|
const v = getCurrentCharacter()
|
||||||
|
if(v.type === 'group'){
|
||||||
|
return
|
||||||
|
}
|
||||||
|
character = v
|
||||||
|
}
|
||||||
|
|
||||||
let db = get(DataBase)
|
let db = get(DataBase)
|
||||||
text = text.replace(/\*/g,'')
|
text = text.replace(/\*/g,'')
|
||||||
@@ -164,6 +171,9 @@ export async function sayTTS(character:character,text:string) {
|
|||||||
}
|
}
|
||||||
case 'huggingface': {
|
case 'huggingface': {
|
||||||
while(true){
|
while(true){
|
||||||
|
if(character.hfTTS.language !== 'en'){
|
||||||
|
text = await runTranslator(text, false, 'en', character.hfTTS.language)
|
||||||
|
}
|
||||||
const audioContext = new AudioContext();
|
const audioContext = new AudioContext();
|
||||||
const response = await fetch(`https://api-inference.huggingface.co/models/${character.hfTTS.model}`, {
|
const response = await fetch(`https://api-inference.huggingface.co/models/${character.hfTTS.model}`, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ export async function translate(text:string, reverse:boolean) {
|
|||||||
return runTranslator(text, reverse, db.translator,db.aiModel.startsWith('novellist') ? 'ja' : 'en')
|
return runTranslator(text, reverse, db.translator,db.aiModel.startsWith('novellist') ? 'ja' : 'en')
|
||||||
}
|
}
|
||||||
|
|
||||||
async function runTranslator(text:string, reverse:boolean, from:string,target:'en'|'ja') {
|
export async function runTranslator(text:string, reverse:boolean, from:string,target:string) {
|
||||||
const arg = {
|
const arg = {
|
||||||
|
|
||||||
from: reverse ? from : target,
|
from: reverse ? from : target,
|
||||||
|
|||||||
@@ -366,3 +366,9 @@ export async function decryptBuffer(data:Uint8Array, keys:string){
|
|||||||
|
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getCurrentCharacter(){
|
||||||
|
const db = get(DataBase)
|
||||||
|
const selectedChar = get(selectedCharID)
|
||||||
|
return db.characters[selectedChar]
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user