From 30b128bc9e75879d1730200cd52ef2e089063551 Mon Sep 17 00:00:00 2001 From: Hermes Date: Fri, 28 Aug 2026 05:21:36 +0000 Subject: [PATCH] docs: serial identity, enhance hop/window, optional systemd unit --- README.md | 41 ++++++++++++++++++++++++++++------ deploy/livekit-cameras.service | 16 +++++++++++++ 2 files changed, 50 insertions(+), 7 deletions(-) create mode 100644 deploy/livekit-cameras.service diff --git a/README.md b/README.md index cd2af44..07fff6a 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,9 @@ publishes: - a camera video track (1280x720 @ 30 fps by default, MJPG from V4L2) - a microphone audio track (16 kHz mono, cleaned with speechbrain) +Identity is the USB serial, pinned by udev (`/dev/camNN` + `slots.json`). +`--cameras 1,5` means participants `cam-01` and `cam-05`, not discovery order. + ## Layout ``` @@ -20,6 +23,9 @@ config.py .env / environment configuration prefetch_model.py one-time speechbrain model download generate_udev_rules.py (re)generate udev pinning + slots.json from live state slots.json stable slot map: cam-NN -> USB serial, /dev/camNN, ALSA card +smoke_test.py one-camera LiveKit publish with enhancement ON +scripts/bench_enhance.py RTF bench (1 s window / 200 ms hop) +deploy/livekit-cameras.service optional systemd unit (do not enable blindly) ``` ## Setup @@ -52,6 +58,9 @@ sudo udevadm trigger --subsystem-match=video4linux --action=add sudo udevadm trigger --subsystem-match=sound --action=add ``` +The generator bakes the **current physical wiring** as canonical. Do not +re-run `--write` unless you intend to remap slots. + ## Run ```bash @@ -62,11 +71,28 @@ sudo udevadm trigger --subsystem-match=sound --action=add ## Audio cleanup -The mic audio is cleaned per chunk (default 200 ms) by -`speechbrain/metricgan-plus-voicebank` (16 kHz, CPU). One worker process per -camera loads the model once and reuses it; on this 28-core box all 20 stay -real-time. `ENHANCE_MODE=off` (or a failed model load with `auto`) falls back -to a lightweight high-pass + soft-clip DSP path so streams still work. +The mic audio is cleaned per hop (default 200 ms) by +`speechbrain/metricgan-plus-voicebank` (16 kHz, CPU) over a 1 s rolling +window (`ENHANCE_CHUNK_S=1.0`, `ENHANCE_HOP_S=0.2`). One worker process +per camera loads the model once and reuses it. `enhance_batch` must be +called with `lengths=torch.tensor([1.0])` (relative, not sample count). +`ENHANCE_MODE=off` (or a failed model load with `auto`) falls back to a +lightweight high-pass + soft-clip DSP path so streams still work. + +Until the 1 s window is full, hops use the DSP fallback so LiveKit is +not silent on startup. + +## systemd (optional, not enabled) + +```bash +sudo cp deploy/livekit-cameras.service /etc/systemd/system/ +sudo systemctl daemon-reload +# only if you want 24/7: +sudo systemctl enable --now livekit-cameras +``` + +Requires a LiveKit server already listening (this host uses +`/tmp/livekit-server --config /tmp/livekit-test.yaml` on :7880). ## Notes @@ -74,6 +100,7 @@ to a lightweight high-pass + soft-clip DSP path so streams still work. -input_format mjpeg`) — cheap, and converts to BGRA for LiveKit. - Audio: ALSA mics on these C920s deliver 16 kHz **stereo** only; the worker downmixes to mono for LiveKit. -- Camera <-> card pairing is resolved by matching USB port paths under /sys, - so each mic belongs to its own camera. +- Camera identity is USB serial via `slots.json` / udev; USB port is + fallback only for cameras not yet in the map. - Workers auto-restart (up to 10 times) if a camera drops. +- Local smoke: `.venv/bin/python smoke_test.py` (needs livekit-server on 7880). diff --git a/deploy/livekit-cameras.service b/deploy/livekit-cameras.service new file mode 100644 index 0000000..9ad0f05 --- /dev/null +++ b/deploy/livekit-cameras.service @@ -0,0 +1,16 @@ +[Unit] +Description=Publish C920 cameras (speechbrain audio) to LiveKit +After=network-online.target sound.target +Wants=network-online.target + +[Service] +Type=simple +WorkingDirectory=/home/fdenkena/livekit-cameras +ExecStart=/home/fdenkena/livekit-cameras/.venv/bin/python /home/fdenkena/livekit-cameras/run.py +Restart=on-failure +RestartSec=5 +Environment=PYTHONUNBUFFERED=1 +Environment=LIVEKIT_URL=ws://127.0.0.1:7880 + +[Install] +WantedBy=multi-user.target