code cleanup, fully functional backend.
This commit is contained in:
parent
d5de27ca8b
commit
643d01b23d
11 changed files with 76 additions and 93 deletions
42
.compilerc
42
.compilerc
|
|
@ -1,42 +0,0 @@
|
||||||
{
|
|
||||||
"env": {
|
|
||||||
"development": {
|
|
||||||
"application/javascript": {
|
|
||||||
"presets": [
|
|
||||||
[
|
|
||||||
"env",
|
|
||||||
{
|
|
||||||
"targets": {
|
|
||||||
"electron": "8.2"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"react"
|
|
||||||
],
|
|
||||||
"plugins": [
|
|
||||||
"transform-async-to-generator"
|
|
||||||
],
|
|
||||||
"sourceMaps": "inline"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"production": {
|
|
||||||
"application/javascript": {
|
|
||||||
"presets": [
|
|
||||||
[
|
|
||||||
"env",
|
|
||||||
{
|
|
||||||
"targets": {
|
|
||||||
"electron": "8.2"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"react"
|
|
||||||
],
|
|
||||||
"plugins": [
|
|
||||||
"transform-async-to-generator"
|
|
||||||
],
|
|
||||||
"sourceMaps": "none"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,25 +0,0 @@
|
||||||
{
|
|
||||||
"env": {
|
|
||||||
"browser": true,
|
|
||||||
"es2021": true
|
|
||||||
},
|
|
||||||
"extends": [
|
|
||||||
"airbnb-base"
|
|
||||||
],
|
|
||||||
"parserOptions": {
|
|
||||||
"ecmaVersion": "latest",
|
|
||||||
"sourceType": "module"
|
|
||||||
},
|
|
||||||
"rules": {
|
|
||||||
"linebreak-style":"off",
|
|
||||||
"indent":["error", "tab"],
|
|
||||||
"no-tabs":"off",
|
|
||||||
"prefer-destructuring": ["error", {
|
|
||||||
"AssignmentExpression": {
|
|
||||||
"array": false,
|
|
||||||
"object": true
|
|
||||||
}
|
|
||||||
}],
|
|
||||||
"no-console": ["error", { "allow": ["warn", "error"] }]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
5
.gitignore
vendored
5
.gitignore
vendored
|
|
@ -100,5 +100,8 @@ language_detection_model/*
|
||||||
!language_detection_model/Where to get language detection model.txt
|
!language_detection_model/Where to get language detection model.txt
|
||||||
.vscode/
|
.vscode/
|
||||||
package-lock.json
|
package-lock.json
|
||||||
src/backend/loquendoBot_backend.exe
|
|
||||||
src/sounds/tts/*
|
src/sounds/tts/*
|
||||||
|
loquendoBot_backend.spec
|
||||||
|
forge.config.js
|
||||||
|
backend/*
|
||||||
|
src/backend/loquendoBot_backend.exe
|
||||||
|
|
@ -2,7 +2,7 @@ module.exports = {
|
||||||
packagerConfig: {
|
packagerConfig: {
|
||||||
icon: './src/images/icon.ico',
|
icon: './src/images/icon.ico',
|
||||||
asar: true,
|
asar: true,
|
||||||
extraResource: ['./src/config/loquendo.db', './src/sounds', './backend', './speech_to_text_models'],
|
extraResource: ['./src/config/loquendo.db', './src/sounds', './backend', './language_detection_model', './speech_to_text_models'],
|
||||||
},
|
},
|
||||||
rebuildConfig: {},
|
rebuildConfig: {},
|
||||||
makers: [
|
makers: [
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,6 @@
|
||||||
"package": "npm run backend && electron-forge package",
|
"package": "npm run backend && electron-forge package",
|
||||||
"make": "electron-forge make",
|
"make": "electron-forge make",
|
||||||
"publish": "electron-forge publish",
|
"publish": "electron-forge publish",
|
||||||
"lint": "echo \"No linting configured\"",
|
|
||||||
"backend": "pyinstaller --noconsole --onefile --collect-all vosk --distpath ./backend ./src/backend/loquendoBot_backend.py"
|
"backend": "pyinstaller --noconsole --onefile --collect-all vosk --distpath ./backend ./src/backend/loquendoBot_backend.py"
|
||||||
},
|
},
|
||||||
"keywords": [],
|
"keywords": [],
|
||||||
|
|
|
||||||
|
|
@ -33,8 +33,8 @@ settings = configparser.ConfigParser()
|
||||||
app = Flask(__name__)
|
app = Flask(__name__)
|
||||||
|
|
||||||
|
|
||||||
settingsPath = ""
|
settingsPath = os.path.normpath(sys.argv[1])
|
||||||
environment = ""
|
environment = sys.argv[2]
|
||||||
q = queue.Queue()
|
q = queue.Queue()
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -45,10 +45,23 @@ q = queue.Queue()
|
||||||
|
|
||||||
class LanguageDetection:
|
class LanguageDetection:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
pretrained_lang_model = (
|
if environment == "dev":
|
||||||
r"C:\repos\LoquendoBotV2\language_detection_model\lid.176.bin"
|
settings_folder = os.path.dirname(settingsPath)
|
||||||
|
src_folder = os.path.dirname(settings_folder)
|
||||||
|
main_folder = os.path.dirname(src_folder)
|
||||||
|
language_detection_model = os.path.join(
|
||||||
|
main_folder, "language_detection_model", f"lid.176.bin"
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
resources_folder = os.path.dirname(settingsPath)
|
||||||
|
language_detection_model = os.path.join(
|
||||||
|
resources_folder, "language_detection_model", f"lid.176.bin"
|
||||||
|
)
|
||||||
|
|
||||||
|
language_detection_model = (
|
||||||
|
rf"{language_detection_model}"
|
||||||
)
|
)
|
||||||
self.model = fasttext.load_model(pretrained_lang_model)
|
self.model = fasttext.load_model(language_detection_model)
|
||||||
|
|
||||||
def predict_lang(self, text):
|
def predict_lang(self, text):
|
||||||
predictions = self.model.predict(text, k=5) # returns top 2 matching languages
|
predictions = self.model.predict(text, k=5) # returns top 2 matching languages
|
||||||
|
|
@ -58,17 +71,31 @@ class LanguageDetection:
|
||||||
|
|
||||||
return language_codes
|
return language_codes
|
||||||
|
|
||||||
|
|
||||||
class STT:
|
class STT:
|
||||||
samplerate = None
|
samplerate = None
|
||||||
args = ""
|
args = ""
|
||||||
remaining = ""
|
remaining = ""
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
device_info = sd.query_devices(0, "input")
|
settings.read(settingsPath)
|
||||||
|
device_info = sd.query_devices(int(settings["STT"]["MICROPHONE"]), "input")
|
||||||
self.samplerate = int(device_info["default_samplerate"])
|
self.samplerate = int(device_info["default_samplerate"])
|
||||||
|
|
||||||
|
if environment == "dev":
|
||||||
|
settings_folder = os.path.dirname(settingsPath)
|
||||||
|
src_folder = os.path.dirname(settings_folder)
|
||||||
|
main_folder = os.path.dirname(src_folder)
|
||||||
|
vosk_model = os.path.join(
|
||||||
|
main_folder, "speech_to_text_models", settings["STT"]["LANGUAGE"]
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
resources_folder = os.path.dirname(settingsPath)
|
||||||
|
vosk_model = os.path.join(
|
||||||
|
resources_folder, "speech_to_text_models", settings["STT"]["LANGUAGE"]
|
||||||
|
)
|
||||||
|
|
||||||
self.model = Model(
|
self.model = Model(
|
||||||
r"C:\repos\LoquendoBotV2\speech_to_text_models\vosk-model-small-es-0.42"
|
rf"{vosk_model}"
|
||||||
)
|
)
|
||||||
self.dump_fn = None
|
self.dump_fn = None
|
||||||
|
|
||||||
|
|
@ -234,7 +261,7 @@ def get_voices():
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
LANGUAGE = LanguageDetection()
|
LANGUAGE = LanguageDetection()
|
||||||
lang = LANGUAGE.predict_lang("hola")
|
lang = LANGUAGE.predict_lang("hola cómo estás")
|
||||||
print(lang)
|
print(lang)
|
||||||
text = "Keep it up. You are awesome"
|
text = "Keep it up. You are awesome"
|
||||||
translated = MyMemoryTranslator(
|
translated = MyMemoryTranslator(
|
||||||
|
|
@ -242,8 +269,6 @@ if __name__ == "__main__":
|
||||||
).translate(text)
|
).translate(text)
|
||||||
print(translated)
|
print(translated)
|
||||||
if len(sys.argv) > 1:
|
if len(sys.argv) > 1:
|
||||||
environment = sys.argv[2]
|
|
||||||
settingsPath = os.path.normpath(sys.argv[1])
|
|
||||||
settings.read(settingsPath)
|
settings.read(settingsPath)
|
||||||
port = int(settings["GENERAL"]["PORT"])
|
port = int(settings["GENERAL"]["PORT"])
|
||||||
else:
|
else:
|
||||||
|
|
|
||||||
|
|
@ -55,7 +55,7 @@ async function getBackendServerStatus() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function getSTT() {
|
function startSTT() {
|
||||||
const eventSource = new EventSource('http://127.0.0.1:9000/stream');
|
const eventSource = new EventSource('http://127.0.0.1:9000/stream');
|
||||||
|
|
||||||
eventSource.addEventListener('message', (event) => {
|
eventSource.addEventListener('message', (event) => {
|
||||||
|
|
@ -134,7 +134,9 @@ async function initiateBackend() {
|
||||||
createBackendServer().then(() => {
|
createBackendServer().then(() => {
|
||||||
getBackendServerStatus();
|
getBackendServerStatus();
|
||||||
getInstalledVoices();
|
getInstalledVoices();
|
||||||
getSTT();
|
if (settings.STT.USE_STT) {
|
||||||
|
startSTT();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error during backend initialization:', error);
|
console.error('Error during backend initialization:', error);
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,17 @@ function getAvailableMediaDevices(type) {
|
||||||
// Microphones
|
// Microphones
|
||||||
getAvailableMediaDevices('audioinput')
|
getAvailableMediaDevices('audioinput')
|
||||||
.then((microphones) => {
|
.then((microphones) => {
|
||||||
microphones.forEach((mic, i) => {
|
let i = 0;
|
||||||
|
let tempname = '';
|
||||||
|
for (let mic of microphones) {
|
||||||
|
if (mic.deviceId === 'default') {
|
||||||
|
tempname = mic.label.slice(10); // remove "default -" from the label to get the default device name.
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mic.deviceId === 'communications' || mic.label === tempname) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
const option = document.createElement('option');
|
const option = document.createElement('option');
|
||||||
|
|
||||||
// Set the options value and text.
|
// Set the options value and text.
|
||||||
|
|
@ -31,7 +41,8 @@ getAvailableMediaDevices('audioinput')
|
||||||
if (i === microphones.length - 1) {
|
if (i === microphones.length - 1) {
|
||||||
document.getElementById('microphone').value = settings.STT.SELECTED_MICROPHONE;
|
document.getElementById('microphone').value = settings.STT.SELECTED_MICROPHONE;
|
||||||
}
|
}
|
||||||
});
|
i++;
|
||||||
|
}
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
console.error('Error retrieving microphones:', error);
|
console.error('Error retrieving microphones:', error);
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,6 @@ const ini = require('ini');
|
||||||
const path = require('path'); // get directory path
|
const path = require('path'); // get directory path
|
||||||
|
|
||||||
const { ipcRenderer, shell } = require('electron'); // necessary electron libraries to send data to the app
|
const { ipcRenderer, shell } = require('electron'); // necessary electron libraries to send data to the app
|
||||||
const say = require('say');
|
|
||||||
const io = require('socket.io-client');
|
const io = require('socket.io-client');
|
||||||
|
|
||||||
const util = require('util');
|
const util = require('util');
|
||||||
|
|
@ -101,20 +100,23 @@ fs.readdir(notificationSounds, (err, files) => {
|
||||||
|
|
||||||
// Check for installed stt models
|
// Check for installed stt models
|
||||||
fs.readdir(sttModels, (err, files) => {
|
fs.readdir(sttModels, (err, files) => {
|
||||||
files.forEach((file, i) => {
|
for (let file of files) {
|
||||||
|
if (file.includes('.txt')) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
// Create a new option element.
|
// Create a new option element.
|
||||||
const option = document.createElement('option');
|
const option = document.createElement('option');
|
||||||
|
|
||||||
// Set the options value and text.
|
// Set the options value and text.
|
||||||
option.value = i;
|
option.value = file;
|
||||||
option.innerHTML = file;
|
option.innerHTML = file;
|
||||||
|
|
||||||
// Add the option to the sound selector.
|
// Add the option to the sound selector.
|
||||||
sttModel.appendChild(option);
|
sttModel.appendChild(option);
|
||||||
});
|
}
|
||||||
|
|
||||||
// set the saved notification sound
|
// set the saved notification sound
|
||||||
sttModel.selectedIndex = settings.AUDIO.NOTIFICATION_SOUND;
|
sttModel.value = settings.STT.LANGUAGE;
|
||||||
});
|
});
|
||||||
|
|
||||||
async function getAudioDevices() {
|
async function getAudioDevices() {
|
||||||
|
|
|
||||||
|
|
@ -80,13 +80,20 @@ document.body.querySelector('#primaryVoice').addEventListener('change', () => {
|
||||||
|
|
||||||
document.body.querySelector('#microphone').addEventListener('change', () => {
|
document.body.querySelector('#microphone').addEventListener('change', () => {
|
||||||
var select = document.querySelector('#microphone');
|
var select = document.querySelector('#microphone');
|
||||||
settings.STT.MICROPHONE = select.selectedIndex;
|
settings.STT.MICROPHONE = select.value;
|
||||||
settings.STT.MICROPHONE_ID = select.options[select.selectedIndex].text;
|
settings.STT.MICROPHONE_ID = select.options[select.selectedIndex].text;
|
||||||
fs.writeFileSync(settingsPath, ini.stringify(settings));
|
fs.writeFileSync(settingsPath, ini.stringify(settings));
|
||||||
createNotification('Saved microphone!', 'success');
|
createNotification('Saved microphone!', 'success');
|
||||||
startVoiceRecognition();
|
startVoiceRecognition();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
document.body.querySelector('#sttModel').addEventListener('change', () => {
|
||||||
|
var select = document.querySelector('#sttModel');
|
||||||
|
settings.STT.LANGUAGE = select.value;
|
||||||
|
fs.writeFileSync(settingsPath, ini.stringify(settings));
|
||||||
|
createNotification('Saved voice detection language!', 'success');
|
||||||
|
});
|
||||||
|
|
||||||
document.body.querySelector('#defaultLanguage').addEventListener('change', () => {
|
document.body.querySelector('#defaultLanguage').addEventListener('change', () => {
|
||||||
var select = document.querySelector('#defaultLanguage');
|
var select = document.querySelector('#defaultLanguage');
|
||||||
settings.TTS.PRIMARY_TTS_LANGUAGE_INDEX = select.selectedIndex;
|
settings.TTS.PRIMARY_TTS_LANGUAGE_INDEX = select.selectedIndex;
|
||||||
|
|
|
||||||
|
|
@ -150,6 +150,7 @@ async function createIniFile() {
|
||||||
MICROPHONE_ID: 'default',
|
MICROPHONE_ID: 'default',
|
||||||
SELECTED_MICROPHONE: 'default',
|
SELECTED_MICROPHONE: 'default',
|
||||||
MICROPHONE: 5,
|
MICROPHONE: 5,
|
||||||
|
LANGUAGE: 'vosk-model-small-es-0.42',
|
||||||
},
|
},
|
||||||
AUDIO: {
|
AUDIO: {
|
||||||
USE_NOTIFICATION_SOUNDS: true,
|
USE_NOTIFICATION_SOUNDS: true,
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue