# LiveKit server connection # Remote LiveKit. Local livekit-server.service is disabled. # Signaling must be wss://. The client verifies the TLS cert (do not use ws://). LIVEKIT_URL=wss://livekit.uni-wh.de:7800 LIVEKIT_API_KEY=APIKey_xxx LIVEKIT_API_SECRET=APIsecret_xxx # Room / naming # Conference room. Publishers and the KMS wall must use this same name. LIVEKIT_ROOM=uwh-telhai PARTICIPANT_PREFIX=cam # Published on local camera participants as LiveKit attributes tag/tags. PARTICIPANT_TAGS=uwh # Display wall: empty = show local cameras (filter OFF). Set to uwh to hide # local tagged participants so remotes fill the wall instead. DISPLAY_HIDE_TAGS= # Streams # "all" = every discovered camera, "1,3,5" or "0-19" = subset CAMERAS=all VIDEO_WIDTH=640 VIDEO_HEIGHT=360 VIDEO_FPS=30 VIDEO_MIN_FPS=5 VIDEO_BITRATE=1200000 # Rally 1080p encode (bps). Rollback if encode/gst dies: 12000000 then restart cameras. VIDEO_RALLY_BITRATE=20000000 VIDEO_CODEC=h264 VIDEO_ENCODER=vaapi LIBVA_DRM_DEVICE=/dev/dri/renderD129 LIBVA_DRIVER_NAME=iHD # Audio AUDIO_SAMPLE_RATE=16000 AUDIO_CHANNELS=1 # Audio cleanup (speechbrain) # mode: auto (default: enhanced if the model is cached, otherwise passthrough) # force (always enhance), off (always passthrough) ENHANCE_MODE=auto # speechbrain model repo (must be 16 kHz; metricGAN-plus runs ~20-40ms/frame on CPU) ENHANCE_MODEL=speechbrain/metricgan-plus-voicebank # model window vs publish hop: 1 s context, 100 ms emit ENHANCE_CHUNK_S=1.0 ENHANCE_HOP_S=0.1 # MetricGAN mask: auto (OpenVINO CPU, Torch fallback) | openvino | torch ENHANCE_INFER=auto # C920 stereo Delay-and-Sum (SpeechBrain GCC-PHAT) before MetricGAN # auto (default): beamform if speechbrain loads, else average channels # force: require DelaySum_Beamformer, off: average L/R BEAMFORM_MODE=auto # One BLAS/Torch thread per worker (20 workers vs 28 cores) TORCH_NUM_THREADS=1 # Recompute GCC-PHAT TDOA every N hops (5 * hop) BEAMFORM_TDOA_EVERY=5 # One MetricGAN process for all cameras (workers send hops over a unix socket). # ENHANCE_DAEMON=0 reverts to per-worker model load (~10 GiB extra RAM). ENHANCE_DAEMON=1 ENHANCE_SOCKET=/tmp/livekit-enhance.sock # --- optional latency knobs (defaults keep current behavior) --- # AUDIO_QUEUE_MS=60 # LiveKit AudioSource queue; unset = max(150, hop_ms+50) # VIDEO_HOLD_S=0 # hold published video this many seconds; unset = match hop; 0 = no hold # WORKER_SPLIT_EXECUTOR=1 # dedicated thread pools: ffmpeg reads vs enhance # ENHANCE_SPEAKER_ONLY=1 # MetricGAN+beamform only on DISPLAY_SPEAKER_CAMERA (rally) # AUDIO_GATE=1 # optional hop mute; off by default so two talkers both publish # AUDIO_GATE_OPEN_DB=-28 # AUDIO_GATE_CLOSE_DB=-34 # AUDIO_GATE_HOLD_S=0.3 # DISPLAY_VIDEO_CAPACITY=1 # VideoStream ring; 0 = unbounded, 1 = latest frame # DISPLAY_VIDEO_FORMAT=bgra # request BGRA from SDK (skip extra convert) # DISPLAY_GST_QUEUE_BUFFERS=1 # DISPLAY_SPEAKER_PUSH=arrival # timer | arrival (push speaker pane on decode) # # Suggested A/B (wall, ~hop 50 ms, speaker-only enhance): # ENHANCE_HOP_S=0.05 AUDIO_QUEUE_MS=60 WORKER_SPLIT_EXECUTOR=1 # ENHANCE_SPEAKER_ONLY=1 DISPLAY_VIDEO_CAPACITY=1 DISPLAY_VIDEO_FORMAT=bgra # DISPLAY_GST_QUEUE_BUFFERS=1 DISPLAY_SPEAKER_PUSH=arrival # Aggressive (no neural enhance, 20 ms hops): # ENHANCE_MODE=off BEAMFORM_MODE=off ENHANCE_HOP_S=0.02 AUDIO_QUEUE_MS=40 VIDEO_HOLD_S=0 # Misc PUBLISH_TIMEOUT_S=60 LOG_LEVEL=INFO # Headless display wall (run_displays.py / livekit-displays.service) # 3 DRM roles: 20-cam grid, designated speaker camera, screenshare STUB DISPLAY_COUNT=3 DISPLAY_ROLES=grid,speaker,screenshare # Empty = auto (connected heads first, prefer Arc HDMI-A-*) DISPLAY_CONNECTORS= DISPLAY_IDENTITY=display-wall # Speaker HDMI pane: LiveKit identity of the Logitech Rally (not a C920). # The Rally is not on this host yet — pane shows a placeholder until `rally` joins. DISPLAY_SPEAKER_CAMERA=rally DISPLAY_GRID_COLS=5 DISPLAY_GRID_ROWS=4 DISPLAY_GRID_WIDTH=1920 DISPLAY_GRID_HEIGHT=1080 DISPLAY_GRID_FPS=30 # Yellow tile border when a participant raises a hand (MoveNet on the wall). # DISPLAY_HAND_RAISE=0 to disable. Displays-only restart. DISPLAY_HAND_RAISE=1 DISPLAY_HAND_RAISE_HZ=4 DISPLAY_HAND_RAISE_HOLD_S=1.0 # DISPLAY_HAND_RAISE_MODEL=thunder # thunder (256) or lightning (192); displays-only # Green speaker chrome: LiveKit candidates, hop RMS picks louder vs two talkers. # DISPLAY_SPEAK_MIN_DB=-40 # DISPLAY_SPEAK_RISE_DB=3 # DISPLAY_SPEAK_MARGIN_DB=6 # DISPLAY_SPEAK_HOLD_S=0.6 # DISPLAY_SPEAK_CORR=0.6 # hop xcorr; similar waveforms = bleed, keep louder # DISPLAY_SPEAK_CONFIRM=2 # consecutive hops before a new seat greens # Screen share is a stub until production LiveKit is online. LIVEKIT_PUBLIC_URL= # Person-aware background blur on C920 publish (OpenVINO CPU, not iGPU/Arc). # Empty seats passthrough. Rally is not blurred. Rollback: PORTRAIT_BLUR=0 then # cameras-only restart. PORTRAIT_BLUR=1 # PORTRAIT_HZ=8 # PORTRAIT_BLUR_PX=7 # PORTRAIT_HOLD_S=0.8 # PORTRAIT_SHM_DIR=/run/livekit-cameras/portrait