diff --git a/public/script.js b/public/script.js index 7d1fdb94a..c3e344e2e 100644 --- a/public/script.js +++ b/public/script.js @@ -3453,6 +3453,7 @@ window["TavernAI"].getContext = function () { onlineStatus: online_status, maxContext: Number(max_context), chatMetadata: chat_metadata, + streamingProcessor, addOneMessage: addOneMessage, generate: Generate, getTokenCount: getTokenCount, diff --git a/public/scripts/extensions/elevenlabstts/index.js b/public/scripts/extensions/elevenlabstts/index.js index dc408dc82..9643142dc 100644 --- a/public/scripts/extensions/elevenlabstts/index.js +++ b/public/scripts/extensions/elevenlabstts/index.js @@ -1,5 +1,6 @@ -import { saveSettingsDebounced } from "../../../script.js"; +import { callPopup, saveSettingsDebounced } from "../../../script.js"; import { extension_settings, getContext } from "../../extensions.js"; +import { getStringHash } from "../../utils.js"; const UPDATE_INTERVAL = 1000; let API_KEY @@ -12,6 +13,7 @@ let audioControl let lastCharacterId = null; let lastGroupId = null; let lastChatId = null; +let lastMessageHash = null; async function moduleWorker() { @@ -45,13 +47,22 @@ async function moduleWorker() { // There's no new messages let diff = lastMessageNumber - currentMessageNumber; - if (diff == 0) { + let hashNew = getStringHash((chat.length && chat[chat.length - 1].mes) ?? ''); + + if (diff == 0 && hashNew === lastMessageHash) { + return; + } + + const message = chat[chat.length - 1]; + + // We're currently swiping or streaming. Don't generate voice + if (message.mes === '...' || (context.streamingProcessor && !context.streamingProcessor.isFinished)) { return; } // New messages, add new chat to history + lastMessageHash = hashNew; currentMessageNumber = lastMessageNumber; - const message = chat[chat.length - 1] console.debug(`Adding message from ${message.name} for TTS processing: "${message.mes}"`); ttsJobQueue.push(message); @@ -174,6 +185,30 @@ async function playAudioData(audioBlob) { }) } +window['elevenlabsPreview'] = function(id) { + const audio = document.getElementById(id); + audio.play(); +} + +async function onElevenlabsVoicesClick() { + let popupText = ''; + + try { + const voiceIds = await fetchTtsVoiceIds(); + + for (const voice of voiceIds) { + popupText += `
${voice.name}
`; + popupText += ``; + } + } + catch { + popupText = 'Could not load voices list. Check your API key.' + } + + + callPopup(popupText, 'text'); +} + function completeCurrentAudioJob() { queueProcessorReady = true lastAudioPosition = 0 @@ -227,6 +262,7 @@ function saveLastValues() { lastGroupId = context.groupId; lastCharacterId = context.characterId; lastChatId = context.chatId; + lastMessageHash = getStringHash((context.chat.length && context.chat[context.chat.length - 1].mes) ?? ''); } async function tts(text, voiceId) { @@ -431,14 +467,18 @@ $(document).ready(function () {
- + + -
+
+ + +
@@ -451,6 +491,7 @@ $(document).ready(function () { $('#extensions_settings').append(settingsHtml); $('#elevenlabs_apply').on('click', onElevenlabsApplyClick); $('#elevenlabs_enabled').on('click', onElevenlabsEnableClick); + $('#elevenlabs_voices').on('click', onElevenlabsVoicesClick); } addAudioControl(); addExtensionControls(); diff --git a/public/scripts/extensions/elevenlabstts/style.css b/public/scripts/extensions/elevenlabstts/style.css index 1941ce3c1..35bb63131 100644 --- a/public/scripts/extensions/elevenlabstts/style.css +++ b/public/scripts/extensions/elevenlabstts/style.css @@ -19,3 +19,10 @@ opacity: 1; filter: brightness(1.2); } + +.voice_preview { + margin: 0.25rem 0.5rem; + display: flex; + justify-content: space-between; + align-items: center; +} \ No newline at end of file