@iobroker/assistant-satellite 0.1.2 → 0.1.3
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 +1 -1
- package/build/probe.js +4 -2
- package/build/probe.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -143,7 +143,7 @@ threshold should be validated on the target device.
|
|
|
143
143
|
Placeholder for the next version (at the beginning of the line):
|
|
144
144
|
### **WORK IN PROGRESS**
|
|
145
145
|
-->
|
|
146
|
-
### 0.1.
|
|
146
|
+
### 0.1.3 (2026-07-05)
|
|
147
147
|
* (@GermanBluefox) Added Wake-word probe
|
|
148
148
|
|
|
149
149
|
### 0.0.4 (2026-07-05)
|
package/build/probe.js
CHANGED
|
@@ -7,6 +7,7 @@ exports.probeWakeWord = probeWakeWord;
|
|
|
7
7
|
* verify detection from the GUI — works even before the satellite is fully configured (no server needed).
|
|
8
8
|
*/
|
|
9
9
|
const models_1 = require("./models");
|
|
10
|
+
const config_1 = require("./config");
|
|
10
11
|
const wakeword_1 = require("./wakeword");
|
|
11
12
|
const audio_1 = require("./audio");
|
|
12
13
|
const vad_1 = require("./vad");
|
|
@@ -18,8 +19,9 @@ const FRAME_BYTES = 1280 * 2; // 80 ms @ 16 kHz mono 16-bit
|
|
|
18
19
|
async function probeWakeWord(cfg, log, seconds,
|
|
19
20
|
/** Called per frame with the CURRENT score/RMS and whether the wake word has fired so far. */
|
|
20
21
|
onProgress) {
|
|
21
|
-
const
|
|
22
|
-
const
|
|
22
|
+
const words = (0, config_1.parseWakewords)(cfg.wakewordModel);
|
|
23
|
+
const modelSets = await Promise.all(words.map(w => (0, models_1.ensureModels)(cfg.modelsDir, w, log)));
|
|
24
|
+
const wakeword = new wakeword_1.WakeWord(modelSets, cfg.wakewordThreshold, log);
|
|
23
25
|
await wakeword.load();
|
|
24
26
|
const mic = new audio_1.Mic((0, audio_1.resolveBackend)(cfg.audioBackend), cfg.micDevice, log);
|
|
25
27
|
let remainder = Buffer.alloc(0);
|
package/build/probe.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"probe.js","sourceRoot":"","sources":["../src/probe.ts"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"probe.js","sourceRoot":"","sources":["../src/probe.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Wake-word probe: open the microphone for a few seconds and report whether the wake word was\n * detected and the peak score/level seen. Used by the adapter's \"Test wake word\" button so users can\n * verify detection from the GUI — works even before the satellite is fully configured (no server needed).\n */\nimport { ensureModels } from './models';\nimport { parseWakewords } from './config';\nimport { WakeWord } from './wakeword';\nimport { Mic, resolveBackend } from './audio';\nimport { rms } from './vad';\nimport type { SatelliteConfig } from './config';\nimport type { Logger } from './index';\n\nconst FRAME_BYTES = 1280 * 2; // 80 ms @ 16 kHz mono 16-bit\n\nexport interface WakeProbeResult {\n detected: boolean;\n peakScore: number;\n peakRms: number;\n frames: number;\n threshold: number;\n}\n\n/**\n * Listen for `seconds` and run wake-word detection. `onProgress` is called with the running peak\n * score/RMS so the caller can show a live indicator. Resolves when the window ends.\n */\nexport async function probeWakeWord(\n cfg: SatelliteConfig,\n log: Logger,\n seconds: number,\n /** Called per frame with the CURRENT score/RMS and whether the wake word has fired so far. */\n onProgress?: (score: number, rms: number, detected: boolean) => void,\n): Promise<WakeProbeResult> {\n const words = parseWakewords(cfg.wakewordModel);\n const modelSets = await Promise.all(words.map(w => ensureModels(cfg.modelsDir, w, log)));\n const wakeword = new WakeWord(modelSets, cfg.wakewordThreshold, log);\n await wakeword.load();\n const mic = new Mic(resolveBackend(cfg.audioBackend), cfg.micDevice, log);\n\n let remainder = Buffer.alloc(0);\n let pumping = false;\n let peakScore = 0;\n let peakRms = 0;\n let frames = 0;\n let detected = false;\n\n const pump = async (): Promise<void> => {\n if (pumping) {\n return;\n }\n pumping = true;\n try {\n while (remainder.length >= FRAME_BYTES) {\n const frame = Buffer.from(remainder.subarray(0, FRAME_BYTES));\n remainder = remainder.subarray(FRAME_BYTES);\n frames++;\n const level = rms(frame);\n if (level > peakRms) {\n peakRms = level;\n }\n const score = await wakeword.process(frame);\n const current = score ?? 0;\n if (current > peakScore) {\n peakScore = current;\n }\n if (wakeword.triggered(score)) {\n detected = true;\n }\n onProgress?.(current, level, detected); // current frame values for a live meter\n }\n } finally {\n pumping = false;\n }\n };\n\n mic.start(d => {\n remainder = Buffer.concat([remainder, d]);\n void pump();\n });\n await new Promise<void>(res => setTimeout(res, Math.max(1, seconds) * 1000));\n await new Promise<void>(res => setTimeout(res, 200)); // let the last frames drain\n await mic.stop();\n\n return { detected, peakScore, peakRms, frames, threshold: cfg.wakewordThreshold };\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@iobroker/assistant-satellite",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
4
4
|
"description": "Standalone voice satellite for the ioBroker.assistant adapter (wake word + mic streaming + TTS playback over the Hannah UDP protocol). Runs on a bare Pi via npx, no ioBroker required.",
|
|
5
5
|
"author": "ioBroker",
|
|
6
6
|
"publishConfig": {
|