zebra-report: deploy telemetry fingerprint + camera-error breadcrumbs
Pulls in zebra-report 1ed5263: every entry now emits a one-shot
'session: ua=... ctx={...} devs={...} picked={...}' line so the
signal-server log carries browser + audioCtx + device-count + saved-
deviceId-shortprefix context for diagnosing the open tickets
(0001 fedora chrome silence, 0002 fedora firefox cannot share camera).
Camera-open errors now include e.name + the constraints we tried
plus auto-recovery from OverconstrainedError + saved deviceId.
This commit is contained in:
parent
0f36e02e42
commit
8e762fb100
1 changed files with 79 additions and 4 deletions
|
|
@ -4560,7 +4560,36 @@ async function sfuPublishCamera(){
|
||||||
* speaker can choose camera-on while still using a different audio
|
* speaker can choose camera-on while still using a different audio
|
||||||
* input (monitor source, music mode, etc) */
|
* input (monitor source, music mode, etc) */
|
||||||
stream = await navigator.mediaDevices.getUserMedia({ video: videoConstraints, audio: false });
|
stream = await navigator.mediaDevices.getUserMedia({ video: videoConstraints, audio: false });
|
||||||
} catch(e){ logLine('err','camera open cancelled: '+e.message); fsm.send('FAILED', { error: e.message }); fsm.send('DONE'); return; }
|
} catch(e){
|
||||||
|
/* surface e.name + the constraints we tried so signal-server telemetry
|
||||||
|
* can disambiguate NotFoundError (device gone) vs OverconstrainedError
|
||||||
|
* (saved deviceId or 720p/16:9 not supported) vs NotAllowedError (user
|
||||||
|
* declined permission) vs NotReadableError (camera held by another app).
|
||||||
|
* Defect #0002 fedora firefox: e.message alone wasn't enough to pick
|
||||||
|
* the right branch. */
|
||||||
|
const exact = videoConstraints.deviceId && videoConstraints.deviceId.exact;
|
||||||
|
logLine('err',
|
||||||
|
'camera open cancelled: '+(e.name||'Error')+' — '+e.message+
|
||||||
|
' (constraints: 1280x720@30 16:9'+(exact?' deviceId='+String(exact).slice(0,8):'')+')'
|
||||||
|
);
|
||||||
|
/* OverconstrainedError + a saved deviceId is the canonical "saved
|
||||||
|
* device gone or renamed" case — retry once without deviceId so the
|
||||||
|
* user gets default camera rather than a permanent fail. */
|
||||||
|
if (e.name === 'OverconstrainedError' && exact){
|
||||||
|
logLine('', 'camera open retry without saved deviceId');
|
||||||
|
try {
|
||||||
|
const fallbackConstraints = Object.assign({}, videoConstraints);
|
||||||
|
delete fallbackConstraints.deviceId;
|
||||||
|
stream = await navigator.mediaDevices.getUserMedia({ video: fallbackConstraints, audio: false });
|
||||||
|
logLine('', 'camera open recovered with default device');
|
||||||
|
} catch(e2){
|
||||||
|
logLine('err','camera open retry failed: '+(e2.name||'Error')+' — '+e2.message);
|
||||||
|
fsm.send('FAILED', { error: e2.message }); fsm.send('DONE'); return;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
fsm.send('FAILED', { error: e.message }); fsm.send('DONE'); return;
|
||||||
|
}
|
||||||
|
}
|
||||||
fsm.send('ACQUIRED', { stream });
|
fsm.send('ACQUIRED', { stream });
|
||||||
sfuCameraStream = stream;
|
sfuCameraStream = stream;
|
||||||
const pc = new RTCPeerConnection(rtcConfig);
|
const pc = new RTCPeerConnection(rtcConfig);
|
||||||
|
|
@ -6029,6 +6058,52 @@ async function handleSignal(raw){
|
||||||
broadcastSpotlight();
|
broadcastSpotlight();
|
||||||
reorderTiles();
|
reorderTiles();
|
||||||
logLine('', 'joined as '+myRole+' — uuid '+myUUID);
|
logLine('', 'joined as '+myRole+' — uuid '+myUUID);
|
||||||
|
/* one-shot session fingerprint for telemetry (see docs/tickets/
|
||||||
|
* 0001 + 0002): captures the browser + audio/video device state
|
||||||
|
* at entry so a reporter's signal-server log carries enough
|
||||||
|
* context to disambiguate browser-specific defects. Mobile + UA
|
||||||
|
* fields land first because the bug shape often correlates with
|
||||||
|
* a single UA family (fxhp-phone-firefox, fedora-chrome, etc).
|
||||||
|
* Best-effort — wrapped + caught so a hostile UA doesn't break
|
||||||
|
* entry. */
|
||||||
|
(async () => {
|
||||||
|
try {
|
||||||
|
const ua = navigator.userAgent || '';
|
||||||
|
const isMobile = /Mobi|Android|iPhone|iPad|iPod/.test(ua);
|
||||||
|
const browser =
|
||||||
|
/Firefox\//.test(ua) ? 'firefox' :
|
||||||
|
/Edg\//.test(ua) ? 'edge' :
|
||||||
|
/Chrome\//.test(ua) ? 'chrome' :
|
||||||
|
/Safari\//.test(ua) ? 'safari' : 'other';
|
||||||
|
let sr = 'n/a', bl = 'n/a', sinkSupp = false, ctxSink = 'n/a';
|
||||||
|
try {
|
||||||
|
if (audioCtx){
|
||||||
|
sr = audioCtx.sampleRate;
|
||||||
|
bl = (audioCtx.baseLatency != null) ? audioCtx.baseLatency.toFixed(4) : 'n/a';
|
||||||
|
sinkSupp = typeof audioCtx.setSinkId === 'function';
|
||||||
|
ctxSink = (audioCtx.sinkId === undefined) ? 'n/a' : (audioCtx.sinkId || 'default');
|
||||||
|
}
|
||||||
|
} catch(_){}
|
||||||
|
let outCount = 0, inCount = 0, camCount = 0;
|
||||||
|
try {
|
||||||
|
const devs = await navigator.mediaDevices.enumerateDevices();
|
||||||
|
for (const d of devs){
|
||||||
|
if (d.kind === 'audiooutput') outCount++;
|
||||||
|
else if (d.kind === 'audioinput') inCount++;
|
||||||
|
else if (d.kind === 'videoinput') camCount++;
|
||||||
|
}
|
||||||
|
} catch(_){}
|
||||||
|
const pickShort = id => id ? String(id).slice(0,8) : '';
|
||||||
|
logLine('',
|
||||||
|
'session: ua='+browser+(isMobile?'/mobile':'/desktop')+
|
||||||
|
' ctx={sr='+sr+' baseLat='+bl+' sinkSupp='+(sinkSupp?1:0)+' sink='+ctxSink+'}'+
|
||||||
|
' devs={out='+outCount+' in='+inCount+' cam='+camCount+'}'+
|
||||||
|
' picked={mic='+pickShort(micDeviceId)+
|
||||||
|
' cam='+pickShort(cameraDeviceId)+
|
||||||
|
' spk='+pickShort(speakerDeviceId)+'}'
|
||||||
|
);
|
||||||
|
} catch(_){}
|
||||||
|
})();
|
||||||
/* dot, leave/mute button visibility, sec-room reveal, entry-row
|
/* dot, leave/mute button visibility, sec-room reveal, entry-row
|
||||||
* hide and status text are all driven by applyCallStateUI()
|
* hide and status text are all driven by applyCallStateUI()
|
||||||
* from the 'joined' state. Welcome already dispatched WELCOME
|
* from the 'joined' state. Welcome already dispatched WELCOME
|
||||||
|
|
@ -8008,9 +8083,9 @@ logLine('', 'ready — pick a handle, type a rendezvous code, enter the space');
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<footer style="margin:2.2rem auto 0;font-size:0.65rem;color:#999;line-height:1.7;word-break:break-all;font-family:monospace">
|
<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> · built <span class="stamp-date">2026-06-06</span><br>
|
<span id="pi-seal" style="color:#777;cursor:default;user-select:none" title="">page integrity</span> · built <span class="stamp-date">2026-06-07</span><br>
|
||||||
md5 <span class="stamp-md5">43f585be4e478d110d4250eff68b9d68</span><br>
|
md5 <span class="stamp-md5">14af06bd5893feb70229dded7e6c5497</span><br>
|
||||||
sha256 <span class="stamp-sha">6677c5b69c23976a7c9d35104fdc324fe69fa80d24120e1f32aaab23ebdd0606</span><br>
|
sha256 <span class="stamp-sha">e603642628f264fa919f55be33e6578d77d2d42858566c2d708beefce091aed5</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">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>
|
<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>
|
</footer>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue