diff --git a/public/scripts/extensions/tts/novel.js b/public/scripts/extensions/tts/novel.js
index f3393c96a..05c6effa7 100644
--- a/public/scripts/extensions/tts/novel.js
+++ b/public/scripts/extensions/tts/novel.js
@@ -1,4 +1,4 @@
-import { getRequestHeaders } from "../../../script.js"
+import { getRequestHeaders, callPopup } from "../../../script.js"
import { getPreviewString } from "./index.js"
export { NovelTtsProvider }
@@ -9,22 +9,63 @@ class NovelTtsProvider {
//########//
settings
+ ready = false
voices = []
separator = ' . '
audioElement = document.createElement('audio')
defaultSettings = {
- voiceMap: {}
+ voiceMap: {},
+ customVoices: []
}
get settingsHtml() {
- let html = `Use NovelAI's TTS engine.
- The Voice IDs in the preview list are only examples, as it can be any string of text. Feel free to try different options!
- Hint: Save an API key in the NovelAI API settings to use it here.`;
+ let html = `
+
+
+ Use NovelAI's TTS engine.
+ The default Voice IDs are only examples. Add custom voices and Novel will create a new random voice for it. Feel free to try different options!
+
+ Hint: Save an API key in the NovelAI API settings to use it here.
+
+
+
+ `;
return html;
}
onSettingsChange() {
+
+ }
+
+ // Add a new Novel custom voice to provider
+ async addCustomVoice(){
+ const voiceName = await callPopup('
Custom Voice name:
', 'input')
+ this.settings.customVoices.push(voiceName)
+ this.populateCustomVoices()
+ }
+
+ // Delete selected custom voice from provider
+ deleteCustomVoice() {
+ const selected = $("#tts-novel-custom-voices-select").find(':selected').val();
+ const voiceIndex = this.settings.customVoices.indexOf(selected);
+
+ if (voiceIndex !== -1) {
+ this.settings.customVoices.splice(voiceIndex, 1);
+ }
+ this.populateCustomVoices()
+ }
+
+ // Create the UI dropdown list of voices in provider
+ populateCustomVoices(){
+ let voiceSelect = $("#tts-novel-custom-voices-select")
+ voiceSelect.empty()
+ this.settings.customVoices.forEach(voice => {
+ voiceSelect.append(``)
+ })
}
loadSettings(settings) {
@@ -32,6 +73,8 @@ class NovelTtsProvider {
if (Object.keys(settings).length == 0) {
console.info("Using default TTS Provider settings")
}
+ $("#tts-novel-custom-voices-add").on('click', () => (this.addCustomVoice()))
+ $("#tts-novel-custom-voices-delete").on('click',() => (this.deleteCustomVoice()))
// Only accept keys defined in defaultSettings
this.settings = this.defaultSettings
@@ -44,9 +87,22 @@ class NovelTtsProvider {
}
}
+ this.populateCustomVoices()
+ this.checkReady()
console.info("Settings loaded")
}
+ // 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.
+ async checkReady(){
+ try {
+ await this.fetchTtsVoiceIds()
+ this.ready = true
+
+ } catch {
+ this.ready = false
+ }
+ }
async onApplyClick() {
return
@@ -73,7 +129,7 @@ class NovelTtsProvider {
// API CALLS //
//###########//
async fetchTtsVoiceIds() {
- const voices = [
+ let voices = [
{ name: 'Ligeia', voice_id: 'Ligeia', lang: 'en-US', preview_url: false },
{ name: 'Aini', voice_id: 'Aini', lang: 'en-US', preview_url: false },
{ name: 'Orea', voice_id: 'Orea', lang: 'en-US', preview_url: false },
@@ -89,6 +145,12 @@ class NovelTtsProvider {
{ name: 'Lam', voice_id: 'Lam', lang: 'en-US', preview_url: false },
];
+ // Add in custom voices to the map
+ let addVoices = this.settings.customVoices.map(voice =>
+ ({ name: voice, voice_id: voice, lang: 'en-US', preview_url: false })
+ )
+ voices = voices.concat(addVoices)
+
return voices;
}