1
1
mirror of https://github.com/leon-ai/leon.git synced 2024-11-27 16:16:48 +03:00

Merge branch 'develop' into over-http

This commit is contained in:
louistiti 2022-02-02 18:37:00 +08:00
commit 5c88c134f4
No known key found for this signature in database
GPG Key ID: 0A1C3B043E70C77D
19 changed files with 2145 additions and 306 deletions

View File

@ -17,7 +17,7 @@ LEON_AFTER_SPEECH=false
# Enable/disable Leon's speech-to-text
LEON_STT=false
# Speech-to-text provider
LEON_STT_PROVIDER=deepspeech
LEON_STT_PROVIDER=coqui-stt
# Enable/disable Leon's text-to-speech
LEON_TTS=false

View File

@ -14,7 +14,7 @@ Please check if there is no similar issue before creating this one.
- Leon version:
- OS (or browser) version:
- Node.js version:
- Complete "npm run check" output:
- Complete "leon check" (or "npm run check") output:
- (if using Docker) Complete "npm run docker:check" output:
- (optional) Leon package version:

2
.gitignore vendored
View File

@ -9,7 +9,7 @@ bridges/python/.venv/*
downloads/*
logs/*
server/src/config/**/*.json
bin/deepspeech/*
bin/coqui/*
bin/flite/*
*.pyc

View File

@ -29,10 +29,6 @@
<a href="https://blog.getleon.ai/the-story-behind-leon/">Story</a>
</p>
<svg width="4438" height="1000" viewBox="0 0 4438 1000" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M2223.75 250C2051.25 250 1926.87 362.5 1926.87 531.25C1926.87 700 2066.72 812.5 2239.38 812.5C2343.59 812.5 2435.47 771.25 2492.34 701.719L2372.81 632.656C2341.25 667.188 2293.28 687.344 2239.38 687.344C2164.53 687.344 2100.94 648.281 2077.34 585.781H2515.16C2518.59 568.281 2520.63 550.156 2520.63 531.094C2520.63 362.5 2396.41 250 2223.75 250ZM2076.09 476.562C2095.62 414.219 2149.06 375 2223.75 375C2298.59 375 2352.03 414.219 2371.41 476.562H2076.09ZM2040.78 78.125L1607.81 828.125L1174.69 78.125H1337.03L1607.66 546.875L1878.28 78.125H2040.78ZM577.344 0L1154.69 1000H0L577.344 0ZM3148.75 531.25C3148.75 625 3210 687.5 3305 687.5C3369.38 687.5 3417.66 658.281 3442.5 610.625L3562.5 679.844C3512.81 762.656 3419.69 812.5 3305 812.5C3132.34 812.5 3008.13 700 3008.13 531.25C3008.13 362.5 3132.5 250 3305 250C3419.69 250 3512.66 299.844 3562.5 382.656L3442.5 451.875C3417.66 404.219 3369.38 375 3305 375C3210.16 375 3148.75 437.5 3148.75 531.25ZM4437.5 78.125V796.875H4296.88V78.125H4437.5ZM3906.25 250C3733.75 250 3609.38 362.5 3609.38 531.25C3609.38 700 3749.38 812.5 3921.88 812.5C4026.09 812.5 4117.97 771.25 4174.84 701.719L4055.31 632.656C4023.75 667.188 3975.78 687.344 3921.88 687.344C3847.03 687.344 3783.44 648.281 3759.84 585.781H4197.66C4201.09 568.281 4203.12 550.156 4203.12 531.094C4203.12 362.5 4078.91 250 3906.25 250ZM3758.59 476.562C3778.13 414.219 3831.41 375 3906.25 375C3981.09 375 4034.53 414.219 4053.91 476.562H3758.59ZM2961.25 265.625V417.031C2945.63 412.5 2929.06 409.375 2911.25 409.375C2820.47 409.375 2755 471.875 2755 565.625V796.875H2614.38V265.625H2755V409.375C2755 330 2847.34 265.625 2961.25 265.625Z" fill="black"/>
</svg>
---
## 👋 Introduction
@ -83,8 +79,6 @@ Gitpod will automatically setup an environment and run an instance for you.
- [Node.js](https://nodejs.org/) >= 16
- [npm](https://npmjs.com/) >= 8
- [Python](https://www.python.org/downloads/) >= 3
- [Pipenv](https://docs.pipenv.org) >= 2020.11.15
- Supported OSes: Linux, macOS and Windows
To install these prerequisites, you can follow the [How To section](https://docs.getleon.ai/how-to/) of the documentation.
@ -92,28 +86,22 @@ To install these prerequisites, you can follow the [How To section](https://docs
### Installation
```sh
# Clone the repository (stable branch)
git clone -b master https://github.com/leon-ai/leon.git leon
# OR download the latest release at: https://github.com/leon-ai/leon/releases/latest
# Install the Leon CLI
npm install --global @leon-ai/cli
# Go to the project root
cd leon
# Install
npm install
# Install Leon (stable branch)
leon create birth
# OR install from the develop branch: leon create birth --develop
```
### Usage
```sh
# Check the setup went well
npm run check
# Build
npm run build
leon check
# Run
npm start
leon start
# Go to http://localhost:1337
# Hooray! Leon is running
@ -122,11 +110,11 @@ npm start
### Docker Installation
```sh
# Build
npm run docker:build
# Install Leon
leon create birth --docker
# Run
npm run docker:run
leon start
# Go to http://localhost:1337
# Hooray! Leon is running
@ -184,7 +172,7 @@ You'll find a write-up on this [blog post](https://blog.getleon.ai/the-story-beh
<img src="https://github.com/GregoireAMATO.png?size=128" />
GrAMATO
</a><br>
<sub><sup>30 USD / month</sup></sub>
<sub><sup>17 USD / month</sup></sub>
</td>
<td align="center" valign="middle" width="128">
<a href="https://github.com/phareal">
@ -194,9 +182,9 @@ You'll find a write-up on this [blog post](https://blog.getleon.ai/the-story-beh
<sub><sup>17 USD / month</sup></sub>
</td>
<td align="center" valign="middle" width="128">
<a href="https://github.com/marvinpoo">
<img src="https://github.com/marvinpoo.png?size=128" />
marvinpoo
<a href="https://github.com/Divlo">
<img src="https://github.com/Divlo.png?size=128" />
Divlo
</a><br>
<sub><sup>10 USD / month</sup></sub>
</td>

View File

@ -7,7 +7,7 @@
const request = require('superagent')
const record = require('node-record-lpcm16')
const { Detector, Models } = require('snowboy')
const { Detector, Models } = require('@bugsounet/snowboy')
const { io } = require('socket.io-client')
process.env.LEON_HOST = process.env.LEON_HOST || 'http://localhost'
@ -39,7 +39,7 @@ request.get(`${url}/api/v1/info`)
})
const detector = new Detector({
resource: `${__dirname}/node_modules/snowboy/resources/common.res`,
resource: `${__dirname}/node_modules/@bugsounet/snowboy/resources/common.res`,
models,
audioGain: 2.0,
applyFrontend: true

2064
hotword/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -14,7 +14,8 @@
"license": "MIT",
"dependencies": {
"node-record-lpcm16": "^0.3.0",
"snowboy": "git+https://github.com/leon-ai/snowboy.git",
"@mapbox/node-pre-gyp": "^1.0.8",
"@bugsounet/snowboy": "^2.2.3",
"socket.io-client": "^4.0.0",
"superagent": "^3.5.2"
}

200
package-lock.json generated
View File

@ -23,7 +23,6 @@
"archiver": "^5.3.0",
"async": "^3.2.0",
"cross-env": "^7.0.3",
"deepspeech": "^0.9.3",
"dotenv": "^10.0.0",
"execa": "^5.0.0",
"fastify": "^3.25.2",
@ -35,6 +34,7 @@
"node-wav": "0.0.2",
"socket.io": "^4.4.0",
"socket.io-client": "^4.4.0",
"stt": "^1.1.0",
"superagent": "^6.1.0"
},
"devDependencies": {
@ -7988,21 +7988,6 @@
"node": ">=0.10.0"
}
},
"node_modules/deepspeech": {
"version": "0.9.3",
"resolved": "https://registry.npmjs.org/deepspeech/-/deepspeech-0.9.3.tgz",
"integrity": "sha512-80yqUWEWgzclY9pjukpq0TdkQEbJ6NzqZ899vsLZfa4YcK35uOWIf+ILK55zQ+Ii/TEJ6Eo62Vc2saedQ/AK6w==",
"dependencies": {
"argparse": "1.0.x",
"memory-stream": "1.0.x",
"node-pre-gyp": "0.15.x",
"node-wav": "0.0.2",
"sox-stream": "2.0.x"
},
"bin": {
"deepspeech": "client.js"
}
},
"node_modules/defaults": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz",
@ -8245,9 +8230,9 @@
}
},
"node_modules/engine.io": {
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.1.0.tgz",
"integrity": "sha512-ErhZOVu2xweCjEfYcTdkCnEYUiZgkAcBBAhW4jbIvNG8SLU3orAqoJCiytZjYF7eTpVmmCrLDjLIEaPlUAs1uw==",
"version": "6.1.2",
"resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.1.2.tgz",
"integrity": "sha512-v/7eGHxPvO2AWsksyx2PUsQvBafuvqs0jJJQ0FdmJG1b9qIvgSbqDRGwNhfk2XHaTTbTXiC4quRE8Q9nRjsrQQ==",
"dependencies": {
"@types/cookie": "^0.4.1",
"@types/cors": "^2.8.12",
@ -10226,9 +10211,9 @@
}
},
"node_modules/follow-redirects": {
"version": "1.14.1",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.1.tgz",
"integrity": "sha512-HWqDgT7ZEkqRzBvc2s64vSZ/hfOceEol3ac/7tKwzuvEyWx3/4UegXh5oBOIotkGsObyk3xznnSRVADBgWSQVg==",
"version": "1.14.7",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.7.tgz",
"integrity": "sha512-+hbxoLbFMbRKDwohX8GkTataGqO6Jb7jGwpAlwgy2bIz25XtRm7KEzJM76R1WiNT5SwZkX4Y75SwBolkpmE7iQ==",
"funding": [
{
"type": "individual",
@ -10675,11 +10660,11 @@
"integrity": "sha512-5tXH6Bx/kNGd3MgffdmP4dy2Z+G4eaXw0SE81Tq3BNadtnMR5/ySMzX4SLEzHJzSmPNn4HIdpQsBvXMUykr58w=="
},
"node_modules/google-p12-pem": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/google-p12-pem/-/google-p12-pem-3.0.3.tgz",
"integrity": "sha512-wS0ek4ZtFx/ACKYF3JhyGe5kzH7pgiQ7J5otlumqR9psmWMYc+U9cErKlCYVYHoUaidXHdZ2xbo34kB+S+24hA==",
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/google-p12-pem/-/google-p12-pem-3.1.3.tgz",
"integrity": "sha512-MC0jISvzymxePDVembypNefkAQp+DRP7dBE+zNUPaIjEspIlYg0++OrsNr248V9tPbz6iqtZ7rX1hxWA5B8qBQ==",
"dependencies": {
"node-forge": "^0.10.0"
"node-forge": "^1.0.0"
},
"bin": {
"gp12-pem": "build/src/bin/gp12-pem.js"
@ -16866,9 +16851,9 @@
"dev": true
},
"node_modules/nanoid": {
"version": "3.1.30",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.30.tgz",
"integrity": "sha512-zJpuPDwOv8D2zq2WRoMe1HsfZthVewpel9CAvTfc/2mBD1uUT/agc5f7GHGWXlYkFvi1mVxe4IjvP2HNrop7nQ==",
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.2.0.tgz",
"integrity": "sha512-fmsZYa9lpn69Ad5eDn7FMcnnSR+8R34W9qJEijxYhTbfOWzr22n1QxCMzXLK+ODyW2973V3Fux959iQoUxzUIA==",
"dev": true,
"bin": {
"nanoid": "bin/nanoid.cjs"
@ -16932,19 +16917,49 @@
}
},
"node_modules/node-fetch": {
"version": "2.6.1",
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz",
"integrity": "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==",
"version": "2.6.7",
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz",
"integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==",
"dependencies": {
"whatwg-url": "^5.0.0"
},
"engines": {
"node": "4.x || >=6.0.0"
},
"peerDependencies": {
"encoding": "^0.1.0"
},
"peerDependenciesMeta": {
"encoding": {
"optional": true
}
}
},
"node_modules/node-fetch/node_modules/tr46": {
"version": "0.0.3",
"resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
"integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o="
},
"node_modules/node-fetch/node_modules/webidl-conversions": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
"integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE="
},
"node_modules/node-fetch/node_modules/whatwg-url": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
"integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=",
"dependencies": {
"tr46": "~0.0.3",
"webidl-conversions": "^3.0.0"
}
},
"node_modules/node-forge": {
"version": "0.10.0",
"resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.10.0.tgz",
"integrity": "sha512-PPmu8eEeG9saEUvI97fm4OYxXVB6bFvyNTyiUOBichBpFG8A1Ljw3bY62+5oOjDEMHRnd0Y7HQ+x7uzxOzC6JA==",
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.2.1.tgz",
"integrity": "sha512-Fcvtbb+zBcZXbTTVwqGA5W+MKBj56UjVRevvchv5XrcyXbmNdesfZL37nlcWOfpgHhgmxApw3tQbTr4CqNmX4w==",
"engines": {
"node": ">= 6.0.0"
"node": ">= 6.13.0"
}
},
"node_modules/node-gyp-build": {
@ -18690,9 +18705,9 @@
}
},
"node_modules/shelljs": {
"version": "0.8.4",
"resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.4.tgz",
"integrity": "sha512-7gk3UZ9kOfPLIAbslLzyWeGiEqx9e3rxwZM0KE6EL8GlGwjym9Mrlx5/p33bWTu9YG6vcS4MBxYZDHYr5lr8BQ==",
"version": "0.8.5",
"resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.5.tgz",
"integrity": "sha512-TiwcRcrkhHvbrZbnRcFYMLl30Dfov3HKqzp5tO5b4pt6G/SezKcYhmDg15zXVBswHmctSAQKznqNW2LO5tTDow==",
"dev": true,
"dependencies": {
"glob": "^7.0.0",
@ -19178,6 +19193,21 @@
"node": ">=0.10.0"
}
},
"node_modules/stt": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/stt/-/stt-1.1.0.tgz",
"integrity": "sha512-HAhK+1/dKAL9qfjVL+p69Xgb/UsjCh+xUVoMqtOPvw6ZmQXVl2HJN8Q91CQQMo78tgIcK83u4mdunTkS8aPehA==",
"dependencies": {
"argparse": "1.0.x",
"memory-stream": "1.0.x",
"node-pre-gyp": "0.15.x",
"node-wav": "0.0.2",
"sox-stream": "2.0.x"
},
"bin": {
"stt": "client.js"
}
},
"node_modules/stubs": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/stubs/-/stubs-3.0.0.tgz",
@ -26744,18 +26774,6 @@
"resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz",
"integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg=="
},
"deepspeech": {
"version": "0.9.3",
"resolved": "https://registry.npmjs.org/deepspeech/-/deepspeech-0.9.3.tgz",
"integrity": "sha512-80yqUWEWgzclY9pjukpq0TdkQEbJ6NzqZ899vsLZfa4YcK35uOWIf+ILK55zQ+Ii/TEJ6Eo62Vc2saedQ/AK6w==",
"requires": {
"argparse": "1.0.x",
"memory-stream": "1.0.x",
"node-pre-gyp": "0.15.x",
"node-wav": "0.0.2",
"sox-stream": "2.0.x"
}
},
"defaults": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz",
@ -26948,9 +26966,9 @@
}
},
"engine.io": {
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.1.0.tgz",
"integrity": "sha512-ErhZOVu2xweCjEfYcTdkCnEYUiZgkAcBBAhW4jbIvNG8SLU3orAqoJCiytZjYF7eTpVmmCrLDjLIEaPlUAs1uw==",
"version": "6.1.2",
"resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.1.2.tgz",
"integrity": "sha512-v/7eGHxPvO2AWsksyx2PUsQvBafuvqs0jJJQ0FdmJG1b9qIvgSbqDRGwNhfk2XHaTTbTXiC4quRE8Q9nRjsrQQ==",
"requires": {
"@types/cookie": "^0.4.1",
"@types/cors": "^2.8.12",
@ -28414,9 +28432,9 @@
}
},
"follow-redirects": {
"version": "1.14.1",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.1.tgz",
"integrity": "sha512-HWqDgT7ZEkqRzBvc2s64vSZ/hfOceEol3ac/7tKwzuvEyWx3/4UegXh5oBOIotkGsObyk3xznnSRVADBgWSQVg=="
"version": "1.14.7",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.7.tgz",
"integrity": "sha512-+hbxoLbFMbRKDwohX8GkTataGqO6Jb7jGwpAlwgy2bIz25XtRm7KEzJM76R1WiNT5SwZkX4Y75SwBolkpmE7iQ=="
},
"form-data": {
"version": "2.3.3",
@ -28752,11 +28770,11 @@
}
},
"google-p12-pem": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/google-p12-pem/-/google-p12-pem-3.0.3.tgz",
"integrity": "sha512-wS0ek4ZtFx/ACKYF3JhyGe5kzH7pgiQ7J5otlumqR9psmWMYc+U9cErKlCYVYHoUaidXHdZ2xbo34kB+S+24hA==",
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/google-p12-pem/-/google-p12-pem-3.1.3.tgz",
"integrity": "sha512-MC0jISvzymxePDVembypNefkAQp+DRP7dBE+zNUPaIjEspIlYg0++OrsNr248V9tPbz6iqtZ7rX1hxWA5B8qBQ==",
"requires": {
"node-forge": "^0.10.0"
"node-forge": "^1.0.0"
}
},
"googleapis": {
@ -33465,9 +33483,9 @@
"dev": true
},
"nanoid": {
"version": "3.1.30",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.30.tgz",
"integrity": "sha512-zJpuPDwOv8D2zq2WRoMe1HsfZthVewpel9CAvTfc/2mBD1uUT/agc5f7GHGWXlYkFvi1mVxe4IjvP2HNrop7nQ==",
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.2.0.tgz",
"integrity": "sha512-fmsZYa9lpn69Ad5eDn7FMcnnSR+8R34W9qJEijxYhTbfOWzr22n1QxCMzXLK+ODyW2973V3Fux959iQoUxzUIA==",
"dev": true
},
"natural-compare": {
@ -33515,14 +33533,38 @@
}
},
"node-fetch": {
"version": "2.6.1",
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz",
"integrity": "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw=="
"version": "2.6.7",
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz",
"integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==",
"requires": {
"whatwg-url": "^5.0.0"
},
"dependencies": {
"tr46": {
"version": "0.0.3",
"resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
"integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o="
},
"webidl-conversions": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
"integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE="
},
"whatwg-url": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
"integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=",
"requires": {
"tr46": "~0.0.3",
"webidl-conversions": "^3.0.0"
}
}
}
},
"node-forge": {
"version": "0.10.0",
"resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.10.0.tgz",
"integrity": "sha512-PPmu8eEeG9saEUvI97fm4OYxXVB6bFvyNTyiUOBichBpFG8A1Ljw3bY62+5oOjDEMHRnd0Y7HQ+x7uzxOzC6JA=="
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.2.1.tgz",
"integrity": "sha512-Fcvtbb+zBcZXbTTVwqGA5W+MKBj56UjVRevvchv5XrcyXbmNdesfZL37nlcWOfpgHhgmxApw3tQbTr4CqNmX4w=="
},
"node-gyp-build": {
"version": "4.2.3",
@ -34856,9 +34898,9 @@
}
},
"shelljs": {
"version": "0.8.4",
"resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.4.tgz",
"integrity": "sha512-7gk3UZ9kOfPLIAbslLzyWeGiEqx9e3rxwZM0KE6EL8GlGwjym9Mrlx5/p33bWTu9YG6vcS4MBxYZDHYr5lr8BQ==",
"version": "0.8.5",
"resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.5.tgz",
"integrity": "sha512-TiwcRcrkhHvbrZbnRcFYMLl30Dfov3HKqzp5tO5b4pt6G/SezKcYhmDg15zXVBswHmctSAQKznqNW2LO5tTDow==",
"dev": true,
"requires": {
"glob": "^7.0.0",
@ -35241,6 +35283,18 @@
"resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz",
"integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo="
},
"stt": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/stt/-/stt-1.1.0.tgz",
"integrity": "sha512-HAhK+1/dKAL9qfjVL+p69Xgb/UsjCh+xUVoMqtOPvw6ZmQXVl2HJN8Q91CQQMo78tgIcK83u4mdunTkS8aPehA==",
"requires": {
"argparse": "1.0.x",
"memory-stream": "1.0.x",
"node-pre-gyp": "0.15.x",
"node-wav": "0.0.2",
"sox-stream": "2.0.x"
}
},
"stubs": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/stubs/-/stubs-3.0.0.tgz",

View File

@ -68,7 +68,6 @@
"archiver": "^5.3.0",
"async": "^3.2.0",
"cross-env": "^7.0.3",
"deepspeech": "^0.9.3",
"dotenv": "^10.0.0",
"execa": "^5.0.0",
"fastify": "^3.25.2",
@ -80,6 +79,7 @@
"node-wav": "0.0.2",
"socket.io": "^4.4.0",
"socket.io-client": "^4.4.0",
"stt": "^1.1.0",
"superagent": "^6.1.0"
},
"devDependencies": {

View File

@ -17,7 +17,7 @@ export default () => new Promise(async (resolve, reject) => {
const npmMinRequiredVersion = '5'
const pythonMinRequiredVersion = '3'
const flitePath = 'bin/flite/flite'
const deepSpeechPath = 'bin/deepspeech/lm.binary'
const coquiLanguageModelPath = 'bin/coqui/huge-vocabulary.scorer'
const amazonPath = 'server/src/config/voice/amazon.json'
const googleCloudPath = 'server/src/config/voice/google-cloud.json'
const watsonSttPath = 'server/src/config/voice/watson-stt.json'
@ -173,11 +173,11 @@ export default () => new Promise(async (resolve, reject) => {
}
log.info('Offline STT')
if (!fs.existsSync(deepSpeechPath)) {
if (!fs.existsSync(coquiLanguageModelPath)) {
report.can_offline_stt.v = false
log.warning(`Cannot find ${deepSpeechPath}. You can setup the offline STT by running: "npm run setup:offline-stt"`)
log.warning(`Cannot find ${coquiLanguageModelPath}. You can setup the offline STT by running: "npm run setup:offline-stt"`)
} else {
log.success(`Found DeepSpeech language model at ${deepSpeechPath}`)
log.success(`Found Coqui language model at ${coquiLanguageModelPath}`)
}
// Report

View File

@ -36,6 +36,8 @@ export default () => new Promise(async (resolve, reject) => {
log.info('Installing hotword dependencies...')
await command('cd hotword && npm install', { shell: true })
log.success('Offline hotword detection installed')
await command('cd hotword/node_modules/@bugsounet/snowboy && CXXFLAGS="--std=c++17" ../../../node_modules/@mapbox/node-pre-gyp/bin/node-pre-gyp clean configure build', { shell: true })
log.success('Snowboy bindings compiled')
resolve()
} catch (e) {

View File

@ -10,23 +10,24 @@ import os from '@/helpers/os'
export default () => new Promise(async (resolve, reject) => {
log.info('Setting up offline speech-to-text...')
const destDeepSpeechFolder = 'bin/deepspeech'
const destCoquiFolder = 'bin/coqui'
const tmpDir = 'scripts/tmp'
const deepSpeechVersion = '0.9.3'
// check this repo for updates: https://github.com/coqui-ai/STT-models/tree/main/english/coqui
const coquiModelVersion = '1.0.0'
let downloader = 'wget'
if (os.get().type === 'macos') {
downloader = 'curl -L -O'
}
if (!fs.existsSync(`${destDeepSpeechFolder}/deepspeech.scorer`)) {
if (!fs.existsSync(`${destCoquiFolder}/model.tflite`)) {
try {
log.info('Downloading pre-trained model...')
await command(`cd ${tmpDir} && ${downloader} https://github.com/mozilla/DeepSpeech/releases/download/v${deepSpeechVersion}/deepspeech-${deepSpeechVersion}-models.pbmm`, { shell: true })
await command(`cd ${tmpDir} && ${downloader} https://github.com/mozilla/DeepSpeech/releases/download/v${deepSpeechVersion}/deepspeech-${deepSpeechVersion}-models.scorer`, { shell: true })
await command(`cd ${tmpDir} && ${downloader} https://github.com/coqui-ai/STT-models/releases/download/english/coqui/v${coquiModelVersion}-huge-vocab/model.tflite`, { shell: true })
await command(`cd ${tmpDir} && ${downloader} https://github.com/coqui-ai/STT-models/releases/download/english/coqui/v${coquiModelVersion}-huge-vocab/huge-vocabulary.scorer`, { shell: true })
log.success('Pre-trained model download done')
log.info('Moving...')
await command(`mv -f ${tmpDir}/deepspeech-${deepSpeechVersion}-models.pbmm ${destDeepSpeechFolder}/deepspeech.pbmm`, { shell: true })
await command(`mv -f ${tmpDir}/deepspeech-${deepSpeechVersion}-models.scorer ${destDeepSpeechFolder}/deepspeech.scorer`, { shell: true })
await command(`mv -f ${tmpDir}/model.tflite ${destCoquiFolder}/model.tflite`, { shell: true })
await command(`mv -f ${tmpDir}/huge-vocabulary.scorer ${destCoquiFolder}/huge-vocabulary.scorer`, { shell: true })
log.success('Move done')
log.success('Offline speech-to-text installed')

View File

@ -1,32 +1 @@
const fs = require('fs')
const path = require('path')
const os = require('os')
/**
* Trigger preinstall hook to remove DeepSpeech on Windows
*/
console.info('\x1b[36m➡ %s\x1b[0m', 'Running Leon\'s installation...')
if (os.type().indexOf('Windows') !== -1) {
const packageJsonPath = path.join(__dirname, '../../package.json')
const packageJson = require(packageJsonPath) // eslint-disable-line global-require
console.warn('\x1b[33m❗ %s\x1b[0m', 'The Leon\'s voice offline mode is not available on Windows')
console.info('\x1b[36m➡ %s\x1b[0m', 'Backing up package.json...')
fs.copyFileSync('package.json', 'package.json.backup')
console.log('\x1b[32m✔ %s\x1b[0m', 'package.json has been backed up')
try {
if (packageJson?.dependencies.deepspeech) {
console.info('\x1b[36m➡ %s\x1b[0m', 'Removing DeepSpeech dependency...')
delete packageJson.dependencies.deepspeech
fs.writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2))
console.log('\x1b[32m✔ %s\x1b[0m', 'DeepSpeech dependency has been removed.')
}
} catch (e) {
console.error('\x1b[31m✖ %s\x1b[0m', 'Failed to remove DeepSpeech dependency')
}
}

