From 42083b371b28dfbb2a9e23b00de12b155fbc5724 Mon Sep 17 00:00:00 2001 From: XTer Date: Thu, 14 Mar 2024 00:36:56 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E4=BA=86=E7=AC=AC=E4=B8=80?= =?UTF-8?q?=E7=89=88GSVI=E7=9A=84TTS=E9=80=82=E9=85=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- public/scripts/extensions/tts/gsvi.js | 268 +++++++++++++++++++++++++ public/scripts/extensions/tts/index.js | 2 + 2 files changed, 270 insertions(+) create mode 100644 public/scripts/extensions/tts/gsvi.js diff --git a/public/scripts/extensions/tts/gsvi.js b/public/scripts/extensions/tts/gsvi.js new file mode 100644 index 000000000..fc39a4c41 --- /dev/null +++ b/public/scripts/extensions/tts/gsvi.js @@ -0,0 +1,268 @@ +import { doExtrasFetch, getApiUrl, modules } from '../../extensions.js'; +import { saveTtsProviderSettings } from './index.js'; + +export { GSVITtsProvider }; + +class GSVITtsProvider { + //########// + // Config // + //########// + + settings; + ready = false; + separator = '. '; + + characterList = {}; + voices = []; + /** + * Perform any text processing before passing to TTS engine. + * @param {string} text Input text + * @returns {string} Processed text + */ + processText(text) { + text = text.replace('
', '\n'); // Replace
with newline + return text; + } + + languageLabels = { + '多语种混合': '多语种混合', + '中文': '中文', + '英文': '英文', + '日文': '日文', + '中英混合': '中英混合', + '日英混合': '日英混合', + }; + defaultSettings = { + provider_endpoint: 'http://127.0.0.1:5000', + + language: '多语种混合', + + cha_name: '', + character_emotion: 'default', + + speed: 1, + + top_k: 6, + top_p: 0.85, + temperature: 0.75, + batch_size: 10, + + stream: false, + stream_chunk_size: 100, + }; + + + // 新增获取角色和情绪的方法 + async fetchCharacterList() { + const response = await fetch(this.settings.provider_endpoint + '/character_list'); + if (!response.ok) { + throw new Error(`HTTP ${response.status}: ${await response.text()}`); + } + const characterList = await response.json(); + this.characterList = characterList; + this.voices = Object.keys(characterList); + + } + + + + get settingsHtml() { + let html = ` + + +
+ + + + + +
Goto API Document.
+ + + + + + + + + + + + + + + + + + + + + + `; + + return html; + } + + onSettingsChange() { + // Update provider settings based on input fields + this.settings.provider_endpoint = $('#gsvi_tts_endpoint').val(); + this.settings.language = $('#gsvi_api_language').val(); + + + // Update the rest of TTS settings based on input fields + this.settings.speed = parseFloat($('#gsvi_speed').val()); + this.settings.temperature = parseFloat($('#gsvi_temperature').val()); + this.settings.top_k = parseInt($('#gsvi_top_k').val(), 10); + this.settings.top_p = parseFloat($('#gsvi_top_p').val()); + this.settings.batch_size = parseInt($('#gsvi_batch_size').val(), 10); + this.settings.stream = $('#gsvi_tts_streaming').is(':checked'); + this.settings.stream_chunk_size = parseInt($('#gsvi_stream_chunk_size').val(), 10); + + // Update UI to reflect changes + $('#gsvi_tts_speed_output').text(this.settings.speed); + $('#gsvi_tts_temperature_output').text(this.settings.temperature); + $('#gsvi_top_k_output').text(this.settings.top_k); + $('#gsvi_top_p_output').text(this.settings.top_p); + $('#gsvi_stream_chunk_size_output').text(this.settings.stream_chunk_size); + $('#gsvi_batch_size_output').text(this.settings.batch_size); + + + + + // Persist settings changes + saveTtsProviderSettings(); + + } + + async loadSettings(settings) { + // Populate Provider UI given input settings + if (Object.keys(settings).length === 0) { + console.info('Using default TTS Provider settings'); + } + + // Only accept keys defined in defaultSettings + this.settings = { ...this.defaultSettings, ...settings }; + + // Fetch character and emotion list + // Set initial values from the settings + $('#gsvi_tts_endpoint').val(this.settings.provider_endpoint); + $('#gsvi_api_language').val(this.settings.language); + + $('#gsvi_speed').val(this.settings.speed); + $('#gsvi_temperature').val(this.settings.temperature); + $('#gsvi_top_k').val(this.settings.top_k); + $('#gsvi_top_p').val(this.settings.top_p); + $('#gsvi_batch_size').val(this.settings.batch_size); + $('#gsvi_tts_streaming').prop('checked', this.settings.stream); + $('#gsvi_stream_chunk_size').val(this.settings.stream_chunk_size); + + // Update UI to reflect initial settings + $('#gsvi_tts_speed_output').text(this.settings.speed); + $('#gsvi_tts_temperature_output').text(this.settings.temperature); + $('#gsvi_top_k_output').text(this.settings.top_k); + $('#gsvi_top_p_output').text(this.settings.top_p); + $('#gsvi_stream_chunk_size_output').text(this.settings.stream_chunk_size); + + // Register event listeners to update settings on user interaction + // (Similar to before, ensure event listeners for character and emotion selection are included) + // Register input/change event listeners to update settings on user interaction + $('#xtts_tts_endpoint').on('input', () => { this.onSettingsChange(); }); + $('#gsvi_api_language').on('change', () => { this.onSettingsChange(); }); + + $('#gsvi_speed').on('input', () => { this.onSettingsChange(); }); + $('#gsvi_temperature').on('input', () => { this.onSettingsChange(); }); + $('#gsvi_top_k').on('input', () => { this.onSettingsChange(); }); + $('#gsvi_top_p').on('input', () => { this.onSettingsChange(); }); + $('#gsvi_batch_size').on('input', () => { this.onSettingsChange(); }); + $('#gsvi_tts_streaming').on('change', () => { this.onSettingsChange(); }); + $('#gsvi_stream_chunk_size').on('input', () => { this.onSettingsChange(); }); + + + await this.checkReady(); + console.debug('GSVI: Settings loaded'); + } + + + + // Perform a simple readiness check by trying to fetch voiceIds + async checkReady() { + await Promise.allSettled([this.fetchCharacterList()]); + } + + async onRefreshClick() { + return; + } + + //#################// + // TTS Interfaces // + //#################// + + async getVoice(voiceName) { + if (this.voices.length == 0) { + this.fetchCharacterList(); + } + if (!this.voices.includes(voiceName)) { + throw `TTS Voice name ${voiceName} not found`; + } + return { name: voiceName, voice_id: voiceName, preview_url: false, lang: 'zh-CN' }; + } + + async generateTts(text, voiceId) { + const response = await this.fetchTtsGeneration(text, voiceId); + return response; + } + + //###########// + // API CALLS // + //###########// + async fetchTtsVoiceObjects() { + if (this.voices.length == 0) { + await this.fetchCharacterList(); + } + console.log(this.voices); + const voices = this.voices.map(x => ({ name: x, voice_id: x, preview_url: false, lang: 'zh-CN' })); + return voices; + } + + + async fetchTtsGeneration(inputText, voiceId) { + console.info(`Generating new TTS for voice_id ${voiceId}`); + + + const params = new URLSearchParams(); + params.append('text', inputText); + params.append('cha_name', voiceId); + params.append('text_language', this.settings.language); + params.append('batch_size', this.settings.batch_size.toString()); + params.append('speed', this.settings.speed.toString()); + params.append('top_k', this.settings.top_k.toString()); + params.append('top_p', this.settings.top_p.toString()); + params.append('temperature', this.settings.temperature.toString()); + params.append('stream', this.settings.stream.toString()); + + + return `${this.settings.provider_endpoint}/tts?${params.toString()}`; + + } + + // Interface not used by GSVI TTS + async fetchTtsFromHistory(history_item_id) { + return Promise.resolve(history_item_id); + } + +} diff --git a/public/scripts/extensions/tts/index.js b/public/scripts/extensions/tts/index.js index b86e42ede..a1f2382d6 100644 --- a/public/scripts/extensions/tts/index.js +++ b/public/scripts/extensions/tts/index.js @@ -11,6 +11,7 @@ import { power_user } from '../../power-user.js'; import { registerSlashCommand } from '../../slash-commands.js'; import { OpenAITtsProvider } from './openai.js'; import { XTTSTtsProvider } from './xtts.js'; +import { GSVITtsProvider } from './gsvi.js'; import { AllTalkTtsProvider } from './alltalk.js'; import { SpeechT5TtsProvider } from './speecht5.js'; export { talkingAnimation }; @@ -71,6 +72,7 @@ let ttsProviders = { ElevenLabs: ElevenLabsTtsProvider, Silero: SileroTtsProvider, XTTSv2: XTTSTtsProvider, + GSVI: GSVITtsProvider, System: SystemTtsProvider, Coqui: CoquiTtsProvider, Edge: EdgeTtsProvider,