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.
This commit is contained in:
@@ -0,0 +1,199 @@
|
||||
"""Green speaking chrome on the KMS grid (LiveKit active-speaker)."""
|
||||
import numpy as np
|
||||
|
||||
from display_grid import FRAME_RAISE, FRAME_SPEAK, CameraGrid, bgra_to_i420, bgra_to_yuv_pixel
|
||||
|
||||
|
||||
def test_set_speakers_paints_green_i420_border():
|
||||
g = CameraGrid(width=1920, height=1080, cols=5, rows=4)
|
||||
src = np.zeros((360, 640, 4), dtype=np.uint8)
|
||||
src[:] = (40, 40, 40, 255)
|
||||
g.set_frame_i420("cam-07", bgra_to_i420(src), 640, 360)
|
||||
before = np.frombuffer(g.render_i420(), dtype=np.uint8).copy()
|
||||
g.set_speakers(["cam-07"])
|
||||
assert g.speaking("cam-07") is True
|
||||
after = np.frombuffer(g.render_i420(), dtype=np.uint8)
|
||||
assert not np.array_equal(before, after)
|
||||
idx = g.identities.index("cam-07")
|
||||
ox, oy = g.tile_origin(idx)
|
||||
yplane = after[: g.width * g.height].reshape(g.height, g.width)
|
||||
yv, _, _ = bgra_to_yuv_pixel(FRAME_SPEAK)
|
||||
assert int(yplane[oy, ox + g.tile_w // 2]) == yv
|
||||
# Extra thickness lives in the gutter, not on the feed.
|
||||
assert int(yplane[oy - 2, ox + g.tile_w // 2]) == yv
|
||||
ix, iy, iw, _ih = g.inner_rect(idx)
|
||||
assert int(yplane[iy, ix + iw // 2]) != yv
|
||||
|
||||
|
||||
def test_speaking_overrides_yellow_then_yellow_returns():
|
||||
g = CameraGrid(width=1920, height=1080, cols=5, rows=4)
|
||||
src = np.zeros((360, 640, 4), dtype=np.uint8)
|
||||
g.set_frame_i420("cam-07", bgra_to_i420(src), 640, 360)
|
||||
g.set_highlight("cam-07", True)
|
||||
g.set_speakers(["cam-07"])
|
||||
idx = g.identities.index("cam-07")
|
||||
ox, oy = g.tile_origin(idx)
|
||||
yplane = np.frombuffer(g.render_i420(), dtype=np.uint8)[: g.width * g.height].reshape(
|
||||
g.height, g.width)
|
||||
y_speak, _, _ = bgra_to_yuv_pixel(FRAME_SPEAK)
|
||||
y_raise, _, _ = bgra_to_yuv_pixel(FRAME_RAISE)
|
||||
assert int(yplane[oy, ox + g.tile_w // 2]) == y_speak
|
||||
g.set_speakers([])
|
||||
yplane = np.frombuffer(g.render_i420(), dtype=np.uint8)[: g.width * g.height].reshape(
|
||||
g.height, g.width)
|
||||
assert g.speaking("cam-07") is False
|
||||
assert g.highlighted("cam-07") is True
|
||||
assert int(yplane[oy, ox + g.tile_w // 2]) == y_raise
|
||||
|
||||
|
||||
def test_clear_drops_speaking():
|
||||
g = CameraGrid(width=1920, height=1080, cols=5, rows=4)
|
||||
src = np.zeros((360, 640, 4), dtype=np.uint8)
|
||||
g.set_frame_i420("cam-01", bgra_to_i420(src), 640, 360)
|
||||
g.set_speakers(["cam-01"])
|
||||
g.clear("cam-01")
|
||||
assert g.speaking("cam-01") is False
|
||||
|
||||
|
||||
class _P:
|
||||
def __init__(self, identity, keep=True):
|
||||
self.identity = identity
|
||||
self.keep = keep
|
||||
|
||||
|
||||
def test_active_speaker_ids_keeps_order_and_filter():
|
||||
from display_grid import active_speaker_ids, primary_grid_speaker
|
||||
speakers = [_P("cam-07"), _P("rally", False), _P("cam-03"), _P("")]
|
||||
assert active_speaker_ids(speakers, want=lambda p: p.keep) == ["cam-07", "cam-03"]
|
||||
ids = ["rally", "cam-03", "cam-07"]
|
||||
assert primary_grid_speaker(ids, ["cam-01", "cam-03", "cam-07"]) == ["cam-03"]
|
||||
assert primary_grid_speaker(["rally"], ["cam-01"]) == []
|
||||
|
||||
|
||||
def test_select_grid_speakers_drops_floor_noise():
|
||||
from display_grid import select_grid_speakers
|
||||
assert select_grid_speakers(
|
||||
[("cam-01", -34.0), ("cam-02", -36.0)], min_db=-24.0, margin_db=6.0,
|
||||
) == []
|
||||
|
||||
|
||||
def test_select_grid_speakers_bleed_keeps_louder_only():
|
||||
from display_grid import select_grid_speakers
|
||||
assert select_grid_speakers(
|
||||
[("cam-07", -12.0), ("cam-08", -22.0)], min_db=-24.0, margin_db=6.0,
|
||||
) == ["cam-07"]
|
||||
|
||||
|
||||
def test_select_grid_speakers_two_talkers_both_kept():
|
||||
from display_grid import select_grid_speakers
|
||||
assert select_grid_speakers(
|
||||
[("cam-07", -12.0), ("cam-08", -14.0)], min_db=-24.0, margin_db=6.0,
|
||||
) == ["cam-07", "cam-08"]
|
||||
|
||||
|
||||
def test_select_grid_speakers_normal_speech_above_mic_floor():
|
||||
"""Conversational C920 speech is often ~-24 dBFS; absolute -20 missed it."""
|
||||
from display_grid import select_grid_speakers
|
||||
floors = {"cam-07": -34.0, "cam-08": -34.0}
|
||||
assert select_grid_speakers(
|
||||
[("cam-07", -24.0), ("cam-08", -33.0)],
|
||||
min_db=-40.0, margin_db=6.0, floors=floors, rise_db=6.0,
|
||||
) == ["cam-07"]
|
||||
|
||||
|
||||
def test_select_grid_speakers_two_talkers_each_above_own_floor():
|
||||
from display_grid import select_grid_speakers
|
||||
floors = {"cam-07": -34.0, "cam-08": -36.0}
|
||||
assert select_grid_speakers(
|
||||
[("cam-07", -24.0), ("cam-08", -26.0)],
|
||||
min_db=-40.0, margin_db=6.0, floors=floors, rise_db=6.0,
|
||||
) == ["cam-07", "cam-08"]
|
||||
|
||||
|
||||
def test_select_quiet_mic_speech_not_cut_by_abs_min():
|
||||
"""Quiet C920 idle is ~-45; +3 dB speech is still below -40 dBFS."""
|
||||
from display_grid import select_grid_speakers
|
||||
floors = {"cam-10": -45.0, "cam-01": -37.0}
|
||||
assert select_grid_speakers(
|
||||
[("cam-10", -41.5), ("cam-01", -36.5)],
|
||||
min_db=-40.0, margin_db=6.0, floors=floors, rise_db=3.0,
|
||||
) == ["cam-10"]
|
||||
|
||||
|
||||
def test_update_noise_floor_tracks_idle_not_speech():
|
||||
from display_grid import update_noise_floor
|
||||
fl = update_noise_floor(-34.0, -33.5, speaking=False, rise_db=4.0)
|
||||
assert -34.0 < fl < -33.5
|
||||
stuck = update_noise_floor(-34.0, -20.0, speaking=True, rise_db=4.0)
|
||||
assert stuck == -34.0
|
||||
|
||||
|
||||
def test_confirm_speakers_needs_two_hops_new_talker():
|
||||
from display_grid import confirm_speakers
|
||||
first, counts = confirm_speakers({}, ["cam-07"], need=2)
|
||||
assert first == []
|
||||
second, counts = confirm_speakers(counts, ["cam-07"], need=2)
|
||||
assert second == ["cam-07"]
|
||||
# already on: one hop of continued speech keeps chrome
|
||||
stay, _ = confirm_speakers(counts, ["cam-07"], need=2, already=["cam-07"])
|
||||
assert stay == ["cam-07"]
|
||||
# a one-hop idle spike on another seat does not light
|
||||
spike, _ = confirm_speakers({}, ["cam-01"], need=2, already=["cam-07"])
|
||||
assert spike == []
|
||||
|
||||
|
||||
def test_waveform_similarity_high_for_delayed_copy():
|
||||
from display_grid import waveform_similarity
|
||||
t = np.linspace(0, 1, 1600, endpoint=False)
|
||||
a = np.sin(2 * np.pi * 220 * t).astype(np.float32)
|
||||
b = np.roll(a * 0.4, 80)
|
||||
assert waveform_similarity(a, b) > 0.85
|
||||
|
||||
|
||||
def test_waveform_similarity_low_for_independent_signals():
|
||||
from display_grid import waveform_similarity
|
||||
rng = np.random.default_rng(0)
|
||||
a = rng.normal(size=1600).astype(np.float32)
|
||||
b = rng.normal(size=1600).astype(np.float32)
|
||||
assert waveform_similarity(a, b) < 0.35
|
||||
|
||||
|
||||
def test_collapse_bleed_drops_similar_quieter_mic():
|
||||
from display_grid import collapse_bleed
|
||||
t = np.linspace(0, 1, 1600, endpoint=False)
|
||||
src = np.sin(2 * np.pi * 180 * t).astype(np.float32)
|
||||
waves = {"cam-07": src, "cam-08": np.roll(src * 0.3, 40)}
|
||||
levels = {"cam-07": -12.0, "cam-08": -18.0}
|
||||
assert collapse_bleed(["cam-07", "cam-08"], waves, levels, corr_min=0.4) == ["cam-07"]
|
||||
|
||||
|
||||
def test_collapse_bleed_keeps_two_unlike_talkers():
|
||||
from display_grid import collapse_bleed
|
||||
t = np.linspace(0, 1, 1600, endpoint=False)
|
||||
a = np.sin(2 * np.pi * 180 * t).astype(np.float32)
|
||||
b = np.sin(2 * np.pi * 440 * t + 1.3).astype(np.float32)
|
||||
waves = {"cam-07": a, "cam-08": b}
|
||||
levels = {"cam-07": -12.0, "cam-08": -13.0}
|
||||
assert collapse_bleed(["cam-07", "cam-08"], waves, levels, corr_min=0.6) == [
|
||||
"cam-07", "cam-08",
|
||||
]
|
||||
|
||||
|
||||
def test_hold_speakers_adds_second_talker_immediately():
|
||||
from display_grid import hold_speakers
|
||||
cur, until = hold_speakers(
|
||||
["cam-07"], ["cam-07", "cam-08"], prev_peak=-12.0, new_peak=-12.0,
|
||||
now=10.0, hold_until=10.5, hold_s=0.6, switch_db=3.0)
|
||||
assert cur == ["cam-07", "cam-08"]
|
||||
|
||||
|
||||
def test_hold_speakers_ignores_similar_bleed_flicker():
|
||||
from display_grid import hold_speakers
|
||||
cur, until = hold_speakers(
|
||||
["cam-07"], ["cam-08"], prev_peak=-12.0, new_peak=-12.5,
|
||||
now=10.2, hold_until=10.8, hold_s=0.6, switch_db=3.0)
|
||||
assert cur == ["cam-07"]
|
||||
cur, _ = hold_speakers(
|
||||
["cam-07"], ["cam-08"], prev_peak=-12.0, new_peak=-8.0,
|
||||
now=10.2, hold_until=10.8, hold_s=0.6, switch_db=3.0)
|
||||
assert cur == ["cam-08"]
|
||||
Reference in New Issue
Block a user