diff --git a/zebra-report/zebra-spaces.html b/zebra-report/zebra-spaces.html
index 59112b3..9fd2b84 100644
--- a/zebra-report/zebra-spaces.html
+++ b/zebra-report/zebra-spaces.html
@@ -3369,17 +3369,33 @@ async function setSenderBitrate(sender){
* for speech. Opus VBR only spends what it needs; idle music stays around
* 200–300 kbps and only peaks claim the ceiling. */
p.encodings[0].maxBitrate = musicMode ? 256000 : 40000;
+ /* Audio rides ahead of video in the sender's egress queue. Fox
+ * 2026-06-04: wiggling a terminal window caused 1-5s cutouts on
+ * listeners even with a 4s playoutDelayHint buffer. Cause: the
+ * wiggle triggered a big screen-share keyframe burst that
+ * monopolized the egress queue; audio packets queued behind it
+ * arrived too late and the buffer drained. Setting priority='high'
+ * + networkPriority='high' on audio tells the browser to drain
+ * audio first when its outgoing queue is contended. Video keeps
+ * the default ('low' on the screen/camera senders below). */
+ p.encodings[0].priority = 'high';
+ p.encodings[0].networkPriority = 'high';
await sender.setParameters(p);
} catch(_){}
}
/* explicit bitrate setter for non-mic senders (screen video, screen audio).
- * setSenderBitrate above is locked to the mic's musicMode value. */
+ * setSenderBitrate above is locked to the mic's musicMode value. Audio kind
+ * gets high priority like the mic; video kind gets low priority so audio
+ * wins the egress queue under contention. */
async function setSenderMaxBitrate(sender, bps){
if (!sender) return;
try {
const p = sender.getParameters();
if (!p.encodings || !p.encodings.length) p.encodings = [{}];
p.encodings[0].maxBitrate = bps;
+ const isVideo = sender.track && sender.track.kind === 'video';
+ p.encodings[0].priority = isVideo ? 'low' : 'high';
+ p.encodings[0].networkPriority = isVideo ? 'low' : 'high';
await sender.setParameters(p);
} catch(_){}
}
@@ -5925,8 +5941,8 @@ logLine('', 'ready — pick a handle, type a rendezvous code, enter the space');