@lumiastream/wakeword 1.0.1 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Readme.md +155 -2
- package/lib/index.js +75 -0
- package/lib/list-devices.js +128 -0
- package/lib/test-devices.js +85 -0
- package/lib/voice.js +17 -5
- package/package.json +6 -3
package/Readme.md
CHANGED
|
@@ -1,3 +1,156 @@
|
|
|
1
|
-
|
|
1
|
+
# LumiaWakeWord
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
A wake word detection library using Vosk and SoX for real-time voice recognition.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
- Real-time wake word detection
|
|
7
|
+
- Multi-platform support (Windows, macOS, Linux)
|
|
8
|
+
- Audio device selection (especially useful for Windows)
|
|
9
|
+
- Confidence threshold filtering
|
|
10
|
+
- Dynamic grammar updates
|
|
11
|
+
|
|
12
|
+
## Installation
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
npm install @lumiastream/wakeword
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Quick Start
|
|
19
|
+
|
|
20
|
+
```javascript
|
|
21
|
+
import { startWakeWord, listAudioDevices } from "@lumiastream/wakeword";
|
|
22
|
+
|
|
23
|
+
// List available audio devices
|
|
24
|
+
const devices = await listAudioDevices();
|
|
25
|
+
console.log("Available devices:", devices);
|
|
26
|
+
|
|
27
|
+
// Start wake word detection
|
|
28
|
+
const wakeWord = startWakeWord({
|
|
29
|
+
grammar: ["hello", "lumia", "computer"],
|
|
30
|
+
confidence: 0.7,
|
|
31
|
+
device: "0" // Optional: specify audio device
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
// Handle detections
|
|
35
|
+
wakeWord.stdout.on("data", (data) => {
|
|
36
|
+
const lines = data.toString().split("\n");
|
|
37
|
+
for (const line of lines) {
|
|
38
|
+
if (line.startsWith("voice|")) {
|
|
39
|
+
const word = line.split("|")[1];
|
|
40
|
+
console.log(`Wake word detected: ${word}`);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## Audio Device Selection
|
|
47
|
+
|
|
48
|
+
### Windows Users
|
|
49
|
+
Windows users often need to select the correct audio input device. Use these commands to find and test devices:
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
# List all available audio devices
|
|
53
|
+
npm run list-devices
|
|
54
|
+
|
|
55
|
+
# Interactive device testing
|
|
56
|
+
npm run test-devices
|
|
57
|
+
|
|
58
|
+
# Use a specific device
|
|
59
|
+
AUDIO_DEVICE=1 npm start
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### Setting the Audio Device
|
|
63
|
+
|
|
64
|
+
**Method 1: Environment Variable**
|
|
65
|
+
```bash
|
|
66
|
+
set AUDIO_DEVICE=1
|
|
67
|
+
npm start
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
**Method 2: Programmatically**
|
|
71
|
+
```javascript
|
|
72
|
+
startWakeWord({
|
|
73
|
+
device: "1",
|
|
74
|
+
grammar: ["hello", "lumia"]
|
|
75
|
+
});
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
See [AUDIO_DEVICES.md](AUDIO_DEVICES.md) for detailed device configuration guide.
|
|
79
|
+
|
|
80
|
+
## API Reference
|
|
81
|
+
|
|
82
|
+
### `listAudioDevices()`
|
|
83
|
+
Returns a Promise that resolves to an array of available audio devices.
|
|
84
|
+
|
|
85
|
+
```javascript
|
|
86
|
+
const devices = await listAudioDevices();
|
|
87
|
+
// Returns: [{ id: "0", name: "Microphone (Realtek)" }, ...]
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
### `startWakeWord(options)`
|
|
91
|
+
Starts the wake word detection process.
|
|
92
|
+
|
|
93
|
+
**Options:**
|
|
94
|
+
- `device` (string): Audio device ID to use
|
|
95
|
+
- `soxPath` (string): Path to SoX binary (optional)
|
|
96
|
+
- `sampleRate` (number): Sample rate, default 16000
|
|
97
|
+
- `grammar` (string[]): Array of wake words to detect
|
|
98
|
+
- `confidence` (number): Confidence threshold (0-1), default 0.7
|
|
99
|
+
|
|
100
|
+
**Returns:** ChildProcess instance
|
|
101
|
+
|
|
102
|
+
## Scripts
|
|
103
|
+
|
|
104
|
+
```bash
|
|
105
|
+
npm run list-devices # List available audio devices
|
|
106
|
+
npm run test-devices # Interactive device testing
|
|
107
|
+
npm start # Start wake word detection
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
## Example
|
|
111
|
+
|
|
112
|
+
Run the included example:
|
|
113
|
+
```bash
|
|
114
|
+
node example.js
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
## Dependencies
|
|
118
|
+
|
|
119
|
+
- [Vosk](https://alphacephei.com/vosk/) - Speech recognition toolkit
|
|
120
|
+
- [SoX](http://sox.sourceforge.net/) - Sound processing tool
|
|
121
|
+
- Vosk model included: vosk-model-small-en-us-0.15
|
|
122
|
+
|
|
123
|
+
## Platform Notes
|
|
124
|
+
|
|
125
|
+
### Windows
|
|
126
|
+
- Default uses device "0" if not specified
|
|
127
|
+
- Use `npm run test-devices` to find the correct device
|
|
128
|
+
- USB microphones may appear as separate devices
|
|
129
|
+
|
|
130
|
+
### macOS/Linux
|
|
131
|
+
- Uses system default audio input automatically
|
|
132
|
+
- Device selection usually not needed
|
|
133
|
+
|
|
134
|
+
## Troubleshooting
|
|
135
|
+
|
|
136
|
+
1. **No audio detected on Windows:**
|
|
137
|
+
- Run `npm run test-devices` to find the correct device
|
|
138
|
+
- Set `AUDIO_DEVICE` environment variable
|
|
139
|
+
|
|
140
|
+
2. **Poor recognition quality:**
|
|
141
|
+
- Adjust confidence threshold (lower = more sensitive)
|
|
142
|
+
- Try different audio devices
|
|
143
|
+
- Ensure microphone is not muted
|
|
144
|
+
|
|
145
|
+
3. **Device not found:**
|
|
146
|
+
- Ensure microphone is connected before starting
|
|
147
|
+
- Check system audio settings
|
|
148
|
+
|
|
149
|
+
## SoX Binaries
|
|
150
|
+
|
|
151
|
+
Pre-compiled SoX binaries are included for all platforms.
|
|
152
|
+
Source: https://github.com/zackees/static-sox/tree/main/bin
|
|
153
|
+
|
|
154
|
+
## License
|
|
155
|
+
|
|
156
|
+
See LICENSE file for details.
|
package/lib/index.js
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { listAudioDevices } from "./list-devices.js";
|
|
2
|
+
import { spawn } from "child_process";
|
|
3
|
+
import { dirname, join } from "node:path";
|
|
4
|
+
import { fileURLToPath } from "node:url";
|
|
5
|
+
|
|
6
|
+
const here = dirname(fileURLToPath(import.meta.url));
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* List available audio input devices
|
|
10
|
+
* @returns {Promise<Array<{id: string, name: string}>>} Array of available devices
|
|
11
|
+
*/
|
|
12
|
+
export { listAudioDevices };
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Start the wake word detection with optional device selection
|
|
16
|
+
* @param {Object} options - Configuration options
|
|
17
|
+
* @param {string} [options.device] - Audio device ID to use
|
|
18
|
+
* @param {string} [options.soxPath] - Path to SoX binary
|
|
19
|
+
* @param {number} [options.sampleRate] - Sample rate (default: 16000)
|
|
20
|
+
* @param {Array<string>} [options.grammar] - Wake words to detect
|
|
21
|
+
* @param {number} [options.confidence] - Confidence threshold (0-1)
|
|
22
|
+
* @returns {ChildProcess} The spawned voice detection process
|
|
23
|
+
*/
|
|
24
|
+
export function startWakeWord(options = {}) {
|
|
25
|
+
const {
|
|
26
|
+
device = null,
|
|
27
|
+
soxPath = null,
|
|
28
|
+
sampleRate = 16000,
|
|
29
|
+
grammar = [],
|
|
30
|
+
confidence = 0.7,
|
|
31
|
+
} = options;
|
|
32
|
+
|
|
33
|
+
const voiceScript = join(here, "voice.js");
|
|
34
|
+
const args = [voiceScript];
|
|
35
|
+
|
|
36
|
+
if (soxPath) {
|
|
37
|
+
args.push(soxPath);
|
|
38
|
+
} else {
|
|
39
|
+
args.push(""); // placeholder for default sox path
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
if (device) {
|
|
43
|
+
args.push(device);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const env = { ...process.env };
|
|
47
|
+
if (sampleRate) {
|
|
48
|
+
env.SAMPLE_RATE = sampleRate.toString();
|
|
49
|
+
}
|
|
50
|
+
if (device && !args[2]) {
|
|
51
|
+
env.AUDIO_DEVICE = device;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const proc = spawn("node", args, {
|
|
55
|
+
env,
|
|
56
|
+
stdio: ["pipe", "pipe", "inherit"],
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
// Send initial grammar if provided
|
|
60
|
+
if (grammar.length > 0) {
|
|
61
|
+
proc.stdin.write(`update,${grammar.join(",")}\n`);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// Send confidence threshold if provided
|
|
65
|
+
if (confidence !== 0.7) {
|
|
66
|
+
proc.stdin.write(`confidence,${confidence}\n`);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
return proc;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export default {
|
|
73
|
+
listAudioDevices,
|
|
74
|
+
startWakeWord,
|
|
75
|
+
};
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import { spawn } from "child_process";
|
|
2
|
+
import { dirname, join } from "node:path";
|
|
3
|
+
import { fileURLToPath } from "node:url";
|
|
4
|
+
import { existsSync } from "node:fs";
|
|
5
|
+
|
|
6
|
+
const here = dirname(fileURLToPath(import.meta.url));
|
|
7
|
+
|
|
8
|
+
function unpacked(p) {
|
|
9
|
+
return p.includes("app.asar")
|
|
10
|
+
? p.replace("app.asar", "app.asar.unpacked")
|
|
11
|
+
: p;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const exeName = { win32: "sox.exe", darwin: "soxmac", linux: "soxlinux" }[
|
|
15
|
+
process.platform
|
|
16
|
+
];
|
|
17
|
+
|
|
18
|
+
let soxPath = process.argv[2] || join(here, "..", "binaries", exeName);
|
|
19
|
+
soxPath = unpacked(soxPath);
|
|
20
|
+
|
|
21
|
+
if (!existsSync(soxPath)) {
|
|
22
|
+
console.error(`SoX not found: ${soxPath}`);
|
|
23
|
+
process.exit(1);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export function listAudioDevices() {
|
|
27
|
+
return new Promise((resolve, reject) => {
|
|
28
|
+
if (process.platform !== "win32") {
|
|
29
|
+
// On macOS and Linux, SoX uses default device
|
|
30
|
+
resolve([{ id: "default", name: "Default Audio Input" }]);
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// Windows: Parse available devices from SoX help output
|
|
35
|
+
const proc = spawn(soxPath, ["-t", "waveaudio", "-h"], {
|
|
36
|
+
encoding: "utf8",
|
|
37
|
+
windowsHide: true,
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
let output = "";
|
|
41
|
+
let errorOutput = "";
|
|
42
|
+
|
|
43
|
+
proc.stdout?.on("data", (data) => {
|
|
44
|
+
output += data.toString();
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
proc.stderr?.on("data", (data) => {
|
|
48
|
+
errorOutput += data.toString();
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
proc.on("close", (code) => {
|
|
52
|
+
const devices = [];
|
|
53
|
+
|
|
54
|
+
// Parse output for device list
|
|
55
|
+
const lines = (output + errorOutput).split("\n");
|
|
56
|
+
let inDeviceList = false;
|
|
57
|
+
|
|
58
|
+
for (const line of lines) {
|
|
59
|
+
// Look for input device section
|
|
60
|
+
if (line.includes("Input:") || line.includes("input")) {
|
|
61
|
+
inDeviceList = true;
|
|
62
|
+
continue;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// Stop at output section
|
|
66
|
+
if (line.includes("Output:") || line.includes("output")) {
|
|
67
|
+
inDeviceList = false;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// Parse device entries (typically in format "0: Device Name")
|
|
71
|
+
if (inDeviceList) {
|
|
72
|
+
const match = line.match(/^\s*(\d+):\s*(.+)$/);
|
|
73
|
+
if (match) {
|
|
74
|
+
devices.push({
|
|
75
|
+
id: match[1],
|
|
76
|
+
name: match[2].trim(),
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
if (devices.length === 0) {
|
|
83
|
+
// Fallback: try to extract any numbered devices
|
|
84
|
+
const allMatches = (output + errorOutput).matchAll(/(\d+):\s*([^\n]+)/g);
|
|
85
|
+
for (const match of allMatches) {
|
|
86
|
+
const name = match[2].trim();
|
|
87
|
+
// Filter out obvious non-device entries
|
|
88
|
+
if (!name.includes("SoX") && !name.includes("Usage") && name.length > 0) {
|
|
89
|
+
devices.push({
|
|
90
|
+
id: match[1],
|
|
91
|
+
name: name,
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// If still no devices found, provide default options
|
|
98
|
+
if (devices.length === 0) {
|
|
99
|
+
devices.push(
|
|
100
|
+
{ id: "0", name: "Device 0 (Default)" },
|
|
101
|
+
{ id: "1", name: "Device 1" },
|
|
102
|
+
{ id: "2", name: "Device 2" }
|
|
103
|
+
);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
resolve(devices);
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
proc.on("error", (err) => {
|
|
110
|
+
reject(err);
|
|
111
|
+
});
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// If run directly, list devices
|
|
116
|
+
if (import.meta.url === `file://${process.argv[1]}`) {
|
|
117
|
+
listAudioDevices()
|
|
118
|
+
.then((devices) => {
|
|
119
|
+
console.log("Available audio input devices:");
|
|
120
|
+
devices.forEach((device) => {
|
|
121
|
+
console.log(` ${device.id}: ${device.name}`);
|
|
122
|
+
});
|
|
123
|
+
})
|
|
124
|
+
.catch((err) => {
|
|
125
|
+
console.error("Error listing devices:", err);
|
|
126
|
+
process.exit(1);
|
|
127
|
+
});
|
|
128
|
+
}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { listAudioDevices } from "./list-devices.js";
|
|
4
|
+
import { spawn } from "child_process";
|
|
5
|
+
import readline from "node:readline";
|
|
6
|
+
import { dirname, join } from "node:path";
|
|
7
|
+
import { fileURLToPath } from "node:url";
|
|
8
|
+
|
|
9
|
+
const here = dirname(fileURLToPath(import.meta.url));
|
|
10
|
+
|
|
11
|
+
async function testDevice(deviceId) {
|
|
12
|
+
console.log(`\nTesting device ${deviceId}...`);
|
|
13
|
+
console.log("Speak into your microphone. Press Ctrl+C to stop.\n");
|
|
14
|
+
|
|
15
|
+
const voiceScript = join(here, "voice.js");
|
|
16
|
+
const proc = spawn("node", [voiceScript, undefined, deviceId], {
|
|
17
|
+
stdio: ["pipe", "inherit", "inherit"],
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
// Send test grammar
|
|
21
|
+
proc.stdin.write("update,hello,test,lumia\n");
|
|
22
|
+
|
|
23
|
+
return new Promise((resolve) => {
|
|
24
|
+
proc.on("close", () => {
|
|
25
|
+
resolve();
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
// Allow user to stop with Ctrl+C
|
|
29
|
+
process.on("SIGINT", () => {
|
|
30
|
+
proc.kill();
|
|
31
|
+
resolve();
|
|
32
|
+
});
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
async function main() {
|
|
37
|
+
console.log("LumiaWakeWord Audio Device Tester");
|
|
38
|
+
console.log("==================================\n");
|
|
39
|
+
|
|
40
|
+
try {
|
|
41
|
+
const devices = await listAudioDevices();
|
|
42
|
+
|
|
43
|
+
if (process.platform !== "win32") {
|
|
44
|
+
console.log("Note: On macOS/Linux, the default audio input is used automatically.");
|
|
45
|
+
console.log("Device selection is primarily for Windows users.\n");
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
console.log("Available audio input devices:");
|
|
49
|
+
devices.forEach((device) => {
|
|
50
|
+
console.log(` ${device.id}: ${device.name}`);
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
if (process.platform === "win32") {
|
|
54
|
+
const rl = readline.createInterface({
|
|
55
|
+
input: process.stdin,
|
|
56
|
+
output: process.stdout,
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
const deviceId = await new Promise((resolve) => {
|
|
60
|
+
rl.question(
|
|
61
|
+
"\nEnter device ID to test (or press Enter for default): ",
|
|
62
|
+
(answer) => {
|
|
63
|
+
rl.close();
|
|
64
|
+
resolve(answer.trim() || "0");
|
|
65
|
+
}
|
|
66
|
+
);
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
await testDevice(deviceId);
|
|
70
|
+
|
|
71
|
+
console.log("\n\nTo use this device permanently, you can:");
|
|
72
|
+
console.log(`1. Set environment variable: AUDIO_DEVICE=${deviceId}`);
|
|
73
|
+
console.log(`2. Pass as 3rd argument when running voice.js`);
|
|
74
|
+
console.log(`3. Update your application to pass the device ID\n`);
|
|
75
|
+
} else {
|
|
76
|
+
console.log("\nTesting default audio input...");
|
|
77
|
+
await testDevice(null);
|
|
78
|
+
}
|
|
79
|
+
} catch (err) {
|
|
80
|
+
console.error("Error:", err);
|
|
81
|
+
process.exit(1);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
main();
|
package/lib/voice.js
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
// voice.js (ESM)
|
|
2
1
|
import { Model, Recognizer, setLogLevel } from "vosk-koffi";
|
|
3
2
|
import record from "./record.js";
|
|
4
3
|
import { dirname, join } from "node:path";
|
|
@@ -18,16 +17,20 @@ function unpacked(p) {
|
|
|
18
17
|
}
|
|
19
18
|
|
|
20
19
|
/* ------------------------------------------------------------------ */
|
|
21
|
-
/* 1. Resolve SoX binary
|
|
20
|
+
/* 1. Resolve SoX binary and audio device */
|
|
22
21
|
/* ------------------------------------------------------------------ */
|
|
23
22
|
const exeName = { win32: "sox.exe", darwin: "soxmac", linux: "soxlinux" }[
|
|
24
23
|
process.platform
|
|
25
24
|
];
|
|
26
25
|
|
|
27
|
-
/* Priority: argv[2]
|
|
26
|
+
/* Priority for sox path: argv[2] → fallback to sibling binaries/<exe> */
|
|
27
|
+
/* Priority for device: argv[3] → env var → default */
|
|
28
28
|
let soxPath = process.argv[2] || join(here, "..", "binaries", exeName);
|
|
29
29
|
soxPath = unpacked(soxPath);
|
|
30
30
|
|
|
31
|
+
// Parse device from argv[3] or environment variable
|
|
32
|
+
let audioDevice = process.argv[3] || process.env.AUDIO_DEVICE || null;
|
|
33
|
+
|
|
31
34
|
if (!existsSync(soxPath)) throw new Error(`SoX not found: ${soxPath}`);
|
|
32
35
|
try {
|
|
33
36
|
chmodSync(soxPath, 0o755);
|
|
@@ -60,8 +63,17 @@ rec.setWords(true);
|
|
|
60
63
|
/* 4. Start the microphone */
|
|
61
64
|
/* ------------------------------------------------------------------ */
|
|
62
65
|
const recArgs = { sampleRate: SAMPLE_RATE, threshold: 0, binPath: soxPath };
|
|
63
|
-
|
|
66
|
+
|
|
67
|
+
// Set device based on platform and configuration
|
|
68
|
+
if (audioDevice !== null) {
|
|
69
|
+
// User specified a device explicitly
|
|
70
|
+
recArgs.device = audioDevice;
|
|
71
|
+
console.error(`Using audio device: ${audioDevice}`);
|
|
72
|
+
} else if (process.platform === "win32") {
|
|
73
|
+
// Windows: default to device 0 if not specified
|
|
64
74
|
recArgs.device = "0";
|
|
75
|
+
console.error("Using default Windows audio device: 0");
|
|
76
|
+
console.error("To specify a different device, use: AUDIO_DEVICE=<device_id> or pass as 3rd argument");
|
|
65
77
|
}
|
|
66
78
|
|
|
67
79
|
const mic = record.record(recArgs).stream();
|
|
@@ -123,7 +135,7 @@ const rl = readline.createInterface({ input: process.stdin, terminal: false });
|
|
|
123
135
|
|
|
124
136
|
rl.on("line", (line) => {
|
|
125
137
|
const trimmed = line.trim();
|
|
126
|
-
if (!trimmed.startsWith("update,")
|
|
138
|
+
if (!trimmed.startsWith("update,") && !trimmed.startsWith("confidence,"))
|
|
127
139
|
return;
|
|
128
140
|
|
|
129
141
|
if (trimmed.startsWith("confidence,")) {
|
package/package.json
CHANGED
|
@@ -1,15 +1,18 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lumiastream/wakeword",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"type": "module",
|
|
5
|
-
"main": "lib/
|
|
5
|
+
"main": "lib/index.js",
|
|
6
6
|
"files": [
|
|
7
7
|
"lib/",
|
|
8
8
|
"models/",
|
|
9
9
|
"binaries/"
|
|
10
10
|
],
|
|
11
11
|
"scripts": {
|
|
12
|
-
"postinstall": "chmod +x binaries/soxmac binaries/soxlinux binaries/sox.exe || true"
|
|
12
|
+
"postinstall": "chmod +x binaries/soxmac binaries/soxlinux binaries/sox.exe || true",
|
|
13
|
+
"list-devices": "node lib/list-devices.js",
|
|
14
|
+
"test-devices": "node lib/test-devices.js",
|
|
15
|
+
"start": "node lib/voice.js"
|
|
13
16
|
},
|
|
14
17
|
"dependencies": {
|
|
15
18
|
"vosk-koffi": "^1.1.1"
|