Merge pull request #2804 from v3ucn/CosyVoice TTS API for the CosyVoice

010b3fa49230e98f6e5c2da05f1f987d8016e7aa

Cohee <18619528+Cohee1207@users.noreply.github.com>

Signed
2 files changed, +208 -0Ignore whitespace
public/scripts/extensions/tts/cosyvoice.js+206 -0
@@ -0,0 +1,206 @@
1import { saveTtsProviderSettings } from './index.js';
2
3export { CosyVoiceProvider };
4
5class CosyVoiceProvider {
6 //########//
7 // Config //
8 //########//
9
10 settings;
11 ready = false;
12 voices = [];
13 separator = '. ';
14 audioElement = document.createElement('audio');
15
16 /**
17 * Perform any text processing before passing to TTS engine.
18 * @param {string} text Input text
19 * @returns {string} Processed text
20 */
21 processText(text) {
22 return text;
23 }
24
25 audioFormats = ['wav', 'ogg', 'silk', 'mp3', 'flac'];
26
27 languageLabels = {
28 'Auto': 'auto',
29 };
30
31 langKey2LangCode = {
32 'zh': 'zh-CN',
33 'en': 'en-US',
34 'ja': 'ja-JP',
35 'ko': 'ko-KR',
36 };
37
38 modelTypes = {
39 CosyVoice: 'CosyVoice',
40 };
41
42 defaultSettings = {
43 provider_endpoint: 'http://localhost:9880',
44 format: 'wav',
45 lang: 'auto',
46 streaming: false,
47
48 };
49
50 get settingsHtml() {
51 let html = `
52
53 <label for="tts_endpoint">Provider Endpoint:</label>
54 <input id="tts_endpoint" type="text" class="text_pole" maxlength="250" height="300" value="${this.defaultSettings.provider_endpoint}"/>
55 <span>Windows users Use <a target="_blank" href="https://github.com/v3ucn/CosyVoice_For_Windows">CosyVoice_For_Windows</a>(Unofficial).</span><br/>
56 <span>Macos Users Use <a target="_blank" href="https://github.com/v3ucn/CosyVoice_for_MacOs">CosyVoice_for_MacOs</a>(Unofficial).</span><br/>
57 <br/>
58
59 `;
60
61 return html;
62 }
63
64 onSettingsChange() {
65 // Used when provider settings are updated from UI
66 this.settings.provider_endpoint = $('#tts_endpoint').val();
67
68
69 saveTtsProviderSettings();
70 this.changeTTSSettings();
71 }
72
73 async loadSettings(settings) {
74 // Pupulate Provider UI given input settings
75 if (Object.keys(settings).length == 0) {
76 console.info('Using default TTS Provider settings');
77 }
78
79 // Only accept keys defined in defaultSettings
80 this.settings = this.defaultSettings;
81
82 for (const key in settings) {
83 if (key in this.settings) {
84 this.settings[key] = settings[key];
85 } else {
86 console.debug(`Ignoring non-user-configurable setting: ${key}`);
87 }
88 }
89
90 // Set initial values from the settings
91 $('#tts_endpoint').val(this.settings.provider_endpoint);
92
93
94 await this.checkReady();
95
96 console.info('ITS: Settings loaded');
97 }
98
99 // Perform a simple readiness check by trying to fetch voiceIds
100 async checkReady() {
101 await Promise.allSettled([this.fetchTtsVoiceObjects(), this.changeTTSSettings()]);
102 }
103
104 async onRefreshClick() {
105 return;
106 }
107
108 //#################//
109 // TTS Interfaces //
110 //#################//
111
112 async getVoice(voiceName) {
113
114
115
116 if (this.voices.length == 0) {
117 this.voices = await this.fetchTtsVoiceObjects();
118 }
119
120
121
122 const match = this.voices.filter(
123 v => v.name == voiceName,
124 )[0];
125 console.log(match);
126 if (!match) {
127 throw `TTS Voice name ${voiceName} not found`;
128 }
129 return match;
130 }
131
132
133
134 async generateTts(text, voiceId) {
135 const response = await this.fetchTtsGeneration(text, voiceId);
136 return response;
137 }
138
139 //###########//
140 // API CALLS //
141 //###########//
142 async fetchTtsVoiceObjects() {
143 const response = await fetch(`${this.settings.provider_endpoint}/speakers`);
144 console.info(response);
145
146 if (!response.ok) {
147 throw new Error(`HTTP ${response.status}: ${await response.json()}`);
148 }
149 const responseJson = await response.json();
150
151
152 this.voices = responseJson;
153
154 return responseJson;
155 }
156
157 // Each time a parameter is changed, we change the configuration
158 async changeTTSSettings() {
159 }
160
161 /**
162 * Fetch TTS generation from the API.
163 * @param {string} inputText Text to generate TTS for
164 * @param {string} voiceId Voice ID to use (model_type&speaker_id))
165 * @returns {Promise<Response|string>} Fetch response
166 */
167 async fetchTtsGeneration(inputText, voiceId, lang = null, forceNoStreaming = false) {
168 console.info(`Generating new TTS for voice_id ${voiceId}`);
169
170 const streaming = this.settings.streaming;
171
172 const params = {
173 text: inputText,
174 speaker: voiceId,
175 };
176
177 if (streaming) {
178 params['streaming'] = 1;
179 }
180
181 const url = `${this.settings.provider_endpoint}/`;
182
183 const response = await fetch(
184 url,
185 {
186 method: 'POST',
187 headers: {
188 'Content-Type': 'application/json',
189 },
190 body: JSON.stringify(params), // Convert parameter objects to JSON strings
191 },
192 );
193 if (!response.ok) {
194 toastr.error(response.statusText, 'TTS Generation Failed');
195 throw new Error(`HTTP ${response.status}: ${await response.text()}`);
196 }
197 return response;
198 }
199
200
201
202 // Interface not used
203 async fetchTtsFromHistory(history_item_id) {
204 return Promise.resolve(history_item_id);
205 }
206}
public/scripts/extensions/tts/index.js+2 -0
@@ -15,6 +15,7 @@ import { VITSTtsProvider } from './vits.js';
15import { GSVITtsProvider } from './gsvi.js';15import { GSVITtsProvider } from './gsvi.js';
16import { SBVits2TtsProvider } from './sbvits2.js';16import { SBVits2TtsProvider } from './sbvits2.js';
17import { AllTalkTtsProvider } from './alltalk.js';17import { AllTalkTtsProvider } from './alltalk.js';
18import { CosyVoiceProvider } from './cosyvoice.js';
18import { SpeechT5TtsProvider } from './speecht5.js';19import { SpeechT5TtsProvider } from './speecht5.js';
19import { AzureTtsProvider } from './azure.js';20import { AzureTtsProvider } from './azure.js';
20import { SlashCommandParser } from '../../slash-commands/SlashCommandParser.js';21import { SlashCommandParser } from '../../slash-commands/SlashCommandParser.js';
@@ -86,6 +87,7 @@ const ttsProviders = {
86 AllTalk: AllTalkTtsProvider,87 AllTalk: AllTalkTtsProvider,
87 Azure: AzureTtsProvider,88 Azure: AzureTtsProvider,
88 Coqui: CoquiTtsProvider,89 Coqui: CoquiTtsProvider,
90 'CosyVoice (Unofficial)': CosyVoiceProvider,
89 Edge: EdgeTtsProvider,91 Edge: EdgeTtsProvider,
90 ElevenLabs: ElevenLabsTtsProvider,92 ElevenLabs: ElevenLabsTtsProvider,
91 GSVI: GSVITtsProvider,93 GSVI: GSVITtsProvider,