Files
root 95bb7c50ee feat: point the fleet at wss LiveKit room uwh-telhai
Publish and subscribe over wss://livekit.uni-wh.de:7800 and refuse
cleartext ws://. Conference room is uwh-telhai. Includes the uncommitted
encoded H.264 publish path, Rally hairpin, and KMS wall overlay.
2026-10-11 00:48:50 +00:00

64 lines
2.0 KiB
Python

"""Pin Logitech C920 exposure so 360p stays 30 fps.
Aperture-priority + exposure_dynamic_framerate=1 lets the sensor sit at
~66 ms / gain 255 and drop to 15 fps. Manual 333 (0.1 ms units = 1/30 s)
with dyn-fps off holds the gst 30 fps request.
"""
from __future__ import annotations
import logging
import os
import subprocess
log = logging.getLogger("cameras.uvc-exposure")
# UVC: 1 = Manual Mode, 3 = Aperture Priority. Time unit is 0.1 ms.
AUTO_EXPOSURE_MANUAL = 1
EXPOSURE_TIME_30FPS = 333
def pin_cmd(
device: str,
*,
auto_exposure: int = AUTO_EXPOSURE_MANUAL,
exposure_time: int = EXPOSURE_TIME_30FPS,
dynamic_framerate: int = 0,
) -> list[str]:
cmd = [
"v4l2-ctl",
"-d",
str(device),
f"--set-ctrl=auto_exposure={int(auto_exposure)}",
f"--set-ctrl=exposure_dynamic_framerate={int(dynamic_framerate)}",
]
# Time is inactive under aperture-priority (3); setting it fails the whole pin.
if int(auto_exposure) == AUTO_EXPOSURE_MANUAL:
cmd.insert(4, f"--set-ctrl=exposure_time_absolute={int(exposure_time)}")
return cmd
def pin_from_env() -> tuple[int, int, int]:
ae = int(os.environ.get("VIDEO_AUTO_EXPOSURE", str(AUTO_EXPOSURE_MANUAL)))
exp = int(os.environ.get("VIDEO_EXPOSURE_TIME", str(EXPOSURE_TIME_30FPS)))
dyn = int(os.environ.get("VIDEO_EXPOSURE_DYNAMIC", "0"))
return ae, exp, dyn
def pin_c920_exposure(device: str) -> None:
ae, exp, dyn = pin_from_env()
cmd = pin_cmd(device, auto_exposure=ae, exposure_time=exp, dynamic_framerate=dyn)
try:
r = subprocess.run(cmd, capture_output=True, text=True, timeout=5)
except OSError as exc:
log.warning("pin %s failed: %s", device, exc)
return
if r.returncode:
log.warning("pin %s rc=%s %s", device, r.returncode, (r.stderr or "").strip())
return
log.info("pinned %s ae=%s time=%s dynfps=%s", device, ae, exp, dyn)
def pin_devices(devices: list[str]) -> None:
for dev in devices:
pin_c920_exposure(dev)