zebra-report: revert remaining new Chrome-path codec params

Choppy persisted after every other dial-back. The only remaining new
Chrome-publisher params were the fullband pin and the 320k bump. Drop
both. Chrome publisher's SDP now back to the pre-feature shape
(stereo + FEC + 256k, no maxplaybackrate / sprop-maxcapturerate / cbr).

Kept: Firefox SDP regex fix, UA-gated NACK, speaker picker.
This commit is contained in:
russell@unturf.com 2026-06-03 18:12:49 -04:00
parent fcbac50caf
commit 147dbc0f9e
No known key found for this signature in database

View file

@ -2161,7 +2161,7 @@ async function sfuPublish(){
for (const tr of micStream.getTracks()){ tagTrack(tr); pc.addTrack(tr, micStream); }
setSenderBitrate(pc.getSenders().find(s=>s.track && s.track.kind==='audio'));
const offer = await pc.createOffer();
offer.sdp = preferStereoOpus(offer.sdp, musicMode ? 320000 : 40000, { music: musicMode });
offer.sdp = preferStereoOpus(offer.sdp, musicMode ? 256000 : 40000, { music: musicMode });
await pc.setLocalDescription(offer);
await waitForIceGathering(pc);
const res = await fetch(SFU_BASE + '/publish?room=' + encodeURIComponent(roomID) + '&pub=' + myKeys.pubHex, {
@ -2251,7 +2251,7 @@ async function sfuPublishScreen(){
const offer = await pc.createOffer();
/* screen-share audio is always music-grade — system audio capture is
* what users actually broadcast, not voice */
offer.sdp = preferStereoOpus(offer.sdp, 320000, { music: true });
offer.sdp = preferStereoOpus(offer.sdp, 256000, { music: true });
await pc.setLocalDescription(offer);
await waitForIceGathering(pc);
const url = SFU_BASE + '/publish?room=' + encodeURIComponent(roomID)
@ -2271,7 +2271,7 @@ async function sfuPublishScreen(){
for (const s of pc.getSenders()){
if (!s.track) continue;
if (s.track.kind === 'video') setSenderMaxBitrate(s, 6000000);
if (s.track.kind === 'audio') setSenderMaxBitrate(s, 320000);
if (s.track.kind === 'audio') setSenderMaxBitrate(s, 256000);
}
/* Screen share CANNOT auto-rebuild like mic + camera — getDisplayMedia
* requires a fresh user gesture (transient activation). Auto-calling
@ -2343,7 +2343,7 @@ async function sfuPublishGame(iframe){
}
stream.getVideoTracks()[0].addEventListener('ended', () => { sfuUnpublishGame(); });
const offer = await pc.createOffer();
offer.sdp = preferStereoOpus(offer.sdp, 320000, { music: true });
offer.sdp = preferStereoOpus(offer.sdp, 256000, { music: true });
await pc.setLocalDescription(offer);
await waitForIceGathering(pc);
const url = SFU_BASE + '/publish?room=' + encodeURIComponent(roomID)
@ -2360,7 +2360,7 @@ async function sfuPublishGame(iframe){
for (const s of pc.getSenders()){
if (!s.track) continue;
if (s.track.kind === 'video') setSenderMaxBitrate(s, 4000000);
if (s.track.kind === 'audio') setSenderMaxBitrate(s, 320000);
if (s.track.kind === 'audio') setSenderMaxBitrate(s, 256000);
}
/* game-share doesn't auto-rebuild on 'failed' — its capture source is
* a user-selected iframe via Region Capture; the user would have to
@ -2924,7 +2924,7 @@ async function setSenderBitrate(sender){
* for transient-heavy material (orchestral, drums). 40 kbps mono is plenty
* for speech. Opus VBR only spends what it needs; idle music stays around
* 200300 kbps and only peaks claim the ceiling. */
p.encodings[0].maxBitrate = musicMode ? 320000 : 40000;
p.encodings[0].maxBitrate = musicMode ? 256000 : 40000;
await sender.setParameters(p);
} catch(_){}
}
@ -2944,11 +2944,8 @@ async function setSenderMaxBitrate(sender, bps){
* codec-level maxaveragebitrate cap (separate from RTP-level maxBitrate)
* has to be raised explicitly for music to actually use the headroom.
*
* Music mode also pins fullband (maxplaybackrate / sprop-maxcapturerate =
* 48000) so Opus can't opportunistically narrow to 16/24 kHz under BWE
* pressure. NACK is gated by RTCRtpSender.getCapabilities so each browser
* only advertises what it can back up. cbr=0 is explicit so no browser
* quirk silently flips us to constant-rate. */
* NACK is gated by RTCRtpSender.getCapabilities so each browser only
* advertises what it can back up — no LCD across mixed-browser rooms. */
function preferStereoOpus(sdp, maxAvgBps, opts){
const music = !!(opts && opts.music);
/* DTX is great for voice (silence is silence) but its comfort-noise
@ -2967,15 +2964,17 @@ function preferStereoOpus(sdp, maxAvgBps, opts){
if (!opusPTs.length) return sdp;
/* useinbandfec=1: forward error correction so a single dropped
* packet doesn't audibly chop — Opus reconstructs from FEC.
* maxplaybackrate / sprop-maxcapturerate=48000: fullband both ways.
* cbr=0: explicit VBR. Opus VBR only spends what it needs; the high
* ceiling is just headroom for transients, not a constant load. */
*
* maxplaybackrate / sprop-maxcapturerate=48000 and cbr=0 were tried
* here and rolled back: choppy persisted after every other dial-back
* (NACK off, maxptime off, bitrate to 320k). The "fullband pin" was
* the only Chrome-publisher-side remaining new param. Removing it
* restores Chrome's original music-mode behaviour. Don't re-add
* without verifying it doesn't reintroduce the choppy. */
const want = {
'stereo': '1', 'sprop-stereo': '1',
'maxaveragebitrate': String(maxAvgBps),
'useinbandfec': '1', 'usedtx': dtx,
'maxplaybackrate': '48000', 'sprop-maxcapturerate': '48000',
'cbr': '0',
};
for (const pt of opusPTs){
const fmtpRe = new RegExp('a=fmtp:' + pt + ' ([^\\r\\n]*)', 'g');
@ -3842,7 +3841,7 @@ async function connectToPeer(uuid, weOffer){
};
if (weOffer){
const offer = await pc.createOffer();
offer.sdp = preferStereoOpus(offer.sdp, musicMode ? 320000 : 40000, { music: musicMode });
offer.sdp = preferStereoOpus(offer.sdp, musicMode ? 256000 : 40000, { music: musicMode });
await pc.setLocalDescription(offer);
await waitForIceGathering(pc);
await sendEncSDP(uuid, 'offer', pc.localDescription);
@ -4467,8 +4466,8 @@ logLine('', 'ready — pick a handle, type a rendezvous code, enter the space');
<footer style="margin:2.2rem auto 0;font-size:0.65rem;color:#999;line-height:1.7;word-break:break-all;font-family:monospace">
<span id="pi-seal" style="color:#777;cursor:default;user-select:none" title="">page integrity</span> &nbsp;·&nbsp; built <span class="stamp-date">2026-06-03</span><br>
md5 <span class="stamp-md5">cad5e6b7e0ea29bb564786f6960b5511</span><br>
sha256 <span class="stamp-sha">75a63cb186572f644db0788d06b8ab96f2359d5c3e5fbd5a03afc7fae4b5ea9b</span><br>
md5 <span class="stamp-md5">438b3d7f452d60edd79baae0a03094af</span><br>
sha256 <span class="stamp-sha">203ace58efa704b3499137bd26d0a881df84d40ef73913e20aa2d7ba6d001fa6</span><br>
<span style="color:#bbb">hashes are of this page with these two fields zeroed — to verify, blank them and re-hash</span><br>
<span style="color:#bbb">one self-contained file — <strong>save a copy</strong> and verify against these hashes; point at your own servers with ?signal= and ?turncred=, or <a href="host-your-own.html" style="color:#999">host your own community</a></span>
</footer>