From d263740557a9cdbf45469bf9eada1b2302e19016 Mon Sep 17 00:00:00 2001 From: "russell@unturf.com" Date: Fri, 5 Jun 2026 14:14:24 -0400 Subject: [PATCH] zebra-spaces: deploy duplicate-publisher audio dedup --- zebra-report/zebra-spaces.html | 30 ++++++++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/zebra-report/zebra-spaces.html b/zebra-report/zebra-spaces.html index 9d23ccb..9fea2d1 100644 --- a/zebra-report/zebra-spaces.html +++ b/zebra-report/zebra-spaces.html @@ -2965,9 +2965,35 @@ function attachAudioStreamViaWorklet(uuid, stream, targetSeconds){ if (existing){ try { existing.src.disconnect(); } catch(_){} try { if (existing.jbuf) existing.jbuf.disconnect(); } catch(_){} + try { if (existing.capture) existing.capture.disconnect(); } catch(_){} + try { if (existing.captureLpf) existing.captureLpf.disconnect(); } catch(_){} try { existing.gain.disconnect(); } catch(_){} listenerAudioNodes.delete(uuid); } + /* DEDUP by publisher pubkey: if a different uuid in + * listenerAudioNodes belongs to the SAME publisher (e.g. they + * rejoined with a new session uuid before the old session's + * peer-left fired), detach the older entry. Two worklets+gains + * connected to destination = host audio played twice. Fox + * 2026-06-05: "fxhp-android-firefox is playing host audio + * twice." */ + try { + const mm = members.get(uuid); + if (mm && mm.pubkey){ + const myPubHex = hex(unb64(mm.pubkey)); + for (const [otherUuid] of [...listenerAudioNodes]){ + if (otherUuid === uuid) continue; + const otherMm = members.get(otherUuid); + if (!otherMm || !otherMm.pubkey) continue; + try { + if (hex(unb64(otherMm.pubkey)) === myPubHex){ + logLine('', 'audio dedup: detaching stale uuid='+otherUuid.slice(0,4)+' for pub='+myPubHex.slice(0,4)); + detachListenerStream(otherUuid); + } + } catch(_){} + } + } + } catch(_){} let src; try { src = audioCtx.createMediaStreamSource(stream); } catch(e){ logLine('err','createMediaStreamSource '+uuid.slice(0,4)+': '+e.message); return false; } @@ -7477,8 +7503,8 @@ logLine('', 'ready โ€” pick a handle, type a rendezvous code, enter the space');