import { cancelTtsPlay, eventSource, event_types, getCurrentChatId, isStreamingEnabled, name2, saveSettingsDebounced, substituteParams } from '../../../script.js'; import { ModuleWorkerWrapper, extension_settings, getContext, renderExtensionTemplateAsync } from '../../extensions.js'; import { delay, escapeRegex, getBase64Async, getStringHash, onlyUnique } from '../../utils.js'; import { EdgeTtsProvider } from './edge.js'; import { ElevenLabsTtsProvider } from './elevenlabs.js'; import { SileroTtsProvider } from './silerotts.js'; import { GptSovitsV2Provider } from './gpt-sovits-v2.js'; import { CoquiTtsProvider } from './coqui.js'; import { SystemTtsProvider } from './system.js'; import { NovelTtsProvider } from './novel.js'; import { power_user } from '../../power-user.js'; import { OpenAITtsProvider } from './openai.js'; import { OpenAICompatibleTtsProvider } from './openai-compatible.js'; import { XTTSTtsProvider } from './xtts.js'; import { VITSTtsProvider } from './vits.js'; import { GSVITtsProvider } from './gsvi.js'; import { SBVits2TtsProvider } from './sbvits2.js'; import { AllTalkTtsProvider } from './alltalk.js'; import { CosyVoiceProvider } from './cosyvoice.js'; import { SpeechT5TtsProvider } from './speecht5.js'; import { AzureTtsProvider } from './azure.js'; import { SlashCommandParser } from '../../slash-commands/SlashCommandParser.js'; import { SlashCommand } from '../../slash-commands/SlashCommand.js'; import { ARGUMENT_TYPE, SlashCommandArgument, SlashCommandNamedArgument } from '../../slash-commands/SlashCommandArgument.js'; import { debounce_timeout } from '../../constants.js'; import { SlashCommandEnumValue, enumTypes } from '../../slash-commands/SlashCommandEnumValue.js'; import { enumIcons } from '../../slash-commands/SlashCommandCommonEnumsProvider.js'; import { POPUP_TYPE, callGenericPopup } from '../../popup.js'; import { GoogleTranslateTtsProvider } from './google-translate.js'; import { GoogleNativeTtsProvider } from './google-native.js'; import { ChatterboxTtsProvider } from './chatterbox.js'; import { KokoroTtsProvider } from './kokoro.js'; import { TtsWebuiProvider } from './tts-webui.js'; const UPDATE_INTERVAL = 1000; const wrapper = new ModuleWorkerWrapper(moduleWorker); let voiceMapEntries = []; let voiceMap = {}; // {charName:voiceid, charName2:voiceid2} let lastChatId = null; let lastMessage = null; let lastMessageHash = null; let periodicMessageGenerationTimer = null; let lastPositionOfParagraphEnd = -1; let currentInitVoiceMapPromise = null; const DEFAULT_VOICE_MARKER = '[Default Voice]'; const DISABLED_VOICE_MARKER = 'disabled'; export function getPreviewString(lang) { const previewStrings = { 'en-US': 'The quick brown fox jumps over the lazy dog', 'en-GB': 'Sphinx of black quartz, judge my vow', 'fr-FR': 'Portez ce vieux whisky au juge blond qui fume', 'de-DE': 'Victor jagt zwölf Boxkämpfer quer über den großen Sylter Deich', 'it-IT': 'Pranzo d\'acqua fa volti sghembi', 'es-ES': 'Quiere la boca exhausta vid, kiwi, piña y fugaz jamón', 'es-MX': 'Fabio me exige, sin tapujos, que añada cerveza al whisky', 'ru-RU': 'В чащах юга жил бы цитрус? Да, но фальшивый экземпляр!', 'pt-BR': 'Vejo xá gritando que fez show sem playback.', 'pt-PR': 'Todo pajé vulgar faz boquinha sexy com kiwi.', 'uk-UA': 'Фабрикуймо гідність, лящім їжею, ґав хапаймо, з\'єднавці чаш!', 'pl-PL': 'Pchnąć w tę łódź jeża lub ośm skrzyń fig', 'cs-CZ': 'Příliš žluťoučký kůň úpěl ďábelské ódy', 'sk-SK': 'Vyhŕňme si rukávy a vyprážajme čínske ryžové cestoviny', 'hu-HU': 'Árvíztűrő tükörfúrógép', 'tr-TR': 'Pijamalı hasta yağız şoföre çabucak güvendi', 'nl-NL': 'De waard heeft een kalfje en een pinkje opgegeten', 'sv-SE': 'Yxskaftbud, ge vårbygd, zinkqvarn', 'da-DK': 'Quizdeltagerne spiste jordbær med fløde, mens cirkusklovnen Walther spillede på xylofon', 'ja-JP': 'いろはにほへと ちりぬるを わかよたれそ つねならむ うゐのおくやま けふこえて あさきゆめみし ゑひもせす', 'ko-KR': '가나다라마바사아자차카타파하', 'zh-CN': '我能吞下玻璃而不伤身体', 'ro-RO': 'Muzicologă în bej vând whisky și tequila, preț fix', 'bg-BG': 'Щъркелите се разпръснаха по цялото небе', 'el-GR': 'Ταχίστη αλώπηξ βαφής ψημένη γη, δρασκελίζει υπέρ νωθρού κυνός', 'fi-FI': 'Voi veljet, miksi juuri teille myin nämä vehkeet?', 'he-IL': 'הקצינים צעקו: "כל הכבוד לצבא הצבאות!"', 'id-ID': 'Jangkrik itu memang enak, apalagi kalau digoreng', 'ms-MY': 'Muzik penyanyi wanita itu menggambarkan kehidupan yang penuh dengan duka nestapa', 'th-TH': 'เป็นไงบ้างครับ ผมชอบกินข้าวผัดกระเพราหมูกรอบ', 'vi-VN': 'Cô bé quàng khăn đỏ đang ngồi trên bãi cỏ xanh', 'ar-SA': 'أَبْجَدِيَّة عَرَبِيَّة', 'hi-IN': 'श्वेता ने श्वेता के श्वेते हाथों में श्वेता का श्वेता चावल पकड़ा', }; const fallbackPreview = 'Neque porro quisquam est qui dolorem ipsum quia dolor sit amet'; return previewStrings[lang] ?? fallbackPreview; } /** * Registers a TTS provider. * @param {string} name Name of the TTS provider to register. * @param {function} provider Provider class. */ export function registerTtsProvider(name, provider) { if (!name || typeof name !== 'string') { throw new Error(`TTS provider name ${name} is not a valid string.`); } if (!provider || typeof provider !== 'function') { throw new Error(`TTS provider ${name} is not a valid provider class.`); } if (ttsProviders[name]) { throw new Error(`TTS provider ${name} is already registered.`); } ttsProviders[name] = provider; console.info(`Registered TTS provider: ${name}`); $('#tts_provider').append($('