language detection fixes and installer change.

This commit is contained in:
Khyretos 2024-01-03 14:26:08 +01:00
parent 5cfdd498c9
commit d83c0ad753
28 changed files with 216 additions and 149 deletions

4
.gitignore vendored
View file

@ -104,5 +104,7 @@ src/sounds/tts/*
loquendoBot_backend.spec
forge.config.js
backend/*
src/backend/loquendoBot_backend.exe
!backend/loquendoBot_backend.py
backend/loquendoBot_backend.exe
src/config/twitch-emotes.json
dist/*

View file

@ -11,7 +11,7 @@ logger = logging.getLogger("waitress")
logger.setLevel(logging.INFO)
gevent.monkey.patch_all()
import gevent.queue
# import gevent.queue
import configparser
import pyttsx3
@ -28,8 +28,6 @@ from deep_translator import (
MyMemoryTranslator,
)
import emoji
from vosk import Model, KaldiRecognizer, SetLogLevel
# global variables
@ -68,7 +66,7 @@ class LanguageDetection:
self.model = fasttext.load_model(language_detection_model)
def predict_lang(self, text):
predictions = self.model.predict(text, k=5) # returns top 2 matching languages
predictions = self.model.predict(text, k=3) # returns top 2 matching languages
language_codes = []
for prediction in predictions[0]:
language_codes.append(prediction.replace("__label__", ""))
@ -98,6 +96,7 @@ class STT:
vosk_model = os.path.join(
resources_folder, "speech_to_text_models", settings["STT"]["LANGUAGE"]
)
print(vosk_model)
self.model = Model(rf"{vosk_model}")
self.dump_fn = None
@ -137,8 +136,10 @@ class STT:
def stop_recognition(self):
self.is_running = False
speech_recognition_service = STT()
settings.read(settingsPath)
print(settingsPath)
if settings["STT"]["USE_STT"] and bool(settings["STT"]["LANGUAGE"]):
speech_recognition_service = STT()
class TTS:
@ -156,16 +157,16 @@ class TTS:
break
self.engine.setProperty("voice", matching_id)
if environment == "dev":
settings_folder = os.path.dirname(settingsPath)
if environment == "dev":
src_folder = os.path.dirname(settings_folder)
bot_folder = os.path.dirname(src_folder)
saveLocation = os.path.join(
src_folder, "sounds\\tts", f"Internal_{count}.mp3"
bot_folder, "sounds", f"Internal_{count}.mp3"
)
else:
resources_folder = os.path.dirname(settingsPath)
saveLocation = os.path.join(
resources_folder, "sounds\\tts", f"Internal_{count}.mp3"
settings_folder, "sounds", f"Internal_{count}.mp3"
)
self.engine.save_to_file(message, saveLocation)
@ -180,8 +181,9 @@ class TTS:
return [voice.name for voice in voices]
text_to_speech_service = TTS()
settings.read(settingsPath)
if settings["TTS"]["USE_TTS"]:
text_to_speech_service = TTS()
# endpoints

View file

@ -1,36 +0,0 @@
module.exports = {
packagerConfig: {
icon: './src/images/icon.ico',
asar: true,
extraResource: ['./src/config/loquendo.db', './src/sounds', './backend', './language_detection_model', './speech_to_text_models'],
},
rebuildConfig: {},
makers: [
{
name: '@electron-forge/maker-squirrel',
config: {
setupIcon: './src/images/icon.ico',
},
},
{
name: '@electron-forge/maker-zip',
platforms: ['darwin'],
},
{
name: '@electron-forge/maker-deb',
config: {
options: {},
},
},
{
name: '@electron-forge/maker-rpm',
config: {},
},
],
plugins: [
{
name: '@electron-forge/plugin-auto-unpack-natives',
config: {},
},
],
};

View file

@ -1,6 +1,6 @@
MIT License
Copyright (c) 2021 Khyretis
Copyright (c) 2021 Khyretos
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View file

@ -1,14 +1,37 @@
{
"name": "loquendo-bot",
"productName": "LoquendoBot",
"version": "2.5.0",
"description": "Bot assistant for streamers over different platforms",
"main": "src/main.js",
"scripts": {
"start": "electron-forge start",
"package": "npm run backend && electron-forge package",
"make": "electron-forge make",
"build": "npm run backend && electron-builder",
"publish": "electron-forge publish",
"backend": "pyinstaller --noconsole --onefile --collect-all vosk --distpath ./backend ./src/backend/loquendoBot_backend.py"
"backend": "pyinstaller --noconsole --onefile --collect-all vosk --distpath ./backend ./backend/loquendoBot_backend.py"
},
"build": {
"appId": "LoquendoBot",
"win": {
"target": [
"nsis"
],
"icon": "./src/images/icon.ico"
},
"nsis": {
"oneClick": false,
"installerIcon": "./src/images/icon.ico",
"uninstallerIcon": "./src/images/icon.ico",
"uninstallDisplayName": "LoquendoBot-uninstaller",
"license": "license.md",
"allowToChangeInstallationDirectory": "true"
},
"extraResources": [
"speech_to_text_models/Where to get STT models.txt",
"backend/loquendoBot_backend.exe",
"language_detection_model",
"sounds"
]
},
"keywords": [],
"author": {
@ -18,7 +41,6 @@
"license": "ISC",
"dependencies": {
"axios": "^1.4.0",
"electron-squirrel-startup": "^1.0.0",
"emoji-picker-element": "^1.21.0",
"express": "^4.18.2",
"flag-icons": "^7.1.0",
@ -38,12 +60,12 @@
"@electron-forge/cli": "^6.2.1",
"@electron-forge/maker-deb": "^6.2.1",
"@electron-forge/maker-rpm": "^6.2.1",
"@electron-forge/maker-squirrel": "^6.2.1",
"@electron-forge/maker-zip": "^6.2.1",
"@electron-forge/plugin-auto-unpack-natives": "^6.2.1",
"@electron-internal/eslint-config": "^1.0.1",
"@electron-toolkit/eslint-config": "^1.0.2",
"electron": "^25.9.8",
"electron-builder": "^24.9.1",
"eslint": "^8.56.0",
"eslint-config-prettier": "^9.1.0",
"eslint-plugin-prettier": "^5.1.2",

View file

@ -1 +1,3 @@
https://alphacephei.com/vosk/models
Download the model from here: https://alphacephei.com/vosk/models unzip it
and drop the folder in the 'speech_to_text_models' folder. Restart the app
to load the changes.

View file

@ -36,25 +36,14 @@ html {
box-sizing: inherit;
}
html,
body {
height: 100%;
margin: 0;
/* border-top-left-radius: 20px; */
/* border-top-right-radius: 20px; */
overflow-x: hidden;
}
body {
font-family: 'Segoe UI', sans-serif;
background: transparent;
}
/* Styling of window frame and titlebar */
body {
/* border: 1px solid #48545c; */
overflow-y: hidden;
position: relative;
/* overflow-y: hidden;
overflow-x: hidden; */
}
#titlebar {

