mirror of
https://github.com/SillyTavern/SillyTavern.git
synced 2025-06-05 21:59:27 +02:00
update checkReady. add voiceMap ui select
This commit is contained in:
@ -42,8 +42,9 @@ const languageLabels = {
|
|||||||
|
|
||||||
function throwIfModuleMissing() {
|
function throwIfModuleMissing() {
|
||||||
if (!modules.includes('coqui-tts')) {
|
if (!modules.includes('coqui-tts')) {
|
||||||
toastr.error(`Add coqui-tts to enable-modules and restart the Extras API.`, "Coqui TTS module not loaded.", { timeOut: 10000, extendedTimeOut: 20000, preventDuplicates: true });
|
const message = `Coqui TTS module not loaded. Add coqui-tts to enable-modules and restart the Extras API.`
|
||||||
throw new Error(DEBUG_PREFIX, `Coqui TTS module not loaded.`);
|
// toastr.error(message, { timeOut: 10000, extendedTimeOut: 20000, preventDuplicates: true });
|
||||||
|
throw new Error(DEBUG_PREFIX, message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -84,7 +85,6 @@ class CoquiTtsProvider {
|
|||||||
//#############################//
|
//#############################//
|
||||||
|
|
||||||
settings
|
settings
|
||||||
ready
|
|
||||||
|
|
||||||
defaultSettings = {
|
defaultSettings = {
|
||||||
voiceMap: "",
|
voiceMap: "",
|
||||||
@ -148,7 +148,6 @@ class CoquiTtsProvider {
|
|||||||
loadSettings(settings) {
|
loadSettings(settings) {
|
||||||
// Only accept keys defined in defaultSettings
|
// Only accept keys defined in defaultSettings
|
||||||
this.settings = this.defaultSettings
|
this.settings = this.defaultSettings
|
||||||
this.ready = false
|
|
||||||
|
|
||||||
for (const key in settings) {
|
for (const key in settings) {
|
||||||
if (key in this.settings) {
|
if (key in this.settings) {
|
||||||
@ -231,17 +230,8 @@ 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(){
|
||||||
try {
|
throwIfModuleMissing()
|
||||||
if (!modules.includes('coqui-tts')){
|
await this.fetchTtsVoiceIds()
|
||||||
this.ready = false
|
|
||||||
return
|
|
||||||
}
|
|
||||||
await this.fetchTtsVoiceIds()
|
|
||||||
this.ready = true
|
|
||||||
|
|
||||||
} catch {
|
|
||||||
this.ready = false
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
updateVoiceMap() {
|
updateVoiceMap() {
|
||||||
|
@ -11,7 +11,6 @@ class EdgeTtsProvider {
|
|||||||
//########//
|
//########//
|
||||||
|
|
||||||
settings
|
settings
|
||||||
ready = false
|
|
||||||
voices = []
|
voices = []
|
||||||
separator = ' . '
|
separator = ' . '
|
||||||
audioElement = document.createElement('audio')
|
audioElement = document.createElement('audio')
|
||||||
@ -61,17 +60,8 @@ class EdgeTtsProvider {
|
|||||||
|
|
||||||
// Perform a simple readiness check by trying to fetch voiceIds
|
// Perform a simple readiness check by trying to fetch voiceIds
|
||||||
async checkReady(){
|
async checkReady(){
|
||||||
try {
|
throwIfModuleMissing()
|
||||||
if (!modules.includes('edge-tts')){
|
await this.fetchTtsVoiceIds()
|
||||||
this.ready = false
|
|
||||||
return
|
|
||||||
}
|
|
||||||
await this.fetchTtsVoiceIds()
|
|
||||||
this.ready = true
|
|
||||||
|
|
||||||
} catch {
|
|
||||||
this.ready = false
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async onApplyClick() {
|
async onApplyClick() {
|
||||||
@ -162,8 +152,9 @@ class EdgeTtsProvider {
|
|||||||
}
|
}
|
||||||
function throwIfModuleMissing() {
|
function throwIfModuleMissing() {
|
||||||
if (!modules.includes('edge-tts')) {
|
if (!modules.includes('edge-tts')) {
|
||||||
toastr.error(`Edge TTS module not loaded. Add edge-tts to enable-modules and restart the Extras API.`)
|
const message = `Edge TTS module not loaded. Add edge-tts to enable-modules and restart the Extras API.`
|
||||||
throw new Error(`Edge TTS module not loaded.`)
|
// toastr.error(message)
|
||||||
|
throw new Error(message)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,7 +6,6 @@ class ElevenLabsTtsProvider {
|
|||||||
//########//
|
//########//
|
||||||
|
|
||||||
settings
|
settings
|
||||||
ready = false
|
|
||||||
voices = []
|
voices = []
|
||||||
separator = ' ... ... ... '
|
separator = ' ... ... ... '
|
||||||
|
|
||||||
@ -74,13 +73,7 @@ class ElevenLabsTtsProvider {
|
|||||||
|
|
||||||
// Perform a simple readiness check by trying to fetch voiceIds
|
// Perform a simple readiness check by trying to fetch voiceIds
|
||||||
async checkReady(){
|
async checkReady(){
|
||||||
try {
|
await this.fetchTtsVoiceIds()
|
||||||
await this.fetchTtsVoiceIds()
|
|
||||||
this.ready = true
|
|
||||||
|
|
||||||
} catch {
|
|
||||||
this.ready = false
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async onApplyClick() {
|
async onApplyClick() {
|
||||||
|
@ -13,6 +13,7 @@ export { talkingAnimation };
|
|||||||
|
|
||||||
const UPDATE_INTERVAL = 1000
|
const UPDATE_INTERVAL = 1000
|
||||||
|
|
||||||
|
let voiceMapEntries = []
|
||||||
let voiceMap = {} // {charName:voiceid, charName2:voiceid2}
|
let voiceMap = {} // {charName:voiceid, charName2:voiceid2}
|
||||||
let audioControl
|
let audioControl
|
||||||
let storedvalue = false;
|
let storedvalue = false;
|
||||||
@ -224,8 +225,8 @@ function debugTtsPlayback() {
|
|||||||
console.log(JSON.stringify(
|
console.log(JSON.stringify(
|
||||||
{
|
{
|
||||||
"ttsProviderName": ttsProviderName,
|
"ttsProviderName": ttsProviderName,
|
||||||
|
"voiceMap": voiceMap,
|
||||||
"currentMessageNumber": currentMessageNumber,
|
"currentMessageNumber": currentMessageNumber,
|
||||||
"isWorkerBusy": isWorkerBusy,
|
|
||||||
"audioPaused": audioPaused,
|
"audioPaused": audioPaused,
|
||||||
"audioJobQueue": audioJobQueue,
|
"audioJobQueue": audioJobQueue,
|
||||||
"currentAudioJob": currentAudioJob,
|
"currentAudioJob": currentAudioJob,
|
||||||
@ -486,6 +487,7 @@ function loadSettings() {
|
|||||||
if (Object.keys(extension_settings.tts).length === 0) {
|
if (Object.keys(extension_settings.tts).length === 0) {
|
||||||
Object.assign(extension_settings.tts, defaultSettings)
|
Object.assign(extension_settings.tts, defaultSettings)
|
||||||
}
|
}
|
||||||
|
$('#tts_provider').val(extension_settings.tts.currentProvider)
|
||||||
$('#tts_enabled').prop(
|
$('#tts_enabled').prop(
|
||||||
'checked',
|
'checked',
|
||||||
extension_settings.tts.enabled
|
extension_settings.tts.enabled
|
||||||
@ -513,59 +515,17 @@ function setTtsStatus(status, success) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function parseVoiceMap(voiceMapString) {
|
|
||||||
let parsedVoiceMap = {}
|
|
||||||
for (const [charName, voiceId] of voiceMapString
|
|
||||||
.split(',')
|
|
||||||
.map(s => s.split(':'))) {
|
|
||||||
if (charName && voiceId) {
|
|
||||||
parsedVoiceMap[charName.trim()] = voiceId.trim()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return parsedVoiceMap
|
|
||||||
}
|
|
||||||
|
|
||||||
async function voicemapIsValid(parsedVoiceMap) {
|
|
||||||
let valid = true
|
|
||||||
for (const characterName in parsedVoiceMap) {
|
|
||||||
const parsedVoiceName = parsedVoiceMap[characterName]
|
|
||||||
try {
|
|
||||||
await ttsProvider.getVoice(parsedVoiceName)
|
|
||||||
} catch (error) {
|
|
||||||
console.error(error)
|
|
||||||
valid = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return valid
|
|
||||||
}
|
|
||||||
|
|
||||||
async function updateVoiceMap() {
|
|
||||||
let isValidResult = false
|
|
||||||
|
|
||||||
const value = $('#tts_voice_map').val()
|
|
||||||
const parsedVoiceMap = parseVoiceMap(value)
|
|
||||||
|
|
||||||
isValidResult = await voicemapIsValid(parsedVoiceMap)
|
|
||||||
if (isValidResult) {
|
|
||||||
ttsProvider.settings.voiceMap = String(value)
|
|
||||||
// console.debug(`ttsProvider.voiceMap: ${ttsProvider.settings.voiceMap}`)
|
|
||||||
voiceMap = parsedVoiceMap
|
|
||||||
console.debug(`Saved new voiceMap: ${value}`)
|
|
||||||
saveSettingsDebounced()
|
|
||||||
} else {
|
|
||||||
throw 'Voice map is invalid, check console for errors'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function onApplyClick() {
|
function onApplyClick() {
|
||||||
Promise.all([
|
Promise.all([
|
||||||
ttsProvider.onApplyClick(),
|
ttsProvider.onApplyClick(),
|
||||||
updateVoiceMap()
|
// updateVoiceMap()
|
||||||
]).then(() => {
|
]).then(() => {
|
||||||
extension_settings.tts[ttsProviderName] = ttsProvider.settings
|
extension_settings.tts[ttsProviderName] = ttsProvider.settings
|
||||||
saveSettingsDebounced()
|
saveSettingsDebounced()
|
||||||
setTtsStatus('Successfully applied settings', true)
|
setTtsStatus('Successfully applied settings', true)
|
||||||
console.info(`Saved settings ${ttsProviderName} ${JSON.stringify(ttsProvider.settings)}`)
|
console.info(`Saved settings ${ttsProviderName} ${JSON.stringify(ttsProvider.settings)}`)
|
||||||
|
initVoiceMap()
|
||||||
|
updateVoiceMap()
|
||||||
}).catch(error => {
|
}).catch(error => {
|
||||||
console.error(error)
|
console.error(error)
|
||||||
setTtsStatus(error, false)
|
setTtsStatus(error, false)
|
||||||
@ -608,13 +568,14 @@ function onNarrateTranslatedOnlyClick() {
|
|||||||
// TTS Provider //
|
// TTS Provider //
|
||||||
//##############//
|
//##############//
|
||||||
|
|
||||||
function loadTtsProvider(provider) {
|
async function loadTtsProvider(provider) {
|
||||||
//Clear the current config and add new config
|
//Clear the current config and add new config
|
||||||
$("#tts_provider_settings").html("")
|
$("#tts_provider_settings").html("")
|
||||||
|
|
||||||
if (!provider) {
|
if (!provider) {
|
||||||
provider
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Init provider references
|
// Init provider references
|
||||||
extension_settings.tts.currentProvider = provider
|
extension_settings.tts.currentProvider = provider
|
||||||
ttsProviderName = provider
|
ttsProviderName = provider
|
||||||
@ -626,27 +587,17 @@ function loadTtsProvider(provider) {
|
|||||||
console.warn(`Provider ${ttsProviderName} not in Extension Settings, initiatilizing provider in settings`)
|
console.warn(`Provider ${ttsProviderName} not in Extension Settings, initiatilizing provider in settings`)
|
||||||
extension_settings.tts[ttsProviderName] = {}
|
extension_settings.tts[ttsProviderName] = {}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load voicemap settings
|
|
||||||
let voiceMapFromSettings
|
|
||||||
if ("voiceMap" in extension_settings.tts[ttsProviderName]) {
|
|
||||||
voiceMapFromSettings = extension_settings.tts[ttsProviderName].voiceMap
|
|
||||||
voiceMap = parseVoiceMap(voiceMapFromSettings)
|
|
||||||
} else {
|
|
||||||
voiceMapFromSettings = ""
|
|
||||||
voiceMap = {}
|
|
||||||
}
|
|
||||||
$('#tts_voice_map').val(voiceMapFromSettings)
|
|
||||||
$('#tts_provider').val(ttsProviderName)
|
|
||||||
|
|
||||||
ttsProvider.loadSettings(extension_settings.tts[ttsProviderName])
|
ttsProvider.loadSettings(extension_settings.tts[ttsProviderName])
|
||||||
|
initVoiceMap()
|
||||||
}
|
}
|
||||||
|
|
||||||
function onTtsProviderChange() {
|
function onTtsProviderChange() {
|
||||||
const ttsProviderSelection = $('#tts_provider').val()
|
const ttsProviderSelection = $('#tts_provider').val()
|
||||||
|
extension_settings.tts.currentProvider = ttsProviderSelection
|
||||||
loadTtsProvider(ttsProviderSelection)
|
loadTtsProvider(ttsProviderSelection)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Ensure that TTS provider settings are saved to extension settings.
|
||||||
function onTtsProviderSettingsInput() {
|
function onTtsProviderSettingsInput() {
|
||||||
ttsProvider.onSettingsChange()
|
ttsProvider.onSettingsChange()
|
||||||
|
|
||||||
@ -658,6 +609,191 @@ function onTtsProviderSettingsInput() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//###################//
|
||||||
|
// voiceMap Handling //
|
||||||
|
//###################//
|
||||||
|
|
||||||
|
async function onChatChanged() {
|
||||||
|
await resetTtsPlayback()
|
||||||
|
await initVoiceMap()
|
||||||
|
}
|
||||||
|
|
||||||
|
function getCharacters(){
|
||||||
|
const context = getContext()
|
||||||
|
let characters = []
|
||||||
|
if (context.groupId === null){
|
||||||
|
// Single char chat
|
||||||
|
characters.push(context.name1)
|
||||||
|
characters.push(context.name2)
|
||||||
|
} else {
|
||||||
|
// Group chat
|
||||||
|
characters.push(context.name1)
|
||||||
|
const group = context.groups.find(group => context.groupId == group.id)
|
||||||
|
for (let member of group.members) {
|
||||||
|
// Remove suffix
|
||||||
|
if (member.endsWith('.png')){
|
||||||
|
member = member.slice(0, -4)
|
||||||
|
}
|
||||||
|
characters.push(member)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return characters
|
||||||
|
}
|
||||||
|
|
||||||
|
function sanitizeId(input) {
|
||||||
|
// Remove any non-alphanumeric characters except underscore (_) and hyphen (-)
|
||||||
|
let sanitized = input.replace(/[^a-zA-Z0-9-_]/g, '');
|
||||||
|
|
||||||
|
// Ensure first character is always a letter
|
||||||
|
if (!/^[a-zA-Z]/.test(sanitized)) {
|
||||||
|
sanitized = 'element_' + sanitized;
|
||||||
|
}
|
||||||
|
|
||||||
|
return sanitized;
|
||||||
|
}
|
||||||
|
|
||||||
|
function parseVoiceMap(voiceMapString) {
|
||||||
|
let parsedVoiceMap = {}
|
||||||
|
for (const [charName, voiceId] of voiceMapString
|
||||||
|
.split(',')
|
||||||
|
.map(s => s.split(':'))) {
|
||||||
|
if (charName && voiceId) {
|
||||||
|
parsedVoiceMap[charName.trim()] = voiceId.trim()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return parsedVoiceMap
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Apply voiceMap based on current voiceMapEntries
|
||||||
|
*/
|
||||||
|
function updateVoiceMap() {
|
||||||
|
const tempVoiceMap = {}
|
||||||
|
for (const voice of voiceMapEntries){
|
||||||
|
if (voice.voiceId === null){
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
tempVoiceMap[voice.name] = voice.voiceId
|
||||||
|
}
|
||||||
|
if (Object.keys(tempVoiceMap).length !== 0){
|
||||||
|
voiceMap = tempVoiceMap
|
||||||
|
console.log(`Voicemap updated to ${JSON.stringify(voiceMap)}`)
|
||||||
|
}
|
||||||
|
extension_settings.tts[ttsProviderName].voiceMap = voiceMap
|
||||||
|
saveSettingsDebounced()
|
||||||
|
}
|
||||||
|
|
||||||
|
class VoiceMapEntry {
|
||||||
|
name
|
||||||
|
voiceId
|
||||||
|
selectElement
|
||||||
|
constructor (name, voiceId='disabled') {
|
||||||
|
this.name = name
|
||||||
|
this.voiceId = voiceId
|
||||||
|
this.selectElement = null
|
||||||
|
}
|
||||||
|
|
||||||
|
addUI(voiceIds){
|
||||||
|
let sanitizedName = sanitizeId(this.name)
|
||||||
|
let template = `
|
||||||
|
<div class='tts_voicemap_block_char flex-container flexGap5'>
|
||||||
|
<span id='tts_voicemap_char_${sanitizedName}'>${this.name}</span>
|
||||||
|
<select id='tts_voicemap_char_${sanitizedName}_voice'>
|
||||||
|
<option>disabled</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
`
|
||||||
|
$('#tts_voicemap_block').append(template)
|
||||||
|
|
||||||
|
// Populate voice ID select list
|
||||||
|
for (const voiceId of voiceIds){
|
||||||
|
const option = document.createElement('option');
|
||||||
|
option.innerText = voiceId.name;
|
||||||
|
option.value = voiceId.name;
|
||||||
|
$(`#tts_voicemap_char_${sanitizedName}_voice`).append(option)
|
||||||
|
}
|
||||||
|
|
||||||
|
this.selectElement = $(`#tts_voicemap_char_${sanitizedName}_voice`)
|
||||||
|
this.selectElement.on('change', args => this.onSelectChange(args))
|
||||||
|
this.selectElement.val(this.voiceId)
|
||||||
|
}
|
||||||
|
|
||||||
|
onSelectChange(args) {
|
||||||
|
this.voiceId = this.selectElement.find(':selected').val()
|
||||||
|
updateVoiceMap()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Init voiceMapEntries for character select list. Should only be called when character/chat is changed.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
async function initVoiceMap(){
|
||||||
|
// Clear existing voiceMap state
|
||||||
|
$('#tts_voicemap_block').empty()
|
||||||
|
voiceMapEntries = []
|
||||||
|
|
||||||
|
// Gate initialization if not enabled or TTS Provider not ready. Prevents error popups.
|
||||||
|
const enabled = $('#tts_enabled').is(':checked')
|
||||||
|
if (!enabled){
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Keep errors inside extension UI rather than toastr. Toastr errors for TTS are annoying.
|
||||||
|
try {
|
||||||
|
await ttsProvider.checkReady()
|
||||||
|
} catch (error) {
|
||||||
|
const message = `TTS Provider not ready. ${error}`
|
||||||
|
setTtsStatus(message, false)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
setTtsStatus("TTS Provider Loaded", true)
|
||||||
|
|
||||||
|
// Get characters in current chat
|
||||||
|
const characters = getCharacters()
|
||||||
|
|
||||||
|
// Get saved voicemap from provider settings, handling new and old representations
|
||||||
|
let voiceMapFromSettings = {}
|
||||||
|
if ("voiceMap" in extension_settings.tts[ttsProviderName]) {
|
||||||
|
// Handle previous representation
|
||||||
|
if (typeof extension_settings.tts[ttsProviderName].voiceMap === "string"){
|
||||||
|
voiceMapFromSettings = parseVoiceMap(extension_settings.tts[ttsProviderName].voiceMap)
|
||||||
|
// Handle new representation
|
||||||
|
} else if (typeof extension_settings.tts[ttsProviderName].voiceMap === "object"){
|
||||||
|
voiceMapFromSettings = extension_settings.tts[ttsProviderName].voiceMap
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get voiceIds from provider
|
||||||
|
let voiceIdsFromProvider
|
||||||
|
try {
|
||||||
|
voiceIdsFromProvider = await ttsProvider.fetchTtsVoiceIds()
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
toastr.error("TTS Provider failed to return voice ids.")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Build UI using VoiceMapEntry objects
|
||||||
|
for (const character of characters){
|
||||||
|
if (character === "SillyTavern System"){
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
// Check provider settings for voiceIds
|
||||||
|
let voiceId
|
||||||
|
if (character in voiceMapFromSettings){
|
||||||
|
voiceId = voiceMapFromSettings[character]
|
||||||
|
} else {
|
||||||
|
voiceId = 'disabled'
|
||||||
|
}
|
||||||
|
const voiceMapEntry = new VoiceMapEntry(character, voiceId)
|
||||||
|
voiceMapEntry.addUI(voiceIdsFromProvider)
|
||||||
|
voiceMapEntries.push(voiceMapEntry)
|
||||||
|
}
|
||||||
|
updateVoiceMap()
|
||||||
|
}
|
||||||
|
|
||||||
$(document).ready(function () {
|
$(document).ready(function () {
|
||||||
function addExtensionControls() {
|
function addExtensionControls() {
|
||||||
@ -669,6 +805,8 @@ $(document).ready(function () {
|
|||||||
<div class="inline-drawer-icon fa-solid fa-circle-chevron-down down"></div>
|
<div class="inline-drawer-icon fa-solid fa-circle-chevron-down down"></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="inline-drawer-content">
|
<div class="inline-drawer-content">
|
||||||
|
<div id="tts_status">
|
||||||
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<span>Select TTS Provider</span> </br>
|
<span>Select TTS Provider</span> </br>
|
||||||
<select id="tts_provider">
|
<select id="tts_provider">
|
||||||
@ -696,16 +834,13 @@ $(document).ready(function () {
|
|||||||
<small>Narrate only the translated text</small>
|
<small>Narrate only the translated text</small>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<label>Voice Map</label>
|
<div id="tts_voicemap_block">
|
||||||
<textarea id="tts_voice_map" type="text" class="text_pole textarea_compact" rows="4"
|
|
||||||
placeholder="Enter comma separated map of charName:ttsName. Example: \nAqua:Bella,\nYou:Josh,"></textarea>
|
|
||||||
|
|
||||||
<div id="tts_status">
|
|
||||||
</div>
|
</div>
|
||||||
|
<hr>
|
||||||
<form id="tts_provider_settings" class="inline-drawer-content">
|
<form id="tts_provider_settings" class="inline-drawer-content">
|
||||||
</form>
|
</form>
|
||||||
<div class="tts_buttons">
|
<div class="tts_buttons">
|
||||||
<input id="tts_apply" class="menu_button" type="submit" value="Apply" />
|
<input id="tts_apply" class="menu_button" type="submit" value="Reload / Apply" />
|
||||||
<input id="tts_voices" class="menu_button" type="submit" value="Available voices" />
|
<input id="tts_voices" class="menu_button" type="submit" value="Available voices" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -735,4 +870,6 @@ $(document).ready(function () {
|
|||||||
const wrapper = new ModuleWorkerWrapper(moduleWorker);
|
const wrapper = new ModuleWorkerWrapper(moduleWorker);
|
||||||
setInterval(wrapper.update.bind(wrapper), UPDATE_INTERVAL) // Init depends on all the things
|
setInterval(wrapper.update.bind(wrapper), UPDATE_INTERVAL) // Init depends on all the things
|
||||||
eventSource.on(event_types.MESSAGE_SWIPED, resetTtsPlayback);
|
eventSource.on(event_types.MESSAGE_SWIPED, resetTtsPlayback);
|
||||||
|
eventSource.on(event_types.CHAT_CHANGED, onChatChanged)
|
||||||
|
eventSource.on(event_types.GROUP_UPDATED, onChatChanged)
|
||||||
})
|
})
|
||||||
|
@ -9,7 +9,6 @@ class NovelTtsProvider {
|
|||||||
//########//
|
//########//
|
||||||
|
|
||||||
settings
|
settings
|
||||||
ready = false
|
|
||||||
voices = []
|
voices = []
|
||||||
separator = ' . '
|
separator = ' . '
|
||||||
audioElement = document.createElement('audio')
|
audioElement = document.createElement('audio')
|
||||||
@ -95,13 +94,7 @@ class NovelTtsProvider {
|
|||||||
// Perform a simple readiness check by trying to fetch voiceIds
|
// Perform a simple readiness check by trying to fetch voiceIds
|
||||||
// Doesnt really do much for Novel, not seeing a good way to test this at the moment.
|
// Doesnt really do much for Novel, not seeing a good way to test this at the moment.
|
||||||
async checkReady(){
|
async checkReady(){
|
||||||
try {
|
await this.fetchTtsVoiceIds()
|
||||||
await this.fetchTtsVoiceIds()
|
|
||||||
this.ready = true
|
|
||||||
|
|
||||||
} catch {
|
|
||||||
this.ready = false
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async onApplyClick() {
|
async onApplyClick() {
|
||||||
|
@ -69,17 +69,7 @@ class SileroTtsProvider {
|
|||||||
|
|
||||||
// Perform a simple readiness check by trying to fetch voiceIds
|
// Perform a simple readiness check by trying to fetch voiceIds
|
||||||
async checkReady(){
|
async checkReady(){
|
||||||
try {
|
await this.fetchTtsVoiceIds()
|
||||||
if (!modules.includes('silero-tts')){
|
|
||||||
this.ready = false
|
|
||||||
return
|
|
||||||
}
|
|
||||||
await this.fetchTtsVoiceIds()
|
|
||||||
this.ready = true
|
|
||||||
|
|
||||||
} catch {
|
|
||||||
this.ready = false
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async onApplyClick() {
|
async onApplyClick() {
|
||||||
|
@ -50,4 +50,20 @@
|
|||||||
|
|
||||||
.voice_preview .fa-play {
|
.voice_preview .fa-play {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tts-button {
|
||||||
|
margin: 0;
|
||||||
|
outline: none;
|
||||||
|
border: none;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: 0.3s;
|
||||||
|
opacity: 0.7;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.tts-button:hover {
|
||||||
|
opacity: 1;
|
||||||
}
|
}
|
@ -146,19 +146,12 @@ class SystemTtsProvider {
|
|||||||
$('#system_tts_pitch').val(this.settings.pitch || this.defaultSettings.pitch);
|
$('#system_tts_pitch').val(this.settings.pitch || this.defaultSettings.pitch);
|
||||||
$('#system_tts_pitch_output').text(this.settings.pitch);
|
$('#system_tts_pitch_output').text(this.settings.pitch);
|
||||||
$('#system_tts_rate_output').text(this.settings.rate);
|
$('#system_tts_rate_output').text(this.settings.rate);
|
||||||
this.checkReady()
|
|
||||||
console.info("Settings loaded");
|
console.info("Settings loaded");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Perform a simple readiness check by trying to fetch voiceIds
|
// Perform a simple readiness check by trying to fetch voiceIds
|
||||||
async checkReady(){
|
async checkReady(){
|
||||||
try {
|
await this.fetchTtsVoiceIds()
|
||||||
await this.fetchTtsVoiceIds()
|
|
||||||
this.ready = true
|
|
||||||
|
|
||||||
} catch {
|
|
||||||
this.ready = false
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async onApplyClick() {
|
async onApplyClick() {
|
||||||
|
Reference in New Issue
Block a user