mirror of
https://github.com/ParisNeo/lollms-webui.git
synced 2024-12-18 20:17:50 +00:00
fixed
This commit is contained in:
parent
fc8b48adf6
commit
ab4ce7a857
@ -1,5 +1,5 @@
|
||||
# =================== Lord Of Large Language Multimodal Systems Configuration file ===========================
|
||||
version: 90
|
||||
version: 91
|
||||
binding_name: null
|
||||
model_name: null
|
||||
model_variant: null
|
||||
@ -81,9 +81,9 @@ auto_show_browser: true
|
||||
copy_to_clipboard_add_all_details: false
|
||||
|
||||
# Voice service
|
||||
enable_voice_service: false
|
||||
xtts_enable: false
|
||||
xtts_base_url: http://localhost:8020
|
||||
xtts_use_deepspeed: false
|
||||
xtts_use_deepspeed: true
|
||||
xtts_use_streaming_mode: true
|
||||
auto_read: false
|
||||
xtts_current_voice: null
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit e63dcb81ad726108183724b23f6553e5d28d5258
|
||||
Subproject commit c370b6ecceaa4437de1379ad1e08287b71bb51ca
|
@ -433,7 +433,7 @@ class LOLLMSWebUI(LOLLMSElfServer):
|
||||
run_scripts=True)
|
||||
|
||||
mounted_personalities.append(personality)
|
||||
if self.config.enable_voice_service and self.config.auto_read and len(personality.audio_samples)>0:
|
||||
if self.config.xtts_enable and self.config.auto_read and len(personality.audio_samples)>0:
|
||||
try:
|
||||
from lollms.services.xtts.lollms_xtts import LollmsXTTS
|
||||
if self.tts is None:
|
||||
@ -1194,7 +1194,7 @@ class LOLLMSWebUI(LOLLMSElfServer):
|
||||
client_id=client_id,
|
||||
callback=partial(self.process_chunk,client_id = client_id)
|
||||
)
|
||||
if self.config.enable_voice_service and self.config.auto_read and len(self.personality.audio_samples)>0:
|
||||
if self.config.xtts_enable and self.config.auto_read and len(self.personality.audio_samples)>0:
|
||||
try:
|
||||
self.process_chunk("Generating voice output",MSG_TYPE.MSG_TYPE_STEP_START,client_id=client_id)
|
||||
from lollms.services.xtts.lollms_xtts import LollmsXTTS
|
||||
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
4
web/dist/index.html
vendored
4
web/dist/index.html
vendored
@ -6,8 +6,8 @@
|
||||
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>LoLLMS WebUI - Welcome</title>
|
||||
<script type="module" crossorigin src="/assets/index-9dd9fa43.js"></script>
|
||||
<link rel="stylesheet" href="/assets/index-69152375.css">
|
||||
<script type="module" crossorigin src="/assets/index-f1cd900e.js"></script>
|
||||
<link rel="stylesheet" href="/assets/index-f6ab05b8.css">
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
|
@ -155,7 +155,7 @@
|
||||
</div>
|
||||
<div class="flex flex-row items-center">
|
||||
<div v-if="!isSynthesizingVoice" class="text-lg hover:text-red-600 duration-75 active:scale-90 p-2 cursor-pointer"
|
||||
title="read"
|
||||
title="generate_audio"
|
||||
@click.stop="read()"
|
||||
>
|
||||
<i data-feather="voicemail"></i>
|
||||
@ -491,7 +491,7 @@ export default {
|
||||
}
|
||||
else{
|
||||
this.isSynthesizingVoice=true
|
||||
axios.post("./text2Audio",{text:this.message.content}).then(response => {
|
||||
axios.post("./text2wav",{text:this.message.content}).then(response => {
|
||||
this.isSynthesizingVoice=false
|
||||
let url = response.data.url
|
||||
console.log(url)
|
||||
@ -520,81 +520,97 @@ export default {
|
||||
}
|
||||
},
|
||||
speak() {
|
||||
if (this.msg) {
|
||||
this.speechSynthesis.cancel();
|
||||
this.msg = null;
|
||||
this.isSpeaking = false;
|
||||
return;
|
||||
}
|
||||
let startIndex =0;
|
||||
// Set isSpeaking to true before starting synthesis
|
||||
console.log("voice on")
|
||||
this.isSpeaking = true;
|
||||
|
||||
const chunkSize = 200; // You can adjust the chunk size as needed
|
||||
this.message.content;
|
||||
|
||||
// Create a new SpeechSynthesisUtterance instance
|
||||
this.msg = new SpeechSynthesisUtterance();
|
||||
this.msg.pitch = this.$store.state.config.audio_pitch;
|
||||
|
||||
// Optionally, set the voice and other parameters as before
|
||||
if (this.voices.length > 0) {
|
||||
this.msg.voice = this.voices.filter(voice => voice.name === this.$store.state.config.audio_out_voice)[0];
|
||||
}
|
||||
|
||||
|
||||
// Function to find the index of the last sentence that fits within the chunk size
|
||||
const findLastSentenceIndex = (startIndex) => {
|
||||
let txt = this.message.content.substring(startIndex, startIndex+chunkSize)
|
||||
// Define an array of characters that represent end of sentence markers.
|
||||
const endOfSentenceMarkers = ['.', '!', '?', '\n'];
|
||||
|
||||
// Initialize a variable to store the index of the last end of sentence marker.
|
||||
let lastIndex = -1;
|
||||
|
||||
// Iterate through the end of sentence markers and find the last occurrence in the txt string.
|
||||
endOfSentenceMarkers.forEach(marker => {
|
||||
const markerIndex = txt.lastIndexOf(marker);
|
||||
if (markerIndex > lastIndex) {
|
||||
lastIndex = markerIndex;
|
||||
}
|
||||
if(this.$store.state.config.xtts_enable){
|
||||
this.isSpeaking = true;
|
||||
axios.post("./text2Audio",{text:this.message.content}).then(response => {
|
||||
this.isSpeaking = false;
|
||||
}).catch(ex=>{
|
||||
this.$store.state.toast.showToast(`Error: ${ex}`,4,false)
|
||||
this.isSpeaking = false;
|
||||
});
|
||||
if(lastIndex==-1){lastIndex=txt.length}
|
||||
console.log(lastIndex)
|
||||
return lastIndex+startIndex+1;
|
||||
};
|
||||
}
|
||||
else{
|
||||
if (this.msg) {
|
||||
this.speechSynthesis.cancel();
|
||||
this.msg = null;
|
||||
this.isSpeaking = false;
|
||||
return;
|
||||
}
|
||||
let startIndex =0;
|
||||
// Set isSpeaking to true before starting synthesis
|
||||
console.log("voice on")
|
||||
this.isSpeaking = true;
|
||||
|
||||
// Function to speak a chunk of text
|
||||
const speakChunk = () => {
|
||||
if (this.message.content.includes('.')){
|
||||
const endIndex = findLastSentenceIndex(startIndex);
|
||||
const chunk = this.message.content.substring(startIndex, endIndex);
|
||||
this.msg.text = chunk;
|
||||
startIndex = endIndex + 1;
|
||||
this.msg.onend = (event) => {
|
||||
if (startIndex < this.message.content.length-2) {
|
||||
// Use setTimeout to add a brief delay before speaking the next chunk
|
||||
setTimeout(() => {
|
||||
const chunkSize = 200; // You can adjust the chunk size as needed
|
||||
this.message.content;
|
||||
|
||||
// Create a new SpeechSynthesisUtterance instance
|
||||
this.msg = new SpeechSynthesisUtterance();
|
||||
this.msg.pitch = this.$store.state.config.audio_pitch;
|
||||
|
||||
// Optionally, set the voice and other parameters as before
|
||||
if (this.voices.length > 0) {
|
||||
this.msg.voice = this.voices.filter(voice => voice.name === this.$store.state.config.audio_out_voice)[0];
|
||||
}
|
||||
|
||||
|
||||
// Function to find the index of the last sentence that fits within the chunk size
|
||||
const findLastSentenceIndex = (startIndex) => {
|
||||
let txt = this.message.content.substring(startIndex, startIndex+chunkSize)
|
||||
// Define an array of characters that represent end of sentence markers.
|
||||
const endOfSentenceMarkers = ['.', '!', '?', '\n'];
|
||||
|
||||
// Initialize a variable to store the index of the last end of sentence marker.
|
||||
let lastIndex = -1;
|
||||
|
||||
// Iterate through the end of sentence markers and find the last occurrence in the txt string.
|
||||
endOfSentenceMarkers.forEach(marker => {
|
||||
const markerIndex = txt.lastIndexOf(marker);
|
||||
if (markerIndex > lastIndex) {
|
||||
lastIndex = markerIndex;
|
||||
}
|
||||
});
|
||||
if(lastIndex==-1){lastIndex=txt.length}
|
||||
console.log(lastIndex)
|
||||
return lastIndex+startIndex+1;
|
||||
};
|
||||
|
||||
// Function to speak a chunk of text
|
||||
const speakChunk = () => {
|
||||
if (this.message.content.includes('.')){
|
||||
const endIndex = findLastSentenceIndex(startIndex);
|
||||
const chunk = this.message.content.substring(startIndex, endIndex);
|
||||
this.msg.text = chunk;
|
||||
startIndex = endIndex + 1;
|
||||
this.msg.onend = (event) => {
|
||||
if (startIndex < this.message.content.length-2) {
|
||||
// Use setTimeout to add a brief delay before speaking the next chunk
|
||||
setTimeout(() => {
|
||||
speakChunk();
|
||||
}, 1); // Adjust the delay as needed
|
||||
} else {
|
||||
this.isSpeaking = false;
|
||||
console.log("voice off :",this.message.content.length," ",endIndex)
|
||||
}
|
||||
};
|
||||
this.speechSynthesis.speak(this.msg);
|
||||
|
||||
}
|
||||
else{
|
||||
setTimeout(() => {
|
||||
speakChunk();
|
||||
}, 1); // Adjust the delay as needed
|
||||
} else {
|
||||
this.isSpeaking = false;
|
||||
console.log("voice off :",this.message.content.length," ",endIndex)
|
||||
}
|
||||
};
|
||||
this.speechSynthesis.speak(this.msg);
|
||||
}
|
||||
};
|
||||
|
||||
// Speak the first chunk
|
||||
speakChunk();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
else{
|
||||
setTimeout(() => {
|
||||
speakChunk();
|
||||
}, 1); // Adjust the delay as needed
|
||||
}
|
||||
};
|
||||
|
||||
// Speak the first chunk
|
||||
speakChunk();
|
||||
},
|
||||
|
||||
toggleModel() {
|
||||
|
@ -21,6 +21,17 @@
|
||||
>
|
||||
Playground
|
||||
</RouterLink>
|
||||
<RouterLink
|
||||
v-if="$store.state.config.enable_sd_service"
|
||||
:to="{ name: 'AutoSD' }"
|
||||
class="inline-block border-l border-t border-r rounded-t py-2 px-4 text-blue-700 font-semibold"
|
||||
:class="{
|
||||
'text-green-600 hover:text-green-500 dark:text-green-100 font-bold bg-bg-secondary shadow-no-bottom': isRouteActive('AutoSD'),
|
||||
'bounce-in': isRouteActive('AutoSD'),
|
||||
}"
|
||||
>
|
||||
Auto111-SD
|
||||
</RouterLink>
|
||||
<RouterLink
|
||||
v-if="$store.state.config.enable_comfyui_service"
|
||||
:to="{ name: 'ComfyUI' }"
|
||||
@ -33,7 +44,7 @@
|
||||
ComfyUI
|
||||
</RouterLink>
|
||||
<RouterLink
|
||||
v-if="$store.state.config.enable_voice_service"
|
||||
v-if="$store.state.config.xtts_enable"
|
||||
:to="{ name: 'interactive' }"
|
||||
class="inline-block border-l border-t border-r rounded-t py-2 px-4 text-blue-700 font-semibold"
|
||||
:class="{
|
||||
|
@ -9,12 +9,18 @@ import DiscussionsView from '../views/DiscussionsView.vue'
|
||||
import InteractiveView from '../views/InteractiveView.vue'
|
||||
import NodesView from '../views/NodesView.vue'
|
||||
import ComfyuiView from '../views/ComfyuiView.vue'
|
||||
import AutoSDView from '../views/AutoSDView.vue'
|
||||
|
||||
const router = createRouter({
|
||||
history: createWebHistory(import.meta.env.BASE_URL),
|
||||
routes: [
|
||||
{
|
||||
path: '/comfyui_view/',
|
||||
path: '/auto_sd_view/',
|
||||
name: 'AutoSD',
|
||||
component: AutoSDView
|
||||
},
|
||||
{
|
||||
path: '/autosd_view/',
|
||||
name: 'ComfyUI',
|
||||
component: ComfyuiView
|
||||
},
|
||||
|
@ -1,10 +1,10 @@
|
||||
<template>
|
||||
<div style="width: 100vw; height: 100vh">
|
||||
<iframe :src="$store.state.config.comfyui_base_url" class="m-0 p-0 w-full h-full"></iframe>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
//import "../css/classic.css";
|
||||
</script>
|
||||
<div style="width: 100vw; height: 100vh">
|
||||
<iframe :src="$store.state.config.comfyui_base_url" class="m-0 p-0 w-full h-full"></iframe>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
//import "../css/classic.css";
|
||||
</script>
|
||||
|
@ -228,10 +228,10 @@
|
||||
<label for="app_custom_logo" class="text-sm font-bold" style="margin-right: 1rem;">Application logo:</label>
|
||||
</td>
|
||||
<td>
|
||||
<label for="avatar-upload">
|
||||
<img :src="configFile.app_custom_logo!=''? '/user_infos/'+configFile.app_custom_logo:storeLogo" class="w-50 h-50 rounded-full" style="max-width: 50px; max-height: 50px; cursor: pointer;">
|
||||
<label for="logo-upload">
|
||||
<img :src="configFile.app_custom_logo!=null && configFile.app_custom_logo!=''? '/user_infos/'+configFile.app_custom_logo:storeLogo" class="w-50 h-50 rounded-full" style="max-width: 50px; max-height: 50px; cursor: pointer;">
|
||||
</label>
|
||||
<input type="file" id="avatar-upload" style="display: none" @change="uploadLogo">
|
||||
<input type="file" id="logo-upload" style="display: none" @change="uploadLogo">
|
||||
</td>
|
||||
<td style="width: 10%;">
|
||||
<button class="text-2xl hover:text-red-600 duration-75 active:scale-90 " title="Discard title changes"
|
||||
@ -496,9 +496,9 @@
|
||||
</td>
|
||||
<td>
|
||||
<label for="avatar-upload">
|
||||
<img :src="configFile.user_avatar!=''?'/user_infos/'+configFile.user_avatar: storeLogo" class="w-50 h-50 rounded-full" style="max-width: 50px; max-height: 50px; cursor: pointer;">
|
||||
<img :src="configFile.user_avatar!=null && configFile.user_avatar!=''?'/user_infos/'+configFile.user_avatar: storeLogo" class="w-50 h-50 rounded-full" style="max-width: 50px; max-height: 50px; cursor: pointer;">
|
||||
</label>
|
||||
<input type="file" id="avatar-upload" style="display: none" @change="uploadAvatar()">
|
||||
<input type="file" id="avatar-upload" style="display: none" @change="uploadAvatar">
|
||||
</td>
|
||||
<td style="width: 10%;">
|
||||
<button class="text-2xl hover:text-red-600 duration-75 active:scale-90 " title="Discard title changes"
|
||||
@ -1458,6 +1458,11 @@
|
||||
<a class="hover:text-primary bg-green-200 rounded-lg p-4 m-4 w-full text-center items-center" href="https://github.com/ParisNeo/stable-diffusion-webui/blob/master/LICENSE.txt" target="_blank">automatic1111's sd licence</a>
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
<div class="flex flex-row">
|
||||
<button class="hover:text-primary bg-green-200 rounded-lg p-4 m-4 w-full text-center items-center" @click="reinstallSDService">install sd service</button>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="min-width: 200px;">
|
||||
@ -1839,7 +1844,7 @@
|
||||
<table class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500">
|
||||
<tr>
|
||||
<td style="min-width: 200px;">
|
||||
<label for="enable_voice_service" class="text-sm font-bold" style="margin-right: 1rem;">Enable elastic search service:</label>
|
||||
<label for="xtts_enable" class="text-sm font-bold" style="margin-right: 1rem;">Enable elastic search service:</label>
|
||||
</td>
|
||||
<td>
|
||||
<div class="flex flex-row">
|
||||
@ -1889,15 +1894,15 @@
|
||||
<table class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500">
|
||||
<tr>
|
||||
<td style="min-width: 200px;">
|
||||
<label for="enable_voice_service" class="text-sm font-bold" style="margin-right: 1rem;">Enable voice service:</label>
|
||||
<label for="xtts_enable" class="text-sm font-bold" style="margin-right: 1rem;">Enable voice service:</label>
|
||||
</td>
|
||||
<td>
|
||||
<div class="flex flex-row">
|
||||
<input
|
||||
type="checkbox"
|
||||
id="enable_voice_service"
|
||||
id="xtts_enable"
|
||||
required
|
||||
v-model="configFile.enable_voice_service"
|
||||
v-model="configFile.xtts_enable"
|
||||
@change="settingsChanged=true"
|
||||
class="mt-1 px-2 py-1 border border-gray-300 rounded dark:bg-gray-600"
|
||||
>
|
||||
@ -1938,7 +1943,7 @@
|
||||
</td>
|
||||
<td>
|
||||
<div class="flex flex-row">
|
||||
<select v-model="current_language" @change="settingsChanged=true" :disabled="!enable_voice_service">
|
||||
<select v-model="current_language" @change="settingsChanged=true" :disabled="!xtts_enable">
|
||||
<option v-for="(value, key) in voice_languages" :key="key" :value="value">
|
||||
{{ key }}
|
||||
</option>
|
||||
@ -1953,7 +1958,7 @@
|
||||
</td>
|
||||
<td>
|
||||
<div class="flex flex-row">
|
||||
<select v-model="xtts_current_voice" @change="settingsChanged=true" :disabled="!enable_voice_service">
|
||||
<select v-model="xtts_current_voice" @change="settingsChanged=true" :disabled="!xtts_enable">
|
||||
<option v-for="voice in voices" :key="voice" :value="voice">
|
||||
{{ voice }}
|
||||
</option>
|
||||
@ -1974,7 +1979,7 @@
|
||||
v-model="configFile.xtts_use_deepspeed"
|
||||
@change="settingsChanged=true"
|
||||
class="mt-1 px-2 py-1 border border-gray-300 rounded dark:bg-gray-600"
|
||||
:disabled="!enable_voice_service"
|
||||
:disabled="!xtts_enable"
|
||||
>
|
||||
</div>
|
||||
</td>
|
||||
@ -1992,7 +1997,7 @@
|
||||
v-model="configFile.xtts_use_streaming_mode"
|
||||
@change="settingsChanged=true"
|
||||
class="mt-1 px-2 py-1 border border-gray-300 rounded dark:bg-gray-600"
|
||||
:disabled="!enable_voice_service"
|
||||
:disabled="!xtts_enable"
|
||||
>
|
||||
</div>
|
||||
</td>
|
||||
@ -2010,7 +2015,7 @@
|
||||
v-model="configFile.auto_read"
|
||||
@change="settingsChanged=true"
|
||||
class="mt-1 px-2 py-1 border border-gray-300 rounded dark:bg-gray-600"
|
||||
:disabled="!enable_voice_service"
|
||||
:disabled="!xtts_enable"
|
||||
>
|
||||
</div>
|
||||
</td>
|
||||
@ -3112,9 +3117,12 @@ export default {
|
||||
//await socket.on('install_progress', this.progressListener);
|
||||
//refreshHardwareUsage()
|
||||
},
|
||||
methods: {
|
||||
methods: {
|
||||
install_model(){
|
||||
|
||||
},
|
||||
reinstallSDService(){
|
||||
axios.get('install_sd')
|
||||
axios.post('/install_sd', {client_id:this.$store.state.client_id}, this.posts_headers)
|
||||
.then(response => {
|
||||
|
||||
})
|
||||
@ -3124,7 +3132,7 @@ export default {
|
||||
|
||||
},
|
||||
upgradeSDService(){
|
||||
axios.get('upgrade_sd')
|
||||
axios.post('upgrade_sd', {client_id:this.$store.state.client_id}, this.posts_headers)
|
||||
.then(response => {
|
||||
|
||||
})
|
||||
@ -3134,7 +3142,7 @@ export default {
|
||||
|
||||
},
|
||||
startSDService(){
|
||||
axios.get('start_sd')
|
||||
axios.post('start_sd', {client_id:this.$store.state.client_id}, this.posts_headers)
|
||||
.then(response => {
|
||||
|
||||
})
|
||||
@ -3144,7 +3152,7 @@ export default {
|
||||
|
||||
},
|
||||
showSD(){
|
||||
axios.get('show_sd')
|
||||
axios.post('show_sd', {client_id:this.$store.state.client_id}, this.posts_headers)
|
||||
.then(response => {
|
||||
|
||||
})
|
||||
@ -3427,7 +3435,7 @@ export default {
|
||||
const file = event.target.files[0]; // Get the selected file
|
||||
const formData = new FormData(); // Create a FormData object
|
||||
formData.append('logo', file); // Add the file to the form data with the key 'avatar'
|
||||
console.log("Uploading avatar")
|
||||
console.log("Uploading logo")
|
||||
// Make an API request to upload the avatar
|
||||
axios.post('/upload_logo', formData)
|
||||
.then(response => {
|
||||
@ -5478,13 +5486,13 @@ export default {
|
||||
this.$store.state.config.auto_read = value
|
||||
},
|
||||
},
|
||||
enable_voice_service:{
|
||||
xtts_enable:{
|
||||
get() {
|
||||
return this.$store.state.config.enable_voice_service;
|
||||
return this.$store.state.config.xtts_enable;
|
||||
},
|
||||
set(value) {
|
||||
// You should not set the value directly here; use the updateSetting method instead
|
||||
this.$store.state.config.enable_voice_service = value
|
||||
this.$store.state.config.xtts_enable = value
|
||||
},
|
||||
},
|
||||
current_language:{
|
||||
@ -5726,7 +5734,7 @@ export default {
|
||||
|
||||
},
|
||||
watch: {
|
||||
enable_voice_service(newValue) {
|
||||
xtts_enable(newValue) {
|
||||
if (!newValue) {
|
||||
this.configFile.auto_read = false;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user