Binary file not shown.

Before

Width:  |  Height:  |  Size: 34 KiB

After

Width:  |  Height:  |  Size: 29 KiB

View file

@ -212,6 +212,11 @@
<div class="AdvancedMenuRow inputTTS">
<div class="AdvancedMenuLabel">2<sup>nd</sup> Internal Voice</div>
<select class="menu-select" name="secondaryVoice" id="secondaryVoice"></select>
<i
class="fa fa-question-circle fa-2x SmallButton option-icon-container"
id="Info_SECONDARY_TTS"
tip="This will only work if Language detection is enabled and a language for this voice has been selected"
></i>
</div>
<div class="AdvancedMenuRow inputTTS">
<div class="AdvancedMenuLabel">Test 2<sup>nd</sup> Internal Voice</div>
@ -235,8 +240,13 @@
<select class="menu-select" name="microphone" id="microphone"></select>
</div>
<div class="AdvancedMenuRow voiceLanguageDetection inputSTT">
<div class="AdvancedMenuLabel">Voice Language</div>
<div class="AdvancedMenuLabel">Voice Language model</div>
<select class="menu-select" name="sttModel" id="sttModel" tip="Language Service to use"></select>
<i
class="fa-solid fa-folder-open fa-2x SmallButton option-icon-container"
id="Info_VOICE_MODELS_FOLDER"
tip="Open Voice models folder"
></i>
</div>
</fieldset>
@ -247,27 +257,42 @@
<label for="USE_DETECTION" class="toggle-small"></label>
<div class="AdvancedMenuLabel3">Enable Language detection</div>
</legend>
<div class="AdvancedMenuRow languageDetectionInput">
<div class="AdvancedMenuLabel">Translate chat messages to</div>
<select class="menu-select" name="language" id="TRANSLATE_TO" tip="Language Service to use"></select>
</div>
<div class="AdvancedMenuRow languageDetectionInput">
<div class="AdvancedMenuLabel">Broadcast translation to chat</div>
<input type="checkbox" id="BROADCAST_TRANSLATION" class="checkbox" />
<label for="BROADCAST_TRANSLATION" class="toggle-small"></label>
</div>
<div class="AdvancedMenuRow languageDetectionInput">
<div class="AdvancedMenuLabel">Output translation to TTS</div>
<input type="checkbox" id="OUTPUT_TO_TTS" class="checkbox" />
<label for="OUTPUT_TO_TTS" class="toggle-small"></label>
</div>
<div class="AdvancedMenuRow outputToTtsInput">
<div class="AdvancedMenuLabel">Default TTS service language</div>
<select class="menu-select" name="defaultLanguage" id="defaultLanguage" tip="Language Service to use"></select>
<i
class="fa fa-question-circle fa-2x SmallButton option-icon-container"
id="Info_PRIMARY_TTS_LANGUAGE"
tip="When the selected language is detected Your Primary TTS voice will sound"
></i>
</div>
<div class="AdvancedMenuRow outputToTtsInput">
<div class="AdvancedMenuLabel">2<sup>nd</sup> TTS service language</div>
<select class="menu-select" name="secondaryLanguage" id="secondaryLanguage" tip="Language Service to use"></select>
<i
class="fa fa-question-circle fa-2x SmallButton option-icon-container"
id="Info_SECONDARY_TTS_LANGUAGE"
tip="When the selected language is detected Your Secondary TTS voice will sound"
></i>
</div>
<div class="AdvancedMenuRow languageDetectionInput">
<div class="AdvancedMenuLabel">Translate chat messages to</div>
<select class="menu-select" name="language" id="TRANSLATE_TO" tip="Language Service to use"></select>
</div>
<div class="AdvancedMenuRow languageDetectionInput TRANSLATE_TO">
<div class="AdvancedMenuLabel">Broadcast translation to chat</div>
<input type="checkbox" id="BROADCAST_TRANSLATION" class="checkbox TRANSLATE_TO" />
<label for="BROADCAST_TRANSLATION" class="toggle-small"></label>
</div>
<div class="AdvancedMenuRow languageDetectionInput TRANSLATE_TO">
<div class="AdvancedMenuLabel">Output translation to TTS</div>
<input type="checkbox" id="OUTPUT_TO_TTS" class="checkbox TRANSLATE_TO" />
<label for="OUTPUT_TO_TTS" class="toggle-small"></label>
<i
class="fa fa-question-circle fa-2x SmallButton option-icon-container"
id="Info_OUTPUT_TO_TTS"
tip="All translated messages will be send to primary TTS voice but if message is detected in Secondary TTS language it will output it to the Secondary TTS voice"
></i>
</div>
</fieldset>

