diff --git a/public/scripts/extensions/tts/index.js b/public/scripts/extensions/tts/index.js
index 4ac7b4e47..f5e760109 100644
--- a/public/scripts/extensions/tts/index.js
+++ b/public/scripts/extensions/tts/index.js
@@ -23,24 +23,6 @@ let ttsProviders = {
}
let ttsProvider
let ttsProviderName
-let autoGeneration = true;
-
-function resetTtsPlayback() {
- // Clear currently processing jobs
- currentTtsJob = null;
- currentAudioJob = null;
-
- // Reset audio element
- audioElement.currentTime = 0;
- audioElement.src = null;
-
- // Clearn any queue items
- ttsJobQueue.splice(0, ttsJobQueue.length);
- audioJobQueue.splice(0, audioJobQueue.length);
-
- // Set audio ready to process again
- audioQueueProcessorReady = true;
-}
async function onNarrateOneMessage() {
cancelTtsPlay();
@@ -89,6 +71,12 @@ async function moduleWorker() {
processTtsQueue()
processAudioJobQueue()
updateUiAudioPlayState()
+
+
+ // Auto generation is disabled
+ if (extension_settings.tts.auto_generation == false){
+ return
+ }
// no characters or group selected
if (!context.groupId && context.characterId === undefined) {
@@ -141,6 +129,38 @@ async function moduleWorker() {
ttsJobQueue.push(message)
}
+
+function resetTtsPlayback() {
+ // Clear currently processing jobs
+ currentTtsJob = null;
+ currentAudioJob = null;
+
+ // Reset audio element
+ audioElement.currentTime = 0;
+ audioElement.src = null;
+
+ // Clear any queue items
+ ttsJobQueue.splice(0, ttsJobQueue.length);
+ audioJobQueue.splice(0, audioJobQueue.length);
+
+ // Set audio ready to process again
+ audioQueueProcessorReady = true;
+}
+
+function isTtsProcessing() {
+ let processing = false
+
+ // Check job queues
+ if (ttsJobQueue.length > 0 || audioJobQueue > 0){
+ processing = true
+ }
+ // Check current jobs
+ if (currentTtsJob != null || currentAudioJob != null) {
+ processing = true
+ }
+ return processing
+}
+
//##################//
// Audio Control //
//##################//
@@ -155,6 +175,10 @@ let audioQueueProcessorReady = true
let lastAudioPosition = 0
async function playAudioData(audioBlob) {
+ // Since current audio job can be cancelled, don't playback if it is null
+ if (currentAudioJob == null){
+ console.log("Cancelled TTS playback because currentAudioJob was null")
+ }
const reader = new FileReader()
reader.onload = function (e) {
const srcUrl = e.target.result
@@ -199,9 +223,13 @@ async function onTtsVoicesClick() {
function updateUiAudioPlayState() {
if (extension_settings.tts.enabled == true) {
audioControl.style.display = 'flex'
- const img = !audioElement.paused
- ? 'fa-solid fa-circle-pause'
- : 'fa-solid fa-circle-play'
+ let img
+ // Give user feedback that TTS is active by setting the stop icon if processing or playing
+ if (!audioElement.paused || isTtsProcessing()){
+ img = 'fa-solid fa-stop-circle'
+ } else {
+ img = 'fa-solid fa-circle-play'
+ }
audioControl.className = img
} else {
audioControl.style.display = 'none'
@@ -209,7 +237,14 @@ function updateUiAudioPlayState() {
}
function onAudioControlClicked() {
- audioElement.paused ? audioElement.play() : audioElement.pause()
+ let context = getContext()
+ // Not pausing, doing a full stop to anything TTS is doing. Better UX as pause is not as useful
+ if (!audioElement.paused || isTtsProcessing()){
+ resetTtsPlayback()
+ } else {
+ // Default play behavior if not processing or playing is to play the last message.
+ ttsJobQueue.push(context.chat[context.chat.length - 1])
+ }
updateUiAudioPlayState()
}
@@ -222,6 +257,7 @@ function addAudioControl() {
function completeCurrentAudioJob() {
audioQueueProcessorReady = true
+ currentAudioJob = null
lastAudioPosition = 0
// updateUiPlayState();
}
@@ -259,7 +295,7 @@ async function processAudioJobQueue() {
//################//
let ttsJobQueue = []
-let currentTtsJob
+let currentTtsJob // Null if nothing is currently being processed
let currentMessageNumber = 0
function completeTtsJob() {
@@ -348,14 +384,15 @@ function loadSettings() {
)
$('#tts_narrate_dialogues').prop('checked', extension_settings.tts.narrate_dialogues_only)
$('#tts_narrate_quoted').prop('checked', extension_settings.tts.narrate_quoted_only)
+ $('#tts_auto_generation').prop('checked', extension_settings.tts.auto_generation)
$('body').toggleClass('tts', extension_settings.tts.enabled);
}
const defaultSettings = {
voiceMap: '',
ttsEnabled: false,
- currentProvider: "ElevenLabs"
-
+ currentProvider: "ElevenLabs",
+ auto_generation: true
}
function setTtsStatus(status, success) {
@@ -435,6 +472,11 @@ function onEnableClick() {
saveSettingsDebounced()
}
+function onAutoGenerationClick() {
+ extension_settings.tts.auto_generation = $('#tts_auto_generation').prop('checked');
+ saveSettingsDebounced()
+}
+
function onNarrateDialoguesClick() {
extension_settings.tts.narrate_dialogues_only = $('#tts_narrate_dialogues').prop('checked');
@@ -523,6 +565,10 @@ $(document).ready(function () {
Enabled
+