omnius 1.0.415 → 1.0.417
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 +340 -58
- package/npm-shrinkwrap.json +2 -2
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -603131,25 +603131,29 @@ function liveDashboardRotationActionFromClick(snapshot, lineText, col) {
|
|
|
603131
603131
|
}
|
|
603132
603132
|
function pushDashboardWrapped(lines, value2, width) {
|
|
603133
603133
|
const contentWidth = Math.max(10, width - 2);
|
|
603134
|
-
const
|
|
603134
|
+
const normalized = stripDashboardAnsi(value2).replace(/\s+/g, " ").trimEnd();
|
|
603135
|
+
const leading = normalized.match(/^ */)?.[0] ?? "";
|
|
603136
|
+
const words = normalized.slice(leading.length).trimStart().split(" ").filter(Boolean);
|
|
603135
603137
|
if (words.length === 0) {
|
|
603136
603138
|
lines.push(`│${" ".repeat(contentWidth)}│`);
|
|
603137
603139
|
return;
|
|
603138
603140
|
}
|
|
603139
|
-
let current =
|
|
603141
|
+
let current = leading;
|
|
603140
603142
|
for (const word2 of words) {
|
|
603141
|
-
if (
|
|
603142
|
-
|
|
603143
|
+
if (current === leading) {
|
|
603144
|
+
const available = Math.max(1, contentWidth - leading.length);
|
|
603145
|
+
current = `${leading}${word2.length > available ? word2.slice(0, available) : word2}`;
|
|
603143
603146
|
continue;
|
|
603144
603147
|
}
|
|
603145
603148
|
if (current.length + 1 + word2.length <= contentWidth) {
|
|
603146
603149
|
current += ` ${word2}`;
|
|
603147
603150
|
} else {
|
|
603148
603151
|
lines.push(`│${truncateCell(` ${current}`, contentWidth)}│`);
|
|
603149
|
-
|
|
603152
|
+
const available = Math.max(1, contentWidth - leading.length);
|
|
603153
|
+
current = `${leading}${word2.length > available ? word2.slice(0, available) : word2}`;
|
|
603150
603154
|
}
|
|
603151
603155
|
}
|
|
603152
|
-
if (current) lines.push(`│${truncateCell(` ${current}`, contentWidth)}│`);
|
|
603156
|
+
if (current.trim()) lines.push(`│${truncateCell(` ${current}`, contentWidth)}│`);
|
|
603153
603157
|
}
|
|
603154
603158
|
function isAudioFailureText(value2) {
|
|
603155
603159
|
const text2 = String(value2 ?? "").trim();
|
|
@@ -603159,6 +603163,9 @@ function isAudioFailureText(value2) {
|
|
|
603159
603163
|
function sanitizeLiveAudioError(value2) {
|
|
603160
603164
|
const text2 = String(value2 ?? "").trim();
|
|
603161
603165
|
if (!text2) return "";
|
|
603166
|
+
if (/No live input signal detected after probing \d+ audio source/i.test(text2)) {
|
|
603167
|
+
return "No clear live input signal on selected audio input.";
|
|
603168
|
+
}
|
|
603162
603169
|
if (/transcribe-cli module:\s*No module named ['"]?transcribe_cli/i.test(text2) || /No module named ['"]?transcribe_cli/i.test(text2)) {
|
|
603163
603170
|
const parts = text2.split(/\s*\|\s*/g).map((part) => part.trim()).filter((part) => part && !/transcribe-cli module:\s*No module named ['"]?transcribe_cli/i.test(part) && !/No module named ['"]?transcribe_cli/i.test(part));
|
|
603164
603171
|
const preserved = parts.join(" | ").trim();
|
|
@@ -603541,6 +603548,104 @@ function cameraClassificationsSummary(camera, maxChars = 220) {
|
|
|
603541
603548
|
});
|
|
603542
603549
|
return trimOneLine(items.join("; "), maxChars);
|
|
603543
603550
|
}
|
|
603551
|
+
function cameraClassPriority(kind) {
|
|
603552
|
+
if (kind === "face" || kind === "identity") return 0;
|
|
603553
|
+
if (kind === "segment") return 1;
|
|
603554
|
+
if (kind === "object") return 2;
|
|
603555
|
+
if (kind === "track") return 3;
|
|
603556
|
+
if (kind === "clip") return 4;
|
|
603557
|
+
return 5;
|
|
603558
|
+
}
|
|
603559
|
+
function groupedDashboardClassifications(camera, kinds) {
|
|
603560
|
+
const wanted = new Set(kinds);
|
|
603561
|
+
const grouped = /* @__PURE__ */ new Map();
|
|
603562
|
+
for (const item of camera.classifications ?? []) {
|
|
603563
|
+
if (!wanted.has(item.kind)) continue;
|
|
603564
|
+
const label = trimOneLine(item.label || item.kind, 64) || item.kind;
|
|
603565
|
+
const key = `${item.kind}:${label.toLowerCase()}`;
|
|
603566
|
+
const existing = grouped.get(key);
|
|
603567
|
+
const count = Math.max(1, item.count);
|
|
603568
|
+
if (!existing) {
|
|
603569
|
+
grouped.set(key, {
|
|
603570
|
+
kind: item.kind,
|
|
603571
|
+
label,
|
|
603572
|
+
count,
|
|
603573
|
+
confidence: item.confidence
|
|
603574
|
+
});
|
|
603575
|
+
continue;
|
|
603576
|
+
}
|
|
603577
|
+
existing.count += count;
|
|
603578
|
+
if (item.confidence !== void 0) {
|
|
603579
|
+
existing.confidence = existing.confidence === void 0 ? item.confidence : Math.max(existing.confidence, item.confidence);
|
|
603580
|
+
}
|
|
603581
|
+
}
|
|
603582
|
+
return [...grouped.values()].sort((a2, b) => {
|
|
603583
|
+
const priority = cameraClassPriority(a2.kind) - cameraClassPriority(b.kind);
|
|
603584
|
+
if (priority !== 0) return priority;
|
|
603585
|
+
return (b.confidence ?? 0) - (a2.confidence ?? 0) || b.count - a2.count || a2.label.localeCompare(b.label);
|
|
603586
|
+
});
|
|
603587
|
+
}
|
|
603588
|
+
function formatDashboardClassList(groups, maxItems = 6) {
|
|
603589
|
+
return groups.slice(0, maxItems).map((group) => {
|
|
603590
|
+
const count = group.count > 1 ? ` x${group.count}` : "";
|
|
603591
|
+
const confidence2 = group.confidence !== void 0 ? ` ${group.confidence.toFixed(2)}` : "";
|
|
603592
|
+
return `${group.label}${count}${confidence2}`;
|
|
603593
|
+
}).join("; ");
|
|
603594
|
+
}
|
|
603595
|
+
function cleanCameraSummaryForDashboard(value2) {
|
|
603596
|
+
const raw = String(value2 ?? "").trim();
|
|
603597
|
+
if (!raw) return "";
|
|
603598
|
+
const withoutClip = raw.split(/\s+\|\s+clip:/i)[0] ?? raw;
|
|
603599
|
+
return trimOneLine(
|
|
603600
|
+
withoutClip.replace(/\b(?:mask|crop)=\S+/gi, "").replace(/\bbbox=\[[^\]]*\]/gi, "").replace(/\s{2,}/g, " "),
|
|
603601
|
+
220
|
|
603602
|
+
);
|
|
603603
|
+
}
|
|
603604
|
+
function formatClipDashboardSummary(value2) {
|
|
603605
|
+
const text2 = String(value2 ?? "").trim();
|
|
603606
|
+
if (!text2) return "";
|
|
603607
|
+
const clipText = text2.match(/\bclip:\s*([\s\S]+)$/i)?.[1] ?? text2;
|
|
603608
|
+
const parsed = parseJsonObjectFromText(clipText);
|
|
603609
|
+
if (!parsed) return /\bclip:\s*/i.test(text2) ? `clip: ${trimOneLine(clipText, 120)}` : "";
|
|
603610
|
+
const matches = Array.isArray(parsed["matches"]) ? parsed["matches"] : [];
|
|
603611
|
+
if (matches.length > 0) {
|
|
603612
|
+
const labels = matches.slice(0, 4).map((match) => {
|
|
603613
|
+
const label = trimOneLine(match["label"] ?? match["name"] ?? match["title"] ?? match["id"] ?? "match", 48);
|
|
603614
|
+
const score = boundedConfidence(match["score"] ?? match["similarity"] ?? match["confidence"]);
|
|
603615
|
+
return `${label || "match"}${score !== void 0 ? ` ${score.toFixed(2)}` : ""}`;
|
|
603616
|
+
});
|
|
603617
|
+
return `clip: ${labels.join("; ")}`;
|
|
603618
|
+
}
|
|
603619
|
+
const recognized = Math.max(0, Number(parsed["recognized_count"] ?? 0));
|
|
603620
|
+
const extra = parsed["extra_labels"];
|
|
603621
|
+
if (Array.isArray(extra) && extra.length > 0) {
|
|
603622
|
+
return `clip: extra labels ${extra.slice(0, 4).map((entry) => trimOneLine(entry, 36)).join("; ")}`;
|
|
603623
|
+
}
|
|
603624
|
+
if (typeof extra === "string" && extra.trim()) return `clip: ${trimOneLine(extra, 120)}`;
|
|
603625
|
+
return recognized > 0 ? `clip: ${recognized} recognized match(es)` : "clip: no visual-memory matches";
|
|
603626
|
+
}
|
|
603627
|
+
function formatAudioAnalysisDashboardSummary(value2) {
|
|
603628
|
+
const text2 = String(value2 ?? "").trim();
|
|
603629
|
+
if (!text2) return "";
|
|
603630
|
+
const parsed = parseJsonObjectFromText(text2);
|
|
603631
|
+
const classifications = Array.isArray(parsed?.["classifications"]) ? parsed["classifications"] : [];
|
|
603632
|
+
if (classifications.length > 0) {
|
|
603633
|
+
return `sound classes: ${classifications.slice(0, 4).map((entry) => {
|
|
603634
|
+
const label = trimOneLine(entry["class"] ?? entry["label"] ?? entry["name"] ?? "sound", 44);
|
|
603635
|
+
const score = boundedConfidence(entry["score"] ?? entry["confidence"]);
|
|
603636
|
+
return `${label || "sound"}${score !== void 0 ? ` ${score.toFixed(2)}` : ""}`;
|
|
603637
|
+
}).join("; ")}`;
|
|
603638
|
+
}
|
|
603639
|
+
return `sound: ${trimOneLine(text2.replace(/\{[\s\S]*$/, ""), 140) || trimOneLine(text2, 140)}`;
|
|
603640
|
+
}
|
|
603641
|
+
function formatCameraRotationDashboard(camera) {
|
|
603642
|
+
const orientation = camera.orientation;
|
|
603643
|
+
const rotation = orientation?.rotation ?? camera.rotation ?? 0;
|
|
603644
|
+
const base3 = formatCameraRotation(rotation);
|
|
603645
|
+
if (!orientation) return base3;
|
|
603646
|
+
const confidence2 = orientation.confidence !== void 0 ? ` ${orientation.confidence.toFixed(2)}` : "";
|
|
603647
|
+
return `${base3} (${orientation.source}${confidence2})`;
|
|
603648
|
+
}
|
|
603544
603649
|
function cameraPaneBadge(camera) {
|
|
603545
603650
|
const classifications = camera.classifications ?? [];
|
|
603546
603651
|
const faceCount = classifications.filter((item) => item.kind === "face" || item.kind === "identity").reduce((sum, item) => sum + Math.max(1, item.count), 0);
|
|
@@ -603559,7 +603664,44 @@ function cameraPaneBadge(camera) {
|
|
|
603559
603664
|
}
|
|
603560
603665
|
function cameraSnapshotSummary(camera) {
|
|
603561
603666
|
if (camera.error) return `error: ${trimOneLine(camera.error, 160)}`;
|
|
603562
|
-
return camera.summary || (camera.classifications?.length ? `classifications: ${cameraClassificationsSummary(camera)}` : "") || summarizeInference(camera.inference);
|
|
603667
|
+
return cleanCameraSummaryForDashboard(camera.summary) || (camera.classifications?.length ? `classifications: ${cameraClassificationsSummary(camera)}` : "") || summarizeInference(camera.inference);
|
|
603668
|
+
}
|
|
603669
|
+
function cameraDashboardObservationLines(camera, now2, isLast) {
|
|
603670
|
+
const age = Math.max(0, Math.round((now2 - camera.updatedAt) / 1e3));
|
|
603671
|
+
const root = isLast ? "└─" : "├─";
|
|
603672
|
+
const stem = isLast ? " " : "│ ";
|
|
603673
|
+
const lines = [
|
|
603674
|
+
`${root} ${compactSourceId(camera.source)} age=${age}s rotation=${formatCameraRotationDashboard(camera)}`
|
|
603675
|
+
];
|
|
603676
|
+
if (camera.error) {
|
|
603677
|
+
lines.push(`${stem}└─ error: ${trimOneLine(camera.error, 180)}`);
|
|
603678
|
+
return lines;
|
|
603679
|
+
}
|
|
603680
|
+
const faces = formatDashboardClassList(groupedDashboardClassifications(camera, ["face", "identity"]), 4);
|
|
603681
|
+
const segments = formatDashboardClassList(groupedDashboardClassifications(camera, ["segment"]), 6);
|
|
603682
|
+
const objects = formatDashboardClassList(groupedDashboardClassifications(camera, ["object"]), 6);
|
|
603683
|
+
const tracks = formatDashboardClassList(groupedDashboardClassifications(camera, ["track"]), 4);
|
|
603684
|
+
const triggers = formatDashboardClassList(groupedDashboardClassifications(camera, ["trigger"]), 3);
|
|
603685
|
+
const clip3 = formatClipDashboardSummary(camera.summary) || formatDashboardClassList(groupedDashboardClassifications(camera, ["clip"]), 4);
|
|
603686
|
+
const summary = cameraSnapshotSummary(camera);
|
|
603687
|
+
const includeSummary = summary && !summary.startsWith("classifications:") && !(objects && /^objects:/i.test(summary)) && !(segments && /^segments?:/i.test(summary));
|
|
603688
|
+
const detailLines = [
|
|
603689
|
+
faces ? `faces: ${faces}` : "",
|
|
603690
|
+
segments ? `segments: ${segments}` : "",
|
|
603691
|
+
objects ? `objects: ${objects}` : "",
|
|
603692
|
+
tracks ? `tracks: ${tracks}` : "",
|
|
603693
|
+
triggers ? `triggers: ${triggers}` : "",
|
|
603694
|
+
includeSummary ? summary : "",
|
|
603695
|
+
clip3,
|
|
603696
|
+
camera.framePath ? `frame: ${camera.displayPath || camera.framePath}` : "",
|
|
603697
|
+
camera.orientation?.evidence ? `orientation: ${trimOneLine(camera.orientation.evidence, 120)}` : ""
|
|
603698
|
+
].filter(Boolean);
|
|
603699
|
+
const last2 = Math.max(0, detailLines.length - 1);
|
|
603700
|
+
detailLines.forEach((detail, index) => {
|
|
603701
|
+
lines.push(`${stem}${index === last2 ? "└─" : "├─"} ${detail}`);
|
|
603702
|
+
});
|
|
603703
|
+
if (detailLines.length === 0) lines.push(`${stem}└─ preview pending`);
|
|
603704
|
+
return lines;
|
|
603563
603705
|
}
|
|
603564
603706
|
function formatLiveDashboardFromSnapshot(snapshot, opts = {}) {
|
|
603565
603707
|
const width = Math.max(60, opts.width ?? 100);
|
|
@@ -603599,35 +603741,27 @@ function formatLiveDashboardFromSnapshot(snapshot, opts = {}) {
|
|
|
603599
603741
|
lines.push(`├${horizontal}┤`);
|
|
603600
603742
|
lines.push(`│${truncateCell(" camera observations", width - 2)}│`);
|
|
603601
603743
|
}
|
|
603602
|
-
|
|
603603
|
-
const
|
|
603604
|
-
const
|
|
603605
|
-
const classifications = cameraClassificationsSummary(camera);
|
|
603606
|
-
const detailLines = [
|
|
603607
|
-
`${compactSourceId(camera.source)} age=${age}s rotation=${rotation}`,
|
|
603608
|
-
classifications ? `classifications: ${classifications}` : "",
|
|
603609
|
-
cameraSnapshotSummary(camera),
|
|
603610
|
-
camera.framePath ? `frame: ${camera.displayPath || camera.framePath}` : "",
|
|
603611
|
-
camera.orientation?.evidence ? `orientation: ${trimOneLine(camera.orientation.evidence, 120)}` : ""
|
|
603612
|
-
].filter(Boolean);
|
|
603613
|
-
for (const detail of detailLines.length ? detailLines : ["preview pending"]) {
|
|
603744
|
+
cameras.forEach((camera, index) => {
|
|
603745
|
+
const detailLines = cameraDashboardObservationLines(camera, now2, index === cameras.length - 1);
|
|
603746
|
+
for (const detail of detailLines) {
|
|
603614
603747
|
pushDashboardWrapped(lines, detail, width);
|
|
603615
603748
|
}
|
|
603616
|
-
}
|
|
603749
|
+
});
|
|
603617
603750
|
if (snapshot.audio) {
|
|
603618
603751
|
lines.push(`├${horizontal}┤`);
|
|
603752
|
+
lines.push(`│${truncateCell(" audio monitor", width - 2)}│`);
|
|
603619
603753
|
const transcriptFailure = isAudioFailureText(snapshot.audio.transcript) ? snapshot.audio.transcript : "";
|
|
603620
603754
|
const transcript = transcriptFailure ? "" : snapshot.audio.transcript;
|
|
603621
603755
|
const audioError = sanitizeLiveAudioError([snapshot.audio.error, transcriptFailure].filter(Boolean).join(" | "));
|
|
603622
603756
|
const audioBits = [
|
|
603623
|
-
|
|
603624
|
-
snapshot.audio.activity ?
|
|
603625
|
-
audioError ?
|
|
603626
|
-
transcript ?
|
|
603627
|
-
snapshot.audio.intake ?
|
|
603628
|
-
snapshot.audio.analysis ?
|
|
603757
|
+
`├─ input: ${snapshot.audio.input || snapshot.config.selectedAudioInput || "none"}`,
|
|
603758
|
+
snapshot.audio.activity ? `│ ├─ activity: ${snapshot.audio.activity.waveform} rms=${snapshot.audio.activity.rmsDb.toFixed(1)}dB active=${Math.round(snapshot.audio.activity.activeRatio * 100)}%` : "",
|
|
603759
|
+
audioError ? `│ ├─ error: ${trimOneLine(audioError, 140)}` : "",
|
|
603760
|
+
transcript ? `│ ├─ asr${snapshot.audio.asrBackend ? ` (${snapshot.audio.asrBackend})` : ""}: ${trimOneLine(transcript, 140)}` : "",
|
|
603761
|
+
snapshot.audio.intake ? `│ ├─ intake: ${snapshot.audio.intake.intendedForAgent ? "for-agent" : "ambient"} conf=${snapshot.audio.intake.confidence.toFixed(2)} action=${snapshot.audio.intake.action}` : "",
|
|
603762
|
+
snapshot.audio.analysis ? `│ └─ ${formatAudioAnalysisDashboardSummary(snapshot.audio.analysis)}` : ""
|
|
603629
603763
|
].filter(Boolean);
|
|
603630
|
-
for (const item of audioBits.slice(0, 6)) lines
|
|
603764
|
+
for (const item of audioBits.slice(0, 6)) pushDashboardWrapped(lines, item, width);
|
|
603631
603765
|
}
|
|
603632
603766
|
lines.push(`╰${horizontal}╯`);
|
|
603633
603767
|
return lines;
|
|
@@ -604087,7 +604221,9 @@ async function discoverAudioOutputs() {
|
|
|
604087
604221
|
return { devices: dedupeDevices(devices), errors };
|
|
604088
604222
|
}
|
|
604089
604223
|
async function recordAudioSample(device, durationSec, outputPath3) {
|
|
604090
|
-
const
|
|
604224
|
+
const duration = Math.max(0.2, Math.min(30, Number.isFinite(durationSec) ? durationSec : 1));
|
|
604225
|
+
const ffmpegSeconds = duration < 1 ? duration.toFixed(3) : String(Math.ceil(duration));
|
|
604226
|
+
const arecordSeconds = String(Math.max(1, Math.ceil(duration)));
|
|
604091
604227
|
if (device.startsWith("pulse:") && await commandExists2("ffmpeg", 1500)) {
|
|
604092
604228
|
const source = device.slice("pulse:".length);
|
|
604093
604229
|
await execFileText4("ffmpeg", [
|
|
@@ -604099,14 +604235,38 @@ async function recordAudioSample(device, durationSec, outputPath3) {
|
|
|
604099
604235
|
"-i",
|
|
604100
604236
|
source,
|
|
604101
604237
|
"-t",
|
|
604102
|
-
|
|
604238
|
+
ffmpegSeconds,
|
|
604239
|
+
"-ac",
|
|
604240
|
+
"1",
|
|
604241
|
+
"-ar",
|
|
604242
|
+
"16000",
|
|
604243
|
+
"-acodec",
|
|
604244
|
+
"pcm_s16le",
|
|
604245
|
+
"-y",
|
|
604246
|
+
outputPath3
|
|
604247
|
+
], { timeout: (Math.ceil(duration) + 10) * 1e3 });
|
|
604248
|
+
return;
|
|
604249
|
+
}
|
|
604250
|
+
if (duration < 1 && await commandExists2("ffmpeg", 1500)) {
|
|
604251
|
+
await execFileText4("ffmpeg", [
|
|
604252
|
+
"-hide_banner",
|
|
604253
|
+
"-loglevel",
|
|
604254
|
+
"error",
|
|
604255
|
+
"-f",
|
|
604256
|
+
"alsa",
|
|
604257
|
+
"-i",
|
|
604258
|
+
device || "default",
|
|
604259
|
+
"-t",
|
|
604260
|
+
ffmpegSeconds,
|
|
604103
604261
|
"-ac",
|
|
604104
604262
|
"1",
|
|
604105
604263
|
"-ar",
|
|
604106
604264
|
"16000",
|
|
604265
|
+
"-acodec",
|
|
604266
|
+
"pcm_s16le",
|
|
604107
604267
|
"-y",
|
|
604108
604268
|
outputPath3
|
|
604109
|
-
], { timeout: (
|
|
604269
|
+
], { timeout: (Math.ceil(duration) + 10) * 1e3 });
|
|
604110
604270
|
return;
|
|
604111
604271
|
}
|
|
604112
604272
|
await execFileText4("arecord", [
|
|
@@ -604119,10 +604279,10 @@ async function recordAudioSample(device, durationSec, outputPath3) {
|
|
|
604119
604279
|
"-c",
|
|
604120
604280
|
"1",
|
|
604121
604281
|
"-d",
|
|
604122
|
-
|
|
604282
|
+
arecordSeconds,
|
|
604123
604283
|
"-q",
|
|
604124
604284
|
outputPath3
|
|
604125
|
-
], { timeout: (Number(
|
|
604285
|
+
], { timeout: (Number(arecordSeconds) + 10) * 1e3 });
|
|
604126
604286
|
}
|
|
604127
604287
|
async function scoreCameraOrientationWithOpenCv(framePath) {
|
|
604128
604288
|
if (!await commandExists2("python3", 1200)) return null;
|
|
@@ -604196,19 +604356,25 @@ function hasLiveAudioSignal(activity) {
|
|
|
604196
604356
|
function audioCaptureMethod(device) {
|
|
604197
604357
|
return device.startsWith("pulse:") ? "pulse/ffmpeg" : "arecord";
|
|
604198
604358
|
}
|
|
604199
|
-
async function recordAudioSampleWithRecovery(preferred, devices, durationSec, outputPath3) {
|
|
604359
|
+
async function recordAudioSampleWithRecovery(preferred, devices, durationSec, outputPath3, options2 = {}) {
|
|
604360
|
+
const allowFallback = options2.allowFallback !== false;
|
|
604361
|
+
const requireSignal = options2.requireSignal !== false;
|
|
604200
604362
|
const ordered = [];
|
|
604201
604363
|
const add3 = (id2) => {
|
|
604202
604364
|
const clean5 = String(id2 ?? "").trim();
|
|
604203
604365
|
if (clean5 && !ordered.includes(clean5)) ordered.push(clean5);
|
|
604204
604366
|
};
|
|
604205
604367
|
const preferredInput = preferredLiveAudioInputId(devices, preferred);
|
|
604206
|
-
|
|
604207
|
-
|
|
604208
|
-
|
|
604209
|
-
|
|
604210
|
-
|
|
604211
|
-
|
|
604368
|
+
if (allowFallback) {
|
|
604369
|
+
add3(preferredInput);
|
|
604370
|
+
if (preferred) add3(preferred);
|
|
604371
|
+
for (const device of rankLiveAudioInputDevices(devices, preferred).filter((entry) => !isAudioOutputMonitorDevice(entry))) add3(device.id);
|
|
604372
|
+
add3("pulse:default");
|
|
604373
|
+
add3("default");
|
|
604374
|
+
for (const device of rankLiveAudioInputDevices(devices, preferred).filter((entry) => isAudioOutputMonitorDevice(entry))) add3(device.id);
|
|
604375
|
+
} else {
|
|
604376
|
+
add3(preferred || preferredInput || "default");
|
|
604377
|
+
}
|
|
604212
604378
|
const errors = [];
|
|
604213
604379
|
const attempts = [];
|
|
604214
604380
|
let firstQuietCapture = null;
|
|
@@ -604218,8 +604384,9 @@ async function recordAudioSampleWithRecovery(preferred, devices, durationSec, ou
|
|
|
604218
604384
|
await tryRecordAudioDevice(candidate, durationSec, outputPath3);
|
|
604219
604385
|
const activity = readPcm16WavActivity(outputPath3);
|
|
604220
604386
|
const method = audioCaptureMethod(candidate);
|
|
604221
|
-
|
|
604222
|
-
|
|
604387
|
+
const signalDetected = hasLiveAudioSignal(activity);
|
|
604388
|
+
if (!requireSignal || signalDetected) {
|
|
604389
|
+
return { ok: true, device: candidate, method, errors, attempts, activity, signalDetected };
|
|
604223
604390
|
}
|
|
604224
604391
|
if (!firstQuietCapture) {
|
|
604225
604392
|
firstQuietCapture = {
|
|
@@ -604325,7 +604492,7 @@ function formatLiveStatus(snapshot) {
|
|
|
604325
604492
|
}
|
|
604326
604493
|
return lines.join("\n");
|
|
604327
604494
|
}
|
|
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;
|
|
604495
|
+
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
604496
|
var init_live_sensors = __esm({
|
|
604330
604497
|
"packages/cli/src/tui/live-sensors.ts"() {
|
|
604331
604498
|
"use strict";
|
|
@@ -604336,6 +604503,8 @@ var init_live_sensors = __esm({
|
|
|
604336
604503
|
LOW_LATENCY_VIDEO_INTERVAL_MS = 250;
|
|
604337
604504
|
MIN_AUDIO_INTERVAL_MS = 1500;
|
|
604338
604505
|
LOW_LATENCY_AUDIO_INTERVAL_MS = 2e3;
|
|
604506
|
+
AUDIO_ACTIVITY_INTERVAL_MS = 200;
|
|
604507
|
+
AUDIO_ACTIVITY_SAMPLE_SEC = 0.2;
|
|
604339
604508
|
DEFAULT_CONFIG7 = {
|
|
604340
604509
|
videoEnabled: false,
|
|
604341
604510
|
audioEnabled: false,
|
|
@@ -604368,8 +604537,10 @@ var init_live_sensors = __esm({
|
|
|
604368
604537
|
snapshot;
|
|
604369
604538
|
videoTimer = null;
|
|
604370
604539
|
audioTimer = null;
|
|
604540
|
+
audioActivityTimer = null;
|
|
604371
604541
|
videoInFlight = false;
|
|
604372
604542
|
audioInFlight = false;
|
|
604543
|
+
audioActivityInFlight = false;
|
|
604373
604544
|
statusSink = null;
|
|
604374
604545
|
feedbackSink = null;
|
|
604375
604546
|
agentActionSink = null;
|
|
@@ -604580,10 +604751,7 @@ var init_live_sensors = __esm({
|
|
|
604580
604751
|
errors
|
|
604581
604752
|
};
|
|
604582
604753
|
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
|
-
}
|
|
604754
|
+
if (!this.config.selectedAudioInput) this.config.selectedAudioInput = preferredLiveAudioInputId(inputs.devices);
|
|
604587
604755
|
if (!this.config.selectedAudioOutput) this.config.selectedAudioOutput = firstDeviceId(outputs.devices);
|
|
604588
604756
|
this.persist();
|
|
604589
604757
|
return this.devices;
|
|
@@ -604943,7 +605111,8 @@ var init_live_sensors = __esm({
|
|
|
604943
605111
|
clipSummary = await this.recognizeFrameObjects(preview.framePath, source, sampledAt, { emit: false });
|
|
604944
605112
|
const current = this.snapshot.cameras?.[source];
|
|
604945
605113
|
if (current) {
|
|
604946
|
-
|
|
605114
|
+
const clipLine = formatClipDashboardSummary(clipSummary);
|
|
605115
|
+
current.summary = [cleanCameraSummaryForDashboard(current.summary), clipLine].filter(Boolean).join(" | ");
|
|
604947
605116
|
current.classifications = mergeCameraClassifications(
|
|
604948
605117
|
current.classifications,
|
|
604949
605118
|
classificationsFromClipSummary(clipSummary, sampledAt, preview.framePath)
|
|
@@ -604987,13 +605156,93 @@ ${output}`).join("\n\n");
|
|
|
604987
605156
|
this.videoInFlight = false;
|
|
604988
605157
|
}
|
|
604989
605158
|
}
|
|
605159
|
+
resolveAudioInput() {
|
|
605160
|
+
const selected = String(this.config.selectedAudioInput ?? "").trim();
|
|
605161
|
+
if (selected) return selected;
|
|
605162
|
+
const input = preferredLiveAudioInputId(this.devices.audioInputs) || "default";
|
|
605163
|
+
this.config.selectedAudioInput = input;
|
|
605164
|
+
this.persist();
|
|
605165
|
+
return input;
|
|
605166
|
+
}
|
|
605167
|
+
async previewAudioInput(device = this.config.selectedAudioInput) {
|
|
605168
|
+
const input = String(device || "").trim() || this.resolveAudioInput();
|
|
605169
|
+
ensureLiveDir(this.repoRoot);
|
|
605170
|
+
const recordingPath = join124(liveDir(this.repoRoot), `audio-preview-${Date.now()}.wav`);
|
|
605171
|
+
const capture = await recordAudioSampleWithRecovery(input, this.devices.audioInputs, 0.8, recordingPath, {
|
|
605172
|
+
allowFallback: false
|
|
605173
|
+
});
|
|
605174
|
+
const now2 = Date.now();
|
|
605175
|
+
const activity = capture.activity ?? (capture.ok ? readPcm16WavActivity(recordingPath) : void 0);
|
|
605176
|
+
if (capture.ok) {
|
|
605177
|
+
this.snapshot.audio = {
|
|
605178
|
+
...this.snapshot.audio ?? { updatedAt: now2 },
|
|
605179
|
+
updatedAt: now2,
|
|
605180
|
+
input,
|
|
605181
|
+
output: this.config.selectedAudioOutput,
|
|
605182
|
+
recordingPath,
|
|
605183
|
+
activity,
|
|
605184
|
+
error: void 0
|
|
605185
|
+
};
|
|
605186
|
+
this.persist();
|
|
605187
|
+
this.emitDashboard();
|
|
605188
|
+
const signal = capture.signalDetected === false ? "quiet/no clear mic signal" : "signal detected";
|
|
605189
|
+
return {
|
|
605190
|
+
ok: true,
|
|
605191
|
+
input,
|
|
605192
|
+
recordingPath,
|
|
605193
|
+
activity,
|
|
605194
|
+
message: [
|
|
605195
|
+
`Audio input preview from ${input}: ${signal}`,
|
|
605196
|
+
activity ? `activity ${activity.waveform} rms=${activity.rmsDb.toFixed(1)}dB active=${Math.round(activity.activeRatio * 100)}% peak=${activity.peak.toFixed(3)}` : "",
|
|
605197
|
+
`recording: ${recordingPath}`
|
|
605198
|
+
].filter(Boolean).join("\n")
|
|
605199
|
+
};
|
|
605200
|
+
}
|
|
605201
|
+
const message2 = `Audio input preview failed for ${input}: ${capture.errors.slice(0, 5).join(" | ") || "capture failed"}`;
|
|
605202
|
+
this.snapshot.audio = {
|
|
605203
|
+
...this.snapshot.audio ?? { updatedAt: now2 },
|
|
605204
|
+
updatedAt: now2,
|
|
605205
|
+
input,
|
|
605206
|
+
output: this.config.selectedAudioOutput,
|
|
605207
|
+
error: message2
|
|
605208
|
+
};
|
|
605209
|
+
this.persist();
|
|
605210
|
+
this.emitDashboard();
|
|
605211
|
+
return { ok: false, input, message: message2 };
|
|
605212
|
+
}
|
|
605213
|
+
async sampleAudioActivityNow() {
|
|
605214
|
+
if (!this.config.audioEnabled || this.audioActivityInFlight) return;
|
|
605215
|
+
this.audioActivityInFlight = true;
|
|
605216
|
+
const input = this.resolveAudioInput();
|
|
605217
|
+
try {
|
|
605218
|
+
ensureLiveDir(this.repoRoot);
|
|
605219
|
+
const recordingPath = join124(liveDir(this.repoRoot), "audio-activity.wav");
|
|
605220
|
+
const capture = await recordAudioSampleWithRecovery(input, this.devices.audioInputs, AUDIO_ACTIVITY_SAMPLE_SEC, recordingPath, {
|
|
605221
|
+
allowFallback: false,
|
|
605222
|
+
requireSignal: false
|
|
605223
|
+
});
|
|
605224
|
+
const now2 = Date.now();
|
|
605225
|
+
const activity = capture.activity ?? (capture.ok ? readPcm16WavActivity(recordingPath) : void 0);
|
|
605226
|
+
this.snapshot.audio = {
|
|
605227
|
+
...this.snapshot.audio ?? { updatedAt: now2 },
|
|
605228
|
+
updatedAt: now2,
|
|
605229
|
+
input,
|
|
605230
|
+
output: this.config.selectedAudioOutput,
|
|
605231
|
+
recordingPath,
|
|
605232
|
+
activity,
|
|
605233
|
+
error: capture.ok ? this.snapshot.audio?.error : `Audio activity capture failed from ${input}: ${capture.errors.slice(0, 3).join(" | ")}`
|
|
605234
|
+
};
|
|
605235
|
+
this.persist();
|
|
605236
|
+
this.emitDashboard();
|
|
605237
|
+
} finally {
|
|
605238
|
+
this.audioActivityInFlight = false;
|
|
605239
|
+
}
|
|
605240
|
+
}
|
|
604990
605241
|
async sampleAudioNow() {
|
|
604991
605242
|
if (this.audioInFlight) return "Audio sampler is already running.";
|
|
604992
605243
|
this.audioInFlight = true;
|
|
604993
605244
|
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;
|
|
605245
|
+
const input = this.resolveAudioInput();
|
|
604997
605246
|
if (this.isLiveAudioMutedForTts()) {
|
|
604998
605247
|
const now2 = Date.now();
|
|
604999
605248
|
this.snapshot.audio = {
|
|
@@ -605016,9 +605265,11 @@ ${output}`).join("\n\n");
|
|
|
605016
605265
|
let analysis = "";
|
|
605017
605266
|
let intake;
|
|
605018
605267
|
const audioErrors = [];
|
|
605019
|
-
const capture = await recordAudioSampleWithRecovery(input, this.devices.audioInputs, 3, recordingPath
|
|
605268
|
+
const capture = await recordAudioSampleWithRecovery(input, this.devices.audioInputs, 3, recordingPath, {
|
|
605269
|
+
allowFallback: false
|
|
605270
|
+
});
|
|
605020
605271
|
if (!capture.ok) {
|
|
605021
|
-
const message2 = `Audio capture failed from ${input}
|
|
605272
|
+
const message2 = `Audio capture failed from selected input ${input}: ${capture.errors.slice(0, 5).join(" | ")}`;
|
|
605022
605273
|
this.snapshot.audio = {
|
|
605023
605274
|
updatedAt: Date.now(),
|
|
605024
605275
|
input,
|
|
@@ -605035,12 +605286,9 @@ ${output}`).join("\n\n");
|
|
|
605035
605286
|
this.emitDashboard();
|
|
605036
605287
|
return message2;
|
|
605037
605288
|
}
|
|
605038
|
-
if (capture.device !== this.config.selectedAudioInput) {
|
|
605039
|
-
this.config.selectedAudioInput = capture.device;
|
|
605040
|
-
}
|
|
605041
605289
|
const activity = capture.activity ?? readPcm16WavActivity(recordingPath);
|
|
605042
605290
|
if (capture.ok && capture.signalDetected === false) {
|
|
605043
|
-
audioErrors.push(`No live input signal detected
|
|
605291
|
+
audioErrors.push(`No live input signal detected from selected input ${capture.device}; keeping the explicit selection.`);
|
|
605044
605292
|
}
|
|
605045
605293
|
if (this.config.asrEnabled) {
|
|
605046
605294
|
try {
|
|
@@ -605135,7 +605383,7 @@ ${output}`).join("\n\n");
|
|
|
605135
605383
|
}
|
|
605136
605384
|
this.emitDashboard();
|
|
605137
605385
|
return [
|
|
605138
|
-
`Audio sample captured from ${capture.device}
|
|
605386
|
+
`Audio sample captured from selected input ${capture.device}: ${recordingPath}`,
|
|
605139
605387
|
transcript ? `
|
|
605140
605388
|
ASR${asrBackend ? ` (${asrBackend})` : ""}:
|
|
605141
605389
|
${transcript}` : "",
|
|
@@ -605158,6 +605406,10 @@ ${analysis}` : ""
|
|
|
605158
605406
|
clearTimeout(this.audioTimer);
|
|
605159
605407
|
this.audioTimer = null;
|
|
605160
605408
|
}
|
|
605409
|
+
if (this.audioActivityTimer) {
|
|
605410
|
+
clearTimeout(this.audioActivityTimer);
|
|
605411
|
+
this.audioActivityTimer = null;
|
|
605412
|
+
}
|
|
605161
605413
|
}
|
|
605162
605414
|
scheduleVideoLoop(delayMs) {
|
|
605163
605415
|
if (!this.config.videoEnabled || this.videoTimer) return;
|
|
@@ -605194,6 +605446,22 @@ ${analysis}` : ""
|
|
|
605194
605446
|
}, Math.max(0, delayMs));
|
|
605195
605447
|
this.audioTimer.unref?.();
|
|
605196
605448
|
}
|
|
605449
|
+
scheduleAudioActivityLoop(delayMs) {
|
|
605450
|
+
if (!this.config.audioEnabled || this.audioActivityTimer) return;
|
|
605451
|
+
this.audioActivityTimer = setTimeout(async () => {
|
|
605452
|
+
const startedAt2 = Date.now();
|
|
605453
|
+
this.audioActivityTimer = null;
|
|
605454
|
+
if (!this.config.audioEnabled) return;
|
|
605455
|
+
try {
|
|
605456
|
+
await this.sampleAudioActivityNow();
|
|
605457
|
+
} catch {
|
|
605458
|
+
} finally {
|
|
605459
|
+
const elapsedMs2 = Date.now() - startedAt2;
|
|
605460
|
+
if (this.config.audioEnabled) this.scheduleAudioActivityLoop(Math.max(0, AUDIO_ACTIVITY_INTERVAL_MS - elapsedMs2));
|
|
605461
|
+
}
|
|
605462
|
+
}, Math.max(0, delayMs));
|
|
605463
|
+
this.audioActivityTimer.unref?.();
|
|
605464
|
+
}
|
|
605197
605465
|
ensureLoops() {
|
|
605198
605466
|
if (this.config.videoEnabled && !this.videoTimer) {
|
|
605199
605467
|
this.scheduleVideoLoop(0);
|
|
@@ -605208,6 +605476,12 @@ ${analysis}` : ""
|
|
|
605208
605476
|
clearTimeout(this.audioTimer);
|
|
605209
605477
|
this.audioTimer = null;
|
|
605210
605478
|
}
|
|
605479
|
+
if (this.config.audioEnabled && !this.audioActivityTimer) {
|
|
605480
|
+
this.scheduleAudioActivityLoop(0);
|
|
605481
|
+
} else if (!this.config.audioEnabled && this.audioActivityTimer) {
|
|
605482
|
+
clearTimeout(this.audioActivityTimer);
|
|
605483
|
+
this.audioActivityTimer = null;
|
|
605484
|
+
}
|
|
605211
605485
|
}
|
|
605212
605486
|
emitStatus() {
|
|
605213
605487
|
this.statusSink?.({
|
|
@@ -657472,7 +657746,15 @@ async function showLiveMenu(ctx3, manager) {
|
|
|
657472
657746
|
}
|
|
657473
657747
|
case "audio-input": {
|
|
657474
657748
|
const device = await chooseLiveDevice(ctx3, "Select Audio Input", devices.audioInputs, cfg.selectedAudioInput);
|
|
657475
|
-
if (device)
|
|
657749
|
+
if (device) {
|
|
657750
|
+
manager.configure({ selectedAudioInput: device.id, audioEnabled: true });
|
|
657751
|
+
renderInfo(`Selected audio input: ${device.id}
|
|
657752
|
+
Previewing microphone activity...`);
|
|
657753
|
+
const preview = await manager.previewAudioInput(device.id);
|
|
657754
|
+
if (preview.ok) renderInfo(preview.message);
|
|
657755
|
+
else renderWarning(preview.message);
|
|
657756
|
+
renderLiveDashboard(ctx3, manager);
|
|
657757
|
+
}
|
|
657476
657758
|
continue;
|
|
657477
657759
|
}
|
|
657478
657760
|
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.417",
|
|
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.417",
|
|
10
10
|
"bundleDependencies": [
|
|
11
11
|
"image-to-ascii"
|
|
12
12
|
],
|
package/package.json
CHANGED