mirror of
https://github.com/SillyTavern/SillyTavern.git
synced 2025-02-22 23:18:27 +01:00
name updates, complete custom voices
This commit is contained in:
parent
1417aa12f1
commit
d03af9b41d
@ -6,7 +6,7 @@ TODO:
|
|||||||
|
|
||||||
import { doExtrasFetch, extension_settings, getApiUrl, getContext, modules, ModuleWorkerWrapper } from "../../extensions.js"
|
import { doExtrasFetch, extension_settings, getApiUrl, getContext, modules, ModuleWorkerWrapper } from "../../extensions.js"
|
||||||
import { callPopup } from "../../../script.js"
|
import { callPopup } from "../../../script.js"
|
||||||
import { onTtsProviderSettingsInput } from "./index.js"
|
import { initVoiceMap } from "./index.js"
|
||||||
|
|
||||||
export { CoquiTtsProvider }
|
export { CoquiTtsProvider }
|
||||||
|
|
||||||
@ -63,7 +63,8 @@ class CoquiTtsProvider {
|
|||||||
settings
|
settings
|
||||||
|
|
||||||
defaultSettings = {
|
defaultSettings = {
|
||||||
voiceMap: "",
|
voiceMap: {},
|
||||||
|
customVoices: {},
|
||||||
voiceIds: [],
|
voiceIds: [],
|
||||||
voiceMapDict: {}
|
voiceMapDict: {}
|
||||||
}
|
}
|
||||||
@ -74,8 +75,8 @@ class CoquiTtsProvider {
|
|||||||
<div>
|
<div>
|
||||||
<div style="flex: 50%;">
|
<div style="flex: 50%;">
|
||||||
<small>To use CoquiTTS, select the origin, language, and model, then click Add Voice. The voice will then be available to add to a character. Voices are saved globally. </small><br>
|
<small>To use CoquiTTS, select the origin, language, and model, then click Add Voice. The voice will then be available to add to a character. Voices are saved globally. </small><br>
|
||||||
<label for="coqui_voiceid_select">Select Saved Voice:</label>
|
<label for="coqui_voicename_select">Select Saved Voice:</label>
|
||||||
<select id="coqui_voiceid_select">
|
<select id="coqui_voicename_select">
|
||||||
<!-- Populated by JS -->
|
<!-- Populated by JS -->
|
||||||
</select>
|
</select>
|
||||||
<div class="tts_block">
|
<div class="tts_block">
|
||||||
@ -137,7 +138,7 @@ class CoquiTtsProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
initLocalModels();
|
initLocalModels();
|
||||||
this.updateVoiceMap(); // Overide any manual modification
|
this.updateCustomVoices(); // Overide any manual modification
|
||||||
|
|
||||||
$("#coqui_api_model_div").hide();
|
$("#coqui_api_model_div").hide();
|
||||||
$("#coqui_local_model_div").hide();
|
$("#coqui_local_model_div").hide();
|
||||||
@ -200,48 +201,44 @@ class CoquiTtsProvider {
|
|||||||
// Perform a simple readiness check by trying to fetch voiceIds
|
// Perform a simple readiness check by trying to fetch voiceIds
|
||||||
async checkReady(){
|
async checkReady(){
|
||||||
throwIfModuleMissing()
|
throwIfModuleMissing()
|
||||||
await this.fetchTtsVoiceIds()
|
await this.fetchTtsVoiceObjects()
|
||||||
}
|
}
|
||||||
|
|
||||||
updateVoiceMap() {
|
updateCustomVoices() {
|
||||||
// Takes voiceMapDict and converts it to a string to save to voiceMap
|
// Takes voiceMapDict and converts it to a string to save to voiceMap
|
||||||
this.settings.voiceMap = "";
|
this.settings.customVoices = {};
|
||||||
for (let i in this.settings.voiceMapDict) {
|
for (let voiceName in this.settings.voiceMapDict) {
|
||||||
const voice_settings = this.settings.voiceMapDict[i];
|
const voiceId = this.settings.voiceMapDict[voiceName];
|
||||||
this.settings.voiceMap += i + ":" + voice_settings["model_id"];
|
this.settings.customVoices[voiceName] = voiceId["model_id"];
|
||||||
|
|
||||||
if (voice_settings["model_language"] != null)
|
if (voiceId["model_language"] != null)
|
||||||
this.settings.voiceMap += "[" + voice_settings["model_language"] + "]";
|
this.settings.customVoices[voiceName] += "[" + voiceId["model_language"] + "]";
|
||||||
|
|
||||||
if (voice_settings["model_speaker"] != null)
|
if (voiceId["model_speaker"] != null)
|
||||||
this.settings.voiceMap += "[" + voice_settings["model_speaker"] + "]";
|
this.settings.customVoices[voiceName] += "[" + voiceId["model_speaker"] + "]";
|
||||||
|
|
||||||
this.settings.voiceMap += ",";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update UI select list with voices
|
// Update UI select list with voices
|
||||||
$("#coqui_voiceid_select").empty()
|
$("#coqui_voicename_select").empty()
|
||||||
$('#coqui_voiceid_select')
|
$('#coqui_voicename_select')
|
||||||
.find('option')
|
.find('option')
|
||||||
.remove()
|
.remove()
|
||||||
.end()
|
.end()
|
||||||
.append('<option value="none">Select VoiceId</option>')
|
.append('<option value="none">Select Voice</option>')
|
||||||
.val('none')
|
.val('none')
|
||||||
for (const voiceId in this.settings.voiceMapDict) {
|
for (const voiceName in this.settings.voiceMapDict) {
|
||||||
$("#coqui_voiceid_select").append(new Option(voiceId, voiceId));
|
$("#coqui_voicename_select").append(new Option(voiceName, voiceName));
|
||||||
}
|
}
|
||||||
|
|
||||||
extension_settings.tts.Coqui = this.settings;
|
|
||||||
this.onSettingsChange()
|
this.onSettingsChange()
|
||||||
}
|
}
|
||||||
|
|
||||||
onSettingsChange() {
|
onSettingsChange() {
|
||||||
console.debug(DEBUG_PREFIX, "Settings changes", this.settings);
|
console.debug(DEBUG_PREFIX, "Settings changes", this.settings);
|
||||||
extension_settings.tts.Coqui = this.settings;
|
extension_settings.tts.Coqui = this.settings;
|
||||||
onTtsProviderSettingsInput()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async onApplyClick() {
|
async onRefreshClick() {
|
||||||
this.checkReady()
|
this.checkReady()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -251,7 +248,7 @@ class CoquiTtsProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Ask user for voiceId name to save voice
|
// Ask user for voiceId name to save voice
|
||||||
const voiceId = await callPopup('<h3>Name of Coqui voice to add to voice select dropdown:</h3>', 'input')
|
const voiceName = await callPopup('<h3>Name of Coqui voice to add to voice select dropdown:</h3>', 'input')
|
||||||
|
|
||||||
const model_origin = $("#coqui_model_origin").val();
|
const model_origin = $("#coqui_model_origin").val();
|
||||||
const model_language = $("#coqui_api_language").val();
|
const model_language = $("#coqui_api_language").val();
|
||||||
@ -260,15 +257,15 @@ class CoquiTtsProvider {
|
|||||||
let model_setting_speaker = $("#coqui_api_model_settings_speaker").val();
|
let model_setting_speaker = $("#coqui_api_model_settings_speaker").val();
|
||||||
|
|
||||||
|
|
||||||
if (!voiceId) {
|
if (!voiceName) {
|
||||||
toastr.error(`VoiceId empty, please enter one.`, DEBUG_PREFIX + " voice mapping voiceId", { timeOut: 10000, extendedTimeOut: 20000, preventDuplicates: true });
|
toastr.error(`Voice name empty, please enter one.`, DEBUG_PREFIX + " voice mapping voice name", { timeOut: 10000, extendedTimeOut: 20000, preventDuplicates: true });
|
||||||
this.updateVoiceMap(); // Overide any manual modification
|
this.updateCustomVoices(); // Overide any manual modification
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (model_origin == "none") {
|
if (model_origin == "none") {
|
||||||
toastr.error(`Origin not selected, please select one.`, DEBUG_PREFIX + " voice mapping origin", { timeOut: 10000, extendedTimeOut: 20000, preventDuplicates: true });
|
toastr.error(`Origin not selected, please select one.`, DEBUG_PREFIX + " voice mapping origin", { timeOut: 10000, extendedTimeOut: 20000, preventDuplicates: true });
|
||||||
this.updateVoiceMap(); // Overide any manual modification
|
this.updateCustomVoices(); // Overide any manual modification
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -277,25 +274,25 @@ class CoquiTtsProvider {
|
|||||||
|
|
||||||
if (model_name == "none") {
|
if (model_name == "none") {
|
||||||
toastr.error(`Model not selected, please select one.`, DEBUG_PREFIX + " voice mapping model", { timeOut: 10000, extendedTimeOut: 20000, preventDuplicates: true });
|
toastr.error(`Model not selected, please select one.`, DEBUG_PREFIX + " voice mapping model", { timeOut: 10000, extendedTimeOut: 20000, preventDuplicates: true });
|
||||||
this.updateVoiceMap(); // Overide any manual modification
|
this.updateCustomVoices(); // Overide any manual modification
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.settings.voiceMapDict[voiceId] = { model_type: "local", model_id: "local/" + model_id };
|
this.settings.voiceMapDict[voiceName] = { model_type: "local", model_id: "local/" + model_id };
|
||||||
console.debug(DEBUG_PREFIX, "Registered new voice map: ", voiceId, ":", this.settings.voiceMapDict[voiceId]);
|
console.debug(DEBUG_PREFIX, "Registered new voice map: ", voiceName, ":", this.settings.voiceMapDict[voiceName]);
|
||||||
this.updateVoiceMap(); // Overide any manual modification
|
this.updateCustomVoices(); // Overide any manual modification
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (model_language == "none") {
|
if (model_language == "none") {
|
||||||
toastr.error(`Language not selected, please select one.`, DEBUG_PREFIX + " voice mapping language", { timeOut: 10000, extendedTimeOut: 20000, preventDuplicates: true });
|
toastr.error(`Language not selected, please select one.`, DEBUG_PREFIX + " voice mapping language", { timeOut: 10000, extendedTimeOut: 20000, preventDuplicates: true });
|
||||||
this.updateVoiceMap(); // Overide any manual modification
|
this.updateCustomVoices(); // Overide any manual modification
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (model_name == "none") {
|
if (model_name == "none") {
|
||||||
toastr.error(`Model not selected, please select one.`, DEBUG_PREFIX + " voice mapping model", { timeOut: 10000, extendedTimeOut: 20000, preventDuplicates: true });
|
toastr.error(`Model not selected, please select one.`, DEBUG_PREFIX + " voice mapping model", { timeOut: 10000, extendedTimeOut: 20000, preventDuplicates: true });
|
||||||
this.updateVoiceMap(); // Overide any manual modification
|
this.updateCustomVoices(); // Overide any manual modification
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -324,42 +321,48 @@ class CoquiTtsProvider {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
console.debug(DEBUG_PREFIX, "Current voice map: ", this.settings.voiceMap);
|
console.debug(DEBUG_PREFIX, "Current custom voices: ", this.settings.customVoices);
|
||||||
|
|
||||||
this.settings.voiceMapDict[voiceId] = { model_type: "coqui-api", model_id: model_id, model_language: model_setting_language, model_speaker: model_setting_speaker };
|
this.settings.voiceMapDict[voiceName] = { model_type: "coqui-api", model_id: model_id, model_language: model_setting_language, model_speaker: model_setting_speaker };
|
||||||
|
|
||||||
console.debug(DEBUG_PREFIX, "Registered new voice map: ", voiceId, ":", this.settings.voiceMapDict[voiceId]);
|
console.debug(DEBUG_PREFIX, "Registered new voice map: ", voiceName, ":", this.settings.voiceMapDict[voiceName]);
|
||||||
|
|
||||||
this.updateVoiceMap();
|
this.updateCustomVoices();
|
||||||
|
initVoiceMap() // Update TTS extension voiceMap
|
||||||
|
|
||||||
let successMsg = voiceId + ":" + model_id;
|
let successMsg = voiceName + ":" + model_id;
|
||||||
if (model_setting_language != null)
|
if (model_setting_language != null)
|
||||||
successMsg += "[" + model_setting_language + "]";
|
successMsg += "[" + model_setting_language + "]";
|
||||||
if (model_setting_speaker != null)
|
if (model_setting_speaker != null)
|
||||||
successMsg += "[" + model_setting_speaker + "]";
|
successMsg += "[" + model_setting_speaker + "]";
|
||||||
toastr.info(successMsg, DEBUG_PREFIX + " voice map updated", { timeOut: 10000, extendedTimeOut: 20000, preventDuplicates: true });
|
toastr.info(successMsg, DEBUG_PREFIX + " voice map updated", { timeOut: 10000, extendedTimeOut: 20000, preventDuplicates: true });
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// DBG: assume voiceName is correct
|
|
||||||
// TODO: check voice is correct
|
|
||||||
async getVoice(voiceName) {
|
async getVoice(voiceName) {
|
||||||
console.log(DEBUG_PREFIX, "getVoice", voiceName);
|
let match = await this.fetchTtsVoiceObjects()
|
||||||
const output = { voice_id: voiceName };
|
match = match.filter(
|
||||||
return output;
|
voice => voice.name == voiceName
|
||||||
|
)[0]
|
||||||
|
if (!match) {
|
||||||
|
throw `TTS Voice name ${voiceName} not found in CoquiTTS Provider voice list`
|
||||||
|
}
|
||||||
|
return match;
|
||||||
}
|
}
|
||||||
|
|
||||||
async onRemoveClick() {
|
async onRemoveClick() {
|
||||||
const voiceId = $("#coqui_voiceid_select").val();
|
const voiceName = $("#coqui_voicename_select").val();
|
||||||
|
|
||||||
if (voiceId === "none") {
|
if (voiceName === "none") {
|
||||||
toastr.error(`VoiceId not selected, please select one.`, DEBUG_PREFIX + " voice mapping voiceId", { timeOut: 10000, extendedTimeOut: 20000, preventDuplicates: true });
|
toastr.error(`Voice not selected, please select one.`, DEBUG_PREFIX + " voice mapping voiceId", { timeOut: 10000, extendedTimeOut: 20000, preventDuplicates: true });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Todo erase from voicemap
|
// Todo erase from voicemap
|
||||||
delete (this.settings.voiceMapDict[voiceId]);
|
delete (this.settings.voiceMapDict[voiceName]);
|
||||||
this.updateVoiceMap(); // TODO
|
this.updateCustomVoices();
|
||||||
|
initVoiceMap() // Update TTS extension voiceMap
|
||||||
}
|
}
|
||||||
|
|
||||||
async onModelOriginChange() {
|
async onModelOriginChange() {
|
||||||
@ -677,6 +680,8 @@ class CoquiTtsProvider {
|
|||||||
// ts_models/ja/kokoro/tacotron2-DDC
|
// ts_models/ja/kokoro/tacotron2-DDC
|
||||||
async generateTts(text, voiceId) {
|
async generateTts(text, voiceId) {
|
||||||
throwIfModuleMissing()
|
throwIfModuleMissing()
|
||||||
|
voiceId = this.settings.customVoices[voiceId]
|
||||||
|
|
||||||
const url = new URL(getApiUrl());
|
const url = new URL(getApiUrl());
|
||||||
url.pathname = '/api/text-to-speech/coqui/generate-tts';
|
url.pathname = '/api/text-to-speech/coqui/generate-tts';
|
||||||
|
|
||||||
@ -724,8 +729,11 @@ class CoquiTtsProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Dirty hack to say not implemented
|
// Dirty hack to say not implemented
|
||||||
async fetchTtsVoiceIds() {
|
async fetchTtsVoiceObjects() {
|
||||||
return [{ name: "Voice samples not implemented for coqui TTS yet, search for the model samples online", voice_id: "", lang: "", }]
|
const voiceIds = Object
|
||||||
|
.keys(this.settings.voiceMapDict)
|
||||||
|
.map(voice => ({ name: voice, voice_id: voice, preview_url: false }));
|
||||||
|
return voiceIds
|
||||||
}
|
}
|
||||||
|
|
||||||
// Do nothing
|
// Do nothing
|
||||||
|
Loading…
x
Reference in New Issue
Block a user