View File

@ -1,8 +1,5 @@
import fs from 'fs'
import loader from '@/helpers/loader'
import log from '@/helpers/log'
import os from '@/helpers/os'
import train from '../train'
import generateHttpApiKey from '../generate/generate-http-api-key'
@ -18,8 +15,6 @@ import setupPythonPackages from './setup-python-packages'
*/
(async () => {
try {
const info = os.get()
// Required env vars to setup
process.env.LEON_LANG = 'en-US'
process.env.PIPENV_PIPFILE = 'bridges/python/Pipfile'
@ -36,12 +31,6 @@ import setupPythonPackages from './setup-python-packages'
await generateHttpApiKey()
loader.start()
await train()
if (info.type === 'windows') {
log.info('Windows detected, reinjecting DeepSpeech into package.json...')
fs.unlinkSync('package.json')
fs.renameSync('package.json.backup', 'package.json')
log.success('DeepSpeech has been reinjected into package.json')
}
log.default('')
log.success('Hooray! Leon is installed and ready to go!')

View File

@ -1,30 +1,12 @@
import wav from 'node-wav'
import fs from 'fs'
import { Model } from 'stt'
import log from '@/helpers/log'
log.title('DeepSpeech Parser')
log.title('Coqui STT Parser')
const parser = { }
let DeepSpeech = { }
/* istanbul ignore next */
try {
DeepSpeech = require('deepspeech-gpu') // eslint-disable-line global-require, import/no-unresolved
log.success('GPU version found')
} catch (eGpu) {
log.info('GPU version not found, trying to get the CPU version...')
try {
DeepSpeech = require('deepspeech') // eslint-disable-line global-require, import/no-unresolved
log.success('CPU version found')
} catch (eCpu) {
log.error(`No DeepSpeech library found:\nGPU: ${eGpu}\nCPU: ${eCpu}`)
}
}
let model = { }
let desiredSampleRate = 16000
@ -32,19 +14,14 @@ let desiredSampleRate = 16000
* Model and language model paths
*/
parser.conf = {
model: 'bin/deepspeech/deepspeech.pbmm',
scorer: 'bin/deepspeech/deepspeech.scorer'
model: 'bin/coqui/model.tflite',
scorer: 'bin/coqui/huge-vocabulary.scorer'
}
/**
* Load models
*/
parser.init = (args) => {
/* istanbul ignore if */
if (process.env.LEON_LANG !== 'en-US') {
log.warning('The DeepSpeech parser only accepts the "en-US" language for the moment')
}
log.info(`Loading model from file ${args.model}...`)
if (!fs.existsSync(args.model)) {
@ -61,10 +38,18 @@ parser.init = (args) => {
/* istanbul ignore if */
if (process.env.LEON_NODE_ENV !== 'testing') {
model = new DeepSpeech.Model(args.model)
try {
model = new Model(args.model)
} catch (error) {
throw Error(`model.stt: ${error}`)
}
desiredSampleRate = model.sampleRate()
model.enableExternalScorer(args.scorer)
try {
model.enableExternalScorer(args.scorer)
} catch (error) {
throw Error(`model.enableExternalScorer: ${error}`)
}
}
log.success('Model loaded')

View File

@ -8,9 +8,9 @@ class Stt {
this.socket = socket
this.provider = provider
this.providers = [
'deepspeech',
'google-cloud-stt',
'watson-stt'
'watson-stt',
'coqui-stt'
]
this.parser = { }

View File

@ -1,11 +1,11 @@
import fs from 'fs'
import parser from '@/stt/deepspeech/parser'
import parser from '@/stt/coqui-stt/parser'
describe('DeepSpeech STT parser', () => {
describe('Coqui STT parser', () => {
// Only run these tests if the models exist
if (fs.existsSync(`${global.paths.root}/bin/deepspeech/deepspeech.pbmm`)
&& fs.existsSync(`${global.paths.root}/bin/deepspeech/deepspeech.scorer`)) {
if (fs.existsSync(`${global.paths.root}/bin/coqui/model.tflite`)
&& fs.existsSync(`${global.paths.root}/bin/coqui/huge-vocabulary.scorer`)) {
describe('init()', () => {
test('returns error cannot find model', () => {
expect(parser.init({
@ -15,15 +15,15 @@ describe('DeepSpeech STT parser', () => {
test('returns error cannot find scorer', () => {
expect(parser.init({
model: `${global.paths.root}/bin/deepspeech/deepspeech.pbmm`,
model: `${global.paths.root}/bin/coqui/model.tflite`,
scorer: 'fake-scorer-path'
})).toBeFalsy()
})
test('returns true because all of the paths are good', () => {
expect(parser.init({
model: `${global.paths.root}/bin/deepspeech/deepspeech.pbmm`,
scorer: `${global.paths.root}/bin/deepspeech/deepspeech.scorer`
model: `${global.paths.root}/bin/coqui/model.tflite`,
scorer: `${global.paths.root}/bin/coqui/huge-vocabulary.scorer`
})).toBeTruthy()
})
})

View File

@ -3,7 +3,7 @@ import Stt from '@/stt/stt'
describe('STT', () => {
describe('constructor()', () => {
test('creates a new instance of Stt', () => {
const stt = new Stt({ }, 'deepspeech')
const stt = new Stt({ }, 'coqui-stt')
expect(stt).toBeInstanceOf(Stt)
})
@ -17,7 +17,7 @@ describe('STT', () => {
})
test('initializes the STT parser', () => {
const stt = new Stt({ }, 'deepspeech')
const stt = new Stt({ }, 'coqui-stt')
expect(stt.init()).toBeTruthy()
})