Mimir/scripts/live_status.py
2026-05-19 01:06:23 +01:00

193 lines
7.2 KiB
Python

import json
from pathlib import Path
import sys
import time
ROOT = Path(__file__).resolve().parents[1]
if str(ROOT) not in sys.path:
sys.path.insert(0, str(ROOT))
def read_json(path: Path):
if not path.exists():
return None
return json.loads(path.read_text(encoding="utf-8"))
def read_last_jsonl(path: Path):
if not path.exists():
return None
lines = [line for line in path.read_text(encoding="utf-8").splitlines() if line.strip()]
if not lines:
return None
return json.loads(lines[-1])
def msgpack_head(path: Path):
if not path.exists():
return None
import msgpack
outer = msgpack.unpackb(path.read_bytes(), raw=False)
if not outer:
return None
payload = msgpack.unpackb(outer[0]["payload"], raw=False)
head = payload[:8] if isinstance(payload, list) else payload
summary = {
"key": outer[0].get("key"),
"type": outer[0].get("type"),
"storedAt": outer[0].get("storedAt"),
}
if not isinstance(payload, list):
summary["payload"] = str(payload)[:120]
return summary
summary["schema"] = payload[0] if payload else None
if summary["type"] == "localcast.visual.render_frame":
points = payload[10] if len(payload) > 10 else []
point_prefix_counts = {}
for point in points:
prefix = str(point[0]).split(":", 1)[0]
point_prefix_counts[prefix] = point_prefix_counts.get(prefix, 0) + 1
summary.update(
{
"frameId": payload[1],
"presentTimeNs": payload[5],
"audioAlignmentTimeNs": payload[6],
"pointCount": len(points),
"pointPrefixCounts": dict(sorted(point_prefix_counts.items())),
}
)
elif summary["type"] == "localcast.audio.spatial_frame":
summary.update(
{
"frameId": payload[1],
"audioTimeNs": payload[3],
"sampleRate": payload[4],
"startSample": payload[5],
"frameCount": payload[6],
"channels": payload[9] if len(payload) > 9 else [],
}
)
elif summary["type"] == "localcast.audio.source_events":
summary.update(
{
"frameId": payload[1],
"sampleRate": payload[3],
"startSample": payload[4],
"frameCount": payload[5],
"eventCount": len(payload[6]) if len(payload) > 6 else 0,
"focusCount": len(payload[7]) if len(payload) > 7 else 0,
}
)
elif summary["type"] == "localcast.audio.phase_field":
sources = payload[7] if len(payload) > 7 else []
summary.update(
{
"frameId": payload[1],
"sampleRate": payload[3],
"startSample": payload[4],
"frameCount": payload[5],
"referenceId": payload[6],
"sourceCount": len(sources),
"globalConfidence": payload[8] if len(payload) > 8 else 0.0,
"needsActiveProbe": payload[9] if len(payload) > 9 else True,
"sources": [
{
"sourceId": source.get("sourceId"),
"delayMs": source.get("delayMs"),
"distanceDeltaMeters": source.get("distanceDeltaMeters"),
"coherence": source.get("coherence"),
"fitErrorRadians": source.get("fitErrorRadians"),
"confidence": source.get("confidence"),
"referenceBleed": source.get("referenceBleed"),
"suppressionWeight": source.get("suppressionWeight"),
}
for source in sources
],
}
)
elif summary["type"] == "localcast.audio.mic_field":
summary.update(
{
"frameId": payload[1],
"audioTimeNs": payload[3],
"sampleRate": payload[4],
"startSample": payload[5],
"frameCount": payload[6],
"channels": payload[7] if len(payload) > 7 else [],
"graphId": payload[9] if len(payload) > 9 else "",
}
)
elif summary["type"] in ("localcast.visual.stream_status", "localcast.audio.stream_status"):
summary["payloadHead"] = head
elif summary["type"] == "localcast.calibration.clap_events":
summary.update(
{
"frameId": payload[1],
"eventCount": len(payload[3]) if len(payload) > 3 else 0,
"latestEvent": None
if len(payload) <= 3 or not payload[3]
else {
"stableKey": payload[3][-1][0],
"positionM": payload[3][-1][1],
"acousticOracleNs": payload[3][-1][2],
"visualObservedNs": payload[3][-1][3],
"timingUncertaintyUs": payload[3][-1][4],
"cameraCount": len(payload[3][-1][7]) if len(payload[3][-1]) > 7 else 0,
"cameraOffsetsNs": {
str(peak.get("sensorId")): int(payload[3][-1][2]) - int(peak.get("timestampNs", payload[3][-1][2]))
for peak in (payload[3][-1][7] if len(payload[3][-1]) > 7 else [])
},
},
}
)
return summary
def file_freshness(path: Path, now: float) -> dict:
if not path.exists():
return {"exists": False}
age = max(0.0, now - path.stat().st_mtime)
return {"exists": True, "ageSeconds": age, "bytes": path.stat().st_size}
def main() -> None:
runs = ROOT / "calibration" / "runs"
now = time.time()
files = {
name: file_freshness(runs / name, now)
for name in [
"visual-state.msgpack",
"audio-state.msgpack",
"audio-events.msgpack",
"visual-stream-status.msgpack",
"audio-stream-status.msgpack",
"audio-phase-field.msgpack",
"audio-phase-field-status.json",
"audio-mic-field.msgpack",
"clap-events.msgpack",
"active-probes/active-probes.jsonl",
"visual-lod-cache.json",
"stream-spout-status.json",
"av-sync-status.json",
]
}
payload = {
"createdWallTime": time.strftime("%Y-%m-%dT%H:%M:%S%z"),
"files": files,
"avSync": read_json(runs / "av-sync-status.json"),
"spout": read_json(runs / "stream-spout-status.json"),
"visualHead": msgpack_head(runs / "visual-state.msgpack"),
"audioHead": msgpack_head(runs / "audio-state.msgpack"),
"eventsHead": msgpack_head(runs / "audio-events.msgpack"),
"phaseFieldHead": msgpack_head(runs / "audio-phase-field.msgpack"),
"phaseRuntime": read_json(runs / "audio-phase-field-status.json"),
"micFieldHead": msgpack_head(runs / "audio-mic-field.msgpack"),
"clapHead": msgpack_head(runs / "clap-events.msgpack"),
"lastActiveProbe": read_last_jsonl(runs / "active-probes" / "active-probes.jsonl"),
}
print(json.dumps(payload, indent=2, default=str))
if __name__ == "__main__":
main()