@lumiastream/wakeword 1.0.1-alpha.6 → 1.0.1-alpha.7

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/lib/record.js ADDED
@@ -0,0 +1,119 @@
1
+ "use strict";
2
+
3
+ const assert = require("assert");
4
+ const debug = require("debug")("record");
5
+ const { spawn } = require("child_process");
6
+ const recorders = require("./recorders");
7
+
8
+ class Recording {
9
+ constructor(options = {}) {
10
+ const defaults = {
11
+ sampleRate: 16000,
12
+ channels: 1,
13
+ compress: false,
14
+ threshold: 0.5,
15
+ thresholdStart: null,
16
+ thresholdEnd: null,
17
+ silence: "1.0",
18
+ recorder: "sox",
19
+ endOnSilence: false,
20
+ audioType: "wav",
21
+ binPath: null,
22
+ bufferSize: null,
23
+ arguments: [],
24
+ };
25
+
26
+ this.options = Object.assign(defaults, options);
27
+
28
+ const recorder = recorders.load(this.options.recorder);
29
+ const { cmd, args, spawnOptions = {} } = recorder(this.options);
30
+
31
+ this.cmd = cmd;
32
+ this.args = args;
33
+ this.cmdOptions = Object.assign(
34
+ { encoding: "binary", stdio: "pipe" },
35
+ spawnOptions
36
+ );
37
+
38
+ debug(`Started recording`);
39
+ debug(this.options);
40
+
41
+ const command = ` ${this.cmd} ${this.args.join(" ")}`;
42
+ debug(command);
43
+
44
+ return this.start();
45
+ }
46
+
47
+ start() {
48
+ const { cmd, args, cmdOptions } = this;
49
+
50
+ const cp = spawn(cmd, args, cmdOptions);
51
+ const rec = cp.stdout;
52
+ const err = cp.stderr;
53
+
54
+ this.process = cp; // expose child process
55
+ this._stream = rec; // expose output stream
56
+
57
+ cp.on("close", (code) => {
58
+ if (code === 0) return;
59
+ rec.emit(
60
+ "error",
61
+ `${this.cmd} has exited with error code ${code}.
62
+
63
+ Enable debugging with the environment variable DEBUG=record.`
64
+ );
65
+ });
66
+
67
+ err.on("data", (chunk) => {
68
+ debug(`STDERR: ${chunk}`);
69
+ });
70
+
71
+ rec.on("data", (chunk) => {
72
+ debug(`Recording ${chunk.length} bytes`);
73
+ });
74
+
75
+ rec.on("end", () => {
76
+ debug("Recording ended");
77
+ });
78
+
79
+ return this;
80
+ }
81
+
82
+ stop() {
83
+ assert(this.process, "Recording not yet started");
84
+
85
+ this.process.kill();
86
+ }
87
+
88
+ pause() {
89
+ assert(this.process, "Recording not yet started");
90
+
91
+ this.process.kill("SIGSTOP");
92
+ this._stream.pause();
93
+ debug("Paused recording");
94
+ }
95
+
96
+ resume() {
97
+ assert(this.process, "Recording not yet started");
98
+
99
+ this.process.kill("SIGCONT");
100
+ this._stream.resume();
101
+ debug("Resumed recording");
102
+ }
103
+
104
+ isPaused() {
105
+ assert(this.process, "Recording not yet started");
106
+
107
+ return this._stream.isPaused();
108
+ }
109
+
110
+ stream() {
111
+ assert(this._stream, "Recording not yet started");
112
+
113
+ return this._stream;
114
+ }
115
+ }
116
+
117
+ module.exports = {
118
+ record: (...args) => new Recording(...args),
119
+ };
@@ -0,0 +1,27 @@
1
+ // On some systems (RasPi), arecord is the prefered recording binary
2
+ module.exports = (options) => {
3
+ let cmd = "arecord";
4
+
5
+ if (options.binPath) {
6
+ cmd = options.binPath;
7
+ }
8
+
9
+ const args = [
10
+ "-q", // show no progress
11
+ "-r",
12
+ options.sampleRate, // sample rate
13
+ "-c",
14
+ options.channels, // channels
15
+ "-t",
16
+ options.audioType, // audio type
17
+ "-f",
18
+ "S16_LE", // Sample format
19
+ "-", // pipe
20
+ ];
21
+
22
+ if (options.device) {
23
+ args.unshift("-D", options.device);
24
+ }
25
+
26
+ return { cmd, args };
27
+ };
@@ -0,0 +1,18 @@
1
+ const path = require('path')
2
+
3
+ function load (recorderName) {
4
+ try {
5
+ const recoderPath = path.resolve(__dirname, recorderName)
6
+ return require(recoderPath)
7
+ } catch (err) {
8
+ if (err.code === 'MODULE_NOT_FOUND') {
9
+ throw new Error(`No such recorder found: ${recorderName}`)
10
+ }
11
+
12
+ throw err
13
+ }
14
+ }
15
+
16
+ module.exports = {
17
+ load
18
+ }
@@ -0,0 +1,36 @@
1
+ module.exports = (options) => {
2
+ let cmd = "rec";
3
+
4
+ if (options.binPath) {
5
+ cmd = options.binPath;
6
+ }
7
+
8
+ let args = [
9
+ "-q", // show no progress
10
+ "-r",
11
+ options.sampleRate, // sample rate
12
+ "-c",
13
+ options.channels, // channels
14
+ "-e",
15
+ "signed-integer", // sample encoding
16
+ "-b",
17
+ "16", // precision (bits)
18
+ "-t",
19
+ options.audioType, // audio type
20
+ "-", // pipe
21
+ ];
22
+
23
+ if (options.endOnSilence) {
24
+ args = args.concat([
25
+ "silence",
26
+ "1",
27
+ "0.1",
28
+ options.thresholdStart || options.threshold + "%",
29
+ "1",
30
+ options.silence,
31
+ options.thresholdEnd || options.threshold + "%",
32
+ ]);
33
+ }
34
+
35
+ return { cmd, args };
36
+ };
@@ -0,0 +1,51 @@
1
+ module.exports = (options) => {
2
+ let cmd = "sox";
3
+
4
+ if (options.binPath) {
5
+ cmd = options.binPath;
6
+ }
7
+
8
+ let args = [
9
+ "--default-device",
10
+ "--no-show-progress", // show no progress
11
+ "--rate",
12
+ options.sampleRate, // sample rate
13
+ "--channels",
14
+ options.channels, // channels
15
+ "--encoding",
16
+ "signed-integer", // sample encoding
17
+ "--bits",
18
+ "16", // precision (bits)
19
+ "--type",
20
+ options.audioType, // audio type
21
+ "-", // pipe
22
+ ];
23
+
24
+ if (options.bufferSize) {
25
+ args.push("--buffer", options.bufferSize);
26
+ }
27
+
28
+ if (options.endOnSilence) {
29
+ args = args.concat([
30
+ "silence",
31
+ "1",
32
+ "0.1",
33
+ options.thresholdStart || options.threshold + "%",
34
+ "1",
35
+ options.silence,
36
+ options.thresholdEnd || options.threshold + "%",
37
+ ]);
38
+ }
39
+
40
+ if (options.arguments) {
41
+ args = args.concat(options.arguments);
42
+ }
43
+
44
+ const spawnOptions = {};
45
+
46
+ if (options.device) {
47
+ spawnOptions.env = { ...process.env, AUDIODEV: options.device };
48
+ }
49
+
50
+ return { cmd, args, spawnOptions };
51
+ };
package/lib/voice.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  import { Model, Recognizer, setLogLevel } from "vosk";
2
- import record from "@lumiastream/record";
2
+ import record from "./record";
3
3
  import { join } from "node:path";
4
4
 
5
5
  const binPath = join(
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lumiastream/wakeword",
3
- "version": "1.0.1-alpha.6",
3
+ "version": "1.0.1-alpha.7",
4
4
  "type": "module",
5
5
  "main": "lib/voice.mjs",
6
6
  "bin": {
@@ -16,7 +16,6 @@
16
16
  "postinstall": "chmod +x binaries/soxmac binaries/soxlinux binaries/sox.exe || true"
17
17
  },
18
18
  "dependencies": {
19
- "@lumiastream/record": "^1.0.1",
20
19
  "vosk": "^0.3.39"
21
20
  }
22
21
  }