mirror of
https://github.com/leon-ai/leon.git
synced 2024-12-18 06:11:34 +03:00
feat(server): on-the-fly language switching
This commit is contained in:
parent
5edcc679f8
commit
f24513a223
@ -28,6 +28,8 @@ LEON_TTS_PROVIDER=flite
|
|||||||
LEON_OVER_HTTP=true
|
LEON_OVER_HTTP=true
|
||||||
# HTTP API key (use "npm run generate:http-api-key" to regenerate one)
|
# HTTP API key (use "npm run generate:http-api-key" to regenerate one)
|
||||||
LEON_HTTP_API_KEY=
|
LEON_HTTP_API_KEY=
|
||||||
|
# Language used for the HTTP API
|
||||||
|
LEON_HTTP_API_LANG=en-US
|
||||||
|
|
||||||
# Enable/disable collaborative logger
|
# Enable/disable collaborative logger
|
||||||
LEON_LOGGER=true
|
LEON_LOGGER=true
|
||||||
|
@ -14,9 +14,12 @@ process.env.LEON_HOST = process.env.LEON_HOST || 'http://localhost'
|
|||||||
process.env.LEON_PORT = process.env.LEON_PORT || 1337
|
process.env.LEON_PORT = process.env.LEON_PORT || 1337
|
||||||
const url = `${process.env.LEON_HOST}:${process.env.LEON_PORT}`
|
const url = `${process.env.LEON_HOST}:${process.env.LEON_PORT}`
|
||||||
const socket = io(url)
|
const socket = io(url)
|
||||||
|
const { argv } = process
|
||||||
|
const lang = argv[2] || 'en'
|
||||||
|
|
||||||
socket.on('connect', () => {
|
socket.on('connect', () => {
|
||||||
socket.emit('init', 'hotword-node')
|
socket.emit('init', 'hotword-node')
|
||||||
|
console.log('Language:', lang)
|
||||||
console.log('Connected to the server')
|
console.log('Connected to the server')
|
||||||
console.log('Waiting for hotword...')
|
console.log('Waiting for hotword...')
|
||||||
})
|
})
|
||||||
@ -33,9 +36,9 @@ request.get(`${url}/api/v1/info`)
|
|||||||
const models = new Models()
|
const models = new Models()
|
||||||
|
|
||||||
models.add({
|
models.add({
|
||||||
file: `${__dirname}/models/leon-${res.body.lang.short}.pmdl`,
|
file: `${__dirname}/models/leon-${lang}.pmdl`,
|
||||||
sensitivity: '0.5',
|
sensitivity: '0.5',
|
||||||
hotwords: `leon-${res.body.lang.short}`
|
hotwords: `leon-${lang}`
|
||||||
})
|
})
|
||||||
|
|
||||||
const detector = new Detector({
|
const detector = new Detector({
|
||||||
|
@ -18,7 +18,7 @@ export default () => new Promise(async (resolve, reject) => {
|
|||||||
const packagesDir = 'packages'
|
const packagesDir = 'packages'
|
||||||
const outputFile = '/core/pkgs-endpoints.json'
|
const outputFile = '/core/pkgs-endpoints.json'
|
||||||
const outputFilePath = path.join(__dirname, `../..${outputFile}`)
|
const outputFilePath = path.join(__dirname, `../..${outputFile}`)
|
||||||
const lang = langs[process.env.LEON_LANG].short.toLowerCase().substr(0, 2)
|
const lang = langs[process.env.LEON_HTTP_API_LANG].short
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const packages = fs.readdirSync(packagesDir)
|
const packages = fs.readdirSync(packagesDir)
|
||||||
@ -49,6 +49,7 @@ export default () => new Promise(async (resolve, reject) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Force if a language is given
|
||||||
if (isFileNeedToBeGenerated) {
|
if (isFileNeedToBeGenerated) {
|
||||||
log.info('Parsing packages configuration...')
|
log.info('Parsing packages configuration...')
|
||||||
|
|
||||||
|
@ -16,7 +16,6 @@ import setupPythonPackages from './setup-python-packages'
|
|||||||
(async () => {
|
(async () => {
|
||||||
try {
|
try {
|
||||||
// Required env vars to setup
|
// Required env vars to setup
|
||||||
process.env.LEON_LANG = 'en-US'
|
|
||||||
process.env.PIPENV_PIPFILE = 'bridges/python/Pipfile'
|
process.env.PIPENV_PIPFILE = 'bridges/python/Pipfile'
|
||||||
process.env.PIPENV_VENV_IN_PROJECT = 'true'
|
process.env.PIPENV_VENV_IN_PROJECT = 'true'
|
||||||
|
|
||||||
|
@ -7,8 +7,7 @@ import path from 'path'
|
|||||||
|
|
||||||
import log from '@/helpers/log'
|
import log from '@/helpers/log'
|
||||||
import string from '@/helpers/string'
|
import string from '@/helpers/string'
|
||||||
|
import lang from '@/helpers/lang'
|
||||||
// import { langs } from '@@/core/langs.json'
|
|
||||||
|
|
||||||
dotenv.config()
|
dotenv.config()
|
||||||
|
|
||||||
@ -18,12 +17,8 @@ dotenv.config()
|
|||||||
* npm run train [en or fr]
|
* npm run train [en or fr]
|
||||||
*/
|
*/
|
||||||
export default () => new Promise(async (resolve, reject) => {
|
export default () => new Promise(async (resolve, reject) => {
|
||||||
// const { argv } = process
|
|
||||||
const packagesDir = 'packages'
|
const packagesDir = 'packages'
|
||||||
const modelFileName = 'server/src/data/leon-model.nlp'
|
const modelFileName = 'server/src/data/leon-model.nlp'
|
||||||
/* const lang = argv[2]
|
|
||||||
? argv[2].toLowerCase()
|
|
||||||
: langs[process.env.LEON_LANG].short.toLowerCase().substr(0, 2) */
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const container = await containerBootstrap()
|
const container = await containerBootstrap()
|
||||||
@ -33,10 +28,6 @@ export default () => new Promise(async (resolve, reject) => {
|
|||||||
|
|
||||||
const nlp = container.get('nlp')
|
const nlp = container.get('nlp')
|
||||||
const nluManager = container.get('nlu-manager')
|
const nluManager = container.get('nlu-manager')
|
||||||
// const dock = await dockStart({ use: ['Basic', 'LangEn', 'LangFr'] })
|
|
||||||
|
|
||||||
// const nlp = dock.get('nlp')
|
|
||||||
// const nluManager = dock.get('nlu-manager')
|
|
||||||
|
|
||||||
nluManager.settings.log = false
|
nluManager.settings.log = false
|
||||||
nluManager.settings.trainByDomain = true
|
nluManager.settings.trainByDomain = true
|
||||||
@ -44,10 +35,11 @@ export default () => new Promise(async (resolve, reject) => {
|
|||||||
nlp.settings.modelFileName = modelFileName
|
nlp.settings.modelFileName = modelFileName
|
||||||
nlp.settings.threshold = 0.8
|
nlp.settings.threshold = 0.8
|
||||||
|
|
||||||
// TODO: grab from core/langs.json
|
const shortLangs = lang.getShortLangs()
|
||||||
const langs = ['en', 'fr']
|
|
||||||
|
for (let h = 0; h < shortLangs.length; h += 1) {
|
||||||
|
const lang = shortLangs[h]
|
||||||
|
|
||||||
langs.forEach(async (lang) => {
|
|
||||||
nlp.addLanguage(lang)
|
nlp.addLanguage(lang)
|
||||||
|
|
||||||
const packages = fs.readdirSync(packagesDir)
|
const packages = fs.readdirSync(packagesDir)
|
||||||
@ -78,7 +70,7 @@ export default () => new Promise(async (resolve, reject) => {
|
|||||||
log.success(`[${lang}] "${string.ucfirst(module)}" module utterance samples trained`)
|
log.success(`[${lang}] "${string.ucfirst(module)}" module utterance samples trained`)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await nlp.train()
|
await nlp.train()
|
||||||
|
@ -5,23 +5,18 @@ import { langs } from '@@/core/langs.json'
|
|||||||
import log from '@/helpers/log'
|
import log from '@/helpers/log'
|
||||||
import string from '@/helpers/string'
|
import string from '@/helpers/string'
|
||||||
import Synchronizer from '@/core/synchronizer'
|
import Synchronizer from '@/core/synchronizer'
|
||||||
|
import lang from '@/helpers/lang'
|
||||||
|
|
||||||
class Brain {
|
class Brain {
|
||||||
constructor (lang) {
|
constructor () {
|
||||||
this.lang = lang
|
this._lang = 'en'
|
||||||
this.broca = JSON.parse(fs.readFileSync(`${__dirname}/../data/en.json`, 'utf8'))
|
this.broca = JSON.parse(fs.readFileSync(`${__dirname}/../data/${this._lang}.json`, 'utf8'))
|
||||||
this.process = { }
|
this.process = { }
|
||||||
this.interOutput = { }
|
this.interOutput = { }
|
||||||
this.finalOutput = { }
|
this.finalOutput = { }
|
||||||
this._socket = { }
|
this._socket = { }
|
||||||
this._tts = { }
|
this._tts = { }
|
||||||
|
|
||||||
// Read into the language file
|
|
||||||
const file = `${__dirname}/../data/${this.lang}.json`
|
|
||||||
if (fs.existsSync(file)) {
|
|
||||||
this.broca = JSON.parse(fs.readFileSync(file, 'utf8'))
|
|
||||||
}
|
|
||||||
|
|
||||||
log.title('Brain')
|
log.title('Brain')
|
||||||
log.success('New instance')
|
log.success('New instance')
|
||||||
}
|
}
|
||||||
@ -42,6 +37,23 @@ class Brain {
|
|||||||
this._tts = newTts
|
this._tts = newTts
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get lang () {
|
||||||
|
return this._lang
|
||||||
|
}
|
||||||
|
|
||||||
|
set lang (newLang) {
|
||||||
|
this._lang = newLang
|
||||||
|
// Update broca
|
||||||
|
this.broca = JSON.parse(fs.readFileSync(`${__dirname}/../data/${this._lang}.json`, 'utf8'))
|
||||||
|
|
||||||
|
if (process.env.LEON_TTS === 'true') {
|
||||||
|
this._tts.init(this._lang, () => {
|
||||||
|
log.title('Brain')
|
||||||
|
log.info('Language has changed')
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Delete intent object file
|
* Delete intent object file
|
||||||
*/
|
*/
|
||||||
@ -114,7 +126,7 @@ class Brain {
|
|||||||
const speeches = []
|
const speeches = []
|
||||||
|
|
||||||
// Ask to repeat if Leon is not sure about the request
|
// Ask to repeat if Leon is not sure about the request
|
||||||
if (obj.classification.confidence < langs[process.env.LEON_LANG].min_confidence) {
|
if (obj.classification.confidence < langs[lang.getLongCode(this._lang)].min_confidence) {
|
||||||
if (!opts.mute) {
|
if (!opts.mute) {
|
||||||
const speech = `${this.wernicke('random_not_sure')}.`
|
const speech = `${this.wernicke('random_not_sure')}.`
|
||||||
|
|
||||||
@ -143,7 +155,7 @@ class Brain {
|
|||||||
*/
|
*/
|
||||||
const intentObj = {
|
const intentObj = {
|
||||||
id: utteranceId,
|
id: utteranceId,
|
||||||
lang: langs[process.env.LEON_LANG].short,
|
lang: this._lang,
|
||||||
package: obj.classification.package,
|
package: obj.classification.package,
|
||||||
module: obj.classification.module,
|
module: obj.classification.module,
|
||||||
action: obj.classification.action,
|
action: obj.classification.action,
|
||||||
@ -198,7 +210,6 @@ class Brain {
|
|||||||
|
|
||||||
// Handle error
|
// Handle error
|
||||||
this.process.stderr.on('data', (data) => {
|
this.process.stderr.on('data', (data) => {
|
||||||
console.log('data', data.toString())
|
|
||||||
const speech = `${this.wernicke('random_package_module_errors', '',
|
const speech = `${this.wernicke('random_package_module_errors', '',
|
||||||
{ '%module_name%': moduleName, '%package_name%': packageName })}!`
|
{ '%module_name%': moduleName, '%package_name%': packageName })}!`
|
||||||
if (!opts.mute) {
|
if (!opts.mute) {
|
||||||
@ -269,7 +280,7 @@ class Brain {
|
|||||||
|
|
||||||
resolve({
|
resolve({
|
||||||
utteranceId,
|
utteranceId,
|
||||||
lang: langs[process.env.LEON_LANG].short,
|
lang: this._lang,
|
||||||
...obj,
|
...obj,
|
||||||
speeches,
|
speeches,
|
||||||
executionTime // In ms, module execution time only
|
executionTime // In ms, module execution time only
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
import { langs } from '@@/core/langs.json'
|
|
||||||
import { version } from '@@/package.json'
|
import { version } from '@@/package.json'
|
||||||
import log from '@/helpers/log'
|
import log from '@/helpers/log'
|
||||||
|
|
||||||
@ -25,7 +24,6 @@ const getInfo = async (fastify, options) => {
|
|||||||
enabled: process.env.LEON_TTS === 'true',
|
enabled: process.env.LEON_TTS === 'true',
|
||||||
provider: process.env.LEON_TTS_PROVIDER
|
provider: process.env.LEON_TTS_PROVIDER
|
||||||
},
|
},
|
||||||
lang: langs[process.env.LEON_LANG],
|
|
||||||
version
|
version
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -4,7 +4,6 @@ import socketio from 'socket.io'
|
|||||||
import { join } from 'path'
|
import { join } from 'path'
|
||||||
|
|
||||||
import { version } from '@@/package.json'
|
import { version } from '@@/package.json'
|
||||||
import { langs } from '@@/core/langs.json'
|
|
||||||
import { endpoints } from '@@/core/pkgs-endpoints.json'
|
import { endpoints } from '@@/core/pkgs-endpoints.json'
|
||||||
import Nlu from '@/core/nlu'
|
import Nlu from '@/core/nlu'
|
||||||
import Brain from '@/core/brain'
|
import Brain from '@/core/brain'
|
||||||
@ -166,7 +165,7 @@ server.handleOnConnection = (socket) => {
|
|||||||
ttsState = 'enabled'
|
ttsState = 'enabled'
|
||||||
|
|
||||||
tts = new Tts(socket, process.env.LEON_TTS_PROVIDER)
|
tts = new Tts(socket, process.env.LEON_TTS_PROVIDER)
|
||||||
tts.init((ttsInstance) => {
|
tts.init('en', (ttsInstance) => {
|
||||||
brain.tts = ttsInstance
|
brain.tts = ttsInstance
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -278,18 +277,12 @@ server.init = async () => {
|
|||||||
log.success(`The current env is ${process.env.LEON_NODE_ENV}`)
|
log.success(`The current env is ${process.env.LEON_NODE_ENV}`)
|
||||||
log.success(`The current version is ${version}`)
|
log.success(`The current version is ${version}`)
|
||||||
|
|
||||||
if (!Object.keys(langs).includes(process.env.LEON_LANG) === true) {
|
|
||||||
process.env.LEON_LANG = 'en-US'
|
|
||||||
log.warning('The language you chose is not supported, then the default language has been applied')
|
|
||||||
}
|
|
||||||
|
|
||||||
log.success(`The current language is ${process.env.LEON_LANG}`)
|
|
||||||
log.success(`The current time zone is ${date.timeZone()}`)
|
log.success(`The current time zone is ${date.timeZone()}`)
|
||||||
|
|
||||||
const sLogger = (process.env.LEON_LOGGER !== 'true') ? 'disabled' : 'enabled'
|
const sLogger = (process.env.LEON_LOGGER !== 'true') ? 'disabled' : 'enabled'
|
||||||
log.success(`Collaborative logger ${sLogger}`)
|
log.success(`Collaborative logger ${sLogger}`)
|
||||||
|
|
||||||
brain = new Brain(langs[process.env.LEON_LANG].short)
|
brain = new Brain()
|
||||||
nlu = new Nlu(brain)
|
nlu = new Nlu(brain)
|
||||||
|
|
||||||
// Train modules utterance samples
|
// Train modules utterance samples
|
||||||
|
@ -10,6 +10,7 @@ import { version } from '@@/package.json'
|
|||||||
import Ner from '@/core/ner'
|
import Ner from '@/core/ner'
|
||||||
import log from '@/helpers/log'
|
import log from '@/helpers/log'
|
||||||
import string from '@/helpers/string'
|
import string from '@/helpers/string'
|
||||||
|
import lang from '@/helpers/lang'
|
||||||
|
|
||||||
class Nlu {
|
class Nlu {
|
||||||
constructor (brain) {
|
constructor (brain) {
|
||||||
@ -72,6 +73,7 @@ class Nlu {
|
|||||||
opts = opts || {
|
opts = opts || {
|
||||||
mute: false // Close Leon mouth e.g. over HTTP
|
mute: false // Close Leon mouth e.g. over HTTP
|
||||||
}
|
}
|
||||||
|
|
||||||
utterance = string.ucfirst(utterance)
|
utterance = string.ucfirst(utterance)
|
||||||
|
|
||||||
if (Object.keys(this.nlp).length === 0) {
|
if (Object.keys(this.nlp).length === 0) {
|
||||||
@ -85,17 +87,9 @@ class Nlu {
|
|||||||
return reject(msg)
|
return reject(msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
const lang = langs[process.env.LEON_LANG].short
|
|
||||||
const guessedLang = await this.nlp.guessLanguage(utterance)
|
|
||||||
|
|
||||||
console.log('guessedLang', guessedLang)
|
|
||||||
|
|
||||||
const result = await this.nlp.process(utterance)
|
const result = await this.nlp.process(utterance)
|
||||||
|
|
||||||
console.log('result', result)
|
|
||||||
|
|
||||||
const {
|
const {
|
||||||
domain, intent, score
|
locale, domain, intent, score
|
||||||
} = result
|
} = result
|
||||||
const [moduleName, actionName] = intent.split('.')
|
const [moduleName, actionName] = intent.split('.')
|
||||||
let obj = {
|
let obj = {
|
||||||
@ -109,6 +103,10 @@ class Nlu {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this.brain.lang !== locale) {
|
||||||
|
this.brain.lang = locale
|
||||||
|
}
|
||||||
|
|
||||||
/* istanbul ignore next */
|
/* istanbul ignore next */
|
||||||
if (process.env.LEON_LOGGER === 'true' && process.env.LEON_NODE_ENV !== 'testing') {
|
if (process.env.LEON_LOGGER === 'true' && process.env.LEON_NODE_ENV !== 'testing') {
|
||||||
this.request
|
this.request
|
||||||
@ -117,7 +115,7 @@ class Nlu {
|
|||||||
.send({
|
.send({
|
||||||
version,
|
version,
|
||||||
utterance,
|
utterance,
|
||||||
lang,
|
lang: this.brain.lang,
|
||||||
classification: obj.classification
|
classification: obj.classification
|
||||||
})
|
})
|
||||||
.then(() => { /* */ })
|
.then(() => { /* */ })
|
||||||
@ -125,7 +123,7 @@ class Nlu {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (intent === 'None') {
|
if (intent === 'None') {
|
||||||
const fallback = Nlu.fallback(obj, langs[process.env.LEON_LANG].fallbacks)
|
const fallback = Nlu.fallback(obj, langs[lang.getLongCode(locale)].fallbacks)
|
||||||
|
|
||||||
if (fallback === false) {
|
if (fallback === false) {
|
||||||
if (!opts.mute) {
|
if (!opts.mute) {
|
||||||
@ -154,8 +152,8 @@ class Nlu {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
obj.entities = await this.ner.extractEntities(
|
obj.entities = await this.ner.extractEntities(
|
||||||
lang,
|
this.brain.lang,
|
||||||
join(__dirname, '../../../packages', obj.classification.package, `data/expressions/${lang}.json`),
|
join(__dirname, '../../../packages', obj.classification.package, `data/expressions/${this.brain.lang}.json`),
|
||||||
obj
|
obj
|
||||||
)
|
)
|
||||||
} catch (e) /* istanbul ignore next */ {
|
} catch (e) /* istanbul ignore next */ {
|
||||||
|
21
server/src/helpers/lang.js
Normal file
21
server/src/helpers/lang.js
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
import { langs } from '@@/core/langs.json'
|
||||||
|
|
||||||
|
const lang = { }
|
||||||
|
|
||||||
|
lang.getShortLangs = () => Object.keys(langs).map((lang) => langs[lang].short)
|
||||||
|
|
||||||
|
lang.getLongCode = (shortLang) => {
|
||||||
|
const langsArr = Object.keys(langs)
|
||||||
|
|
||||||
|
for (let i = 0; i < langsArr.length; i += 1) {
|
||||||
|
const { short } = langs[langsArr[i]]
|
||||||
|
|
||||||
|
if (short === shortLang) {
|
||||||
|
return langsArr[i]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
export default lang
|
@ -22,14 +22,15 @@ let client = { }
|
|||||||
|
|
||||||
synthesizer.conf = {
|
synthesizer.conf = {
|
||||||
OutputFormat: 'mp3',
|
OutputFormat: 'mp3',
|
||||||
VoiceId: voices[process.env.LEON_LANG].VoiceId
|
VoiceId: ''
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize Amazon Polly based on credentials in the JSON file
|
* Initialize Amazon Polly based on credentials in the JSON file
|
||||||
*/
|
*/
|
||||||
synthesizer.init = () => {
|
synthesizer.init = (lang) => {
|
||||||
const config = JSON.parse(fs.readFileSync(`${__dirname}/../../config/voice/amazon.json`, 'utf8'))
|
const config = JSON.parse(fs.readFileSync(`${__dirname}/../../config/voice/amazon.json`, 'utf8'))
|
||||||
|
synthesizer.conf.VoiceId = voices[lang].VoiceId
|
||||||
|
|
||||||
try {
|
try {
|
||||||
client = new Polly(config)
|
client = new Polly(config)
|
||||||
|
@ -21,11 +21,11 @@ synthesizer.conf = {
|
|||||||
/**
|
/**
|
||||||
* There is nothing to initialize for this synthesizer
|
* There is nothing to initialize for this synthesizer
|
||||||
*/
|
*/
|
||||||
synthesizer.init = () => {
|
synthesizer.init = (lang) => {
|
||||||
const flitePath = 'bin/flite/flite'
|
const flitePath = 'bin/flite/flite'
|
||||||
|
|
||||||
/* istanbul ignore if */
|
/* istanbul ignore if */
|
||||||
if (process.env.LEON_LANG !== 'en-US') {
|
if (lang !== 'en-US') {
|
||||||
log.warning('The Flite synthesizer only accepts the "en-US" language for the moment')
|
log.warning('The Flite synthesizer only accepts the "en-US" language for the moment')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -26,7 +26,7 @@ const voices = {
|
|||||||
let client = { }
|
let client = { }
|
||||||
|
|
||||||
synthesizer.conf = {
|
synthesizer.conf = {
|
||||||
voice: voices[process.env.LEON_LANG],
|
voice: '',
|
||||||
audioConfig: {
|
audioConfig: {
|
||||||
audioEncoding: 'MP3'
|
audioEncoding: 'MP3'
|
||||||
}
|
}
|
||||||
@ -36,8 +36,9 @@ synthesizer.conf = {
|
|||||||
* Initialize Google Cloud Text-to-Speech based on credentials in the JSON file
|
* Initialize Google Cloud Text-to-Speech based on credentials in the JSON file
|
||||||
* The env variable "GOOGLE_APPLICATION_CREDENTIALS" provides the JSON file path
|
* The env variable "GOOGLE_APPLICATION_CREDENTIALS" provides the JSON file path
|
||||||
*/
|
*/
|
||||||
synthesizer.init = () => {
|
synthesizer.init = (lang) => {
|
||||||
process.env.GOOGLE_APPLICATION_CREDENTIALS = `${__dirname}/../../config/voice/google-cloud.json`
|
process.env.GOOGLE_APPLICATION_CREDENTIALS = `${__dirname}/../../config/voice/google-cloud.json`
|
||||||
|
synthesizer.conf.voice = voices[lang]
|
||||||
|
|
||||||
try {
|
try {
|
||||||
client = new tts.TextToSpeechClient()
|
client = new tts.TextToSpeechClient()
|
||||||
|
@ -2,6 +2,7 @@ import events from 'events'
|
|||||||
import fs from 'fs'
|
import fs from 'fs'
|
||||||
|
|
||||||
import log from '@/helpers/log'
|
import log from '@/helpers/log'
|
||||||
|
import lang from '@/helpers/lang'
|
||||||
|
|
||||||
class Tts {
|
class Tts {
|
||||||
constructor (socket, provider) {
|
constructor (socket, provider) {
|
||||||
@ -16,6 +17,7 @@ class Tts {
|
|||||||
this.synthesizer = { }
|
this.synthesizer = { }
|
||||||
this.em = new events.EventEmitter()
|
this.em = new events.EventEmitter()
|
||||||
this.speeches = []
|
this.speeches = []
|
||||||
|
this.lang = 'en'
|
||||||
|
|
||||||
log.title('TTS')
|
log.title('TTS')
|
||||||
log.success('New instance')
|
log.success('New instance')
|
||||||
@ -24,9 +26,11 @@ class Tts {
|
|||||||
/**
|
/**
|
||||||
* Initialize the TTS provider
|
* Initialize the TTS provider
|
||||||
*/
|
*/
|
||||||
init (cb) {
|
init (newLang, cb) {
|
||||||
log.info('Initializing TTS...')
|
log.info('Initializing TTS...')
|
||||||
|
|
||||||
|
this.lang = newLang || this.lang
|
||||||
|
|
||||||
if (!this.providers.includes(this.provider)) {
|
if (!this.providers.includes(this.provider)) {
|
||||||
log.error(`The TTS provider "${this.provider}" does not exist or is not yet supported`)
|
log.error(`The TTS provider "${this.provider}" does not exist or is not yet supported`)
|
||||||
|
|
||||||
@ -43,7 +47,7 @@ class Tts {
|
|||||||
|
|
||||||
// Dynamically attribute the synthesizer
|
// Dynamically attribute the synthesizer
|
||||||
this.synthesizer = require(`${__dirname}/${this.provider}/synthesizer`) // eslint-disable-line global-require
|
this.synthesizer = require(`${__dirname}/${this.provider}/synthesizer`) // eslint-disable-line global-require
|
||||||
this.synthesizer.default.init(this.synthesizer.default.conf)
|
this.synthesizer.default.init(lang.getLongCode(this.lang))
|
||||||
|
|
||||||
this.onSaved()
|
this.onSaved()
|
||||||
|
|
||||||
|
@ -22,15 +22,16 @@ const voices = {
|
|||||||
let client = { }
|
let client = { }
|
||||||
|
|
||||||
synthesizer.conf = {
|
synthesizer.conf = {
|
||||||
voice: voices[process.env.LEON_LANG].voice,
|
voice: '',
|
||||||
accept: 'audio/wav'
|
accept: 'audio/wav'
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize Watson Text-to-Speech based on credentials in the JSON file
|
* Initialize Watson Text-to-Speech based on credentials in the JSON file
|
||||||
*/
|
*/
|
||||||
synthesizer.init = () => {
|
synthesizer.init = (lang) => {
|
||||||
const config = JSON.parse(fs.readFileSync(`${__dirname}/../../config/voice/watson-tts.json`, 'utf8'))
|
const config = JSON.parse(fs.readFileSync(`${__dirname}/../../config/voice/watson-tts.json`, 'utf8'))
|
||||||
|
synthesizer.conf.voice = voices[lang].voice
|
||||||
|
|
||||||
try {
|
try {
|
||||||
client = new Tts({
|
client = new Tts({
|
||||||
|
@ -138,7 +138,6 @@ describe('NER', () => {
|
|||||||
)
|
)
|
||||||
|
|
||||||
expect(Ner.logExtraction).toHaveBeenCalledTimes(1)
|
expect(Ner.logExtraction).toHaveBeenCalledTimes(1)
|
||||||
console.log('entities', entities)
|
|
||||||
expect(entities.length).toBe(2)
|
expect(entities.length).toBe(2)
|
||||||
expect(entities.map((e) => e.entity)).toEqual(['start', 'animal'])
|
expect(entities.map((e) => e.entity)).toEqual(['start', 'animal'])
|
||||||
expect(entities.map((e) => e.sourceText)).toEqual(['Please whistle as a', 'bird'])
|
expect(entities.map((e) => e.sourceText)).toEqual(['Please whistle as a', 'bird'])
|
||||||
|
Loading…
Reference in New Issue
Block a user