A play's trace holds the playlist, audio and saved place it fetched (#192)
hls.js sends traceparent on its own requests (xhrSetup); a beacon, which cannot set a header, and Safari's player, fetching the playlist itself, carry it in the query, which the server reads where there is no header. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -18,7 +18,10 @@ function dropHls(){ if(hls){ hls.destroy(); hls=null; } }
|
||||
function setSrc(url: string): Promise<void>|null{
|
||||
dropHls();
|
||||
const native=navigator.vendor.startsWith('Apple')&&!!audio.canPlayType('application/vnd.apple.mpegurl');
|
||||
if(!url.endsWith('.m3u8')||native){ audio.src=url; return null; }
|
||||
// Safari fetches the playlist itself, with no header to carry the tap's trace: in the address
|
||||
// instead (#192). Only the playlist, which is never cached.
|
||||
if(!url.endsWith('.m3u8')){ audio.src=url; return null; }
|
||||
if(native){ audio.src=`${url}?traceparent=${traceparent()}`; return null; }
|
||||
const w=window as any;
|
||||
const ready=w.Hls?Promise.resolve():new Promise<void>((ok,fail)=>{
|
||||
const s=document.createElement('script');
|
||||
@@ -26,7 +29,8 @@ function setSrc(url: string): Promise<void>|null{
|
||||
document.head.append(s);
|
||||
});
|
||||
return ready.then(()=>{
|
||||
hls=new w.Hls();
|
||||
// Its playlist and audio requests join the trace of the tap that played them (#192).
|
||||
hls=new w.Hls({xhrSetup:(xhr: XMLHttpRequest)=>xhr.setRequestHeader('traceparent',traceparent())});
|
||||
hls.on(w.Hls.Events.ERROR,(_,d)=>{ if(d.fatal){ toast('Playback failed: '+d.details,true);
|
||||
report('player_error',{msg:`hls.js: ${d.type} ${d.details}`,feed:player.feed,enclosure:player.enc}); } });
|
||||
hls.loadSource(url); hls.attachMedia(audio);
|
||||
@@ -112,7 +116,8 @@ function savePos(){
|
||||
// cannot tell a finished episode from a started one. NaN before metadata, Infinity on a stream.
|
||||
const duration=isFinite(audio.duration)?Math.floor(audio.duration):null;
|
||||
navigator.sendBeacon?.(
|
||||
`/api/entries/${encodeURIComponent(player.feed)}/${encodeURIComponent(player.guid)}/position`,
|
||||
// A beacon sends no headers, so the trace goes in the address (#192).
|
||||
`/api/entries/${encodeURIComponent(player.feed)}/${encodeURIComponent(player.guid)}/position?traceparent=${traceparent()}`,
|
||||
new Blob([JSON.stringify({secs:Math.floor(audio.currentTime),duration})],{type:'application/json'}));
|
||||
}
|
||||
audio.addEventListener('pause',savePos);
|
||||
|
||||
Reference in New Issue
Block a user