omnius 1.0.415 → 1.0.416
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/dist/index.js +177 -30
- package/npm-shrinkwrap.json +2 -2
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -604087,7 +604087,9 @@ async function discoverAudioOutputs() {
|
|
|
604087
604087
|
return { devices: dedupeDevices(devices), errors };
|
|
604088
604088
|
}
|
|
604089
604089
|
async function recordAudioSample(device, durationSec, outputPath3) {
|
|
604090
|
-
const
|
|
604090
|
+
const duration = Math.max(0.2, Math.min(30, Number.isFinite(durationSec) ? durationSec : 1));
|
|
604091
|
+
const ffmpegSeconds = duration < 1 ? duration.toFixed(3) : String(Math.ceil(duration));
|
|
604092
|
+
const arecordSeconds = String(Math.max(1, Math.ceil(duration)));
|
|
604091
604093
|
if (device.startsWith("pulse:") && await commandExists2("ffmpeg", 1500)) {
|
|
604092
604094
|
const source = device.slice("pulse:".length);
|
|
604093
604095
|
await execFileText4("ffmpeg", [
|
|
@@ -604099,14 +604101,38 @@ async function recordAudioSample(device, durationSec, outputPath3) {
|
|
|
604099
604101
|
"-i",
|
|
604100
604102
|
source,
|
|
604101
604103
|
"-t",
|
|
604102
|
-
|
|
604104
|
+
ffmpegSeconds,
|
|
604103
604105
|
"-ac",
|
|
604104
604106
|
"1",
|
|
604105
604107
|
"-ar",
|
|
604106
604108
|
"16000",
|
|
604109
|
+
"-acodec",
|
|
604110
|
+
"pcm_s16le",
|
|
604107
604111
|
"-y",
|
|
604108
604112
|
outputPath3
|
|
604109
|
-
], { timeout: (
|
|
604113
|
+
], { timeout: (Math.ceil(duration) + 10) * 1e3 });
|
|
604114
|
+
return;
|
|
604115
|
+
}
|
|
604116
|
+
if (duration < 1 && await commandExists2("ffmpeg", 1500)) {
|
|
604117
|
+
await execFileText4("ffmpeg", [
|
|
604118
|
+
"-hide_banner",
|
|
604119
|
+
"-loglevel",
|
|
604120
|
+
"error",
|
|
604121
|
+
"-f",
|
|
604122
|
+
"alsa",
|
|
604123
|
+
"-i",
|
|
604124
|
+
device || "default",
|
|
604125
|
+
"-t",
|
|
604126
|
+
ffmpegSeconds,
|
|
604127
|
+
"-ac",
|
|
604128
|
+
"1",
|
|
604129
|
+
"-ar",
|
|
604130
|
+
"16000",
|
|
604131
|
+
"-acodec",
|
|
604132
|
+
"pcm_s16le",
|
|
604133
|
+
"-y",
|
|
604134
|
+
outputPath3
|
|
604135
|
+
], { timeout: (Math.ceil(duration) + 10) * 1e3 });
|
|
604110
604136
|
return;
|
|
604111
604137
|
}
|
|
604112
604138
|
await execFileText4("arecord", [
|
|
@@ -604119,10 +604145,10 @@ async function recordAudioSample(device, durationSec, outputPath3) {
|
|
|
604119
604145
|
"-c",
|
|
604120
604146
|
"1",
|
|
604121
604147
|
"-d",
|
|
604122
|
-
|
|
604148
|
+
arecordSeconds,
|
|
604123
604149
|
"-q",
|
|
604124
604150
|
outputPath3
|
|
604125
|
-
], { timeout: (Number(
|
|
604151
|
+
], { timeout: (Number(arecordSeconds) + 10) * 1e3 });
|
|
604126
604152
|
}
|
|
604127
604153
|
async function scoreCameraOrientationWithOpenCv(framePath) {
|
|
604128
604154
|
if (!await commandExists2("python3", 1200)) return null;
|
|
@@ -604196,19 +604222,25 @@ function hasLiveAudioSignal(activity) {
|
|
|
604196
604222
|
function audioCaptureMethod(device) {
|
|
604197
604223
|
return device.startsWith("pulse:") ? "pulse/ffmpeg" : "arecord";
|
|
604198
604224
|
}
|
|
604199
|
-
async function recordAudioSampleWithRecovery(preferred, devices, durationSec, outputPath3) {
|
|
604225
|
+
async function recordAudioSampleWithRecovery(preferred, devices, durationSec, outputPath3, options2 = {}) {
|
|
604226
|
+
const allowFallback = options2.allowFallback !== false;
|
|
604227
|
+
const requireSignal = options2.requireSignal !== false;
|
|
604200
604228
|
const ordered = [];
|
|
604201
604229
|
const add3 = (id2) => {
|
|
604202
604230
|
const clean5 = String(id2 ?? "").trim();
|
|
604203
604231
|
if (clean5 && !ordered.includes(clean5)) ordered.push(clean5);
|
|
604204
604232
|
};
|
|
604205
604233
|
const preferredInput = preferredLiveAudioInputId(devices, preferred);
|
|
604206
|
-
|
|
604207
|
-
|
|
604208
|
-
|
|
604209
|
-
|
|
604210
|
-
|
|
604211
|
-
|
|
604234
|
+
if (allowFallback) {
|
|
604235
|
+
add3(preferredInput);
|
|
604236
|
+
if (preferred) add3(preferred);
|
|
604237
|
+
for (const device of rankLiveAudioInputDevices(devices, preferred).filter((entry) => !isAudioOutputMonitorDevice(entry))) add3(device.id);
|
|
604238
|
+
add3("pulse:default");
|
|
604239
|
+
add3("default");
|
|
604240
|
+
for (const device of rankLiveAudioInputDevices(devices, preferred).filter((entry) => isAudioOutputMonitorDevice(entry))) add3(device.id);
|
|
604241
|
+
} else {
|
|
604242
|
+
add3(preferred || preferredInput || "default");
|
|
604243
|
+
}
|
|
604212
604244
|
const errors = [];
|
|
604213
604245
|
const attempts = [];
|
|
604214
604246
|
let firstQuietCapture = null;
|
|
@@ -604218,8 +604250,9 @@ async function recordAudioSampleWithRecovery(preferred, devices, durationSec, ou
|
|
|
604218
604250
|
await tryRecordAudioDevice(candidate, durationSec, outputPath3);
|
|
604219
604251
|
const activity = readPcm16WavActivity(outputPath3);
|
|
604220
604252
|
const method = audioCaptureMethod(candidate);
|
|
604221
|
-
|
|
604222
|
-
|
|
604253
|
+
const signalDetected = hasLiveAudioSignal(activity);
|
|
604254
|
+
if (!requireSignal || signalDetected) {
|
|
604255
|
+
return { ok: true, device: candidate, method, errors, attempts, activity, signalDetected };
|
|
604223
604256
|
}
|
|
604224
604257
|
if (!firstQuietCapture) {
|
|
604225
604258
|
firstQuietCapture = {
|
|
@@ -604325,7 +604358,7 @@ function formatLiveStatus(snapshot) {
|
|
|
604325
604358
|
}
|
|
604326
604359
|
return lines.join("\n");
|
|
604327
604360
|
}
|
|
604328
|
-
var MIN_VIDEO_INTERVAL_MS, LOW_LATENCY_VIDEO_INTERVAL_MS, MIN_AUDIO_INTERVAL_MS, LOW_LATENCY_AUDIO_INTERVAL_MS, DEFAULT_CONFIG7, managers, DASHBOARD_ANSI_STICKY_PATTERN, LiveSensorManager;
|
|
604361
|
+
var MIN_VIDEO_INTERVAL_MS, LOW_LATENCY_VIDEO_INTERVAL_MS, MIN_AUDIO_INTERVAL_MS, LOW_LATENCY_AUDIO_INTERVAL_MS, AUDIO_ACTIVITY_INTERVAL_MS, AUDIO_ACTIVITY_SAMPLE_SEC, DEFAULT_CONFIG7, managers, DASHBOARD_ANSI_STICKY_PATTERN, LiveSensorManager;
|
|
604329
604362
|
var init_live_sensors = __esm({
|
|
604330
604363
|
"packages/cli/src/tui/live-sensors.ts"() {
|
|
604331
604364
|
"use strict";
|
|
@@ -604336,6 +604369,8 @@ var init_live_sensors = __esm({
|
|
|
604336
604369
|
LOW_LATENCY_VIDEO_INTERVAL_MS = 250;
|
|
604337
604370
|
MIN_AUDIO_INTERVAL_MS = 1500;
|
|
604338
604371
|
LOW_LATENCY_AUDIO_INTERVAL_MS = 2e3;
|
|
604372
|
+
AUDIO_ACTIVITY_INTERVAL_MS = 200;
|
|
604373
|
+
AUDIO_ACTIVITY_SAMPLE_SEC = 0.2;
|
|
604339
604374
|
DEFAULT_CONFIG7 = {
|
|
604340
604375
|
videoEnabled: false,
|
|
604341
604376
|
audioEnabled: false,
|
|
@@ -604368,8 +604403,10 @@ var init_live_sensors = __esm({
|
|
|
604368
604403
|
snapshot;
|
|
604369
604404
|
videoTimer = null;
|
|
604370
604405
|
audioTimer = null;
|
|
604406
|
+
audioActivityTimer = null;
|
|
604371
604407
|
videoInFlight = false;
|
|
604372
604408
|
audioInFlight = false;
|
|
604409
|
+
audioActivityInFlight = false;
|
|
604373
604410
|
statusSink = null;
|
|
604374
604411
|
feedbackSink = null;
|
|
604375
604412
|
agentActionSink = null;
|
|
@@ -604580,10 +604617,7 @@ var init_live_sensors = __esm({
|
|
|
604580
604617
|
errors
|
|
604581
604618
|
};
|
|
604582
604619
|
if (!this.config.selectedCamera) this.config.selectedCamera = firstDeviceId(video);
|
|
604583
|
-
|
|
604584
|
-
if (!this.config.selectedAudioInput || isAudioOutputMonitorId(this.config.selectedAudioInput) && preferredInput && !isAudioOutputMonitorId(preferredInput)) {
|
|
604585
|
-
this.config.selectedAudioInput = preferredInput;
|
|
604586
|
-
}
|
|
604620
|
+
if (!this.config.selectedAudioInput) this.config.selectedAudioInput = preferredLiveAudioInputId(inputs.devices);
|
|
604587
604621
|
if (!this.config.selectedAudioOutput) this.config.selectedAudioOutput = firstDeviceId(outputs.devices);
|
|
604588
604622
|
this.persist();
|
|
604589
604623
|
return this.devices;
|
|
@@ -604987,13 +605021,93 @@ ${output}`).join("\n\n");
|
|
|
604987
605021
|
this.videoInFlight = false;
|
|
604988
605022
|
}
|
|
604989
605023
|
}
|
|
605024
|
+
resolveAudioInput() {
|
|
605025
|
+
const selected = String(this.config.selectedAudioInput ?? "").trim();
|
|
605026
|
+
if (selected) return selected;
|
|
605027
|
+
const input = preferredLiveAudioInputId(this.devices.audioInputs) || "default";
|
|
605028
|
+
this.config.selectedAudioInput = input;
|
|
605029
|
+
this.persist();
|
|
605030
|
+
return input;
|
|
605031
|
+
}
|
|
605032
|
+
async previewAudioInput(device = this.config.selectedAudioInput) {
|
|
605033
|
+
const input = String(device || "").trim() || this.resolveAudioInput();
|
|
605034
|
+
ensureLiveDir(this.repoRoot);
|
|
605035
|
+
const recordingPath = join124(liveDir(this.repoRoot), `audio-preview-${Date.now()}.wav`);
|
|
605036
|
+
const capture = await recordAudioSampleWithRecovery(input, this.devices.audioInputs, 0.8, recordingPath, {
|
|
605037
|
+
allowFallback: false
|
|
605038
|
+
});
|
|
605039
|
+
const now2 = Date.now();
|
|
605040
|
+
const activity = capture.activity ?? (capture.ok ? readPcm16WavActivity(recordingPath) : void 0);
|
|
605041
|
+
if (capture.ok) {
|
|
605042
|
+
this.snapshot.audio = {
|
|
605043
|
+
...this.snapshot.audio ?? { updatedAt: now2 },
|
|
605044
|
+
updatedAt: now2,
|
|
605045
|
+
input,
|
|
605046
|
+
output: this.config.selectedAudioOutput,
|
|
605047
|
+
recordingPath,
|
|
605048
|
+
activity,
|
|
605049
|
+
error: void 0
|
|
605050
|
+
};
|
|
605051
|
+
this.persist();
|
|
605052
|
+
this.emitDashboard();
|
|
605053
|
+
const signal = capture.signalDetected === false ? "quiet/no clear mic signal" : "signal detected";
|
|
605054
|
+
return {
|
|
605055
|
+
ok: true,
|
|
605056
|
+
input,
|
|
605057
|
+
recordingPath,
|
|
605058
|
+
activity,
|
|
605059
|
+
message: [
|
|
605060
|
+
`Audio input preview from ${input}: ${signal}`,
|
|
605061
|
+
activity ? `activity ${activity.waveform} rms=${activity.rmsDb.toFixed(1)}dB active=${Math.round(activity.activeRatio * 100)}% peak=${activity.peak.toFixed(3)}` : "",
|
|
605062
|
+
`recording: ${recordingPath}`
|
|
605063
|
+
].filter(Boolean).join("\n")
|
|
605064
|
+
};
|
|
605065
|
+
}
|
|
605066
|
+
const message2 = `Audio input preview failed for ${input}: ${capture.errors.slice(0, 5).join(" | ") || "capture failed"}`;
|
|
605067
|
+
this.snapshot.audio = {
|
|
605068
|
+
...this.snapshot.audio ?? { updatedAt: now2 },
|
|
605069
|
+
updatedAt: now2,
|
|
605070
|
+
input,
|
|
605071
|
+
output: this.config.selectedAudioOutput,
|
|
605072
|
+
error: message2
|
|
605073
|
+
};
|
|
605074
|
+
this.persist();
|
|
605075
|
+
this.emitDashboard();
|
|
605076
|
+
return { ok: false, input, message: message2 };
|
|
605077
|
+
}
|
|
605078
|
+
async sampleAudioActivityNow() {
|
|
605079
|
+
if (!this.config.audioEnabled || this.audioActivityInFlight) return;
|
|
605080
|
+
this.audioActivityInFlight = true;
|
|
605081
|
+
const input = this.resolveAudioInput();
|
|
605082
|
+
try {
|
|
605083
|
+
ensureLiveDir(this.repoRoot);
|
|
605084
|
+
const recordingPath = join124(liveDir(this.repoRoot), "audio-activity.wav");
|
|
605085
|
+
const capture = await recordAudioSampleWithRecovery(input, this.devices.audioInputs, AUDIO_ACTIVITY_SAMPLE_SEC, recordingPath, {
|
|
605086
|
+
allowFallback: false,
|
|
605087
|
+
requireSignal: false
|
|
605088
|
+
});
|
|
605089
|
+
const now2 = Date.now();
|
|
605090
|
+
const activity = capture.activity ?? (capture.ok ? readPcm16WavActivity(recordingPath) : void 0);
|
|
605091
|
+
this.snapshot.audio = {
|
|
605092
|
+
...this.snapshot.audio ?? { updatedAt: now2 },
|
|
605093
|
+
updatedAt: now2,
|
|
605094
|
+
input,
|
|
605095
|
+
output: this.config.selectedAudioOutput,
|
|
605096
|
+
recordingPath,
|
|
605097
|
+
activity,
|
|
605098
|
+
error: capture.ok ? this.snapshot.audio?.error : `Audio activity capture failed from ${input}: ${capture.errors.slice(0, 3).join(" | ")}`
|
|
605099
|
+
};
|
|
605100
|
+
this.persist();
|
|
605101
|
+
this.emitDashboard();
|
|
605102
|
+
} finally {
|
|
605103
|
+
this.audioActivityInFlight = false;
|
|
605104
|
+
}
|
|
605105
|
+
}
|
|
604990
605106
|
async sampleAudioNow() {
|
|
604991
605107
|
if (this.audioInFlight) return "Audio sampler is already running.";
|
|
604992
605108
|
this.audioInFlight = true;
|
|
604993
605109
|
try {
|
|
604994
|
-
const
|
|
604995
|
-
const input = this.config.selectedAudioInput && !isAudioOutputMonitorId(this.config.selectedAudioInput) ? this.config.selectedAudioInput : preferredInput;
|
|
604996
|
-
if (input !== this.config.selectedAudioInput) this.config.selectedAudioInput = input;
|
|
605110
|
+
const input = this.resolveAudioInput();
|
|
604997
605111
|
if (this.isLiveAudioMutedForTts()) {
|
|
604998
605112
|
const now2 = Date.now();
|
|
604999
605113
|
this.snapshot.audio = {
|
|
@@ -605016,9 +605130,11 @@ ${output}`).join("\n\n");
|
|
|
605016
605130
|
let analysis = "";
|
|
605017
605131
|
let intake;
|
|
605018
605132
|
const audioErrors = [];
|
|
605019
|
-
const capture = await recordAudioSampleWithRecovery(input, this.devices.audioInputs, 3, recordingPath
|
|
605133
|
+
const capture = await recordAudioSampleWithRecovery(input, this.devices.audioInputs, 3, recordingPath, {
|
|
605134
|
+
allowFallback: false
|
|
605135
|
+
});
|
|
605020
605136
|
if (!capture.ok) {
|
|
605021
|
-
const message2 = `Audio capture failed from ${input}
|
|
605137
|
+
const message2 = `Audio capture failed from selected input ${input}: ${capture.errors.slice(0, 5).join(" | ")}`;
|
|
605022
605138
|
this.snapshot.audio = {
|
|
605023
605139
|
updatedAt: Date.now(),
|
|
605024
605140
|
input,
|
|
@@ -605035,12 +605151,9 @@ ${output}`).join("\n\n");
|
|
|
605035
605151
|
this.emitDashboard();
|
|
605036
605152
|
return message2;
|
|
605037
605153
|
}
|
|
605038
|
-
if (capture.device !== this.config.selectedAudioInput) {
|
|
605039
|
-
this.config.selectedAudioInput = capture.device;
|
|
605040
|
-
}
|
|
605041
605154
|
const activity = capture.activity ?? readPcm16WavActivity(recordingPath);
|
|
605042
605155
|
if (capture.ok && capture.signalDetected === false) {
|
|
605043
|
-
audioErrors.push(`No live input signal detected
|
|
605156
|
+
audioErrors.push(`No live input signal detected from selected input ${capture.device}; keeping the explicit selection.`);
|
|
605044
605157
|
}
|
|
605045
605158
|
if (this.config.asrEnabled) {
|
|
605046
605159
|
try {
|
|
@@ -605135,7 +605248,7 @@ ${output}`).join("\n\n");
|
|
|
605135
605248
|
}
|
|
605136
605249
|
this.emitDashboard();
|
|
605137
605250
|
return [
|
|
605138
|
-
`Audio sample captured from ${capture.device}
|
|
605251
|
+
`Audio sample captured from selected input ${capture.device}: ${recordingPath}`,
|
|
605139
605252
|
transcript ? `
|
|
605140
605253
|
ASR${asrBackend ? ` (${asrBackend})` : ""}:
|
|
605141
605254
|
${transcript}` : "",
|
|
@@ -605158,6 +605271,10 @@ ${analysis}` : ""
|
|
|
605158
605271
|
clearTimeout(this.audioTimer);
|
|
605159
605272
|
this.audioTimer = null;
|
|
605160
605273
|
}
|
|
605274
|
+
if (this.audioActivityTimer) {
|
|
605275
|
+
clearTimeout(this.audioActivityTimer);
|
|
605276
|
+
this.audioActivityTimer = null;
|
|
605277
|
+
}
|
|
605161
605278
|
}
|
|
605162
605279
|
scheduleVideoLoop(delayMs) {
|
|
605163
605280
|
if (!this.config.videoEnabled || this.videoTimer) return;
|
|
@@ -605194,6 +605311,22 @@ ${analysis}` : ""
|
|
|
605194
605311
|
}, Math.max(0, delayMs));
|
|
605195
605312
|
this.audioTimer.unref?.();
|
|
605196
605313
|
}
|
|
605314
|
+
scheduleAudioActivityLoop(delayMs) {
|
|
605315
|
+
if (!this.config.audioEnabled || this.audioActivityTimer) return;
|
|
605316
|
+
this.audioActivityTimer = setTimeout(async () => {
|
|
605317
|
+
const startedAt2 = Date.now();
|
|
605318
|
+
this.audioActivityTimer = null;
|
|
605319
|
+
if (!this.config.audioEnabled) return;
|
|
605320
|
+
try {
|
|
605321
|
+
await this.sampleAudioActivityNow();
|
|
605322
|
+
} catch {
|
|
605323
|
+
} finally {
|
|
605324
|
+
const elapsedMs2 = Date.now() - startedAt2;
|
|
605325
|
+
if (this.config.audioEnabled) this.scheduleAudioActivityLoop(Math.max(0, AUDIO_ACTIVITY_INTERVAL_MS - elapsedMs2));
|
|
605326
|
+
}
|
|
605327
|
+
}, Math.max(0, delayMs));
|
|
605328
|
+
this.audioActivityTimer.unref?.();
|
|
605329
|
+
}
|
|
605197
605330
|
ensureLoops() {
|
|
605198
605331
|
if (this.config.videoEnabled && !this.videoTimer) {
|
|
605199
605332
|
this.scheduleVideoLoop(0);
|
|
@@ -605208,6 +605341,12 @@ ${analysis}` : ""
|
|
|
605208
605341
|
clearTimeout(this.audioTimer);
|
|
605209
605342
|
this.audioTimer = null;
|
|
605210
605343
|
}
|
|
605344
|
+
if (this.config.audioEnabled && !this.audioActivityTimer) {
|
|
605345
|
+
this.scheduleAudioActivityLoop(0);
|
|
605346
|
+
} else if (!this.config.audioEnabled && this.audioActivityTimer) {
|
|
605347
|
+
clearTimeout(this.audioActivityTimer);
|
|
605348
|
+
this.audioActivityTimer = null;
|
|
605349
|
+
}
|
|
605211
605350
|
}
|
|
605212
605351
|
emitStatus() {
|
|
605213
605352
|
this.statusSink?.({
|
|
@@ -657472,7 +657611,15 @@ async function showLiveMenu(ctx3, manager) {
|
|
|
657472
657611
|
}
|
|
657473
657612
|
case "audio-input": {
|
|
657474
657613
|
const device = await chooseLiveDevice(ctx3, "Select Audio Input", devices.audioInputs, cfg.selectedAudioInput);
|
|
657475
|
-
if (device)
|
|
657614
|
+
if (device) {
|
|
657615
|
+
manager.configure({ selectedAudioInput: device.id, audioEnabled: true });
|
|
657616
|
+
renderInfo(`Selected audio input: ${device.id}
|
|
657617
|
+
Previewing microphone activity...`);
|
|
657618
|
+
const preview = await manager.previewAudioInput(device.id);
|
|
657619
|
+
if (preview.ok) renderInfo(preview.message);
|
|
657620
|
+
else renderWarning(preview.message);
|
|
657621
|
+
renderLiveDashboard(ctx3, manager);
|
|
657622
|
+
}
|
|
657476
657623
|
continue;
|
|
657477
657624
|
}
|
|
657478
657625
|
case "audio-output": {
|
package/npm-shrinkwrap.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "omnius",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.416",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "omnius",
|
|
9
|
-
"version": "1.0.
|
|
9
|
+
"version": "1.0.416",
|
|
10
10
|
"bundleDependencies": [
|
|
11
11
|
"image-to-ascii"
|
|
12
12
|
],
|
package/package.json
CHANGED