View file

@ -1,4 +1,4 @@
/* global settings, sound, twitch, getLanguageProperties, addSingleTooltip, showChatMessage, languageObject, addVoiceService, internalVoices, ttsRequestCount, main, path, pythonPath, settingsPath, ipcRenderer */
/* global settings, resourcesPath, sound, twitch, getLanguageProperties, addSingleTooltip, showChatMessage, languageObject, addVoiceService, internalVoices, ttsRequestCount, main, path, pythonPath, settingsPath, ipcRenderer */
const spawn = require('child_process').spawn;
const kill = require('kill-process-by-name');
@ -45,6 +45,7 @@ async function getInstalledVoices() {
}
function setTranslatedMessage(message) {
if (message.language.selectedLanguage.ISO639 !== message.language.detectedLanguage.ISO639) {
const messageBox = document.getElementById(message.messageId).getElementsByClassName('msg-box')[0];
const translationHeader = document.createElement('div');
@ -56,8 +57,8 @@ function setTranslatedMessage(message) {
translationIcon.className = 'translation-icon';
const languageElement = document.createElement('span');
const language = getLanguageProperties(settings.LANGUAGE.TRANSLATE_TO);
languageElement.classList = `fi fi-${language.ISO3166} fis`;
languageElement.setAttribute('tip', language.name);
languageElement.classList = `fi fi-${message.language.selectedLanguage.ISO3166} fis`;
languageElement.setAttribute('tip', message.language.selectedLanguage.name);
addSingleTooltip(languageElement);
translationIcon.appendChild(languageElement);
messageBox.appendChild(translationIcon);
@ -67,13 +68,16 @@ function setTranslatedMessage(message) {
translationMessage.innerText = message.translation;
messageBox.appendChild(translationMessage);
showChatMessage();
}
if (settings.LANGUAGE.OUTPUT_TO_TTS) {
sound.playVoice({
originalMessage: message.originalMessage,
filteredMessage: message.translation,
logoUrl: message.logoUrl,
username: message.username,
formattedMessage: message.formattedMessage,
language
language: message.language
});
}
}
@ -86,7 +90,7 @@ async function getTranslatedMessage(message) {
},
body: JSON.stringify({
message: message.message,
language: message.language
language: message.language.detectedLanguage.IETF
}) // Convert the data to JSON and include it in the request body
};
@ -97,15 +101,18 @@ async function getTranslatedMessage(message) {
console.log('Translated message:', responseData);
setTranslatedMessage({
originalMessage: message.message,
translation: responseData.translation,
messageId: message.messageId,
ISO3166: message.ISO3166,
language: message.language,
formattedMessage: message.formattedMessage,
username: message.username,
logoUrl: message.logoUrl
});
if (settings.LANGUAGE.BROADCAST_TRANSLATION) {
twitch.sendMessage(`[${message.language} > ${settings.LANGUAGE.TRANSLATE_TO}] @${message.username}: ${responseData.translation}`);
twitch.sendMessage(
`[${message.language.detectedLanguage.name} ${message.language.detectedLanguage.ISO639} > ${message.language.selectedLanguage.name} ${message.language.selectedLanguage.ISO639}] @${message.username}: ${responseData.translation}`
);
}
} else {
console.error('Failed to send termination signal to Flask server.');
@ -119,19 +126,40 @@ async function getTranslatedMessage(message) {
}
function filterLanguage(message) {
const language = getLanguageProperties(message.language);
if (settings.LANGUAGE.TRANSLATE_TO !== 'none') {
const selectedPrimaryLanguage = getLanguageProperties(settings.LANGUAGE.TRANSLATE_TO);
const selectedPrimaryLanguageIndex =
message.languages.indexOf(selectedPrimaryLanguage.ISO639) === -1 ? 99 : message.languages.indexOf(selectedPrimaryLanguage.ISO639);
const selectedSecondaryLanguage = getLanguageProperties(settings.TTS.SECONDARY_TTS_LANGUAGE);
const selectedSecondaryLanguageIndex =
message.languages.indexOf(selectedSecondaryLanguage.ISO639) === -1 ? 99 : message.languages.indexOf(selectedSecondaryLanguage.ISO639);
const detectedLanguage = getLanguageProperties(message.languages[0]);
const language = selectedPrimaryLanguageIndex < selectedSecondaryLanguageIndex ? selectedPrimaryLanguage : detectedLanguage;
if (settings.LANGUAGE.TRANSLATE_TO !== 'none' && selectedPrimaryLanguage.ISO639 !== detectedLanguage.ISO639) {
getTranslatedMessage({
message: message.message,
messageId: message.messageId,
language: language.IETF,
ISO3166: language.ISO3166,
language: {
selectedLanguage: selectedPrimaryLanguage,
detectedLanguage
},
username: message.username,
formattedMessage: message.formattedMessage
formattedMessage: message.formattedMessage,
logoUrl: message.logoUrl
});
} else {
setTranslatedMessage({
originalMessage: message.message,
translation: message.message,
messageId: message.messageId,
language: {
selectedLanguage: selectedPrimaryLanguage,
detectedLanguage: selectedPrimaryLanguage
},
formattedMessage: message.formattedMessage,
username: message.username,
logoUrl: message.logoUrl
});
}
return language;
}
@ -155,7 +183,7 @@ async function getDetectedLanguage(message) {
console.log('Detected Languages:', responseData);
return filterLanguage({
language: responseData.languages[0],
languages: responseData.languages,
message: message.message,
messageId: message.messageId,
username: message.username,
@ -232,7 +260,7 @@ const createBackendServer = () =>
if (main.isPackaged) {
python = spawn(path.join(pythonPath, './loquendoBot_backend.exe'), [settingsPath, 'prod']);
} else {
python = spawn('python', ['-u', path.join(pythonPath, './loquendoBot_backend.py'), settingsPath, 'dev']);
python = spawn('python', ['-u', path.join(resourcesPath, '../backend/loquendoBot_backend.py'), settingsPath, 'dev']);
}
// Capture the stdout of the Python process
python.stdout.on('data', data => {
@ -266,7 +294,7 @@ async function initiateBackend() {
createBackendServer().then(() => {
getBackendServerStatus();
getInstalledVoices();
if (settings.STT.USE_STT) {
if (settings.STT.USE_STT && !settings.STT.LANGUAGE === '') {
startSTT();
}
});

View file

@ -73,6 +73,7 @@ const languages = {
'crimean tatar': { IETF: 'crh-RU', ISO639: 'crh', ISO3166: 'tr' },
'crioulo upper guinea': { IETF: 'pov-GW', ISO639: 'pov', ISO3166: 'gw' },
croatian: { IETF: 'hr-HR', ISO639: 'hr', ISO3166: 'hr' },
'serbo-croatian': { IETF: 'sr-Cyrl-RS', ISO639: 'sh', ISO3166: 'sr' },
czech: { IETF: 'cs-CZ', ISO639: 'cs', ISO3166: 'cz' },
danish: { IETF: 'da-DK', ISO639: 'da', ISO3166: 'dk' },
dari: { IETF: 'prs-AF', ISO639: 'prs', ISO3166: 'af' },
@ -108,6 +109,7 @@ const languages = {
garo: { IETF: 'grt-IN', ISO639: 'grt', ISO3166: 'in' },
georgian: { IETF: 'ka-GE', ISO639: 'ka', ISO3166: 'ge' },
german: { IETF: 'de-DE', ISO639: 'de', ISO3166: 'de' },
'Low German': { IETF: 'nl-NL', ISO639: 'nds', ISO3166: 'nl' },
gilbertese: { IETF: 'gil-KI', ISO639: 'gil', ISO3166: 'ki' },
glavda: { IETF: 'glw-NG', ISO639: 'glw', ISO3166: 'ng' },
greek: { IETF: 'el-GR', ISO639: 'el', ISO3166: 'gr' },

View file

@ -1,3 +1,4 @@
/* eslint-disable no-unused-vars */
const fs = require('fs');
const ini = require('ini');
const path = require('path'); // get directory path
@ -49,8 +50,8 @@ const config = require(path.join(__dirname, './js/settings'));
const mediaDevices = require(path.join(__dirname, './js/mediaDevices'));
const notificationSounds = path.join(__dirname, './sounds/notifications');
const sttModels = path.join(__dirname, '../speech_to_text_models');
const notificationSounds = path.join(resourcesPath, main.isPackaged ? './sounds/notifications' : '../sounds/notifications');
const sttModels = path.join(resourcesPath, main.isPackaged ? './speech_to_text_models' : '../speech_to_text_models');
function reset() {
ipcRenderer.send('restart');
@ -233,10 +234,10 @@ function showChatMessage(article) {
document.querySelector('#chatBox').appendChild(article);
}
const messages = Array.from(document.body.querySelectorAll('.msg-container'));
const messages = document.body.querySelectorAll('.msg-container');
const lastMessage = messages[messages.length - 1];
lastMessage.scrollIntoView({ behavior: 'smooth' });
lastMessage.scrollIntoView();
}
function getPostTime() {

View file

@ -1,4 +1,4 @@
/* global settings, setZoomLevel, webFrame, theme, fs, settingsPath, ini, startVoiceRecognition,notificationSoundAudioDevices, ttsAudioDevices, notificationSound, path, resourcesPath, ipcRenderer, auth, shell, sound, twitch, server, backend */
/* global settings,main sttModels, setZoomLevel, webFrame, theme, fs, settingsPath, ini, startVoiceRecognition,notificationSoundAudioDevices, ttsAudioDevices, notificationSound, path, resourcesPath, ipcRenderer, auth, shell, sound, twitch, server, backend */
function getGeneralSettings() {
// General
@ -130,10 +130,34 @@ document.body.querySelector('#language').addEventListener('change', () => {
createNotification('Saved language!', 'success');
});
function setTranslateToOptions() {
const options = document.querySelectorAll('.TRANSLATE_TO');
const index = parseInt(settings.LANGUAGE.TRANSLATE_TO_INDEX);
if (index === 0) {
settings.LANGUAGE.BROADCAST_TRANSLATION = false;
settings.LANGUAGE.OUTPUT_TO_TTS = false;
options.forEach(item => {
item.style.visibility = 'hidden';
item.style.height = '0px';
item.checked = false;
});
} else {
options.forEach(item => {
item.style.visibility = '';
item.style.height = '';
});
}
}
setTranslateToOptions();
document.body.querySelector('#TRANSLATE_TO').addEventListener('change', () => {
const select = document.querySelector('#TRANSLATE_TO');
settings.LANGUAGE.TRANSLATE_TO_INDEX = select.selectedIndex;
settings.LANGUAGE.TRANSLATE_TO = select.options[select.selectedIndex].value;
setTranslateToOptions();
fs.writeFileSync(settingsPath, ini.stringify(settings));
createNotification('Saved primary voice!', 'success');
});
@ -227,7 +251,9 @@ function createNotification(message = null, type = null) {
}
if (settings.AUDIO.USE_NOTIFICATION_SOUNDS) {
const notfication = new Audio(path.join(resourcesPath, `./sounds/notifications/${alertSound}`));
const notfication = new Audio(
path.join(resourcesPath, main.isPackaged ? `./sounds/notifications/${alertSound}` : `../sounds/notifications/${alertSound}`)
);
notfication.volume = settings.AUDIO.NOTIFICATION_VOLUME / 100;
notfication.play();
}
@ -268,6 +294,10 @@ document.body.querySelector('#OPEN_SETTINGS_FILE').addEventListener('click', ()
shell.openExternal(settingsPath);
});
document.body.querySelector('#Info_VOICE_MODELS_FOLDER').addEventListener('click', () => {
shell.openExternal(sttModels);
});
// #region Use Custom theme toggle logic
document.body.querySelector('#USE_CUSTOM_THEME').addEventListener('click', () => {
const toggle = document.getElementById('USE_CUSTOM_THEME').checked;
@ -488,14 +518,6 @@ document.body.querySelector('#USE_STT').addEventListener('change', () => {
createNotification(`${toggle ? 'Enabled' : 'Disabled'} speech to text!`, 'success');
});
function toggleOutputToTts() {
const toggle = settings.LANGUAGE.OUTPUT_TO_TTS;
const inputs = document.getElementsByClassName('outputToTtsInput');
toggleRadio(toggle, inputs);
}
toggleOutputToTts();
document.body.querySelector('#OUTPUT_TO_TTS').addEventListener('change', () => {
let toggle = document.getElementById('OUTPUT_TO_TTS').checked;
if (!settings.TTS.USE_TTS) {
@ -505,8 +527,6 @@ document.body.querySelector('#OUTPUT_TO_TTS').addEventListener('change', () => {
}
settings.LANGUAGE.OUTPUT_TO_TTS = toggle;
const inputs = document.getElementsByClassName('outputToTtsInput');
toggleRadio(toggle, inputs);
fs.writeFileSync(settingsPath, ini.stringify(settings));
createNotification(`${toggle ? 'Enabled' : 'Disabled'} Outputting translations to TTS!`, 'success');
});

View file

@ -1,4 +1,4 @@
/* global ttsAudioFile, path, getLanguageProperties, resourcesPath, settings, fs, notificationSound, backend, socket, requestData */
/* global ttsAudioFile, main, path, getLanguageProperties, resourcesPath, settings, fs, notificationSound, backend, socket, requestData */
const voiceSoundArray = [];
let status = 0;
@ -6,7 +6,10 @@ const counter = 0;
const playTTS = data =>
new Promise(resolve => {
ttsAudioFile = path.join(resourcesPath, `./sounds/tts/${data.service}_${data.count}.mp3`);
ttsAudioFile = path.join(
resourcesPath,
main.isPackaged ? `./sounds/${data.service}_${data.count}.mp3` : `../sounds/${data.service}_${data.count}.mp3`
);
const tts = new Audio(ttsAudioFile);
tts.setSinkId(settings.AUDIO.TTS_AUDIO_DEVICE);
@ -58,7 +61,12 @@ function add(data) {
function playNotificationSound() {
if (settings.AUDIO.USE_NOTIFICATION_SOUNDS) {
const notfication = new Audio(
path.join(resourcesPath, `./sounds/notifications/${notificationSound.options[settings.AUDIO.NOTIFICATION_SOUND].text}`)
path.join(
resourcesPath,
main.isPackaged
? `./sounds/notifications/${notificationSound.options[settings.AUDIO.NOTIFICATION_SOUND].text}`
: `../sounds/notifications/${notificationSound.options[settings.AUDIO.NOTIFICATION_SOUND].text}`
)
);
notfication
@ -93,10 +101,11 @@ async function playVoice(message) {
let voice = settings.TTS.PRIMARY_VOICE;
textObject.filtered = `${message.username}: ${message.filteredMessage}`;
if (settings.LANGUAGE.USE_DETECTION && settings.TTS.SECONDARY_VOICE && settings.LANGUAGE.OUTPUT_TO_TTS) {
if (settings.LANGUAGE.USE_DETECTION && settings.TTS.SECONDARY_VOICE) {
const secondaryTTSLanguage = getLanguageProperties(settings.TTS.SECONDARY_TTS_LANGUAGE);
if (message.language.ISO639 === secondaryTTSLanguage.ISO639) {
if (message.language.detectedLanguage === null || message.language.detectedLanguage.ISO639 === secondaryTTSLanguage.ISO639) {
voice = settings.TTS.SECONDARY_VOICE;
textObject.filtered = message.originalMessage ? message.originalMessage : message.filteredMessage;
}
}

View file

@ -97,6 +97,7 @@ function ping(element) {
}
async function displayTwitchMessage(logoUrl, username, messageObject, filteredMessage) {
messageId++;
const article = document.createElement('article');
article.className = 'msg-container sender';
article.setAttribute('id', messageId);
@ -144,7 +145,13 @@ async function displayTwitchMessage(logoUrl, username, messageObject, filteredMe
showChatMessage(article);
if (filteredMessage && !settings.LANGUAGE.OUTPUT_TO_TTS) {
sound.playVoice({ filteredMessage, logoUrl, username, formattedMessage, language });
sound.playVoice({
filteredMessage,
logoUrl,
username,
formattedMessage,
language: { selectedLanguage: null, detectedLanguage: language }
});
}
window.article = article;
@ -159,7 +166,6 @@ async function displayTwitchMessage(logoUrl, username, messageObject, filteredMe
window.article = article;
}
messageId++;
sound.playNotificationSound();
}

View file

@ -24,11 +24,6 @@ if (app.isPackaged) {
pythonPath = path.join(resourcesPath, './backend');
}
// Handle creating/removing shortcuts on Windows when installing/uninstalling.
if (require('electron-squirrel-startup')) {
app.quit();
}
async function createWindow() {
if (!fs.existsSync(settingsPath)) {
console.log(resourcesPath);
@ -164,7 +159,7 @@ async function createIniFile() {
MICROPHONE_ID: 'default',
SELECTED_MICROPHONE: 'default',
MICROPHONE: 0,
LANGUAGE: 'vosk-model-small-es-0.42'
LANGUAGE: ''
},
AUDIO: {
USE_NOTIFICATION_SOUNDS: false,

Binary file not shown.