@mattebox/player-diagnostics 0.5.0 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- var matteboxPlayerDiagnostics=(function(e){Object.defineProperty(e,Symbol.toStringTag,{value:`Module`});function t(e,...t){for(;e.firstChild!==null;)e.firstChild.remove();e.append(...t)}function n(e){return!Number.isFinite(e)||e<=0?`0 bps`:e>=1e6?`${(e/1e6).toFixed(e>=1e7?0:1)} Mbps`:e>=1e3?`${Math.round(e/1e3)} kbps`:`${Math.round(e)} bps`}function r(e){if(!Number.isFinite(e))return`–`;let t=Math.max(0,Math.floor(e)),n=Math.floor(t/3600),r=Math.floor(t%3600/60),i=t%60,a=e=>e<10?`0${e}`:`${e}`;return n>0?`${n}:${a(r)}:${a(i)}`:`${r}:${a(i)}`}function i(e,t=1){return e==null||!Number.isFinite(e)?`–`:e.toFixed(t)}function a(e,t){return t>0?`${(e/t*100).toFixed(2)}%`:`0%`}function o(e){return e.length===0?`none`:e.map(e=>`${e.start.toFixed(1)}–${e.end.toFixed(1)}`).join(`, `)}function s(e){return e===null?`–`:e.height===void 0?n(e.bitrate):`${e.height}p, ${n(e.bitrate)}`}let c=[`buffer`,`throughput`,`stalls`,`frames`,`switches`];function l(e,t){let n=e/Math.max(t,1),r=Math.pow(10,Math.floor(Math.log10(Math.max(n,1e-9))));for(let e of[1,2,5,10])if(n<=e*r)return e*r;return 10*r}function u(e,t){let n=document.createElement(`canvas`).getContext(`2d`);if(n===null)return e;n.fillStyle=e;let r=n.fillStyle;return/^#[0-9a-f]{6}$/i.test(r)?`rgba(${Number.parseInt(r.slice(1,3),16)}, ${Number.parseInt(r.slice(3,5),16)}, ${Number.parseInt(r.slice(5,7),16)}, ${t})`:e}function d(e,i,a){function o(){let t=e.getContext(`2d`);if(t===null)return null;let n=window.devicePixelRatio||1,r=e.clientWidth,i=e.clientHeight;if(r===0||i===0)return null;let a=Math.round(r*n),o=Math.round(i*n);return(e.width!==a||e.height!==o)&&(e.width=a,e.height=o),t.setTransform(n,0,0,n,0,0),t.clearRect(0,0,r,i),t.font=`10px ui-monospace, SFMono-Regular, Menlo, Consolas, monospace`,{ctx:t,w:r,h:i,left:44,right:r-8,top:8,bottom:i-18}}function s(e,t,n,i){let a=r=>e.left+(r-t)/(n-t)*(e.right-e.left),o=(n-t)/1e3,s=l(o,6);e.ctx.strokeStyle=u(i.muted,.25),e.ctx.fillStyle=i.muted,e.ctx.textAlign=`center`,e.ctx.textBaseline=`top`;for(let t=0;t<=o;t+=s){let i=a(n-t*1e3);e.ctx.beginPath(),e.ctx.moveTo(i,e.top),e.ctx.lineTo(i,e.bottom),e.ctx.stroke();let o=t===0?`now`:t<60?`-${t}s`:`-${r(t)}`;e.ctx.fillText(o,i,e.bottom+3)}return a}function c(e,t,n,r){let i=n=>e.bottom-n/t*(e.bottom-e.top),a=l(t,4);e.ctx.strokeStyle=u(r.muted,.25),e.ctx.fillStyle=r.muted,e.ctx.textAlign=`right`,e.ctx.textBaseline=`middle`;for(let r=0;r<=t;r+=a){let t=i(r);e.ctx.beginPath(),e.ctx.moveTo(e.left,t),e.ctx.lineTo(e.right,t),e.ctx.stroke(),e.ctx.fillText(n(r),e.left-4,t)}return i}function d(e,t,n,r={}){var i;if(t.length===0)return;e.ctx.save(),e.ctx.strokeStyle=n,e.ctx.lineWidth=(i=r.width)==null?2:i,e.ctx.setLineDash(r.dashed===!0?[4,4]:[]),e.ctx.beginPath();let a;for(let n of t)a===void 0?e.ctx.moveTo(n[0],n[1]):(r.step===!0&&e.ctx.lineTo(n[0],a[1]),e.ctx.lineTo(n[0],n[1])),a=n;e.ctx.stroke(),e.ctx.restore()}function f(e,t,n,r,i=2.5){e.ctx.fillStyle=r,e.ctx.beginPath(),e.ctx.arc(t,n,i,0,Math.PI*2),e.ctx.fill()}function p(e,t,n,r){e.ctx.save(),e.ctx.strokeStyle=n,e.ctx.lineWidth=1,e.ctx.setLineDash([2,3]),e.ctx.beginPath(),e.ctx.moveTo(t,e.top),e.ctx.lineTo(t,e.bottom),e.ctx.stroke(),e.ctx.restore(),e.ctx.fillStyle=n,e.ctx.textAlign=`center`,e.ctx.textBaseline=`top`,e.ctx.fillText(r,t,e.top)}function m(e){t(i);for(let[t,n]of e){let e=document.createElement(`span`);e.setAttribute(`part`,`legend-item`);let r=document.createElement(`span`);r.setAttribute(`part`,`swatch`),r.style.background=n,e.append(r,t),i.append(e)}}function h(e,t){let n=e.findIndex(e=>e.t>=t);return n<0?e.length>0?[e[e.length-1]]:[]:e.slice(Math.max(0,n-1))}function g(e){var t;return(t=e==null?void 0:e.quality.renditions)==null?[]:t}function _(e,t){var i,o,s,c,l,d;let{video:f,engine:h,palette:_}=t,v=(i=h==null?void 0:h.stats.snapshot())==null?null:i,y=(o=v==null||(s=v.presentation)==null?void 0:s.duration)==null?f.duration:o,b=(c=v==null?void 0:v.live)==null?null:c,x=f.currentTime,S=0,C=Number.isFinite(y)&&y>0?y:Math.max(x+10,10);b===null?C>600&&(S=Math.max(0,x-60),C=x+180):(S=b.span.start,C=Math.max(b.span.end,x+10));let w=t=>e.left+(t-S)/(C-S)*(e.right-e.left),T=v===null?[{label:`video`,ranges:Array.from({length:f.buffered.length},(e,t)=>({start:f.buffered.start(t),end:f.buffered.end(t)}))}]:[...v.buffers.entries()].map(([e,t])=>({label:e.replace(`sb:`,``),ranges:t.ranges}));T.length===0&&T.push({label:`video`,ranges:[]});let E=g(h),D=Math.min(34,(e.bottom-e.top-8*(T.length-1))/T.length);e.ctx.textAlign=`left`,e.ctx.textBaseline=`middle`,T.forEach((t,n)=>{let r=e.top+n*(D+8);if(e.ctx.fillStyle=u(_.muted,.15),e.ctx.fillRect(e.left,r,e.right-e.left,D),v!==null)for(let[t,n]of v.quality.appendLog){var i;let a=E.findIndex(e=>e.id===n);e.ctx.fillStyle=u((i=_.series[Math.max(0,a)%_.series.length])==null?_.accent:i,.3),e.ctx.fillRect(w(t.start),r,Math.max(1,w(t.end)-w(t.start)),D)}e.ctx.fillStyle=_.ink;for(let n of t.ranges)e.ctx.fillRect(w(n.start),r+D-4,Math.max(1,w(n.end)-w(n.start)),3);e.ctx.fillStyle=_.muted,e.ctx.fillText(t.label,e.left+4,r+D/2)}),b!==null&&p(e,w(b.edge),_.warn,`edge`),e.ctx.fillStyle=_.accent,e.ctx.fillRect(w(x)-1,e.top,2,e.bottom-e.top),e.ctx.fillStyle=_.muted,e.ctx.textAlign=`left`,e.ctx.textBaseline=`top`,e.ctx.fillText(r(S),e.left,e.bottom+3),e.ctx.textAlign=`right`,e.ctx.fillText(r(C),e.right,e.bottom+3),m([...E.map((e,t)=>{var r;return[e.height===void 0?n(e.bitrate):`${e.height}p`,(r=_.series[t%_.series.length])==null?_.accent:r]}),[`buffered`,_.ink],[`playhead`,_.accent]]);let O=(l=(d=t.samples[t.samples.length-1])==null?void 0:d.ahead)==null?0:l;a.textContent=`${r(x)} of ${r(C)}, ${O.toFixed(1)}s buffered ahead${b===null?``:`, window ${r(b.span.start)} to ${r(b.span.end)}`}`}function v(e,t,r,i){var o,l,u,p,g,_;let v=t.palette,y=h(t.samples,r),b=t.marks.filter(e=>e.kind===`segment`&&e.t>=r),x=c(e,Math.max(1e6,...y.map(e=>Math.max(e.slow,e.fast,e.playingBitrate)),...b.map(e=>e.value))*1.15,e=>(e/1e6).toFixed(e>=1e7?0:1),v),S=s(e,r,i,v);for(let t of b){var C,w,T;let n=((C=t.trackId)==null?void 0:C.startsWith(`aud`))===!0||((w=t.trackId)==null?void 0:w.includes(`audio`))===!0;f(e,S(t.t),x(t.value),(T=n?v.series[4]:v.series[0])==null?v.accent:T)}d(e,y.map(e=>[S(e.t),x(e.slow)]),(o=v.series[1])==null?v.accent:o),d(e,y.map(e=>[S(e.t),x(e.fast)]),(l=v.series[2])==null?v.accent:l,{dashed:!0}),d(e,y.map(e=>[S(e.t),x(e.playingBitrate)]),v.muted,{step:!0,width:1.5}),m([[`video segment`,(u=v.series[0])==null?v.accent:u],[`audio segment`,(p=v.series[4])==null?v.accent:p],[`slow estimate`,(g=v.series[1])==null?v.accent:g],[`fast estimate`,(_=v.series[2])==null?v.accent:_],[`playing bitrate`,v.muted]]);let E=y[y.length-1];a.textContent=E===void 0?`Mbps`:`Mbps. Now: slow ${n(E.slow)}, fast ${n(E.fast)}, playing ${n(E.playingBitrate)}`}function y(e,t,n,r){var i,o,l,f,g;let _=t.palette,v=h(t.samples,n),y=c(e,Math.max(5,...v.map(e=>e.ahead))*1.15,e=>`${e.toFixed(0)}s`,_),b=s(e,n,r,_);e.ctx.fillStyle=u((i=_.series[3])==null?_.accent:i,.25);let x=null;for(let[t,n]of v.entries()){n.stalled&&x===null&&(x=n.t);let r=t===v.length-1;(!n.stalled||r)&&x!==null&&(e.ctx.fillRect(b(x),e.top,Math.max(2,b(n.t)-b(x)),e.bottom-e.top),x=null)}d(e,v.map(e=>[b(e.t),y(e.ahead)]),(o=_.series[0])==null?_.accent:o);for(let r of t.marks)r.t<n||r.kind===`segment`||r.kind===`switch`||(r.kind===`stall`?p(e,b(r.t),_.accent,`!`):r.kind===`seek`?p(e,b(r.t),_.muted,`>`):p(e,b(r.t),_.warn,r.kind.charAt(0).toUpperCase()));m([[`buffered ahead`,(l=_.series[0])==null?_.accent:l],[`stalled`,(f=_.series[3])==null?_.accent:f],[`! stall`,_.accent],[`> seek`,_.muted],[`N F S G recovery`,_.warn]]);let S=t.counters,C=((g=v[v.length-1])==null?void 0:g.stalled)===!0?`, stalled now`:``;a.textContent=`${S.stalls} stalls, ${S.stalledSeconds.toFixed(1)}s stalled in total${C}`}function b(e,t,n,r){var i,o;let l=t.palette,u=h(t.samples,n),f=u.map((e,t)=>{let n=u[t-1],r=n===void 0?.5:Math.max((e.t-n.t)/1e3,.05);return e.decoded/r}),p=c(e,Math.max(30,...f)*1.15,e=>e.toFixed(0),l),g=s(e,n,r,l),_=Math.max(1,...u.map(e=>e.dropped));e.ctx.fillStyle=l.accent;for(let t of u){if(t.dropped===0)continue;let n=t.dropped/_*(e.bottom-e.top)*.6;e.ctx.fillRect(g(t.t)-1.5,e.bottom-n,3,n)}d(e,u.map((e,t)=>{var n;return[g(e.t),p((n=f[t])==null?0:n)]}),(i=l.series[0])==null?l.accent:i),m([[`decoded per second`,(o=l.series[0])==null?l.accent:o],[`dropped, relative`,l.accent]]);let v=t.counters,y=v.decoded>0?(v.dropped/v.decoded*100).toFixed(2):`0.00`;a.textContent=`${v.decoded} decoded, ${v.dropped} dropped (${y}%) this session`}function x(e,t,r,i){var o,c;let l=t.palette,f=h(t.samples,r),_=g(t.engine),v=_.some(e=>e.height!==void 0),y=_.map(e=>{var t;return v?(t=e.height)==null?0:t:e.bitrate}),b=Math.max(1,...y,...f.map(e=>v?e.playingHeight:e.playingBitrate))*1.15,x=t=>e.bottom-t/b*(e.bottom-e.top);e.ctx.strokeStyle=u(l.muted,.25),e.ctx.fillStyle=l.muted,e.ctx.textAlign=`right`,e.ctx.textBaseline=`middle`;for(let t of y){let r=x(t);e.ctx.beginPath(),e.ctx.moveTo(e.left,r),e.ctx.lineTo(e.right,r),e.ctx.stroke(),e.ctx.fillText(v?`${t}p`:n(t),e.left-4,r)}let S=s(e,r,i,l);d(e,f.map(e=>[S(e.t),x(v?e.playingHeight:e.playingBitrate)]),(o=l.series[0])==null?l.accent:o,{step:!0});for(let n of t.marks)n.kind===`switch`&&n.t>=r&&p(e,S(n.t),l.warn,`S`);m([[`playing`,(c=l.series[0])==null?l.accent:c],[`S switch`,l.warn]]);let C=f[f.length-1],w=C===void 0||C.playingId===null?`–`:v?`${C.playingHeight}p`:n(C.playingBitrate);a.textContent=`${t.counters.switches} switches this session, now ${w}`}return{draw(e){let t=o();if(t===null)return;if(e.engine===null&&(e.tab===`throughput`||e.tab===`switches`)){m([]),a.textContent=`A native session: the browser holds this, and says nothing.`;return}let n=performance.now(),r=n-e.window*1e3;switch(e.tab){case`buffer`:_(t,e);break;case`throughput`:v(t,e,r,n);break;case`stalls`:y(t,e,r,n);break;case`frames`:b(t,e,r,n);break;case`switches`:x(t,e,r,n)}}}}function f(e){let t=e.parentNode;return t===null?e instanceof ShadowRoot?e.host:null:t}function p(e){let t=e;for(;t!==null;){if(t instanceof HTMLElement&&t.localName===`mattebox-player`)return t;t=f(t)}return null}function m(e,t){let n=!0,r=()=>{n&&(n=!1,customElements.upgrade(e),`video`in e&&t(e))};return`video`in e?r():customElements.whenDefined(`mattebox-player`).then(r),()=>{n=!1}}let h=`http://www.w3.org/2000/svg`;function g(){let e=document.createElementNS(h,`svg`);e.setAttribute(`viewBox`,`0 0 32 32`),e.setAttribute(`aria-hidden`,`true`),e.setAttribute(`part`,`icon`);let t=document.createElementNS(h,`path`);return t.setAttribute(`fill-rule`,`evenodd`),t.setAttribute(`d`,`M17.534 10.6674C17.534 11.5143 16.8475 12.2008 16.0006 12.2008C15.1538 12.2008 14.4673 11.5143 14.4673 10.6674C14.4673 9.82061 15.1538 9.13411 16.0006 9.13411C16.8475 9.13411 17.534 9.82061 17.534 10.6674Z M14.6678 14.2005C14.6678 13.8323 14.9663 13.5339 15.3345 13.5339H16.6678C17.036 13.5339 17.3345 13.8323 17.3345 14.2005V22.2005C17.3345 22.5687 17.036 22.8672 16.6678 22.8672H15.3345C14.9663 22.8672 14.6678 22.5687 14.6678 22.2005V14.2005Z M28 16C28 22.6274 22.6274 28 16 28C9.37258 28 4 22.6274 4 16C4 9.37258 9.37258 4 16 4C22.6274 4 28 9.37258 28 16ZM24.9333 16C24.9333 20.9337 20.9337 24.9333 16 24.9333C11.0663 24.9333 7.06667 20.9337 7.06667 16C7.06667 11.0663 11.0663 7.06667 16 7.06667C20.9337 7.06667 24.9333 11.0663 24.9333 16Z`),e.append(t),e}function _(e){return Array.from({length:e.length},(t,n)=>({start:e.start(n),end:e.end(n)}))}function v(e){var t;let n=(t=e.getVideoPlaybackQuality)==null?void 0:t.call(e);return{currentTime:e.currentTime,duration:e.duration,paused:e.paused,ended:e.ended,seeking:e.seeking,readyState:e.readyState,networkState:e.networkState,playbackRate:e.playbackRate,volume:e.volume,muted:e.muted,videoWidth:e.videoWidth,videoHeight:e.videoHeight,buffered:_(e.buffered),seekable:_(e.seekable),frames:n===void 0?null:{decoded:n.totalVideoFrames,dropped:n.droppedVideoFrames},mediaError:e.error===null?null:{code:e.error.code,message:e.error.message}}}function y(e){var t,n,r,i,a,o,s;let c=e.stats.snapshot(),l=e,u=e.error;return{phase:c.lifecycle.phase,capabilities:[...e.capabilities()],throughput:{slow:c.stats.throughputEwma,fast:c.stats.throughputFastEwma},bufferGoal:c.scheduling.bufferGoal,buffers:[...c.buffers.entries()].map(([e,t])=>({id:e,codecs:t.codecs,ranges:t.ranges.map(e=>({start:e.start,end:e.end}))})),inflight:[...c.scheduling.inflight.values()].map(e=>({trackId:e.trackId,seq:e.seq,url:e.url})),live:c.live===null?null:{start:c.live.span.start,end:c.live.span.end,edge:c.live.edge,latency:(t=(n=l.live)==null?void 0:n.latency)==null?null:t},tracks:{active:Object.fromEntries([`video`,`audio`,`text`].map(t=>{var n,r;return[t,(n=(r=e.tracks.active(t))==null?void 0:r.id)==null?null:n]})),available:e.tracks.available.map(e=>{var t,n;return{id:e.id,contentType:e.contentType,mimeType:e.mimeType,lang:(t=e.lang)==null?null:t,role:(n=e.role)==null?null:n,renditions:e.renditions.length}})},quality:{playing:(r=(i=e.quality.playing)==null?void 0:i.id)==null?null:r,active:(a=(o=e.quality.active)==null?void 0:o.id)==null?null:a,pinned:e.quality.pinned,allowed:e.quality.allowed.map(e=>e.id),renditions:e.quality.renditions.map(e=>{var t,n,r;return{id:e.id,bitrate:e.bitrate,width:(t=e.width)==null?null:t,height:(n=e.height)==null?null:n,frameRate:(r=e.frameRate)==null?null:r,codecs:e.codecs}})},drm:l.drm===void 0?null:{keySystem:l.drm.keySystem,sessions:[...l.drm.sessions]},error:u===null?null:{category:u.category,code:u.code,fatal:u.fatal,recoverable:u.recoverable,context:(s=u.context)==null?null:s}}}function b(e){var t,n;let{player:r}=e,i=r.engine,a=e.samples.slice(-240),o=performance.now()-12e4;return{at:(/* @__PURE__ */ new Date()).toISOString(),userAgent:navigator.userAgent,source:{url:r.getAttribute(`src`),type:r.getAttribute(`type`),handler:(t=(n=r.player)==null||(n=n.session)==null?void 0:n.handler)==null?null:t},playback:v(r.video),error:r.error,engine:i===null?null:y(i),counters:e.counters,samples:a,marks:e.marks.filter(e=>e.t>=o),support:e.support,trace:i===null?null:e.history}}function x(e){"@babel/helpers - typeof";return x=typeof Symbol==`function`&&typeof Symbol.iterator==`symbol`?function(e){return typeof e}:function(e){return e&&typeof Symbol==`function`&&e.constructor===Symbol&&e!==Symbol.prototype?`symbol`:typeof e},x(e)}function S(e,t){if(x(e)!=`object`||!e)return e;var n=e[Symbol.toPrimitive];if(n!==void 0){var r=n.call(e,t||`default`);if(x(r)!=`object`)return r;throw TypeError(`@@toPrimitive must return a primitive value.`)}return(t===`string`?String:Number)(e)}function C(e){var t=S(e,`string`);return x(t)==`symbol`?t:t+``}function w(e,t,n){return(t=C(t))in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function T(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter(function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable})),n.push.apply(n,r)}return n}function E(e){for(var t=1;t<arguments.length;t++){var n=arguments[t]==null?{}:arguments[t];t%2?T(Object(n),!0).forEach(function(t){w(e,t,n[t])}):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):T(Object(n)).forEach(function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))})}return e}function D(e){return Array.isArray(e)?e.length:typeof e==`object`&&e&&`kind`in e?String(e.kind):0}function O(e){var t,n;return{id:e.id,isLive:e.isLive,duration:(t=e.duration)==null?null:t,live:(n=e.live)==null?null:n,periods:e.periods.map(e=>{var t;return{id:e.id,start:e.start,duration:(t=e.duration)==null?null:t,tracks:e.tracks.map(e=>{var t,n;return{id:e.id,contentType:e.contentType,mimeType:e.mimeType,lang:(t=e.lang)==null?null:t,role:(n=e.role)==null?null:n,protected:e.protection!==null&&e.protection.schemes.length>0,renditions:e.renditions.map(e=>{var t,n;return{id:e.id,bitrate:e.bitrate,width:(t=e.width)==null?null:t,height:(n=e.height)==null?null:n,codecs:e.codecs,segments:D(e.segments)}})}})}})}}function k(e){switch(e.type){case`MANIFEST_LOADED`:return{type:e.type,presentation:O(e.presentation)};case`PLAYLIST_REFRESHED`:return E(E({},e),{},{segments:D(e.segments)});case`SEGMENT_LOADED`:return E(E({},e),{},{bytes:A(e.bytes)});default:return e}}function A(e){return e instanceof ArrayBuffer||ArrayBuffer.isView(e)?e.byteLength:e}function j(e){if(e.kind===`emit`&&e.event===`tracks:changed`)return{kind:e.kind,event:e.event};if(e.kind===`schedule`)return E(E({},e),{},{then:k(e.then)});let t={};for(let[n,r]of Object.entries(e))t[n]=A(r);return t}function M(e,t){return t instanceof ArrayBuffer||ArrayBuffer.isView(t)?t.byteLength:t instanceof Map?Object.fromEntries(t):t instanceof Set?[...t]:typeof t==`function`?`[function]`:typeof Node<`u`&&t instanceof Node?`[${t.nodeName}]`:t}function ee(e){let t={t:e.t,msg:k(e.msg),effects:e.effects.map(j),digest:e.digest};return JSON.parse(JSON.stringify(t,M))}let N=2400,te=/* @__PURE__ */ new Set([`nudge`,`flush`,`skip`,`gap-jump`]);function ne(e){return e.height===void 0?`${Math.round(e.bitrate/1e3)} kbps`:`${e.height}p`}function re(){let e=[],t=[],n=[],r=/* @__PURE__ */ new WeakSet,i=null,a=null,o=0,s=null,c=null,l=null,u=0,d=0,f=0,p=0,m=0;function h(e){t.push(e),t.length>N*2&&t.splice(0,t.length-N*2)}function g(e){let t=e.stats.trace(),n=0;if(a!==null){let e=t.indexOf(a);n=e>=0?e+1:t.findIndex(e=>e.t>o),n<0&&(n=t.length)}let r=t[t.length-1];return r!==void 0&&(a=r,o=r.t),t.slice(n)}function _(e,t){if(!r.has(e)){r.add(e),n.push(ee(e)),n.length>500&&n.splice(0,n.length-500);{let n=e.msg;n.type===`SEGMENT_LOADED`&&n.trackId!==`manifest`&&n.size>0?h({t:e.t,kind:`segment`,value:n.size*8e3/Math.max(n.rtt,1),label:`${n.trackId} #${n.seq}`,trackId:n.trackId}):n.type===`STALLED`?h({t:e.t,kind:`stall`,value:n.at,label:`stalled at ${n.at.toFixed(1)}s`}):n.type===`SEEKING`&&h({t:e.t,kind:`seek`,value:n.to,label:`seek to ${n.to.toFixed(1)}s`});for(let n of e.effects){if(n.kind!==`emit`)continue;let r=n.event.replace(`recovery:`,``);te.has(r)&&h({t:e.t,kind:r,value:t.currentTime,label:`recovery ${r}`})}}}}function v(){e=[],t=[],n=[],r=/* @__PURE__ */ new WeakSet,a=null,o=0,s=null,c=null,l=null,u=0,d=0,f=0,p=0,m=0}function y(){i==null||i(),i=null}return{attach(e,t){y(),v(),t!==null&&(i=t.on(`trace`,t=>{_(t,e)}))},release:y,poll(t,n){var r,i,a,o,v,y,b,x,S,C;let w=performance.now();if(n!==null)for(let e of g(n))_(e,t);let T=(r=n==null?void 0:n.stats.snapshot())==null?null:r,E=(i=n==null?void 0:n.quality.playing)==null?null:i,D=(a=t.getVideoPlaybackQuality)==null?void 0:a.call(t);p=(o=D==null?void 0:D.totalVideoFrames)==null?0:o,m=(v=D==null?void 0:D.droppedVideoFrames)==null?0:v;let O=s===null?0:Math.max(0,m-s.dropped),k=s===null?0:Math.max(0,p-s.decoded);s={dropped:m,decoded:p};let A=0;for(let e=0;e<t.buffered.length;e+=1)t.buffered.start(e)<=t.currentTime+.25&&t.buffered.end(e)>t.currentTime&&(A=t.buffered.end(e)-t.currentTime);let j=!t.paused&&!t.ended&&!t.seeking&&t.readyState<3&&t.currentTime>0;if(j&&l===null?(l=w,u+=1):!j&&l!==null&&(d+=(w-l)/1e3,l=null),E!==null&&c!==null&&E.id!==c){var M;f+=1,h({t:w,kind:`switch`,value:(M=E.height)==null?E.bitrate:M,label:`now ${ne(E)}`})}E!==null&&(c=E.id),e.push({t:w,currentTime:t.currentTime,slow:(y=T==null?void 0:T.stats.throughputEwma)==null?0:y,fast:(b=T==null?void 0:T.stats.throughputFastEwma)==null?0:b,ahead:A,stalled:j,dropped:O,decoded:k,playingId:(x=E==null?void 0:E.id)==null?null:x,playingBitrate:(S=E==null?void 0:E.bitrate)==null?0:S,playingHeight:(C=E==null?void 0:E.height)==null?0:C}),e.length>N&&e.splice(0,e.length-N)},get samples(){return e},get marks(){return t},get history(){return n},get counters(){let e=l===null?0:(performance.now()-l)/1e3;return{stalls:u,stalledSeconds:d+e,switches:f,decoded:p,dropped:m}}}}function P(e,t,n,r,i,a,o){try{var s=e[a](o),c=s.value}catch(e){n(e);return}s.done?t(c):Promise.resolve(c).then(r,i)}function F(e){return function(){var t=this,n=arguments;return new Promise(function(r,i){var a=e.apply(t,n);function o(e){P(a,r,i,o,s,`next`,e)}function s(e){P(a,r,i,o,s,`throw`,e)}o(void 0)})}}let I=[{label:`H.264 High 4.0`,codec:`avc1.640028`,kind:`video`,containers:[`mp4`]},{label:`H.264 Baseline`,codec:`avc1.42e01e`,kind:`video`,containers:[`mp4`]},{label:`H.265 / HEVC Main`,codec:`hvc1.1.6.L123.B0`,kind:`video`,containers:[`mp4`]},{label:`VP9 Profile 0`,codec:`vp09.00.40.08`,kind:`video`,containers:[`mp4`,`webm`]},{label:`AV1 Main`,codec:`av01.0.08M.08`,kind:`video`,containers:[`mp4`,`webm`]},{label:`AAC-LC`,codec:`mp4a.40.2`,kind:`audio`,containers:[`mp4`]},{label:`HE-AAC`,codec:`mp4a.40.5`,kind:`audio`,containers:[`mp4`]},{label:`Opus`,codec:`opus`,kind:`audio`,containers:[`mp4`,`webm`]},{label:`FLAC`,codec:`flac`,kind:`audio`,containers:[`mp4`]},{label:`AC-3`,codec:`ac-3`,kind:`audio`,containers:[`mp4`]},{label:`E-AC-3`,codec:`ec-3`,kind:`audio`,containers:[`mp4`]}],ie=[{label:`Widevine`,keySystems:[`com.widevine.alpha`],levels:[[`HW_SECURE_ALL`,`L1`],[`HW_SECURE_DECODE`,`L1`],[`HW_SECURE_CRYPTO`,`L2`],[`SW_SECURE_DECODE`,`L3`],[`SW_SECURE_CRYPTO`,`L3`]]},{label:`PlayReady`,keySystems:[`com.microsoft.playready.recommendation`,`com.microsoft.playready`],levels:[[`3000`,`SL3000`],[`2000`,`SL2000`],[`150`,`SL150`]]},{label:`FairPlay`,keySystems:[`com.apple.fps`,`com.apple.fps.1_0`],levels:[]},{label:`ClearKey`,keySystems:[`org.w3.clearkey`],levels:[]}],ae=[`1.0`,`1.1`,`1.2`,`1.3`,`1.4`,`2.0`,`2.1`,`2.2`,`2.3`];function L(e,t,n=4e3){return new Promise(r=>{let i=setTimeout(()=>r(t),n);e.then(e=>{clearTimeout(i),r(e)},()=>{clearTimeout(i),r(t)})})}function R(e){return e in globalThis?`yes`:`no`}function oe(){let e=`no`;try{typeof MediaSource<`u`&&`changeType`in SourceBuffer.prototype&&(e=`yes`)}catch(t){e=`no`}return[{label:`Secure context`,value:window.isSecureContext?`yes`:`no`},{label:`MediaSource`,value:R(`MediaSource`)},{label:`ManagedMediaSource`,value:R(`ManagedMediaSource`)},{label:`SourceBuffer.changeType`,value:e},{label:`Encrypted Media (EME)`,value:R(`MediaKeys`)},{label:`MediaCapabilities`,value:navigator.mediaCapabilities===void 0?`no`:`yes`},{label:`WebCodecs`,value:R(`VideoDecoder`)}]}function se(e){try{return typeof MediaSource<`u`&&MediaSource.isTypeSupported(e)}catch(e){return!1}}function ce(e){let t=document.createElement(`video`).canPlayType(e);return t===`probably`?`yes`:t===`maybe`?`maybe`:`no`}function le(e){return z.apply(this,arguments)}function z(){return z=F(function*(e){let t=navigator.mediaCapabilities;if((t==null?void 0:t.decodingInfo)===void 0)return{smooth:`na`,efficient:`na`};let n=`${e.kind}/${e.containers[0]}; codecs="${e.codec}"`,r=e.kind===`video`?{type:`media-source`,video:{contentType:n,width:1920,height:1080,bitrate:6e6,framerate:30}}:{type:`media-source`,audio:{contentType:n,channels:`2`,bitrate:128e3}},i=yield L(t.decodingInfo(r),null);return i===null?{smooth:`na`,efficient:`na`}:i.supported?{smooth:i.smooth?`yes`:`no`,efficient:i.powerEfficient?`yes`:`no`}:{smooth:`no`,efficient:`no`}}),z.apply(this,arguments)}function ue(e){return B.apply(this,arguments)}function B(){return B=F(function*(e){let t=t=>e.containers.includes(t)?se(`${e.kind}/${t}; codecs="${e.codec}"`)?`yes`:`no`:`na`,{smooth:n,efficient:r}=yield le(e);return{label:e.label,codec:e.codec,kind:e.kind,mse:t(`mp4`),webm:t(`webm`),element:ce(`${e.kind}/${e.containers[0]}; codecs="${e.codec}"`),smooth:n,efficient:r}}),B.apply(this,arguments)}function V(e={}){return[E({contentType:`video/mp4; codecs="avc1.42e01e"`},e),E({contentType:`video/mp4; codecs="vp09.00.10.08"`},e)]}function H(e={}){return E({initDataTypes:[`cenc`,`keyids`,`sinf`,`skd`],videoCapabilities:V(),audioCapabilities:[{contentType:`audio/mp4; codecs="mp4a.40.2"`},{contentType:`audio/mp4; codecs="opus"`}]},e)}function U(e,t){return typeof navigator.requestMediaKeySystemAccess==`function`?L(navigator.requestMediaKeySystemAccess(e,[t]).then(e=>e,()=>null),null):Promise.resolve(null)}let de=e=>({label:e,keySystem:null,level:`na`,schemes:`na`,persistent:`na`,identifier:`na`,hdcp:`na`});function fe(e){return W.apply(this,arguments)}function W(){return W=F(function*(e){let t=null,n=null;for(let r of e.keySystems)if(n=yield U(r,H()),n!==null){t=r;break}if(t===null||n===null)return de(e.label);let r=e.levels.length===0?`n/a for this system`:`none granted`;for(let[n,i]of e.levels)if((yield U(t,H({videoCapabilities:V({robustness:n})})))!==null){r=`${i} (${n})`;break}let i=[],a=!1;for(let e of[`cenc`,`cbcs`]){var o;let n=yield U(t,H({videoCapabilities:V({encryptionScheme:e})})),r=n==null||(o=n.getConfiguration().videoCapabilities)==null||(o=o.find(e=>e.contentType!==``))==null?void 0:o.encryptionScheme;r!=null&&(a=!0),r===e&&i.push(e)}let s=a?i.length===0?`none`:i.join(`, `):`unknown (no API)`,c=yield U(t,H({persistentState:`required`,sessionTypes:[`persistent-license`]})),l=yield U(t,H({distinctiveIdentifier:`required`})),u=`na`;try{let e=yield L(n.createMediaKeys(),null);if(e!==null&&typeof e.getStatusForPolicy==`function`){let t=null;for(let n of ae){if((yield L(e.getStatusForPolicy({minHdcpVersion:n}),`unknown`))!==`usable`)break;t=n}u=t===null?`no output protection`:`up to ${t}`}}catch(e){u=`na`}return{label:e.label,keySystem:t,level:r,schemes:s,persistent:c===null?`no`:`yes`,identifier:l===null?`no`:`yes`,hdcp:u}}),W.apply(this,arguments)}let G=null;function K(){return G===null&&(G=F(function*(){return{userAgent:navigator.userAgent,platform:oe(),codecs:yield Promise.all(I.map(ue)),drm:yield Promise.all(ie.map(fe))}})()),G}let q=[30,60,120,300,600],J=[`playback`,`charts`,`engine`,`browser`],pe={playback:`Playback`,charts:`Charts`,engine:`Engine`,browser:`Browser`},me=[`nothing`,`metadata`,`current data`,`future data`,`enough data`],he=[`empty`,`idle`,`loading`,`no source`];function Y(e,t,n){let r=document.createElement(e);return r.setAttribute(`part`,t),n!==void 0&&(r.textContent=n),r}function X(e,t){let n=Y(`button`,e,t);return n.type=`button`,n}function Z(e){switch(e){case`yes`:return[`✓`,`cell ok`];case`no`:return[`✕`,`cell bad`];case`na`:return[`–`,`cell na`];case`maybe`:return[`maybe`,`cell maybe`];default:return[e,`cell`]}}var Q=class extends HTMLElement{static get observedAttributes(){return[`label`,`label-copy`,`label-copied`,`window`]}constructor(){super(),this.player=null,this.cancel=null,this.offs=[],this.sampler=re(),this.timer=void 0,this.drawer=void 0,this.copied=void 0,this.tab=`playback`,this.chartTab=`buffer`,this.support=null,this.probing=!1;let e=this.attachShadow({mode:`open`}),t=document.createElement(`style`);t.textContent=`:host{--mbx-chart-1:#5aa9e0;--mbx-chart-2:#6fbf8f;--mbx-chart-3:#d9a83f;--mbx-chart-4:#e05a6e;--mbx-chart-5:#a98fe0;display:inline-flex;position:relative}:host([hidden]){display:none}:host([inline]){display:block}[part~=button]{width:40px;height:40px;font:inherit;color:inherit;border-radius:var(--mbx-radius);cursor:pointer;opacity:.9;background:0 0;border:0;flex:none;justify-content:center;align-items:center;padding:0;display:inline-flex}[part~=button]:hover{opacity:1}[part~=button]:focus{outline:2px solid var(--mbx-accent);outline-offset:-2px}[part~=button]:focus:not(:focus-visible){outline:none}[part~=icon],::slotted(*){fill:currentColor;width:1.75em;height:1.75em}:host([inline]) [part~=button]{display:none}[part~=panel]{box-sizing:border-box;width:560px;color:var(--mbx-text,#f2f3f5);border-radius:var(--mbx-radius,4px);font:400 12px / 1.5 var(--mbx-mono,ui-monospace, SFMono-Regular, Menlo, Consolas, monospace);text-align:left;white-space:normal;background:#101114f2;flex-direction:column;margin-bottom:8px;display:flex;position:absolute;bottom:100%;right:0;overflow:hidden;box-shadow:0 4px 16px #00000080}[part~=panel][hidden]{display:none}:host([inline]) [part~=panel]{width:auto;max-height:none;box-shadow:none;border-radius:0;margin:0;position:static}[part~=head]{border-bottom:1px solid #ffffff1f;align-items:center;padding:6px;display:flex}[part~=tab],[part~=chart-tab]{font:inherit;color:var(--mbx-muted,#9aa0a6);border-radius:var(--mbx-radius,4px);cursor:pointer;background:0 0;border:0;padding:3px 8px}[part~=tab][aria-selected=true],[part~=chart-tab][aria-selected=true]{color:var(--mbx-text,#f2f3f5);background:#ffffff1f}[part~=copy],[part~=close],[part~=window]{font:inherit;color:inherit;border-radius:var(--mbx-radius,4px);cursor:pointer;background:0 0;border:1px solid #ffffff40;padding:2px 8px}[part~=head]>*{margin:0 2px}[part~=head]>[part~=copy],[part~=chart-tabs]>[part~=window]{margin-left:auto}[part~=window] option{color:#000}[part~=tab]:focus,[part~=chart-tab]:focus,[part~=copy]:focus,[part~=close]:focus,[part~=window]:focus{outline:2px solid var(--mbx-accent,#5b8cff);outline-offset:-2px}[part~=tab]:focus:not(:focus-visible){outline:none}[part~=chart-tab]:focus:not(:focus-visible){outline:none}[part~=copy]:focus:not(:focus-visible){outline:none}[part~=close]:focus:not(:focus-visible){outline:none}[part~=window]:focus:not(:focus-visible){outline:none}[part~=body]{overscroll-behavior:contain;min-height:0;padding:8px;overflow:auto}[part~=page][hidden]{display:none}[part~=rows]{grid-template-columns:max-content 1fr;gap:2px 12px;margin:0;display:grid}[part~=key]{color:var(--mbx-muted,#9aa0a6);white-space:nowrap}[part~=value]{overflow-wrap:anywhere;margin:0}[part~=heading]{letter-spacing:.06em;text-transform:uppercase;color:var(--mbx-muted,#9aa0a6);margin:10px 0 4px;font-size:11px;font-weight:600}[part~=heading]:first-child{margin-top:0}[part~=note]{color:var(--mbx-muted,#9aa0a6);margin:0}[part~=chart-tabs]{flex-wrap:wrap;align-items:center;margin:-2px -2px 4px;display:flex}[part~=chart-tabs]>*{margin:2px}[part~=chart]{width:100%;height:160px;display:block}[part~=legend]{color:var(--mbx-muted,#9aa0a6);flex-wrap:wrap;margin:3px -6px -1px;display:flex}[part~=legend]>*{margin:1px 6px}[part~=swatch]{vertical-align:middle;border-radius:2px;width:10px;height:10px;margin-right:4px;display:inline-block}[part~=readout]{margin-top:4px}[part~=table]{border-collapse:collapse;width:100%;margin-bottom:4px}[part~=cell]{text-align:left;white-space:nowrap;border-bottom:1px solid #ffffff14;padding:2px 6px;font-weight:400}[part~=label]{color:var(--mbx-muted,#9aa0a6)}[part~=ok]{color:var(--mbx-chart-2)}[part~=bad]{color:var(--mbx-chart-4)}[part~=na]{color:var(--mbx-muted,#9aa0a6)}[part~=ok],[part~=bad],[part~=na],[part~=maybe]{font-weight:600}`,this.toggle=X(`button`),this.toggle.setAttribute(`aria-haspopup`,`dialog`),this.toggle.setAttribute(`aria-expanded`,`false`);let n=document.createElement(`slot`);n.name=`icon`,n.append(g()),this.toggle.append(n),this.toggle.addEventListener(`click`,()=>{this.panel.hidden?this.show():this.hide()}),this.panel=Y(`div`,`panel`),this.panel.setAttribute(`role`,`dialog`),this.panel.hidden=!0,this.panel.addEventListener(`keydown`,e=>{e.key!==`Escape`||this.hasAttribute(`inline`)||(e.preventDefault(),this.hide(),this.toggle.focus())});let r=Y(`div`,`head`);r.setAttribute(`role`,`tablist`),this.tabs={},this.pages={},this.body=Y(`div`,`body`);for(let e of J){let t=X(`tab tab-${e}`,pe[e]);t.setAttribute(`role`,`tab`),t.addEventListener(`click`,()=>{this.select(e)}),this.tabs[e]=t,r.append(t);let n=Y(`div`,`page page-${e}`);n.setAttribute(`role`,`tabpanel`),n.hidden=!0,this.pages[e]=n,this.body.append(n)}this.copy=X(`copy`),this.copy.addEventListener(`click`,()=>{this.copyReport()});let i=X(`close`,`✕`);i.setAttribute(`aria-label`,`Close`),i.addEventListener(`click`,()=>{this.hide(),this.toggle.focus()}),r.append(this.copy,i);let a=Y(`div`,`chart-tabs`);a.setAttribute(`role`,`tablist`),this.chartTabs={};for(let e of c){let t=X(`chart-tab chart-tab-${e}`,e);t.setAttribute(`role`,`tab`),t.addEventListener(`click`,()=>{this.chartTab=e,this.markChartTab(),this.draw()}),this.chartTabs[e]=t,a.append(t)}this.windowSelect=Y(`select`,`window`),this.windowSelect.setAttribute(`aria-label`,`Window`);for(let e of q){let t=document.createElement(`option`);t.value=String(e),t.textContent=e<60?`${e} s`:`${e/60} min`,this.windowSelect.append(t)}this.windowSelect.addEventListener(`change`,()=>{this.draw()}),a.append(this.windowSelect),this.canvas=Y(`canvas`,`chart`);let o=Y(`div`,`legend`),s=Y(`p`,`readout`);this.pages.charts.append(a,this.canvas,o,s),this.charts=d(this.canvas,o,s),this.outside=e=>{e.composedPath().includes(this)||this.hide()},this.refit=()=>{this.fit()},this.panel.append(r,this.body),e.append(t,this.toggle,this.panel),this.markTab(),this.markChartTab(),this.renderLabels()}connectedCallback(){var e,t;this.toggleAttribute(`inline`,((e=this.parentElement)==null?void 0:e.localName)!==`mbx-control-bar`);let n=p(this);n!==null&&((t=this.cancel)==null||t.call(this),this.cancel=m(n,e=>{this.isConnected&&this.attach(e)}))}disconnectedCallback(){var e;(e=this.cancel)==null||e.call(this),this.cancel=null,this.detach()}attributeChangedCallback(){this.renderLabels()}attach(e){this.player=e,this.sampler.attach(e.video,e.engine);let t=(e,t,n)=>{e.addEventListener(t,n),this.offs.push(()=>{e.removeEventListener(t,n)})};t(e,`sourcechange`,()=>{this.sampler.attach(e.video,e.engine),this.poll()}),t(e,`error`,e=>{e.detail.fatal&&this.dispatchEvent(new CustomEvent(`report`,{detail:this.report(),bubbles:!0,composed:!0}))}),this.timer=setInterval(()=>{this.poll()},500),this.poll(),this.hasAttribute(`inline`)&&this.show()}detach(){for(let e of this.offs)e();this.offs=[],clearInterval(this.timer),this.timer=void 0,this.sampler.release(),this.hide(),this.player=null}report(){let e=this.player;if(e===null)throw Error(`mbx-diagnostics is not inside a player`);return b({player:e,samples:this.sampler.samples,marks:this.sampler.marks,counters:this.sampler.counters,history:this.sampler.history,support:this.support})}poll(){let e=this.player;e!==null&&(this.sampler.poll(e.video,e.engine),this.panel.hidden||this.paint())}show(){this.panel.hidden&&(this.panel.hidden=!1,this.hasAttribute(`inline`)||(this.setAttribute(`open`,``),this.toggle.setAttribute(`aria-expanded`,`true`),document.addEventListener(`pointerdown`,this.outside,!0),window.addEventListener(`resize`,this.refit),this.fit()),this.paint(),this.drawer=setInterval(()=>{this.draw()},250),this.hasAttribute(`inline`)||this.tabs[this.tab].focus())}hide(){clearInterval(this.drawer),this.drawer=void 0,!this.panel.hidden&&(this.panel.hidden=!0,this.removeAttribute(`open`),this.toggle.setAttribute(`aria-expanded`,`false`),document.removeEventListener(`pointerdown`,this.outside,!0),window.removeEventListener(`resize`,this.refit))}fit(){let e=this.player;if(e===null)return;let t=e.getBoundingClientRect(),n=this.getBoundingClientRect(),r=e.video.getBoundingClientRect().top,i=n.top-r-8;this.panel.style.maxHeight=`${Math.max(120,Math.floor(i))}px`;let a=Math.min(560,Math.max(200,t.width-16));this.panel.style.width=`${a}px`;let o=Math.max(t.left+8,Math.min(n.right-a,t.right-8-a));this.panel.style.right=`auto`,this.panel.style.left=`${o-n.left}px`}select(e){this.tab=e,this.markTab(),this.tabs[e].focus(),this.paint(),this.draw()}markTab(){for(let e of J)this.tabs[e].setAttribute(`aria-selected`,String(e===this.tab)),this.tabs[e].tabIndex=e===this.tab?0:-1,this.pages[e].hidden=e!==this.tab}markChartTab(){for(let e of c)this.chartTabs[e].setAttribute(`aria-selected`,String(e===this.chartTab))}renderLabels(){var e,t;if(this.toggle.setAttribute(`aria-label`,(e=this.getAttribute(`label`))==null?`Diagnostics`:e),this.panel.setAttribute(`aria-label`,(t=this.getAttribute(`label`))==null?`Diagnostics`:t),this.copied===void 0){var n;this.copy.textContent=(n=this.getAttribute(`label-copy`))==null?`Copy report`:n}let r=Number(this.getAttribute(`window`)),i=Number.isFinite(r)&&r>0?r:120;if(!q.includes(i)){let e=document.createElement(`option`);e.value=String(i),e.textContent=`${i} s`,this.windowSelect.append(e)}this.windowSelect.value=String(i)}copyReport(){var e=this;return F(function*(){var t;let n=JSON.stringify(e.report(),null,2);try{yield navigator.clipboard.writeText(n)}catch(e){return}e.copy.textContent=(t=e.getAttribute(`label-copied`))==null?`Copied`:t,clearTimeout(e.copied),e.copied=setTimeout(()=>{e.copied=void 0,e.renderLabels()},1500)})()}palette(){let e=getComputedStyle(this),t=(t,n)=>e.getPropertyValue(t).trim()||n;return{ink:t(`--mbx-text`,`#f2f3f5`),muted:t(`--mbx-muted`,`#9aa0a6`),accent:t(`--mbx-accent`,`#5b8cff`),warn:t(`--mbx-chart-3`,`#d9a83f`),series:[1,2,3,4,5].map(e=>t(`--mbx-chart-${e}`,`#888`))}}draw(){let e=this.player;e===null||this.panel.hidden||this.tab!==`charts`||this.charts.draw({tab:this.chartTab,window:Number(this.windowSelect.value)||120,samples:this.sampler.samples,marks:this.sampler.marks,counters:this.sampler.counters,video:e.video,engine:e.engine,palette:this.palette()})}paint(){let e=this.player;if(!(e===null||this.panel.hidden))switch(this.tab){case`playback`:this.sections(this.pages.playback,this.playbackSections(e));break;case`engine`:this.sections(this.pages.engine,this.engineSections(e.engine));break;case`browser`:this.browser()}}playbackSections(e){var t,c,l,u,d,f,p,m;let h=e.video,g=e.engine,_=(t=h.getVideoPlaybackQuality)==null?void 0:t.call(h),v=this.sampler.counters,y=this.sampler.samples[this.sampler.samples.length-1],b=h.paused?h.ended?`ended`:`paused`:`playing`,x=[[`source`,(c=e.getAttribute(`src`))==null?`–`:c],[`type`,(l=e.getAttribute(`type`))==null?`–`:l],[`handler`,(u=(d=e.player)==null||(d=d.session)==null?void 0:d.handler)==null?`–`:u]];g!==null&&x.push([`phase`,g.stats.snapshot().lifecycle.phase]),e.error===null?h.error!==null&&x.push([`media error`,`${h.error.code} ${h.error.message}`]):x.push([`error`,`${e.error.category}: ${e.error.code}`]);let S=[[`time`,`${r(h.currentTime)} of ${r(h.duration)}`],[`state`,`${b}, ${(f=me[h.readyState])==null?h.readyState:f}, network ${(p=he[h.networkState])==null?h.networkState:p}`],[`rate`,`${h.playbackRate}×`],[`picture`,h.videoWidth>0?`${h.videoWidth}×${h.videoHeight}`:`–`],[`frames`,_===void 0?`–`:`${_.totalVideoFrames} decoded, ${_.droppedVideoFrames} dropped (${a(_.droppedVideoFrames,_.totalVideoFrames)})`],[`buffered`,`${i((m=y==null?void 0:y.ahead)==null?0:m)}s ahead: ${o(ge(h))}`],[`stalls`,`${v.stalls}, ${v.stalledSeconds.toFixed(1)}s in total`]];if(g!==null){let e=g.stats.snapshot();S.push([`throughput`,`slow ${n(e.stats.throughputEwma)}, fast ${n(e.stats.throughputFastEwma)}`],[`playing`,s(g.quality.playing)],[`switches`,String(v.switches)])}return[{title:`Source`,rows:x},{title:`Playback`,rows:S}]}engineSections(e){var t,i,a,s,c,l,u;if(e===null)return[{title:null,rows:[],note:`A native session: the browser plays this, and there is no engine to ask.`}];let d=e.stats.snapshot(),f=e,p=d.live,m=[[`capabilities`,[...e.capabilities()].join(`, `)||`none`],[`phase`,d.lifecycle.phase],[`buffer goal`,`${d.scheduling.bufferGoal}s`],[`throughput`,`slow ${n(d.stats.throughputEwma)}, fast ${n(d.stats.throughputFastEwma)}`],[`in flight`,[...d.scheduling.inflight.values()].map(e=>`${e.trackId} #${e.seq}`).join(`, `)||`none`],[`live`,p===null?`VOD`:`window ${r(p.span.start)} to ${r(p.span.end)}, edge ${r(p.edge)}${((t=f.live)==null?void 0:t.latency)===null||((i=f.live)==null?void 0:i.latency)===void 0?``:`, ${f.live.latency.toFixed(1)}s behind`}`],[`trace`,`${e.stats.trace().length} entries`]],h=e.error;h!==null&&m.push([`last error`,`${h.category}: ${h.code}`]);let g=[...d.buffers.entries()].map(([e,t])=>[e.replace(`sb:`,``),`${t.codecs}: ${o(t.ranges)}${t.pendingAppends>0?`, ${t.pendingAppends} pending`:``}`]),_=e.tracks.available.map(t=>{var n;let r=((n=e.tracks.active(t.contentType))==null?void 0:n.id)===t.id,i=[t.lang,t.role].filter(e=>e!==void 0).join(` · `);return[`${t.contentType}${r?` ●`:``}`,`${t.id}${i===``?``:` (${i})`}, ${t.renditions.length} renditions`]}),v=(a=(s=e.quality.playing)==null?void 0:s.id)==null?null:a,y=(c=(l=e.quality.active)==null?void 0:l.id)==null?null:c,b=new Set(e.quality.allowed.map(e=>e.id)),x=e.quality.renditions.map(t=>{var r;let i=[t.id===v?`playing`:``,t.id===y&&y!==v?`next`:``,t.id===e.quality.pinned?`pinned`:``,b.has(t.id)?``:`capped`].filter(e=>e!==``),a=[t.width!==void 0&&t.height!==void 0?`${t.width}×${t.height}`:``,n(t.bitrate),t.frameRate===void 0?``:`${t.frameRate} fps`,(r=t.codecs)==null?``:r].filter(e=>e!==``).join(`, `);return[t.id,`${a}${i.length>0?` [${i.join(`, `)}]`:``}`]}),S=f.drm===void 0?[]:[[`key system`,(u=f.drm.keySystem)==null?`none yet`:u],[`keys`,f.drm.sessions.length===0?`none yet`:f.drm.sessions.map(e=>`${e.keyId}: ${e.status}`).join(`, `)]];return[{title:`Engine`,rows:m},{title:`Source buffers`,rows:g,note:g.length===0?`none yet`:void 0},{title:`Tracks`,rows:_,note:_.length===0?`none yet`:void 0},{title:`Renditions`,rows:x,note:x.length===0?`none yet`:void 0},...f.drm===void 0?[]:[{title:`DRM`,rows:S}]]}sections(e,t){var n;let r=t.flatMap(e=>{let t=[];return e.title!==null&&t.push([`heading`,e.title]),e.note!==void 0&&e.rows.length===0?t.push([`note`,e.note]):t.push([`rows`,e.rows]),t});for(;e.childElementCount>r.length;)(n=e.lastElementChild)==null||n.remove();r.forEach(([t,n],r)=>{var i;let a=e.children[r],o=t===`heading`?`h3`:t===`note`?`p`:`dl`;if(a===void 0||a.localName!==o){let n=Y(o,t);a===void 0?e.append(n):a.replaceWith(n),a=n}if(typeof n==`string`){a.textContent!==n&&(a.textContent=n);return}for(;a.childElementCount>n.length*2;)(i=a.lastElementChild)==null||i.remove();n.forEach(([e,t],n)=>{let r=a.children[n*2],i=a.children[n*2+1];(r===void 0||i===void 0)&&(r=Y(`dt`,`key`),i=Y(`dd`,`value`),a.append(r,i)),r.textContent!==e&&(r.textContent=e),i.textContent!==t&&(i.textContent=t)})})}browser(){let e=this.pages.browser;this.support!==null||this.probing||(this.probing=!0,t(e,Y(`p`,`note`,`Probing the browser…`)),K().then(t=>{this.support=t,this.probing=!1,this.tables(e,t)}))}tables(e,n){t(e),e.append(Y(`h3`,`heading`,`Platform`),Y(`p`,`note`,n.userAgent));let r=Y(`table`,`table`);for(let e of n.platform){let t=document.createElement(`tr`),[n,i]=Z(e.value);t.append(Y(`th`,`cell label`,e.label),Y(`td`,i,n)),r.append(t)}e.append(r),e.append(Y(`h3`,`heading`,`Codecs`));let i=Y(`table`,`table`),a=document.createElement(`tr`);for(let e of[`Codec`,`MSE fMP4`,`MSE WebM`,`<video>`,`Smooth`,`Efficient`])a.append(Y(`th`,`cell label`,e));i.append(a);for(let e of n.codecs){let t=document.createElement(`tr`),n=Y(`th`,`cell label`,e.label);n.title=e.codec,t.append(n);for(let n of[e.mse,e.webm,e.element,e.smooth,e.efficient]){let[e,r]=Z(n);t.append(Y(`td`,r,e))}i.append(t)}e.append(i),e.append(Y(`h3`,`heading`,`DRM`));let o=Y(`table`,`table`),s=document.createElement(`tr`);for(let e of[`System`,`Available`,`Level`,`Schemes`,`Persistent`,`Identifier`,`HDCP`])s.append(Y(`th`,`cell label`,e));o.append(s);for(let e of n.drm){let t=document.createElement(`tr`),n=Y(`th`,`cell label`,e.label);e.keySystem!==null&&(n.title=e.keySystem),t.append(n);let r=[e.keySystem===null?`no`:`yes`,e.level,e.schemes,e.persistent,e.identifier,e.hdcp];for(let e of r){let[n,r]=Z(e);t.append(Y(`td`,r,n))}o.append(t)}e.append(o)}};function ge(e){return Array.from({length:e.buffered.length},(t,n)=>({start:e.buffered.start(n),end:e.buffered.end(n)}))}let $=`mbx-diagnostics`;return customElements.get(`mbx-diagnostics`)===void 0&&customElements.define($,Q),e.DIAGNOSTICS=$,e.MbxDiagnostics=Q,e.probeSupport=K,e})({});
1
+ var matteboxPlayerDiagnostics=(function(e){Object.defineProperty(e,Symbol.toStringTag,{value:`Module`});function t(e,...t){for(;e.firstChild!==null;)e.firstChild.remove();e.append(...t)}function n(e){return!Number.isFinite(e)||e<=0?`0 bps`:e>=1e6?`${(e/1e6).toFixed(e>=1e7?0:1)} Mbps`:e>=1e3?`${Math.round(e/1e3)} kbps`:`${Math.round(e)} bps`}function r(e){if(!Number.isFinite(e))return`–`;let t=Math.max(0,Math.floor(e)),n=Math.floor(t/3600),r=Math.floor(t%3600/60),i=t%60,a=e=>e<10?`0${e}`:`${e}`;return n>0?`${n}:${a(r)}:${a(i)}`:`${r}:${a(i)}`}function i(e,t=1){return e==null||!Number.isFinite(e)?`–`:e.toFixed(t)}function a(e,t){return t>0?`${(e/t*100).toFixed(2)}%`:`0%`}function o(e){return e.length===0?`none`:e.map(e=>`${e.start.toFixed(1)}–${e.end.toFixed(1)}`).join(`, `)}function s(e){return e===null?`–`:e.height===void 0?n(e.bitrate):`${e.height}p, ${n(e.bitrate)}`}let c=[`buffer`,`throughput`,`stalls`,`frames`,`switches`];function l(e,t){let n=e/Math.max(t,1),r=Math.pow(10,Math.floor(Math.log10(Math.max(n,1e-9))));for(let e of[1,2,5,10])if(n<=e*r)return e*r;return 10*r}function u(e,t){let n=document.createElement(`canvas`).getContext(`2d`);if(n===null)return e;n.fillStyle=e;let r=n.fillStyle;return/^#[0-9a-f]{6}$/i.test(r)?`rgba(${Number.parseInt(r.slice(1,3),16)}, ${Number.parseInt(r.slice(3,5),16)}, ${Number.parseInt(r.slice(5,7),16)}, ${t})`:e}function d(e,i,a){function o(){let t=e.getContext(`2d`);if(t===null)return null;let n=window.devicePixelRatio||1,r=e.clientWidth,i=e.clientHeight;if(r===0||i===0)return null;let a=Math.round(r*n),o=Math.round(i*n);return(e.width!==a||e.height!==o)&&(e.width=a,e.height=o),t.setTransform(n,0,0,n,0,0),t.clearRect(0,0,r,i),t.font=`10px ui-monospace, SFMono-Regular, Menlo, Consolas, monospace`,{ctx:t,w:r,h:i,left:44,right:r-8,top:8,bottom:i-18}}function s(e,t,n,i){let a=r=>e.left+(r-t)/(n-t)*(e.right-e.left),o=(n-t)/1e3,s=l(o,6);e.ctx.strokeStyle=u(i.muted,.25),e.ctx.fillStyle=i.muted,e.ctx.textAlign=`center`,e.ctx.textBaseline=`top`;for(let t=0;t<=o;t+=s){let i=a(n-t*1e3);e.ctx.beginPath(),e.ctx.moveTo(i,e.top),e.ctx.lineTo(i,e.bottom),e.ctx.stroke();let o=t===0?`now`:t<60?`-${t}s`:`-${r(t)}`;e.ctx.fillText(o,i,e.bottom+3)}return a}function c(e,t,n,r){let i=n=>e.bottom-n/t*(e.bottom-e.top),a=l(t,4);e.ctx.strokeStyle=u(r.muted,.25),e.ctx.fillStyle=r.muted,e.ctx.textAlign=`right`,e.ctx.textBaseline=`middle`;for(let r=0;r<=t;r+=a){let t=i(r);e.ctx.beginPath(),e.ctx.moveTo(e.left,t),e.ctx.lineTo(e.right,t),e.ctx.stroke(),e.ctx.fillText(n(r),e.left-4,t)}return i}function d(e,t,n,r={}){var i;if(t.length===0)return;e.ctx.save(),e.ctx.strokeStyle=n,e.ctx.lineWidth=(i=r.width)==null?2:i,e.ctx.setLineDash(r.dashed===!0?[4,4]:[]),e.ctx.beginPath();let a;for(let n of t)a===void 0?e.ctx.moveTo(n[0],n[1]):(r.step===!0&&e.ctx.lineTo(n[0],a[1]),e.ctx.lineTo(n[0],n[1])),a=n;e.ctx.stroke(),e.ctx.restore()}function f(e,t,n,r,i=2.5){e.ctx.fillStyle=r,e.ctx.beginPath(),e.ctx.arc(t,n,i,0,Math.PI*2),e.ctx.fill()}function p(e,t,n,r){e.ctx.save(),e.ctx.strokeStyle=n,e.ctx.lineWidth=1,e.ctx.setLineDash([2,3]),e.ctx.beginPath(),e.ctx.moveTo(t,e.top),e.ctx.lineTo(t,e.bottom),e.ctx.stroke(),e.ctx.restore(),e.ctx.fillStyle=n,e.ctx.textAlign=`center`,e.ctx.textBaseline=`top`,e.ctx.fillText(r,t,e.top)}function m(e){t(i);for(let[t,n]of e){let e=document.createElement(`span`);e.setAttribute(`part`,`legend-item`);let r=document.createElement(`span`);r.setAttribute(`part`,`swatch`),r.style.background=n,e.append(r,t),i.append(e)}}function h(e,t){let n=e.findIndex(e=>e.t>=t);return n<0?e.length>0?[e[e.length-1]]:[]:e.slice(Math.max(0,n-1))}function g(e){var t;return(t=e==null?void 0:e.quality.renditions)==null?[]:t}function _(e,t){var i,o,s,c,l,d;let{video:f,engine:h,palette:_}=t,v=(i=h==null?void 0:h.stats.snapshot())==null?null:i,y=(o=v==null||(s=v.presentation)==null?void 0:s.duration)==null?f.duration:o,b=(c=v==null?void 0:v.live)==null?null:c,x=f.currentTime,S=0,C=Number.isFinite(y)&&y>0?y:Math.max(x+10,10);b===null?C>600&&(S=Math.max(0,x-60),C=x+180):(S=b.span.start,C=Math.max(b.span.end,x+10));let w=t=>e.left+(t-S)/(C-S)*(e.right-e.left),T=v===null?[{label:`video`,ranges:Array.from({length:f.buffered.length},(e,t)=>({start:f.buffered.start(t),end:f.buffered.end(t)}))}]:[...v.buffers.entries()].map(([e,t])=>({label:e.replace(`sb:`,``),ranges:t.ranges}));T.length===0&&T.push({label:`video`,ranges:[]});let E=g(h),D=Math.min(34,(e.bottom-e.top-8*(T.length-1))/T.length);e.ctx.textAlign=`left`,e.ctx.textBaseline=`middle`,T.forEach((t,n)=>{let r=e.top+n*(D+8);if(e.ctx.fillStyle=u(_.muted,.15),e.ctx.fillRect(e.left,r,e.right-e.left,D),v!==null)for(let[t,n]of v.quality.appendLog){var i;let a=E.findIndex(e=>e.id===n);e.ctx.fillStyle=u((i=_.series[Math.max(0,a)%_.series.length])==null?_.accent:i,.3),e.ctx.fillRect(w(t.start),r,Math.max(1,w(t.end)-w(t.start)),D)}e.ctx.fillStyle=_.ink;for(let n of t.ranges)e.ctx.fillRect(w(n.start),r+D-4,Math.max(1,w(n.end)-w(n.start)),3);e.ctx.fillStyle=_.muted,e.ctx.fillText(t.label,e.left+4,r+D/2)}),b!==null&&p(e,w(b.edge),_.warn,`edge`),e.ctx.fillStyle=_.accent,e.ctx.fillRect(w(x)-1,e.top,2,e.bottom-e.top),e.ctx.fillStyle=_.muted,e.ctx.textAlign=`left`,e.ctx.textBaseline=`top`,e.ctx.fillText(r(S),e.left,e.bottom+3),e.ctx.textAlign=`right`,e.ctx.fillText(r(C),e.right,e.bottom+3),m([...E.map((e,t)=>{var r;return[e.height===void 0?n(e.bitrate):`${e.height}p`,(r=_.series[t%_.series.length])==null?_.accent:r]}),[`buffered`,_.ink],[`playhead`,_.accent]]);let O=(l=(d=t.samples[t.samples.length-1])==null?void 0:d.ahead)==null?0:l;a.textContent=`${r(x)} of ${r(C)}, ${O.toFixed(1)}s buffered ahead${b===null?``:`, window ${r(b.span.start)} to ${r(b.span.end)}`}`}function v(e,t,r,i){var o,l,u,p,g,_;let v=t.palette,y=h(t.samples,r),b=t.marks.filter(e=>e.kind===`segment`&&e.t>=r),x=c(e,Math.max(1e6,...y.map(e=>Math.max(e.slow,e.fast,e.playingBitrate)),...b.map(e=>e.value))*1.15,e=>(e/1e6).toFixed(e>=1e7?0:1),v),S=s(e,r,i,v);for(let t of b){var C,w,T;let n=((C=t.trackId)==null?void 0:C.startsWith(`aud`))===!0||((w=t.trackId)==null?void 0:w.includes(`audio`))===!0;f(e,S(t.t),x(t.value),(T=n?v.series[4]:v.series[0])==null?v.accent:T)}d(e,y.map(e=>[S(e.t),x(e.slow)]),(o=v.series[1])==null?v.accent:o),d(e,y.map(e=>[S(e.t),x(e.fast)]),(l=v.series[2])==null?v.accent:l,{dashed:!0}),d(e,y.map(e=>[S(e.t),x(e.playingBitrate)]),v.muted,{step:!0,width:1.5}),m([[`video segment`,(u=v.series[0])==null?v.accent:u],[`audio segment`,(p=v.series[4])==null?v.accent:p],[`slow estimate`,(g=v.series[1])==null?v.accent:g],[`fast estimate`,(_=v.series[2])==null?v.accent:_],[`playing bitrate`,v.muted]]);let E=y[y.length-1];a.textContent=E===void 0?`Mbps`:`Mbps. Now: slow ${n(E.slow)}, fast ${n(E.fast)}, playing ${n(E.playingBitrate)}`}function y(e,t,n,r){var i,o,l,f,g;let _=t.palette,v=h(t.samples,n),y=c(e,Math.max(5,...v.map(e=>e.ahead))*1.15,e=>`${e.toFixed(0)}s`,_),b=s(e,n,r,_);e.ctx.fillStyle=u((i=_.series[3])==null?_.accent:i,.25);let x=null;for(let[t,n]of v.entries()){n.stalled&&x===null&&(x=n.t);let r=t===v.length-1;(!n.stalled||r)&&x!==null&&(e.ctx.fillRect(b(x),e.top,Math.max(2,b(n.t)-b(x)),e.bottom-e.top),x=null)}d(e,v.map(e=>[b(e.t),y(e.ahead)]),(o=_.series[0])==null?_.accent:o);for(let r of t.marks)r.t<n||r.kind===`segment`||r.kind===`switch`||(r.kind===`stall`?p(e,b(r.t),_.accent,`!`):r.kind===`seek`?p(e,b(r.t),_.muted,`>`):p(e,b(r.t),_.warn,r.kind.charAt(0).toUpperCase()));m([[`buffered ahead`,(l=_.series[0])==null?_.accent:l],[`stalled`,(f=_.series[3])==null?_.accent:f],[`! stall`,_.accent],[`> seek`,_.muted],[`N F S G recovery`,_.warn]]);let S=t.counters,C=((g=v[v.length-1])==null?void 0:g.stalled)===!0?`, stalled now`:``;a.textContent=`${S.stalls} stalls, ${S.stalledSeconds.toFixed(1)}s stalled in total${C}`}function b(e,t,n,r){var i,o;let l=t.palette,u=h(t.samples,n),f=u.map((e,t)=>{let n=u[t-1],r=n===void 0?.5:Math.max((e.t-n.t)/1e3,.05);return e.decoded/r}),p=c(e,Math.max(30,...f)*1.15,e=>e.toFixed(0),l),g=s(e,n,r,l),_=Math.max(1,...u.map(e=>e.dropped));e.ctx.fillStyle=l.accent;for(let t of u){if(t.dropped===0)continue;let n=t.dropped/_*(e.bottom-e.top)*.6;e.ctx.fillRect(g(t.t)-1.5,e.bottom-n,3,n)}d(e,u.map((e,t)=>{var n;return[g(e.t),p((n=f[t])==null?0:n)]}),(i=l.series[0])==null?l.accent:i),m([[`decoded per second`,(o=l.series[0])==null?l.accent:o],[`dropped, relative`,l.accent]]);let v=t.counters,y=v.decoded>0?(v.dropped/v.decoded*100).toFixed(2):`0.00`;a.textContent=`${v.decoded} decoded, ${v.dropped} dropped (${y}%) this session`}function x(e,t,r,i){var o,c;let l=t.palette,f=h(t.samples,r),_=g(t.engine),v=_.some(e=>e.height!==void 0),y=_.map(e=>{var t;return v?(t=e.height)==null?0:t:e.bitrate}),b=Math.max(1,...y,...f.map(e=>v?e.playingHeight:e.playingBitrate))*1.15,x=t=>e.bottom-t/b*(e.bottom-e.top);e.ctx.strokeStyle=u(l.muted,.25),e.ctx.fillStyle=l.muted,e.ctx.textAlign=`right`,e.ctx.textBaseline=`middle`;for(let t of y){let r=x(t);e.ctx.beginPath(),e.ctx.moveTo(e.left,r),e.ctx.lineTo(e.right,r),e.ctx.stroke(),e.ctx.fillText(v?`${t}p`:n(t),e.left-4,r)}let S=s(e,r,i,l);d(e,f.map(e=>[S(e.t),x(v?e.playingHeight:e.playingBitrate)]),(o=l.series[0])==null?l.accent:o,{step:!0});for(let n of t.marks)n.kind===`switch`&&n.t>=r&&p(e,S(n.t),l.warn,`S`);m([[`playing`,(c=l.series[0])==null?l.accent:c],[`S switch`,l.warn]]);let C=f[f.length-1],w=C===void 0||C.playingId===null?`–`:v?`${C.playingHeight}p`:n(C.playingBitrate);a.textContent=`${t.counters.switches} switches this session, now ${w}`}return{draw(e){let t=o();if(t===null)return;if(e.engine===null&&(e.tab===`throughput`||e.tab===`switches`)){m([]),a.textContent=`A native session: the browser holds this, and says nothing.`;return}let n=performance.now(),r=n-e.window*1e3;switch(e.tab){case`buffer`:_(t,e);break;case`throughput`:v(t,e,r,n);break;case`stalls`:y(t,e,r,n);break;case`frames`:b(t,e,r,n);break;case`switches`:x(t,e,r,n)}}}}function f(e){let t=e.parentNode;return t===null?e instanceof ShadowRoot?e.host:null:t}function p(e){let t=e;for(;t!==null;){if(t instanceof HTMLElement&&t.localName===`mattebox-player`)return t;t=f(t)}return null}function m(e,t){let n=!0,r=()=>{n&&(n=!1,customElements.upgrade(e),`video`in e&&t(e))};return`video`in e?r():customElements.whenDefined(`mattebox-player`).then(r),()=>{n=!1}}let h=`http://www.w3.org/2000/svg`;function g(){let e=document.createElementNS(h,`svg`);e.setAttribute(`viewBox`,`0 0 32 32`),e.setAttribute(`aria-hidden`,`true`),e.setAttribute(`part`,`icon`);let t=document.createElementNS(h,`path`);return t.setAttribute(`fill-rule`,`evenodd`),t.setAttribute(`d`,`M17.534 10.6674C17.534 11.5143 16.8475 12.2008 16.0006 12.2008C15.1538 12.2008 14.4673 11.5143 14.4673 10.6674C14.4673 9.82061 15.1538 9.13411 16.0006 9.13411C16.8475 9.13411 17.534 9.82061 17.534 10.6674Z M14.6678 14.2005C14.6678 13.8323 14.9663 13.5339 15.3345 13.5339H16.6678C17.036 13.5339 17.3345 13.8323 17.3345 14.2005V22.2005C17.3345 22.5687 17.036 22.8672 16.6678 22.8672H15.3345C14.9663 22.8672 14.6678 22.5687 14.6678 22.2005V14.2005Z M28 16C28 22.6274 22.6274 28 16 28C9.37258 28 4 22.6274 4 16C4 9.37258 9.37258 4 16 4C22.6274 4 28 9.37258 28 16ZM24.9333 16C24.9333 20.9337 20.9337 24.9333 16 24.9333C11.0663 24.9333 7.06667 20.9337 7.06667 16C7.06667 11.0663 11.0663 7.06667 16 7.06667C20.9337 7.06667 24.9333 11.0663 24.9333 16Z`),e.append(t),e}function _(e){return Array.from({length:e.length},(t,n)=>({start:e.start(n),end:e.end(n)}))}function v(e){var t;let n=(t=e.getVideoPlaybackQuality)==null?void 0:t.call(e);return{currentTime:e.currentTime,duration:e.duration,paused:e.paused,ended:e.ended,seeking:e.seeking,readyState:e.readyState,networkState:e.networkState,playbackRate:e.playbackRate,volume:e.volume,muted:e.muted,videoWidth:e.videoWidth,videoHeight:e.videoHeight,buffered:_(e.buffered),seekable:_(e.seekable),frames:n===void 0?null:{decoded:n.totalVideoFrames,dropped:n.droppedVideoFrames},mediaError:e.error===null?null:{code:e.error.code,message:e.error.message}}}function y(e){var t,n,r,i,a,o,s;let c=e.stats.snapshot(),l=e,u=e.error;return{phase:c.lifecycle.phase,capabilities:[...e.capabilities()],throughput:{slow:c.stats.throughputEwma,fast:c.stats.throughputFastEwma},bufferGoal:c.scheduling.bufferGoal,buffers:[...c.buffers.entries()].map(([e,t])=>({id:e,codecs:t.codecs,ranges:t.ranges.map(e=>({start:e.start,end:e.end}))})),inflight:[...c.scheduling.inflight.values()].map(e=>({trackId:e.trackId,seq:e.seq,url:e.url})),live:c.live===null?null:{start:c.live.span.start,end:c.live.span.end,edge:c.live.edge,latency:(t=(n=l.live)==null?void 0:n.latency)==null?null:t},tracks:{active:Object.fromEntries([`video`,`audio`,`text`].map(t=>{var n,r;return[t,(n=(r=e.tracks.active(t))==null?void 0:r.id)==null?null:n]})),available:e.tracks.available.map(e=>{var t,n;return{id:e.id,contentType:e.contentType,mimeType:e.mimeType,lang:(t=e.lang)==null?null:t,role:(n=e.role)==null?null:n,renditions:e.renditions.length}})},quality:{playing:(r=(i=e.quality.playing)==null?void 0:i.id)==null?null:r,active:(a=(o=e.quality.active)==null?void 0:o.id)==null?null:a,pinned:e.quality.pinned,allowed:e.quality.allowed.map(e=>e.id),renditions:e.quality.renditions.map(e=>{var t,n,r;return{id:e.id,bitrate:e.bitrate,width:(t=e.width)==null?null:t,height:(n=e.height)==null?null:n,frameRate:(r=e.frameRate)==null?null:r,codecs:e.codecs}})},drm:l.drm===void 0?null:{keySystem:l.drm.keySystem,sessions:[...l.drm.sessions]},qoe:l.qoe===void 0?null:{startupTime:l.qoe.startupTime,rebuffers:l.qoe.rebuffers,rebufferDuration:l.qoe.rebufferDuration,switches:l.qoe.switches},error:u===null?null:{category:u.category,code:u.code,fatal:u.fatal,recoverable:u.recoverable,context:(s=u.context)==null?null:s}}}function b(e){var t,n;let{player:r}=e,i=r.engine,a=e.samples.slice(-240),o=performance.now()-12e4;return{at:(/* @__PURE__ */ new Date()).toISOString(),userAgent:navigator.userAgent,source:{url:r.getAttribute(`src`),type:r.getAttribute(`type`),handler:(t=(n=r.player)==null||(n=n.session)==null?void 0:n.handler)==null?null:t},playback:v(r.video),error:r.error,engine:i===null?null:y(i),counters:e.counters,samples:a,marks:e.marks.filter(e=>e.t>=o),support:e.support,trace:i===null?null:e.history}}function x(e){"@babel/helpers - typeof";return x=typeof Symbol==`function`&&typeof Symbol.iterator==`symbol`?function(e){return typeof e}:function(e){return e&&typeof Symbol==`function`&&e.constructor===Symbol&&e!==Symbol.prototype?`symbol`:typeof e},x(e)}function S(e,t){if(x(e)!=`object`||!e)return e;var n=e[Symbol.toPrimitive];if(n!==void 0){var r=n.call(e,t||`default`);if(x(r)!=`object`)return r;throw TypeError(`@@toPrimitive must return a primitive value.`)}return(t===`string`?String:Number)(e)}function C(e){var t=S(e,`string`);return x(t)==`symbol`?t:t+``}function w(e,t,n){return(t=C(t))in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function T(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter(function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable})),n.push.apply(n,r)}return n}function E(e){for(var t=1;t<arguments.length;t++){var n=arguments[t]==null?{}:arguments[t];t%2?T(Object(n),!0).forEach(function(t){w(e,t,n[t])}):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):T(Object(n)).forEach(function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))})}return e}function D(e){return Array.isArray(e)?e.length:typeof e==`object`&&e&&`kind`in e?String(e.kind):0}function O(e){var t,n;return{id:e.id,isLive:e.isLive,duration:(t=e.duration)==null?null:t,live:(n=e.live)==null?null:n,periods:e.periods.map(e=>{var t;return{id:e.id,start:e.start,duration:(t=e.duration)==null?null:t,tracks:e.tracks.map(e=>{var t,n;return{id:e.id,contentType:e.contentType,mimeType:e.mimeType,lang:(t=e.lang)==null?null:t,role:(n=e.role)==null?null:n,protected:e.protection!==null&&e.protection.schemes.length>0,renditions:e.renditions.map(e=>{var t,n;return{id:e.id,bitrate:e.bitrate,width:(t=e.width)==null?null:t,height:(n=e.height)==null?null:n,codecs:e.codecs,segments:D(e.segments)}})}})}})}}function k(e){switch(e.type){case`MANIFEST_LOADED`:return{type:e.type,presentation:O(e.presentation)};case`PLAYLIST_REFRESHED`:return E(E({},e),{},{segments:D(e.segments)});case`SEGMENT_LOADED`:return E(E({},e),{},{bytes:A(e.bytes)});default:return e}}function A(e){return e instanceof ArrayBuffer||ArrayBuffer.isView(e)?e.byteLength:e}function j(e){if(e.kind===`emit`&&e.event===`tracks:changed`)return{kind:e.kind,event:e.event};if(e.kind===`schedule`)return E(E({},e),{},{then:k(e.then)});let t={};for(let[n,r]of Object.entries(e))t[n]=A(r);return t}function M(e,t){return t instanceof ArrayBuffer||ArrayBuffer.isView(t)?t.byteLength:t instanceof Map?Object.fromEntries(t):t instanceof Set?[...t]:typeof t==`function`?`[function]`:typeof Node<`u`&&t instanceof Node?`[${t.nodeName}]`:t}function ee(e){let t={t:e.t,msg:k(e.msg),effects:e.effects.map(j),digest:e.digest};return JSON.parse(JSON.stringify(t,M))}let N=2400,te=/* @__PURE__ */ new Set([`nudge`,`flush`,`skip`,`gap-jump`]);function ne(e){return e.height===void 0?`${Math.round(e.bitrate/1e3)} kbps`:`${e.height}p`}function re(){let e=[],t=[],n=[],r=/* @__PURE__ */ new WeakSet,i=null,a=null,o=0,s=null,c=null,l=null,u=0,d=0,f=0,p=0,m=0;function h(e){t.push(e),t.length>N*2&&t.splice(0,t.length-N*2)}function g(e){let t=e.stats.trace(),n=0;if(a!==null){let e=t.indexOf(a);n=e>=0?e+1:t.findIndex(e=>e.t>o),n<0&&(n=t.length)}let r=t[t.length-1];return r!==void 0&&(a=r,o=r.t),t.slice(n)}function _(e,t){if(!r.has(e)){r.add(e),n.push(ee(e)),n.length>500&&n.splice(0,n.length-500);{let n=e.msg;n.type===`SEGMENT_LOADED`&&n.trackId!==`manifest`&&n.size>0?h({t:e.t,kind:`segment`,value:n.size*8e3/Math.max(n.rtt,1),label:`${n.trackId} #${n.seq}`,trackId:n.trackId}):n.type===`STALLED`?h({t:e.t,kind:`stall`,value:n.at,label:`stalled at ${n.at.toFixed(1)}s`}):n.type===`SEEKING`&&h({t:e.t,kind:`seek`,value:n.to,label:`seek to ${n.to.toFixed(1)}s`});for(let n of e.effects){if(n.kind!==`emit`)continue;let r=n.event.replace(`recovery:`,``);te.has(r)&&h({t:e.t,kind:r,value:t.currentTime,label:`recovery ${r}`})}}}}function v(){e=[],t=[],n=[],r=/* @__PURE__ */ new WeakSet,a=null,o=0,s=null,c=null,l=null,u=0,d=0,f=0,p=0,m=0}function y(){i==null||i(),i=null}return{attach(e,t){y(),v(),t!==null&&(i=t.on(`trace`,t=>{_(t,e)}))},release:y,poll(t,n){var r,i,a,o,v,y,b,x,S,C;let w=performance.now();if(n!==null)for(let e of g(n))_(e,t);let T=(r=n==null?void 0:n.stats.snapshot())==null?null:r,E=(i=n==null?void 0:n.quality.playing)==null?null:i,D=(a=t.getVideoPlaybackQuality)==null?void 0:a.call(t);p=(o=D==null?void 0:D.totalVideoFrames)==null?0:o,m=(v=D==null?void 0:D.droppedVideoFrames)==null?0:v;let O=s===null?0:Math.max(0,m-s.dropped),k=s===null?0:Math.max(0,p-s.decoded);s={dropped:m,decoded:p};let A=0;for(let e=0;e<t.buffered.length;e+=1)t.buffered.start(e)<=t.currentTime+.25&&t.buffered.end(e)>t.currentTime&&(A=t.buffered.end(e)-t.currentTime);let j=!t.paused&&!t.ended&&!t.seeking&&t.readyState<3&&t.currentTime>0;if(j&&l===null?(l=w,u+=1):!j&&l!==null&&(d+=(w-l)/1e3,l=null),E!==null&&c!==null&&E.id!==c){var M;f+=1,h({t:w,kind:`switch`,value:(M=E.height)==null?E.bitrate:M,label:`now ${ne(E)}`})}E!==null&&(c=E.id),e.push({t:w,currentTime:t.currentTime,slow:(y=T==null?void 0:T.stats.throughputEwma)==null?0:y,fast:(b=T==null?void 0:T.stats.throughputFastEwma)==null?0:b,ahead:A,stalled:j,dropped:O,decoded:k,playingId:(x=E==null?void 0:E.id)==null?null:x,playingBitrate:(S=E==null?void 0:E.bitrate)==null?0:S,playingHeight:(C=E==null?void 0:E.height)==null?0:C}),e.length>N&&e.splice(0,e.length-N)},get samples(){return e},get marks(){return t},get history(){return n},get counters(){let e=l===null?0:(performance.now()-l)/1e3;return{stalls:u,stalledSeconds:d+e,switches:f,decoded:p,dropped:m}}}}function P(e,t,n,r,i,a,o){try{var s=e[a](o),c=s.value}catch(e){n(e);return}s.done?t(c):Promise.resolve(c).then(r,i)}function F(e){return function(){var t=this,n=arguments;return new Promise(function(r,i){var a=e.apply(t,n);function o(e){P(a,r,i,o,s,`next`,e)}function s(e){P(a,r,i,o,s,`throw`,e)}o(void 0)})}}let I=[{label:`H.264 High 4.0`,codec:`avc1.640028`,kind:`video`,containers:[`mp4`]},{label:`H.264 Baseline`,codec:`avc1.42e01e`,kind:`video`,containers:[`mp4`]},{label:`H.265 / HEVC Main`,codec:`hvc1.1.6.L123.B0`,kind:`video`,containers:[`mp4`]},{label:`VP9 Profile 0`,codec:`vp09.00.40.08`,kind:`video`,containers:[`mp4`,`webm`]},{label:`AV1 Main`,codec:`av01.0.08M.08`,kind:`video`,containers:[`mp4`,`webm`]},{label:`AAC-LC`,codec:`mp4a.40.2`,kind:`audio`,containers:[`mp4`]},{label:`HE-AAC`,codec:`mp4a.40.5`,kind:`audio`,containers:[`mp4`]},{label:`Opus`,codec:`opus`,kind:`audio`,containers:[`mp4`,`webm`]},{label:`FLAC`,codec:`flac`,kind:`audio`,containers:[`mp4`]},{label:`AC-3`,codec:`ac-3`,kind:`audio`,containers:[`mp4`]},{label:`E-AC-3`,codec:`ec-3`,kind:`audio`,containers:[`mp4`]}],ie=[{label:`Widevine`,keySystems:[`com.widevine.alpha`],levels:[[`HW_SECURE_ALL`,`L1`],[`HW_SECURE_DECODE`,`L1`],[`HW_SECURE_CRYPTO`,`L2`],[`SW_SECURE_DECODE`,`L3`],[`SW_SECURE_CRYPTO`,`L3`]]},{label:`PlayReady`,keySystems:[`com.microsoft.playready.recommendation`,`com.microsoft.playready`],levels:[[`3000`,`SL3000`],[`2000`,`SL2000`],[`150`,`SL150`]]},{label:`FairPlay`,keySystems:[`com.apple.fps`,`com.apple.fps.1_0`],levels:[]},{label:`ClearKey`,keySystems:[`org.w3.clearkey`],levels:[]}],ae=[`1.0`,`1.1`,`1.2`,`1.3`,`1.4`,`2.0`,`2.1`,`2.2`,`2.3`];function L(e,t,n=4e3){return new Promise(r=>{let i=setTimeout(()=>r(t),n);e.then(e=>{clearTimeout(i),r(e)},()=>{clearTimeout(i),r(t)})})}function R(e){return e in globalThis?`yes`:`no`}function oe(){let e=`no`;try{typeof MediaSource<`u`&&`changeType`in SourceBuffer.prototype&&(e=`yes`)}catch(t){e=`no`}return[{label:`Secure context`,value:window.isSecureContext?`yes`:`no`},{label:`MediaSource`,value:R(`MediaSource`)},{label:`ManagedMediaSource`,value:R(`ManagedMediaSource`)},{label:`SourceBuffer.changeType`,value:e},{label:`Encrypted Media (EME)`,value:R(`MediaKeys`)},{label:`MediaCapabilities`,value:navigator.mediaCapabilities===void 0?`no`:`yes`},{label:`WebCodecs`,value:R(`VideoDecoder`)}]}function se(e){try{return typeof MediaSource<`u`&&MediaSource.isTypeSupported(e)}catch(e){return!1}}function ce(e){let t=document.createElement(`video`).canPlayType(e);return t===`probably`?`yes`:t===`maybe`?`maybe`:`no`}function le(e){return z.apply(this,arguments)}function z(){return z=F(function*(e){let t=navigator.mediaCapabilities;if((t==null?void 0:t.decodingInfo)===void 0)return{smooth:`na`,efficient:`na`};let n=`${e.kind}/${e.containers[0]}; codecs="${e.codec}"`,r=e.kind===`video`?{type:`media-source`,video:{contentType:n,width:1920,height:1080,bitrate:6e6,framerate:30}}:{type:`media-source`,audio:{contentType:n,channels:`2`,bitrate:128e3}},i=yield L(t.decodingInfo(r),null);return i===null?{smooth:`na`,efficient:`na`}:i.supported?{smooth:i.smooth?`yes`:`no`,efficient:i.powerEfficient?`yes`:`no`}:{smooth:`no`,efficient:`no`}}),z.apply(this,arguments)}function ue(e){return B.apply(this,arguments)}function B(){return B=F(function*(e){let t=t=>e.containers.includes(t)?se(`${e.kind}/${t}; codecs="${e.codec}"`)?`yes`:`no`:`na`,{smooth:n,efficient:r}=yield le(e);return{label:e.label,codec:e.codec,kind:e.kind,mse:t(`mp4`),webm:t(`webm`),element:ce(`${e.kind}/${e.containers[0]}; codecs="${e.codec}"`),smooth:n,efficient:r}}),B.apply(this,arguments)}function V(e={}){return[E({contentType:`video/mp4; codecs="avc1.42e01e"`},e),E({contentType:`video/mp4; codecs="vp09.00.10.08"`},e)]}function H(e={}){return E({initDataTypes:[`cenc`,`keyids`,`sinf`,`skd`],videoCapabilities:V(),audioCapabilities:[{contentType:`audio/mp4; codecs="mp4a.40.2"`},{contentType:`audio/mp4; codecs="opus"`}]},e)}function U(e,t){return typeof navigator.requestMediaKeySystemAccess==`function`?L(navigator.requestMediaKeySystemAccess(e,[t]).then(e=>e,()=>null),null):Promise.resolve(null)}let de=e=>({label:e,keySystem:null,level:`na`,schemes:`na`,persistent:`na`,identifier:`na`,hdcp:`na`});function fe(e){return W.apply(this,arguments)}function W(){return W=F(function*(e){let t=null,n=null;for(let r of e.keySystems)if(n=yield U(r,H()),n!==null){t=r;break}if(t===null||n===null)return de(e.label);let r=e.levels.length===0?`n/a for this system`:`none granted`;for(let[n,i]of e.levels)if((yield U(t,H({videoCapabilities:V({robustness:n})})))!==null){r=`${i} (${n})`;break}let i=[],a=!1;for(let e of[`cenc`,`cbcs`]){var o;let n=yield U(t,H({videoCapabilities:V({encryptionScheme:e})})),r=n==null||(o=n.getConfiguration().videoCapabilities)==null||(o=o.find(e=>e.contentType!==``))==null?void 0:o.encryptionScheme;r!=null&&(a=!0),r===e&&i.push(e)}let s=a?i.length===0?`none`:i.join(`, `):`unknown (no API)`,c=yield U(t,H({persistentState:`required`,sessionTypes:[`persistent-license`]})),l=yield U(t,H({distinctiveIdentifier:`required`})),u=`na`;try{let e=yield L(n.createMediaKeys(),null);if(e!==null&&typeof e.getStatusForPolicy==`function`){let t=null;for(let n of ae){if((yield L(e.getStatusForPolicy({minHdcpVersion:n}),`unknown`))!==`usable`)break;t=n}u=t===null?`no output protection`:`up to ${t}`}}catch(e){u=`na`}return{label:e.label,keySystem:t,level:r,schemes:s,persistent:c===null?`no`:`yes`,identifier:l===null?`no`:`yes`,hdcp:u}}),W.apply(this,arguments)}let G=null;function K(){return G===null&&(G=F(function*(){return{userAgent:navigator.userAgent,platform:oe(),codecs:yield Promise.all(I.map(ue)),drm:yield Promise.all(ie.map(fe))}})()),G}let q=[30,60,120,300,600],J=[`playback`,`charts`,`engine`,`browser`],pe={playback:`Playback`,charts:`Charts`,engine:`Engine`,browser:`Browser`},me=[`nothing`,`metadata`,`current data`,`future data`,`enough data`],he=[`empty`,`idle`,`loading`,`no source`];function Y(e,t,n){let r=document.createElement(e);return r.setAttribute(`part`,t),n!==void 0&&(r.textContent=n),r}function X(e,t){let n=Y(`button`,e,t);return n.type=`button`,n}function Z(e){switch(e){case`yes`:return[`✓`,`cell ok`];case`no`:return[`✕`,`cell bad`];case`na`:return[`–`,`cell na`];case`maybe`:return[`maybe`,`cell maybe`];default:return[e,`cell`]}}var Q=class extends HTMLElement{static get observedAttributes(){return[`label`,`label-copy`,`label-copied`,`window`]}constructor(){super(),this.player=null,this.cancel=null,this.offs=[],this.sampler=re(),this.timer=void 0,this.drawer=void 0,this.copied=void 0,this.tab=`playback`,this.chartTab=`buffer`,this.support=null,this.probing=!1;let e=this.attachShadow({mode:`open`}),t=document.createElement(`style`);t.textContent=`:host{--mbx-chart-1:#5aa9e0;--mbx-chart-2:#6fbf8f;--mbx-chart-3:#d9a83f;--mbx-chart-4:#e05a6e;--mbx-chart-5:#a98fe0;display:inline-flex;position:relative}:host([hidden]){display:none}:host([inline]){display:block}[part~=button]{width:40px;height:40px;font:inherit;color:inherit;border-radius:var(--mbx-radius);cursor:pointer;opacity:.9;background:0 0;border:0;flex:none;justify-content:center;align-items:center;padding:0;display:inline-flex}[part~=button]:hover{opacity:1}[part~=button]:focus{outline:2px solid var(--mbx-accent);outline-offset:-2px}[part~=button]:focus:not(:focus-visible){outline:none}[part~=icon],::slotted(*){fill:currentColor;width:1.75em;height:1.75em}:host([inline]) [part~=button]{display:none}[part~=panel]{box-sizing:border-box;width:560px;color:var(--mbx-text,#f2f3f5);border-radius:var(--mbx-radius,4px);font:400 12px / 1.5 var(--mbx-mono,ui-monospace, SFMono-Regular, Menlo, Consolas, monospace);text-align:left;white-space:normal;background:#101114f2;flex-direction:column;margin-bottom:8px;display:flex;position:absolute;bottom:100%;right:0;overflow:hidden;box-shadow:0 4px 16px #00000080}[part~=panel][hidden]{display:none}:host([inline]) [part~=panel]{width:auto;max-height:none;box-shadow:none;border-radius:0;margin:0;position:static}[part~=head]{border-bottom:1px solid #ffffff1f;align-items:center;padding:6px;display:flex}[part~=tab],[part~=chart-tab]{font:inherit;color:var(--mbx-muted,#9aa0a6);border-radius:var(--mbx-radius,4px);cursor:pointer;background:0 0;border:0;padding:3px 8px}[part~=tab][aria-selected=true],[part~=chart-tab][aria-selected=true]{color:var(--mbx-text,#f2f3f5);background:#ffffff1f}[part~=copy],[part~=close],[part~=window]{font:inherit;color:inherit;border-radius:var(--mbx-radius,4px);cursor:pointer;background:0 0;border:1px solid #ffffff40;padding:2px 8px}[part~=head]>*{margin:0 2px}[part~=head]>[part~=copy],[part~=chart-tabs]>[part~=window]{margin-left:auto}[part~=window] option{color:#000}[part~=tab]:focus,[part~=chart-tab]:focus,[part~=copy]:focus,[part~=close]:focus,[part~=window]:focus{outline:2px solid var(--mbx-accent,#5b8cff);outline-offset:-2px}[part~=tab]:focus:not(:focus-visible){outline:none}[part~=chart-tab]:focus:not(:focus-visible){outline:none}[part~=copy]:focus:not(:focus-visible){outline:none}[part~=close]:focus:not(:focus-visible){outline:none}[part~=window]:focus:not(:focus-visible){outline:none}[part~=body]{overscroll-behavior:contain;min-height:0;padding:8px;overflow:auto}[part~=page][hidden]{display:none}[part~=rows]{grid-template-columns:max-content 1fr;gap:2px 12px;margin:0;display:grid}[part~=key]{color:var(--mbx-muted,#9aa0a6);white-space:nowrap}[part~=value]{overflow-wrap:anywhere;margin:0}[part~=heading]{letter-spacing:.06em;text-transform:uppercase;color:var(--mbx-muted,#9aa0a6);margin:10px 0 4px;font-size:11px;font-weight:600}[part~=heading]:first-child{margin-top:0}[part~=note]{color:var(--mbx-muted,#9aa0a6);margin:0}[part~=chart-tabs]{flex-wrap:wrap;align-items:center;margin:-2px -2px 4px;display:flex}[part~=chart-tabs]>*{margin:2px}[part~=chart]{width:100%;height:160px;display:block}[part~=legend]{color:var(--mbx-muted,#9aa0a6);flex-wrap:wrap;margin:3px -6px -1px;display:flex}[part~=legend]>*{margin:1px 6px}[part~=swatch]{vertical-align:middle;border-radius:2px;width:10px;height:10px;margin-right:4px;display:inline-block}[part~=readout]{margin-top:4px}[part~=table]{border-collapse:collapse;width:100%;margin-bottom:4px}[part~=cell]{text-align:left;white-space:nowrap;border-bottom:1px solid #ffffff14;padding:2px 6px;font-weight:400}[part~=label]{color:var(--mbx-muted,#9aa0a6)}[part~=ok]{color:var(--mbx-chart-2)}[part~=bad]{color:var(--mbx-chart-4)}[part~=na]{color:var(--mbx-muted,#9aa0a6)}[part~=ok],[part~=bad],[part~=na],[part~=maybe]{font-weight:600}`,this.toggle=X(`button`),this.toggle.setAttribute(`aria-haspopup`,`dialog`),this.toggle.setAttribute(`aria-expanded`,`false`);let n=document.createElement(`slot`);n.name=`icon`,n.append(g()),this.toggle.append(n),this.toggle.addEventListener(`click`,()=>{this.panel.hidden?this.show():this.hide()}),this.panel=Y(`div`,`panel`),this.panel.setAttribute(`role`,`dialog`),this.panel.hidden=!0,this.panel.addEventListener(`keydown`,e=>{e.key!==`Escape`||this.hasAttribute(`inline`)||(e.preventDefault(),this.hide(),this.toggle.focus())});let r=Y(`div`,`head`);r.setAttribute(`role`,`tablist`),this.tabs={},this.pages={},this.body=Y(`div`,`body`);for(let e of J){let t=X(`tab tab-${e}`,pe[e]);t.setAttribute(`role`,`tab`),t.addEventListener(`click`,()=>{this.select(e)}),this.tabs[e]=t,r.append(t);let n=Y(`div`,`page page-${e}`);n.setAttribute(`role`,`tabpanel`),n.hidden=!0,this.pages[e]=n,this.body.append(n)}this.copy=X(`copy`),this.copy.addEventListener(`click`,()=>{this.copyReport()});let i=X(`close`,`✕`);i.setAttribute(`aria-label`,`Close`),i.addEventListener(`click`,()=>{this.hide(),this.toggle.focus()}),r.append(this.copy,i);let a=Y(`div`,`chart-tabs`);a.setAttribute(`role`,`tablist`),this.chartTabs={};for(let e of c){let t=X(`chart-tab chart-tab-${e}`,e);t.setAttribute(`role`,`tab`),t.addEventListener(`click`,()=>{this.chartTab=e,this.markChartTab(),this.draw()}),this.chartTabs[e]=t,a.append(t)}this.windowSelect=Y(`select`,`window`),this.windowSelect.setAttribute(`aria-label`,`Window`);for(let e of q){let t=document.createElement(`option`);t.value=String(e),t.textContent=e<60?`${e} s`:`${e/60} min`,this.windowSelect.append(t)}this.windowSelect.addEventListener(`change`,()=>{this.draw()}),a.append(this.windowSelect),this.canvas=Y(`canvas`,`chart`);let o=Y(`div`,`legend`),s=Y(`p`,`readout`);this.pages.charts.append(a,this.canvas,o,s),this.charts=d(this.canvas,o,s),this.outside=e=>{e.composedPath().includes(this)||this.hide()},this.refit=()=>{this.fit()},this.panel.append(r,this.body),e.append(t,this.toggle,this.panel),this.markTab(),this.markChartTab(),this.renderLabels()}connectedCallback(){var e,t;this.toggleAttribute(`inline`,((e=this.parentElement)==null?void 0:e.localName)!==`mbx-control-bar`);let n=p(this);n!==null&&((t=this.cancel)==null||t.call(this),this.cancel=m(n,e=>{this.isConnected&&this.attach(e)}))}disconnectedCallback(){var e;(e=this.cancel)==null||e.call(this),this.cancel=null,this.detach()}attributeChangedCallback(){this.renderLabels()}attach(e){this.player=e,this.sampler.attach(e.video,e.engine);let t=(e,t,n)=>{e.addEventListener(t,n),this.offs.push(()=>{e.removeEventListener(t,n)})};t(e,`sourcechange`,()=>{this.sampler.attach(e.video,e.engine),this.poll()}),t(e,`error`,e=>{e.detail.fatal&&this.dispatchEvent(new CustomEvent(`report`,{detail:this.report(),bubbles:!0,composed:!0}))}),this.timer=setInterval(()=>{this.poll()},500),this.poll(),this.hasAttribute(`inline`)&&this.show()}detach(){for(let e of this.offs)e();this.offs=[],clearInterval(this.timer),this.timer=void 0,this.sampler.release(),this.hide(),this.player=null}report(){let e=this.player;if(e===null)throw Error(`mbx-diagnostics is not inside a player`);return b({player:e,samples:this.sampler.samples,marks:this.sampler.marks,counters:this.sampler.counters,history:this.sampler.history,support:this.support})}poll(){let e=this.player;e!==null&&(this.sampler.poll(e.video,e.engine),this.panel.hidden||this.paint())}show(){this.panel.hidden&&(this.panel.hidden=!1,this.hasAttribute(`inline`)||(this.setAttribute(`open`,``),this.toggle.setAttribute(`aria-expanded`,`true`),document.addEventListener(`pointerdown`,this.outside,!0),window.addEventListener(`resize`,this.refit),this.fit()),this.paint(),this.drawer=setInterval(()=>{this.draw()},250),this.hasAttribute(`inline`)||this.tabs[this.tab].focus())}hide(){clearInterval(this.drawer),this.drawer=void 0,!this.panel.hidden&&(this.panel.hidden=!0,this.removeAttribute(`open`),this.toggle.setAttribute(`aria-expanded`,`false`),document.removeEventListener(`pointerdown`,this.outside,!0),window.removeEventListener(`resize`,this.refit))}fit(){let e=this.player;if(e===null)return;let t=e.getBoundingClientRect(),n=this.getBoundingClientRect(),r=e.video.getBoundingClientRect().top,i=n.top-r-8;this.panel.style.maxHeight=`${Math.max(120,Math.floor(i))}px`;let a=Math.min(560,Math.max(200,t.width-16));this.panel.style.width=`${a}px`;let o=Math.max(t.left+8,Math.min(n.right-a,t.right-8-a));this.panel.style.right=`auto`,this.panel.style.left=`${o-n.left}px`}select(e){this.tab=e,this.markTab(),this.tabs[e].focus(),this.paint(),this.draw()}markTab(){for(let e of J)this.tabs[e].setAttribute(`aria-selected`,String(e===this.tab)),this.tabs[e].tabIndex=e===this.tab?0:-1,this.pages[e].hidden=e!==this.tab}markChartTab(){for(let e of c)this.chartTabs[e].setAttribute(`aria-selected`,String(e===this.chartTab))}renderLabels(){var e,t;if(this.toggle.setAttribute(`aria-label`,(e=this.getAttribute(`label`))==null?`Diagnostics`:e),this.panel.setAttribute(`aria-label`,(t=this.getAttribute(`label`))==null?`Diagnostics`:t),this.copied===void 0){var n;this.copy.textContent=(n=this.getAttribute(`label-copy`))==null?`Copy report`:n}let r=Number(this.getAttribute(`window`)),i=Number.isFinite(r)&&r>0?r:120;if(!q.includes(i)){let e=document.createElement(`option`);e.value=String(i),e.textContent=`${i} s`,this.windowSelect.append(e)}this.windowSelect.value=String(i)}copyReport(){var e=this;return F(function*(){var t;let n=JSON.stringify(e.report(),null,2);try{yield navigator.clipboard.writeText(n)}catch(e){return}e.copy.textContent=(t=e.getAttribute(`label-copied`))==null?`Copied`:t,clearTimeout(e.copied),e.copied=setTimeout(()=>{e.copied=void 0,e.renderLabels()},1500)})()}palette(){let e=getComputedStyle(this),t=(t,n)=>e.getPropertyValue(t).trim()||n;return{ink:t(`--mbx-text`,`#f2f3f5`),muted:t(`--mbx-muted`,`#9aa0a6`),accent:t(`--mbx-accent`,`#5b8cff`),warn:t(`--mbx-chart-3`,`#d9a83f`),series:[1,2,3,4,5].map(e=>t(`--mbx-chart-${e}`,`#888`))}}draw(){let e=this.player;e===null||this.panel.hidden||this.tab!==`charts`||this.charts.draw({tab:this.chartTab,window:Number(this.windowSelect.value)||120,samples:this.sampler.samples,marks:this.sampler.marks,counters:this.sampler.counters,video:e.video,engine:e.engine,palette:this.palette()})}paint(){let e=this.player;if(!(e===null||this.panel.hidden))switch(this.tab){case`playback`:this.sections(this.pages.playback,this.playbackSections(e));break;case`engine`:this.sections(this.pages.engine,this.engineSections(e.engine));break;case`browser`:this.browser()}}playbackSections(e){var t,c,l,u,d,f,p,m;let h=e.video,g=e.engine,_=(t=h.getVideoPlaybackQuality)==null?void 0:t.call(h),v=this.sampler.counters,y=this.sampler.samples[this.sampler.samples.length-1],b=h.paused?h.ended?`ended`:`paused`:`playing`,x=[[`source`,(c=e.getAttribute(`src`))==null?`–`:c],[`type`,(l=e.getAttribute(`type`))==null?`–`:l],[`handler`,(u=(d=e.player)==null||(d=d.session)==null?void 0:d.handler)==null?`–`:u]];g!==null&&x.push([`phase`,g.stats.snapshot().lifecycle.phase]),e.error===null?h.error!==null&&x.push([`media error`,`${h.error.code} ${h.error.message}`]):x.push([`error`,`${e.error.category}: ${e.error.code}`]);let S=[[`time`,`${r(h.currentTime)} of ${r(h.duration)}`],[`state`,`${b}, ${(f=me[h.readyState])==null?h.readyState:f}, network ${(p=he[h.networkState])==null?h.networkState:p}`],[`rate`,`${h.playbackRate}×`],[`picture`,h.videoWidth>0?`${h.videoWidth}×${h.videoHeight}`:`–`],[`frames`,_===void 0?`–`:`${_.totalVideoFrames} decoded, ${_.droppedVideoFrames} dropped (${a(_.droppedVideoFrames,_.totalVideoFrames)})`],[`buffered`,`${i((m=y==null?void 0:y.ahead)==null?0:m)}s ahead: ${o(ge(h))}`],[`stalls`,`${v.stalls}, ${v.stalledSeconds.toFixed(1)}s in total`]];if(g!==null){let e=g.stats.snapshot();S.push([`throughput`,`slow ${n(e.stats.throughputEwma)}, fast ${n(e.stats.throughputFastEwma)}`],[`playing`,s(g.quality.playing)],[`switches`,String(v.switches)])}let C=g==null?void 0:g.qoe;return[{title:`Source`,rows:x},{title:`Playback`,rows:S},...C===void 0?[]:[{title:`Quality of experience`,rows:[[`startup`,C.startupTime===null?`–`:`${C.startupTime.toFixed(2)}s`],[`rebuffers`,`${C.rebuffers}, ${C.rebufferDuration.toFixed(1)}s in total`],[`quality changes`,String(C.switches)]]}]]}engineSections(e){var t,i,a,s,c,l,u;if(e===null)return[{title:null,rows:[],note:`A native session: the browser plays this, and there is no engine to ask.`}];let d=e.stats.snapshot(),f=e,p=d.live,m=[[`capabilities`,[...e.capabilities()].join(`, `)||`none`],[`phase`,d.lifecycle.phase],[`buffer goal`,`${d.scheduling.bufferGoal}s`],[`throughput`,`slow ${n(d.stats.throughputEwma)}, fast ${n(d.stats.throughputFastEwma)}`],[`in flight`,[...d.scheduling.inflight.values()].map(e=>`${e.trackId} #${e.seq}`).join(`, `)||`none`],[`live`,p===null?`VOD`:`window ${r(p.span.start)} to ${r(p.span.end)}, edge ${r(p.edge)}${((t=f.live)==null?void 0:t.latency)===null||((i=f.live)==null?void 0:i.latency)===void 0?``:`, ${f.live.latency.toFixed(1)}s behind`}`],[`trace`,`${e.stats.trace().length} entries`]],h=e.error;h!==null&&m.push([`last error`,`${h.category}: ${h.code}`]);let g=[...d.buffers.entries()].map(([e,t])=>[e.replace(`sb:`,``),`${t.codecs}: ${o(t.ranges)}${t.pendingAppends>0?`, ${t.pendingAppends} pending`:``}`]),_=e.tracks.available.map(t=>{var n;let r=((n=e.tracks.active(t.contentType))==null?void 0:n.id)===t.id,i=[t.lang,t.role].filter(e=>e!==void 0).join(` · `);return[`${t.contentType}${r?` ●`:``}`,`${t.id}${i===``?``:` (${i})`}, ${t.renditions.length} renditions`]}),v=(a=(s=e.quality.playing)==null?void 0:s.id)==null?null:a,y=(c=(l=e.quality.active)==null?void 0:l.id)==null?null:c,b=new Set(e.quality.allowed.map(e=>e.id)),x=e.quality.renditions.map(t=>{var r;let i=[t.id===v?`playing`:``,t.id===y&&y!==v?`next`:``,t.id===e.quality.pinned?`pinned`:``,b.has(t.id)?``:`capped`].filter(e=>e!==``),a=[t.width!==void 0&&t.height!==void 0?`${t.width}×${t.height}`:``,n(t.bitrate),t.frameRate===void 0?``:`${t.frameRate} fps`,(r=t.codecs)==null?``:r].filter(e=>e!==``).join(`, `);return[t.id,`${a}${i.length>0?` [${i.join(`, `)}]`:``}`]}),S=f.drm===void 0?[]:[[`key system`,(u=f.drm.keySystem)==null?`none yet`:u],[`keys`,f.drm.sessions.length===0?`none yet`:f.drm.sessions.map(e=>`${e.keyId}: ${e.status}`).join(`, `)]];return[{title:`Engine`,rows:m},{title:`Source buffers`,rows:g,note:g.length===0?`none yet`:void 0},{title:`Tracks`,rows:_,note:_.length===0?`none yet`:void 0},{title:`Renditions`,rows:x,note:x.length===0?`none yet`:void 0},...f.drm===void 0?[]:[{title:`DRM`,rows:S}]]}sections(e,t){var n;let r=t.flatMap(e=>{let t=[];return e.title!==null&&t.push([`heading`,e.title]),e.note!==void 0&&e.rows.length===0?t.push([`note`,e.note]):t.push([`rows`,e.rows]),t});for(;e.childElementCount>r.length;)(n=e.lastElementChild)==null||n.remove();r.forEach(([t,n],r)=>{var i;let a=e.children[r],o=t===`heading`?`h3`:t===`note`?`p`:`dl`;if(a===void 0||a.localName!==o){let n=Y(o,t);a===void 0?e.append(n):a.replaceWith(n),a=n}if(typeof n==`string`){a.textContent!==n&&(a.textContent=n);return}for(;a.childElementCount>n.length*2;)(i=a.lastElementChild)==null||i.remove();n.forEach(([e,t],n)=>{let r=a.children[n*2],i=a.children[n*2+1];(r===void 0||i===void 0)&&(r=Y(`dt`,`key`),i=Y(`dd`,`value`),a.append(r,i)),r.textContent!==e&&(r.textContent=e),i.textContent!==t&&(i.textContent=t)})})}browser(){let e=this.pages.browser;this.support!==null||this.probing||(this.probing=!0,t(e,Y(`p`,`note`,`Probing the browser…`)),K().then(t=>{this.support=t,this.probing=!1,this.tables(e,t)}))}tables(e,n){t(e),e.append(Y(`h3`,`heading`,`Platform`),Y(`p`,`note`,n.userAgent));let r=Y(`table`,`table`);for(let e of n.platform){let t=document.createElement(`tr`),[n,i]=Z(e.value);t.append(Y(`th`,`cell label`,e.label),Y(`td`,i,n)),r.append(t)}e.append(r),e.append(Y(`h3`,`heading`,`Codecs`));let i=Y(`table`,`table`),a=document.createElement(`tr`);for(let e of[`Codec`,`MSE fMP4`,`MSE WebM`,`<video>`,`Smooth`,`Efficient`])a.append(Y(`th`,`cell label`,e));i.append(a);for(let e of n.codecs){let t=document.createElement(`tr`),n=Y(`th`,`cell label`,e.label);n.title=e.codec,t.append(n);for(let n of[e.mse,e.webm,e.element,e.smooth,e.efficient]){let[e,r]=Z(n);t.append(Y(`td`,r,e))}i.append(t)}e.append(i),e.append(Y(`h3`,`heading`,`DRM`));let o=Y(`table`,`table`),s=document.createElement(`tr`);for(let e of[`System`,`Available`,`Level`,`Schemes`,`Persistent`,`Identifier`,`HDCP`])s.append(Y(`th`,`cell label`,e));o.append(s);for(let e of n.drm){let t=document.createElement(`tr`),n=Y(`th`,`cell label`,e.label);e.keySystem!==null&&(n.title=e.keySystem),t.append(n);let r=[e.keySystem===null?`no`:`yes`,e.level,e.schemes,e.persistent,e.identifier,e.hdcp];for(let e of r){let[n,r]=Z(e);t.append(Y(`td`,r,n))}o.append(t)}e.append(o)}};function ge(e){return Array.from({length:e.buffered.length},(t,n)=>({start:e.buffered.start(n),end:e.buffered.end(n)}))}let $=`mbx-diagnostics`;return customElements.get(`mbx-diagnostics`)===void 0&&customElements.define($,Q),e.DIAGNOSTICS=$,e.MbxDiagnostics=Q,e.probeSupport=K,e})({});
@@ -1 +1 @@
1
- {"version":3,"file":"element.d.ts","sourceRoot":"","sources":["../src/element.ts"],"names":[],"mappings":"AA+BA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AA+ErD,qBAAa,cAAe,SAAQ,WAAW;IAC7C,MAAM,KAAK,kBAAkB,IAAI,SAAS,MAAM,EAAE,CAEjD;IAED,QAAgB,MAAM,CAAoB;IAC1C,QAAgB,MAAM,CAAsB;IAC5C,QAAgB,IAAI,CAAoB;IACxC,iBAAyB,OAAO,CAAU;IAC1C,iBAAyB,MAAM,CAAS;IACxC,QAAgB,KAAK,CAA6C;IAClE,QAAgB,MAAM,CAA6C;IACnE,QAAgB,MAAM,CAA4C;IAClE,QAAgB,GAAG,CAAM;IACzB,QAAgB,QAAQ,CAAW;IACnC,QAAgB,OAAO,CAAiB;IACxC,QAAgB,OAAO,CAAU;IAEjC,iBAAyB,MAAM,CAAoB;IACnD,iBAAyB,KAAK,CAAc;IAC5C,iBAAyB,IAAI,CAAc;IAC3C,iBAAyB,IAAI,CAAiC;IAC9D,iBAAyB,KAAK,CAA2B;IACzD,iBAAyB,IAAI,CAAoB;IACjD,iBAAyB,MAAM,CAAoB;IACnD,iBAAyB,SAAS,CAAsC;IACxE,iBAAyB,YAAY,CAAoB;IACzD,iBAAyB,OAAO,CAAgC;IAChE,iBAAyB,KAAK,CAAa;;IAwH3C,iBAAiB,IAAI,IAAI;IAYzB,oBAAoB,IAAI,IAAI;IAM5B,wBAAwB,IAAI,IAAI;IAIhC,OAAO,CAAC,MAAM;IA4Bd,OAAO,CAAC,MAAM;IAUd,6BAA6B;IAC7B,MAAM,IAAI,iBAAiB;IAa3B,OAAO,CAAC,IAAI;IAOZ,OAAO,CAAC,IAAI;IAiBZ,OAAO,CAAC,IAAI;IAWZ,0GAA0G;IAC1G,OAAO,CAAC,GAAG;IAeX,OAAO,CAAC,MAAM;IAQd,OAAO,CAAC,OAAO;IAQf,OAAO,CAAC,YAAY;IAMpB,OAAO,CAAC,YAAY;YAiBN,UAAU;IAexB,kEAAkE;IAClE,OAAO,CAAC,OAAO;IAaf,OAAO,CAAC,IAAI;IAeZ,oDAAoD;IACpD,OAAO,CAAC,KAAK;IAkBb,OAAO,CAAC,gBAAgB;IAoDxB,OAAO,CAAC,cAAc;IA2GtB;;;;OAIG;IACH,OAAO,CAAC,QAAQ;IAuChB,uFAAuF;IACvF,OAAO,CAAC,OAAO;IAYf,OAAO,CAAC,MAAM;CAoEf"}
1
+ {"version":3,"file":"element.d.ts","sourceRoot":"","sources":["../src/element.ts"],"names":[],"mappings":"AA+BA,OAAO,KAAK,EAAE,iBAAiB,EAAc,MAAM,aAAa,CAAC;AAgFjE,qBAAa,cAAe,SAAQ,WAAW;IAC7C,MAAM,KAAK,kBAAkB,IAAI,SAAS,MAAM,EAAE,CAEjD;IAED,QAAgB,MAAM,CAAoB;IAC1C,QAAgB,MAAM,CAAsB;IAC5C,QAAgB,IAAI,CAAoB;IACxC,iBAAyB,OAAO,CAAU;IAC1C,iBAAyB,MAAM,CAAS;IACxC,QAAgB,KAAK,CAA6C;IAClE,QAAgB,MAAM,CAA6C;IACnE,QAAgB,MAAM,CAA4C;IAClE,QAAgB,GAAG,CAAM;IACzB,QAAgB,QAAQ,CAAW;IACnC,QAAgB,OAAO,CAAiB;IACxC,QAAgB,OAAO,CAAU;IAEjC,iBAAyB,MAAM,CAAoB;IACnD,iBAAyB,KAAK,CAAc;IAC5C,iBAAyB,IAAI,CAAc;IAC3C,iBAAyB,IAAI,CAAiC;IAC9D,iBAAyB,KAAK,CAA2B;IACzD,iBAAyB,IAAI,CAAoB;IACjD,iBAAyB,MAAM,CAAoB;IACnD,iBAAyB,SAAS,CAAsC;IACxE,iBAAyB,YAAY,CAAoB;IACzD,iBAAyB,OAAO,CAAgC;IAChE,iBAAyB,KAAK,CAAa;;IAwH3C,iBAAiB,IAAI,IAAI;IAYzB,oBAAoB,IAAI,IAAI;IAM5B,wBAAwB,IAAI,IAAI;IAIhC,OAAO,CAAC,MAAM;IA4Bd,OAAO,CAAC,MAAM;IAUd,6BAA6B;IAC7B,MAAM,IAAI,iBAAiB;IAa3B,OAAO,CAAC,IAAI;IAOZ,OAAO,CAAC,IAAI;IAiBZ,OAAO,CAAC,IAAI;IAWZ,0GAA0G;IAC1G,OAAO,CAAC,GAAG;IAeX,OAAO,CAAC,MAAM;IAQd,OAAO,CAAC,OAAO;IAQf,OAAO,CAAC,YAAY;IAMpB,OAAO,CAAC,YAAY;YAiBN,UAAU;IAexB,kEAAkE;IAClE,OAAO,CAAC,OAAO;IAaf,OAAO,CAAC,IAAI;IAeZ,oDAAoD;IACpD,OAAO,CAAC,KAAK;IAkBb,OAAO,CAAC,gBAAgB;IAmExB,OAAO,CAAC,cAAc;IA2GtB;;;;OAIG;IACH,OAAO,CAAC,QAAQ;IAuChB,uFAAuF;IACvF,OAAO,CAAC,OAAO;IAYf,OAAO,CAAC,MAAM;CAoEf"}
package/dist/element.js CHANGED
@@ -417,13 +417,25 @@ var MbxDiagnostics = class extends HTMLElement {
417
417
  const snapshot = engine.stats.snapshot();
418
418
  playback.push(["throughput", `slow ${bitrate(snapshot.stats.throughputEwma)}, fast ${bitrate(snapshot.stats.throughputFastEwma)}`], ["playing", rendition(engine.quality.playing)], ["switches", String(counters.switches)]);
419
419
  }
420
- return [{
421
- title: "Source",
422
- rows: source
423
- }, {
424
- title: "Playback",
425
- rows: playback
426
- }];
420
+ const qoe = engine?.qoe;
421
+ return [
422
+ {
423
+ title: "Source",
424
+ rows: source
425
+ },
426
+ {
427
+ title: "Playback",
428
+ rows: playback
429
+ },
430
+ ...qoe === void 0 ? [] : [{
431
+ title: "Quality of experience",
432
+ rows: [
433
+ ["startup", qoe.startupTime === null ? "–" : `${qoe.startupTime.toFixed(2)}s`],
434
+ ["rebuffers", `${qoe.rebuffers}, ${qoe.rebufferDuration.toFixed(1)}s in total`],
435
+ ["quality changes", String(qoe.switches)]
436
+ ]
437
+ }]
438
+ ];
427
439
  }
428
440
  engineSections(engine) {
429
441
  if (engine === null) return [{
@@ -1 +1 @@
1
- {"version":3,"file":"element.js","names":[],"sources":["../src/element.ts"],"sourcesContent":["/**\n * <mbx-diagnostics>: what the session is doing, for an integrator's eyes.\n * In the bar it is a button that opens a panel over the picture; anywhere\n * else inside the player, the panel itself, open, in flow. Four pages:\n * the playback facts, the charts, the engine's state, and what the browser\n * supports. A button copies the report, and `report()` hands it to a page,\n * which also gets it as a `report` event on every fatal error, so a page\n * sends it where its errors go.\n *\n * The sampler runs while the element is attached, panel open or not, so\n * the counts cover the session, and keeps the session's trace, slimmed,\n * from the engine's `trace` events, or off its ring where it emits none. The pages redraw twice a second while\n * shown, the charts four times. The browser is probed once, the first\n * time its page is shown: the key-system probes are not free, and Firefox\n * asks the viewer about a DRM module it has not enabled.\n *\n * A native session has no engine, and the engine's rules say a native\n * session has no diagnostics beyond the video's own: the playback page and\n * the buffer, stall and frame charts read the video, the rest says so.\n *\n * No class fields: the ES2015 build would lower them into helpers, and the\n * player's emit check bans helpers. State is declared, then assigned.\n */\nimport type { Mattebox } from 'mattebox';\nimport type { Charts, ChartTab, Palette } from './charts.js';\nimport { CHART_TABS, createCharts } from './charts.js';\nimport { setChildren } from './dom.js';\nimport { bitrate, clock, fixed, ranges, rendition, share } from './format.js';\nimport type { PlayerError, PlayerHost } from './host.js';\nimport { findPlayer, whenPlayer } from './host.js';\nimport { icon } from './icon.js';\nimport type { DiagnosticsReport } from './report.js';\nimport { buildReport } from './report.js';\nimport type { Sampler } from './sampler.js';\nimport { createSampler } from './sampler.js';\nimport { STYLE } from './style.js';\nimport type { Cell, Support } from './support.js';\nimport { probeSupport } from './support.js';\n\nconst POLL_MS = 500;\nconst DRAW_MS = 250;\nconst WINDOW = 120;\nconst WINDOWS = [30, 60, 120, 300, 600];\nconst PANEL_WIDTH = 560;\n/** Air between the panel's top and the picture's, and around it. */\nconst AIR = 8;\n\nconst TABS = ['playback', 'charts', 'engine', 'browser'] as const;\ntype Tab = (typeof TABS)[number];\nconst TAB_NAMES: Readonly<Record<Tab, string>> = {\n playback: 'Playback',\n charts: 'Charts',\n engine: 'Engine',\n browser: 'Browser',\n};\n\nconst READY_STATES = ['nothing', 'metadata', 'current data', 'future data', 'enough data'];\nconst NETWORK_STATES = ['empty', 'idle', 'loading', 'no source'];\n\ntype Pair = readonly [string, string];\n\ninterface Section {\n readonly title: string | null;\n readonly rows: readonly Pair[];\n /** A line instead of rows, for a section with nothing to list. */\n readonly note?: string | undefined;\n}\n\n/** The optional namespaces the pages read, cast once, the way the player does it. */\ninterface Namespaces {\n readonly live?: { readonly latency: number | null; readonly atEdge: boolean };\n readonly drm?: {\n readonly keySystem: string | null;\n readonly sessions: ReadonlyArray<{ readonly keyId: string; readonly status: string }>;\n };\n}\n\nfunction el<K extends keyof HTMLElementTagNameMap>(\n tag: K,\n part: string,\n text?: string,\n): HTMLElementTagNameMap[K] {\n const node = document.createElement(tag);\n node.setAttribute('part', part);\n if (text !== undefined) node.textContent = text;\n return node;\n}\n\nfunction button(part: string, text?: string): HTMLButtonElement {\n const node = el('button', part, text);\n node.type = 'button';\n return node;\n}\n\n/** A cell's text and its part: a tick, a cross, a dash, or the text itself. */\nfunction cell(value: Cell): [string, string] {\n switch (value) {\n case 'yes':\n return ['✓', 'cell ok'];\n case 'no':\n return ['✕', 'cell bad'];\n case 'na':\n return ['–', 'cell na'];\n case 'maybe':\n return ['maybe', 'cell maybe'];\n default:\n return [value, 'cell'];\n }\n}\n\nexport class MbxDiagnostics extends HTMLElement {\n static get observedAttributes(): readonly string[] {\n return ['label', 'label-copy', 'label-copied', 'window'];\n }\n\n declare private player: PlayerHost | null;\n declare private cancel: (() => void) | null;\n declare private offs: Array<() => void>;\n declare private readonly sampler: Sampler;\n declare private readonly charts: Charts;\n declare private timer: ReturnType<typeof setInterval> | undefined;\n declare private drawer: ReturnType<typeof setInterval> | undefined;\n declare private copied: ReturnType<typeof setTimeout> | undefined;\n declare private tab: Tab;\n declare private chartTab: ChartTab;\n declare private support: Support | null;\n declare private probing: boolean;\n\n declare private readonly toggle: HTMLButtonElement;\n declare private readonly panel: HTMLElement;\n declare private readonly body: HTMLElement;\n declare private readonly tabs: Record<Tab, HTMLButtonElement>;\n declare private readonly pages: Record<Tab, HTMLElement>;\n declare private readonly copy: HTMLButtonElement;\n declare private readonly canvas: HTMLCanvasElement;\n declare private readonly chartTabs: Record<ChartTab, HTMLButtonElement>;\n declare private readonly windowSelect: HTMLSelectElement;\n declare private readonly outside: (event: PointerEvent) => void;\n declare private readonly refit: () => void;\n\n constructor() {\n super();\n this.player = null;\n this.cancel = null;\n this.offs = [];\n this.sampler = createSampler();\n this.timer = undefined;\n this.drawer = undefined;\n this.copied = undefined;\n this.tab = 'playback';\n this.chartTab = 'buffer';\n this.support = null;\n this.probing = false;\n\n const root = this.attachShadow({ mode: 'open' });\n const style = document.createElement('style');\n style.textContent = STYLE;\n\n this.toggle = button('button');\n this.toggle.setAttribute('aria-haspopup', 'dialog');\n this.toggle.setAttribute('aria-expanded', 'false');\n const slot = document.createElement('slot');\n slot.name = 'icon';\n slot.append(icon());\n this.toggle.append(slot);\n this.toggle.addEventListener('click', () => {\n if (this.panel.hidden) this.show();\n else this.hide();\n });\n\n this.panel = el('div', 'panel');\n this.panel.setAttribute('role', 'dialog');\n this.panel.hidden = true;\n this.panel.addEventListener('keydown', (event) => {\n if (event.key !== 'Escape' || this.hasAttribute('inline')) return;\n event.preventDefault();\n this.hide();\n this.toggle.focus();\n });\n\n const head = el('div', 'head');\n head.setAttribute('role', 'tablist');\n this.tabs = {} as Record<Tab, HTMLButtonElement>;\n this.pages = {} as Record<Tab, HTMLElement>;\n this.body = el('div', 'body');\n for (const tab of TABS) {\n const node = button(`tab tab-${tab}`, TAB_NAMES[tab]);\n node.setAttribute('role', 'tab');\n node.addEventListener('click', () => {\n this.select(tab);\n });\n this.tabs[tab] = node;\n head.append(node);\n const page = el('div', `page page-${tab}`);\n page.setAttribute('role', 'tabpanel');\n page.hidden = true;\n this.pages[tab] = page;\n this.body.append(page);\n }\n this.copy = button('copy');\n this.copy.addEventListener('click', () => {\n void this.copyReport();\n });\n const close = button('close', '✕');\n close.setAttribute('aria-label', 'Close');\n close.addEventListener('click', () => {\n this.hide();\n this.toggle.focus();\n });\n head.append(this.copy, close);\n\n // The charts page: its own tabs, the window, the canvas, the legend and the readout.\n const chartTabs = el('div', 'chart-tabs');\n chartTabs.setAttribute('role', 'tablist');\n this.chartTabs = {} as Record<ChartTab, HTMLButtonElement>;\n for (const tab of CHART_TABS) {\n const node = button(`chart-tab chart-tab-${tab}`, tab);\n node.setAttribute('role', 'tab');\n node.addEventListener('click', () => {\n this.chartTab = tab;\n this.markChartTab();\n this.draw();\n });\n this.chartTabs[tab] = node;\n chartTabs.append(node);\n }\n this.windowSelect = el('select', 'window');\n this.windowSelect.setAttribute('aria-label', 'Window');\n for (const seconds of WINDOWS) {\n const option = document.createElement('option');\n option.value = String(seconds);\n option.textContent = seconds < 60 ? `${seconds} s` : `${seconds / 60} min`;\n this.windowSelect.append(option);\n }\n this.windowSelect.addEventListener('change', () => {\n this.draw();\n });\n chartTabs.append(this.windowSelect);\n this.canvas = el('canvas', 'chart');\n const legend = el('div', 'legend');\n const readout = el('p', 'readout');\n this.pages.charts.append(chartTabs, this.canvas, legend, readout);\n this.charts = createCharts(this.canvas, legend, readout);\n\n this.outside = (event: PointerEvent): void => {\n if (!event.composedPath().includes(this)) this.hide();\n };\n this.refit = (): void => {\n this.fit();\n };\n\n this.panel.append(head, this.body);\n root.append(style, this.toggle, this.panel);\n this.markTab();\n this.markChartTab();\n this.renderLabels();\n }\n\n connectedCallback(): void {\n // In the bar, a button and a popup; anywhere else, the panel in flow.\n this.toggleAttribute('inline', this.parentElement?.localName !== 'mbx-control-bar');\n const found = findPlayer(this);\n if (found === null) return;\n this.cancel?.();\n this.cancel = whenPlayer(found, (player) => {\n if (!this.isConnected) return;\n this.attach(player);\n });\n }\n\n disconnectedCallback(): void {\n this.cancel?.();\n this.cancel = null;\n this.detach();\n }\n\n attributeChangedCallback(): void {\n this.renderLabels();\n }\n\n private attach(player: PlayerHost): void {\n this.player = player;\n this.sampler.attach(player.video, player.engine);\n const on = (target: EventTarget, name: string, fn: (event: Event) => void): void => {\n target.addEventListener(name, fn);\n this.offs.push(() => {\n target.removeEventListener(name, fn);\n });\n };\n on(player, 'sourcechange', () => {\n this.sampler.attach(player.video, player.engine);\n this.poll();\n });\n on(player, 'error', (event) => {\n const error = (event as CustomEvent<PlayerError>).detail;\n if (error.fatal) {\n this.dispatchEvent(\n new CustomEvent('report', { detail: this.report(), bubbles: true, composed: true }),\n );\n }\n });\n this.timer = setInterval(() => {\n this.poll();\n }, POLL_MS);\n this.poll();\n if (this.hasAttribute('inline')) this.show();\n }\n\n private detach(): void {\n for (const off of this.offs) off();\n this.offs = [];\n clearInterval(this.timer);\n this.timer = undefined;\n this.sampler.release();\n this.hide();\n this.player = null;\n }\n\n /** The report, as of now. */\n report(): DiagnosticsReport {\n const player = this.player;\n if (player === null) throw new Error('mbx-diagnostics is not inside a player');\n return buildReport({\n player,\n samples: this.sampler.samples,\n marks: this.sampler.marks,\n counters: this.sampler.counters,\n history: this.sampler.history,\n support: this.support,\n });\n }\n\n private poll(): void {\n const player = this.player;\n if (player === null) return;\n this.sampler.poll(player.video, player.engine);\n if (!this.panel.hidden) this.paint();\n }\n\n private show(): void {\n if (!this.panel.hidden) return;\n this.panel.hidden = false;\n if (!this.hasAttribute('inline')) {\n this.setAttribute('open', '');\n this.toggle.setAttribute('aria-expanded', 'true');\n document.addEventListener('pointerdown', this.outside, true);\n window.addEventListener('resize', this.refit);\n this.fit();\n }\n this.paint();\n this.drawer = setInterval(() => {\n this.draw();\n }, DRAW_MS);\n if (!this.hasAttribute('inline')) this.tabs[this.tab].focus();\n }\n\n private hide(): void {\n clearInterval(this.drawer);\n this.drawer = undefined;\n if (this.panel.hidden) return;\n this.panel.hidden = true;\n this.removeAttribute('open');\n this.toggle.setAttribute('aria-expanded', 'false');\n document.removeEventListener('pointerdown', this.outside, true);\n window.removeEventListener('resize', this.refit);\n }\n\n /** The panel never leaves the picture: fitted to the room above the button, within the player's width. */\n private fit(): void {\n const player = this.player;\n if (player === null) return;\n const box = player.getBoundingClientRect();\n const host = this.getBoundingClientRect();\n const top = player.video.getBoundingClientRect().top;\n const room = host.top - top - AIR;\n this.panel.style.maxHeight = `${Math.max(120, Math.floor(room))}px`;\n const width = Math.min(PANEL_WIDTH, Math.max(200, box.width - AIR * 2));\n this.panel.style.width = `${width}px`;\n const left = Math.max(box.left + AIR, Math.min(host.right - width, box.right - AIR - width));\n this.panel.style.right = 'auto';\n this.panel.style.left = `${left - host.left}px`;\n }\n\n private select(tab: Tab): void {\n this.tab = tab;\n this.markTab();\n this.tabs[tab].focus();\n this.paint();\n this.draw();\n }\n\n private markTab(): void {\n for (const tab of TABS) {\n this.tabs[tab].setAttribute('aria-selected', String(tab === this.tab));\n this.tabs[tab].tabIndex = tab === this.tab ? 0 : -1;\n this.pages[tab].hidden = tab !== this.tab;\n }\n }\n\n private markChartTab(): void {\n for (const tab of CHART_TABS) {\n this.chartTabs[tab].setAttribute('aria-selected', String(tab === this.chartTab));\n }\n }\n\n private renderLabels(): void {\n this.toggle.setAttribute('aria-label', this.getAttribute('label') ?? 'Diagnostics');\n this.panel.setAttribute('aria-label', this.getAttribute('label') ?? 'Diagnostics');\n if (this.copied === undefined) {\n this.copy.textContent = this.getAttribute('label-copy') ?? 'Copy report';\n }\n const raw = Number(this.getAttribute('window'));\n const seconds = Number.isFinite(raw) && raw > 0 ? raw : WINDOW;\n if (!WINDOWS.includes(seconds)) {\n const option = document.createElement('option');\n option.value = String(seconds);\n option.textContent = `${seconds} s`;\n this.windowSelect.append(option);\n }\n this.windowSelect.value = String(seconds);\n }\n\n private async copyReport(): Promise<void> {\n const text = JSON.stringify(this.report(), null, 2);\n try {\n await navigator.clipboard.writeText(text);\n } catch {\n return;\n }\n this.copy.textContent = this.getAttribute('label-copied') ?? 'Copied';\n clearTimeout(this.copied);\n this.copied = setTimeout(() => {\n this.copied = undefined;\n this.renderLabels();\n }, 1500);\n }\n\n /** The colours the charts draw with, off the element's tokens. */\n private palette(): Palette {\n const computed = getComputedStyle(this);\n const token = (name: string, fallback: string): string =>\n computed.getPropertyValue(name).trim() || fallback;\n return {\n ink: token('--mbx-text', '#f2f3f5'),\n muted: token('--mbx-muted', '#9aa0a6'),\n accent: token('--mbx-accent', '#5b8cff'),\n warn: token('--mbx-chart-3', '#d9a83f'),\n series: [1, 2, 3, 4, 5].map((i) => token(`--mbx-chart-${i}`, '#888')),\n };\n }\n\n private draw(): void {\n const player = this.player;\n if (player === null || this.panel.hidden || this.tab !== 'charts') return;\n this.charts.draw({\n tab: this.chartTab,\n window: Number(this.windowSelect.value) || WINDOW,\n samples: this.sampler.samples,\n marks: this.sampler.marks,\n counters: this.sampler.counters,\n video: player.video,\n engine: player.engine,\n palette: this.palette(),\n });\n }\n\n /** The page shown, from the facts of the moment. */\n private paint(): void {\n const player = this.player;\n if (player === null || this.panel.hidden) return;\n switch (this.tab) {\n case 'playback':\n this.sections(this.pages.playback, this.playbackSections(player));\n break;\n case 'engine':\n this.sections(this.pages.engine, this.engineSections(player.engine));\n break;\n case 'browser':\n this.browser();\n break;\n default:\n break;\n }\n }\n\n private playbackSections(player: PlayerHost): Section[] {\n const video = player.video;\n const engine = player.engine;\n const quality = video.getVideoPlaybackQuality?.();\n const counters = this.sampler.counters;\n const last = this.sampler.samples[this.sampler.samples.length - 1];\n const state = video.paused ? (video.ended ? 'ended' : 'paused') : 'playing';\n const source: Pair[] = [\n ['source', player.getAttribute('src') ?? '–'],\n ['type', player.getAttribute('type') ?? '–'],\n ['handler', player.player?.session?.handler ?? '–'],\n ];\n if (engine !== null) source.push(['phase', engine.stats.snapshot().lifecycle.phase]);\n if (player.error !== null) {\n source.push(['error', `${player.error.category}: ${player.error.code}`]);\n } else if (video.error !== null) {\n source.push(['media error', `${video.error.code} ${video.error.message}`]);\n }\n const playback: Pair[] = [\n ['time', `${clock(video.currentTime)} of ${clock(video.duration)}`],\n [\n 'state',\n `${state}, ${READY_STATES[video.readyState] ?? video.readyState}, network ${NETWORK_STATES[video.networkState] ?? video.networkState}`,\n ],\n ['rate', `${video.playbackRate}×`],\n ['picture', video.videoWidth > 0 ? `${video.videoWidth}×${video.videoHeight}` : '–'],\n [\n 'frames',\n quality === undefined\n ? '–'\n : `${quality.totalVideoFrames} decoded, ${quality.droppedVideoFrames} dropped (${share(quality.droppedVideoFrames, quality.totalVideoFrames)})`,\n ],\n ['buffered', `${fixed(last?.ahead ?? 0)}s ahead: ${ranges(playbackRanges(video))}`],\n ['stalls', `${counters.stalls}, ${counters.stalledSeconds.toFixed(1)}s in total`],\n ];\n if (engine !== null) {\n const snapshot = engine.stats.snapshot();\n playback.push(\n [\n 'throughput',\n `slow ${bitrate(snapshot.stats.throughputEwma)}, fast ${bitrate(snapshot.stats.throughputFastEwma)}`,\n ],\n ['playing', rendition(engine.quality.playing)],\n ['switches', String(counters.switches)],\n );\n }\n return [\n { title: 'Source', rows: source },\n { title: 'Playback', rows: playback },\n ];\n }\n\n private engineSections(engine: Mattebox | null): Section[] {\n if (engine === null) {\n return [\n {\n title: null,\n rows: [],\n note: 'A native session: the browser plays this, and there is no engine to ask.',\n },\n ];\n }\n const state = engine.stats.snapshot();\n const optional = engine as Namespaces;\n const live = state.live;\n const rows: Pair[] = [\n ['capabilities', [...engine.capabilities()].join(', ') || 'none'],\n ['phase', state.lifecycle.phase],\n ['buffer goal', `${state.scheduling.bufferGoal}s`],\n [\n 'throughput',\n `slow ${bitrate(state.stats.throughputEwma)}, fast ${bitrate(state.stats.throughputFastEwma)}`,\n ],\n [\n 'in flight',\n [...state.scheduling.inflight.values()].map((r) => `${r.trackId} #${r.seq}`).join(', ') ||\n 'none',\n ],\n [\n 'live',\n live === null\n ? 'VOD'\n : `window ${clock(live.span.start)} to ${clock(live.span.end)}, edge ${clock(live.edge)}${\n optional.live?.latency === null || optional.live?.latency === undefined\n ? ''\n : `, ${optional.live.latency.toFixed(1)}s behind`\n }`,\n ],\n ['trace', `${engine.stats.trace().length} entries`],\n ];\n const error = engine.error;\n if (error !== null) rows.push(['last error', `${error.category}: ${error.code}`]);\n\n const buffers: Pair[] = [...state.buffers.entries()].map(([id, buffer]) => [\n id.replace('sb:', ''),\n `${buffer.codecs}: ${ranges(buffer.ranges)}${buffer.pendingAppends > 0 ? `, ${buffer.pendingAppends} pending` : ''}`,\n ]);\n\n const tracks: Pair[] = engine.tracks.available.map((track) => {\n const active = engine.tracks.active(track.contentType)?.id === track.id;\n const name = [track.lang, track.role].filter((v) => v !== undefined).join(' · ');\n return [\n `${track.contentType}${active ? ' ●' : ''}`,\n `${track.id}${name === '' ? '' : ` (${name})`}, ${track.renditions.length} renditions`,\n ];\n });\n\n const playing = engine.quality.playing?.id ?? null;\n const active = engine.quality.active?.id ?? null;\n const allowed = new Set(engine.quality.allowed.map((r) => r.id));\n const renditions: Pair[] = engine.quality.renditions.map((r) => {\n const flags = [\n r.id === playing ? 'playing' : '',\n r.id === active && active !== playing ? 'next' : '',\n r.id === engine.quality.pinned ? 'pinned' : '',\n allowed.has(r.id) ? '' : 'capped',\n ].filter((f) => f !== '');\n const size = r.width !== undefined && r.height !== undefined ? `${r.width}×${r.height}` : '';\n const text = [\n size,\n bitrate(r.bitrate),\n r.frameRate === undefined ? '' : `${r.frameRate} fps`,\n r.codecs ?? '',\n ]\n .filter((v) => v !== '')\n .join(', ');\n return [r.id, `${text}${flags.length > 0 ? ` [${flags.join(', ')}]` : ''}`];\n });\n\n const drm: Pair[] =\n optional.drm === undefined\n ? []\n : [\n ['key system', optional.drm.keySystem ?? 'none yet'],\n [\n 'keys',\n optional.drm.sessions.length === 0\n ? 'none yet'\n : optional.drm.sessions.map((s) => `${s.keyId}: ${s.status}`).join(', '),\n ],\n ];\n\n return [\n { title: 'Engine', rows },\n {\n title: 'Source buffers',\n rows: buffers,\n note: buffers.length === 0 ? 'none yet' : undefined,\n },\n { title: 'Tracks', rows: tracks, note: tracks.length === 0 ? 'none yet' : undefined },\n {\n title: 'Renditions',\n rows: renditions,\n note: renditions.length === 0 ? 'none yet' : undefined,\n },\n ...(optional.drm === undefined ? [] : [{ title: 'DRM', rows: drm }]),\n ];\n }\n\n /**\n * Draws sections into a page, reusing what is there: a heading and a\n * list per section, a row per pair, texts replaced only where they\n * changed, so a page open for an hour neither flickers nor grows.\n */\n private sections(page: HTMLElement, sections: readonly Section[]): void {\n const wanted = sections.flatMap((section) => {\n const nodes: Array<['heading' | 'note' | 'rows', string | readonly Pair[]]> = [];\n if (section.title !== null) nodes.push(['heading', section.title]);\n if (section.note !== undefined && section.rows.length === 0)\n nodes.push(['note', section.note]);\n else nodes.push(['rows', section.rows]);\n return nodes;\n });\n while (page.childElementCount > wanted.length) page.lastElementChild?.remove();\n wanted.forEach(([kind, content], i) => {\n let node = page.children[i] as HTMLElement | undefined;\n const tag = kind === 'heading' ? 'h3' : kind === 'note' ? 'p' : 'dl';\n if (node === undefined || node.localName !== tag) {\n const fresh = el(tag, kind);\n if (node === undefined) page.append(fresh);\n else node.replaceWith(fresh);\n node = fresh;\n }\n if (typeof content === 'string') {\n if (node.textContent !== content) node.textContent = content;\n return;\n }\n // Rows: a key and a value each, as children of the list in pairs.\n while (node.childElementCount > content.length * 2) node.lastElementChild?.remove();\n content.forEach(([key, value], j) => {\n let dt = node.children[j * 2] as HTMLElement | undefined;\n let dd = node.children[j * 2 + 1] as HTMLElement | undefined;\n if (dt === undefined || dd === undefined) {\n dt = el('dt', 'key');\n dd = el('dd', 'value');\n node.append(dt, dd);\n }\n if (dt.textContent !== key) dt.textContent = key;\n if (dd.textContent !== value) dd.textContent = value;\n });\n });\n }\n\n /** The browser page: probed once, the first time it is shown, then a set of tables. */\n private browser(): void {\n const page = this.pages.browser;\n if (this.support !== null || this.probing) return;\n this.probing = true;\n setChildren(page, el('p', 'note', 'Probing the browser…'));\n void probeSupport().then((support) => {\n this.support = support;\n this.probing = false;\n this.tables(page, support);\n });\n }\n\n private tables(page: HTMLElement, support: Support): void {\n setChildren(page);\n page.append(el('h3', 'heading', 'Platform'), el('p', 'note', support.userAgent));\n const platform = el('table', 'table');\n for (const row of support.platform) {\n const tr = document.createElement('tr');\n const [text, part] = cell(row.value);\n tr.append(el('th', 'cell label', row.label), el('td', part, text));\n platform.append(tr);\n }\n page.append(platform);\n\n page.append(el('h3', 'heading', 'Codecs'));\n const codecs = el('table', 'table');\n const head = document.createElement('tr');\n for (const name of ['Codec', 'MSE fMP4', 'MSE WebM', '<video>', 'Smooth', 'Efficient']) {\n head.append(el('th', 'cell label', name));\n }\n codecs.append(head);\n for (const row of support.codecs) {\n const tr = document.createElement('tr');\n const label = el('th', 'cell label', row.label);\n label.title = row.codec;\n tr.append(label);\n for (const value of [row.mse, row.webm, row.element, row.smooth, row.efficient]) {\n const [text, part] = cell(value);\n tr.append(el('td', part, text));\n }\n codecs.append(tr);\n }\n page.append(codecs);\n\n page.append(el('h3', 'heading', 'DRM'));\n const drm = el('table', 'table');\n const drmHead = document.createElement('tr');\n for (const name of [\n 'System',\n 'Available',\n 'Level',\n 'Schemes',\n 'Persistent',\n 'Identifier',\n 'HDCP',\n ]) {\n drmHead.append(el('th', 'cell label', name));\n }\n drm.append(drmHead);\n for (const row of support.drm) {\n const tr = document.createElement('tr');\n const label = el('th', 'cell label', row.label);\n if (row.keySystem !== null) label.title = row.keySystem;\n tr.append(label);\n const values: Cell[] = [\n row.keySystem === null ? 'no' : 'yes',\n row.level,\n row.schemes,\n row.persistent,\n row.identifier,\n row.hdcp,\n ];\n for (const value of values) {\n const [text, part] = cell(value);\n tr.append(el('td', part, text));\n }\n drm.append(tr);\n }\n page.append(drm);\n }\n}\n\nfunction playbackRanges(video: HTMLVideoElement): Array<{ start: number; end: number }> {\n return Array.from({ length: video.buffered.length }, (_, i) => ({\n start: video.buffered.start(i),\n end: video.buffered.end(i),\n }));\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"element.js","names":[],"sources":["../src/element.ts"],"sourcesContent":["/**\n * <mbx-diagnostics>: what the session is doing, for an integrator's eyes.\n * In the bar it is a button that opens a panel over the picture; anywhere\n * else inside the player, the panel itself, open, in flow. Four pages:\n * the playback facts, the charts, the engine's state, and what the browser\n * supports. A button copies the report, and `report()` hands it to a page,\n * which also gets it as a `report` event on every fatal error, so a page\n * sends it where its errors go.\n *\n * The sampler runs while the element is attached, panel open or not, so\n * the counts cover the session, and keeps the session's trace, slimmed,\n * from the engine's `trace` events, or off its ring where it emits none. The pages redraw twice a second while\n * shown, the charts four times. The browser is probed once, the first\n * time its page is shown: the key-system probes are not free, and Firefox\n * asks the viewer about a DRM module it has not enabled.\n *\n * A native session has no engine, and the engine's rules say a native\n * session has no diagnostics beyond the video's own: the playback page and\n * the buffer, stall and frame charts read the video, the rest says so.\n *\n * No class fields: the ES2015 build would lower them into helpers, and the\n * player's emit check bans helpers. State is declared, then assigned.\n */\nimport type { Mattebox } from 'mattebox';\nimport type { Charts, ChartTab, Palette } from './charts.js';\nimport { CHART_TABS, createCharts } from './charts.js';\nimport { setChildren } from './dom.js';\nimport { bitrate, clock, fixed, ranges, rendition, share } from './format.js';\nimport type { PlayerError, PlayerHost } from './host.js';\nimport { findPlayer, whenPlayer } from './host.js';\nimport { icon } from './icon.js';\nimport type { DiagnosticsReport, QoeFigures } from './report.js';\nimport { buildReport } from './report.js';\nimport type { Sampler } from './sampler.js';\nimport { createSampler } from './sampler.js';\nimport { STYLE } from './style.js';\nimport type { Cell, Support } from './support.js';\nimport { probeSupport } from './support.js';\n\nconst POLL_MS = 500;\nconst DRAW_MS = 250;\nconst WINDOW = 120;\nconst WINDOWS = [30, 60, 120, 300, 600];\nconst PANEL_WIDTH = 560;\n/** Air between the panel's top and the picture's, and around it. */\nconst AIR = 8;\n\nconst TABS = ['playback', 'charts', 'engine', 'browser'] as const;\ntype Tab = (typeof TABS)[number];\nconst TAB_NAMES: Readonly<Record<Tab, string>> = {\n playback: 'Playback',\n charts: 'Charts',\n engine: 'Engine',\n browser: 'Browser',\n};\n\nconst READY_STATES = ['nothing', 'metadata', 'current data', 'future data', 'enough data'];\nconst NETWORK_STATES = ['empty', 'idle', 'loading', 'no source'];\n\ntype Pair = readonly [string, string];\n\ninterface Section {\n readonly title: string | null;\n readonly rows: readonly Pair[];\n /** A line instead of rows, for a section with nothing to list. */\n readonly note?: string | undefined;\n}\n\n/** The optional namespaces the pages read, cast once, the way the player does it. */\ninterface Namespaces {\n readonly live?: { readonly latency: number | null; readonly atEdge: boolean };\n readonly qoe?: QoeFigures;\n readonly drm?: {\n readonly keySystem: string | null;\n readonly sessions: ReadonlyArray<{ readonly keyId: string; readonly status: string }>;\n };\n}\n\nfunction el<K extends keyof HTMLElementTagNameMap>(\n tag: K,\n part: string,\n text?: string,\n): HTMLElementTagNameMap[K] {\n const node = document.createElement(tag);\n node.setAttribute('part', part);\n if (text !== undefined) node.textContent = text;\n return node;\n}\n\nfunction button(part: string, text?: string): HTMLButtonElement {\n const node = el('button', part, text);\n node.type = 'button';\n return node;\n}\n\n/** A cell's text and its part: a tick, a cross, a dash, or the text itself. */\nfunction cell(value: Cell): [string, string] {\n switch (value) {\n case 'yes':\n return ['✓', 'cell ok'];\n case 'no':\n return ['✕', 'cell bad'];\n case 'na':\n return ['–', 'cell na'];\n case 'maybe':\n return ['maybe', 'cell maybe'];\n default:\n return [value, 'cell'];\n }\n}\n\nexport class MbxDiagnostics extends HTMLElement {\n static get observedAttributes(): readonly string[] {\n return ['label', 'label-copy', 'label-copied', 'window'];\n }\n\n declare private player: PlayerHost | null;\n declare private cancel: (() => void) | null;\n declare private offs: Array<() => void>;\n declare private readonly sampler: Sampler;\n declare private readonly charts: Charts;\n declare private timer: ReturnType<typeof setInterval> | undefined;\n declare private drawer: ReturnType<typeof setInterval> | undefined;\n declare private copied: ReturnType<typeof setTimeout> | undefined;\n declare private tab: Tab;\n declare private chartTab: ChartTab;\n declare private support: Support | null;\n declare private probing: boolean;\n\n declare private readonly toggle: HTMLButtonElement;\n declare private readonly panel: HTMLElement;\n declare private readonly body: HTMLElement;\n declare private readonly tabs: Record<Tab, HTMLButtonElement>;\n declare private readonly pages: Record<Tab, HTMLElement>;\n declare private readonly copy: HTMLButtonElement;\n declare private readonly canvas: HTMLCanvasElement;\n declare private readonly chartTabs: Record<ChartTab, HTMLButtonElement>;\n declare private readonly windowSelect: HTMLSelectElement;\n declare private readonly outside: (event: PointerEvent) => void;\n declare private readonly refit: () => void;\n\n constructor() {\n super();\n this.player = null;\n this.cancel = null;\n this.offs = [];\n this.sampler = createSampler();\n this.timer = undefined;\n this.drawer = undefined;\n this.copied = undefined;\n this.tab = 'playback';\n this.chartTab = 'buffer';\n this.support = null;\n this.probing = false;\n\n const root = this.attachShadow({ mode: 'open' });\n const style = document.createElement('style');\n style.textContent = STYLE;\n\n this.toggle = button('button');\n this.toggle.setAttribute('aria-haspopup', 'dialog');\n this.toggle.setAttribute('aria-expanded', 'false');\n const slot = document.createElement('slot');\n slot.name = 'icon';\n slot.append(icon());\n this.toggle.append(slot);\n this.toggle.addEventListener('click', () => {\n if (this.panel.hidden) this.show();\n else this.hide();\n });\n\n this.panel = el('div', 'panel');\n this.panel.setAttribute('role', 'dialog');\n this.panel.hidden = true;\n this.panel.addEventListener('keydown', (event) => {\n if (event.key !== 'Escape' || this.hasAttribute('inline')) return;\n event.preventDefault();\n this.hide();\n this.toggle.focus();\n });\n\n const head = el('div', 'head');\n head.setAttribute('role', 'tablist');\n this.tabs = {} as Record<Tab, HTMLButtonElement>;\n this.pages = {} as Record<Tab, HTMLElement>;\n this.body = el('div', 'body');\n for (const tab of TABS) {\n const node = button(`tab tab-${tab}`, TAB_NAMES[tab]);\n node.setAttribute('role', 'tab');\n node.addEventListener('click', () => {\n this.select(tab);\n });\n this.tabs[tab] = node;\n head.append(node);\n const page = el('div', `page page-${tab}`);\n page.setAttribute('role', 'tabpanel');\n page.hidden = true;\n this.pages[tab] = page;\n this.body.append(page);\n }\n this.copy = button('copy');\n this.copy.addEventListener('click', () => {\n void this.copyReport();\n });\n const close = button('close', '✕');\n close.setAttribute('aria-label', 'Close');\n close.addEventListener('click', () => {\n this.hide();\n this.toggle.focus();\n });\n head.append(this.copy, close);\n\n // The charts page: its own tabs, the window, the canvas, the legend and the readout.\n const chartTabs = el('div', 'chart-tabs');\n chartTabs.setAttribute('role', 'tablist');\n this.chartTabs = {} as Record<ChartTab, HTMLButtonElement>;\n for (const tab of CHART_TABS) {\n const node = button(`chart-tab chart-tab-${tab}`, tab);\n node.setAttribute('role', 'tab');\n node.addEventListener('click', () => {\n this.chartTab = tab;\n this.markChartTab();\n this.draw();\n });\n this.chartTabs[tab] = node;\n chartTabs.append(node);\n }\n this.windowSelect = el('select', 'window');\n this.windowSelect.setAttribute('aria-label', 'Window');\n for (const seconds of WINDOWS) {\n const option = document.createElement('option');\n option.value = String(seconds);\n option.textContent = seconds < 60 ? `${seconds} s` : `${seconds / 60} min`;\n this.windowSelect.append(option);\n }\n this.windowSelect.addEventListener('change', () => {\n this.draw();\n });\n chartTabs.append(this.windowSelect);\n this.canvas = el('canvas', 'chart');\n const legend = el('div', 'legend');\n const readout = el('p', 'readout');\n this.pages.charts.append(chartTabs, this.canvas, legend, readout);\n this.charts = createCharts(this.canvas, legend, readout);\n\n this.outside = (event: PointerEvent): void => {\n if (!event.composedPath().includes(this)) this.hide();\n };\n this.refit = (): void => {\n this.fit();\n };\n\n this.panel.append(head, this.body);\n root.append(style, this.toggle, this.panel);\n this.markTab();\n this.markChartTab();\n this.renderLabels();\n }\n\n connectedCallback(): void {\n // In the bar, a button and a popup; anywhere else, the panel in flow.\n this.toggleAttribute('inline', this.parentElement?.localName !== 'mbx-control-bar');\n const found = findPlayer(this);\n if (found === null) return;\n this.cancel?.();\n this.cancel = whenPlayer(found, (player) => {\n if (!this.isConnected) return;\n this.attach(player);\n });\n }\n\n disconnectedCallback(): void {\n this.cancel?.();\n this.cancel = null;\n this.detach();\n }\n\n attributeChangedCallback(): void {\n this.renderLabels();\n }\n\n private attach(player: PlayerHost): void {\n this.player = player;\n this.sampler.attach(player.video, player.engine);\n const on = (target: EventTarget, name: string, fn: (event: Event) => void): void => {\n target.addEventListener(name, fn);\n this.offs.push(() => {\n target.removeEventListener(name, fn);\n });\n };\n on(player, 'sourcechange', () => {\n this.sampler.attach(player.video, player.engine);\n this.poll();\n });\n on(player, 'error', (event) => {\n const error = (event as CustomEvent<PlayerError>).detail;\n if (error.fatal) {\n this.dispatchEvent(\n new CustomEvent('report', { detail: this.report(), bubbles: true, composed: true }),\n );\n }\n });\n this.timer = setInterval(() => {\n this.poll();\n }, POLL_MS);\n this.poll();\n if (this.hasAttribute('inline')) this.show();\n }\n\n private detach(): void {\n for (const off of this.offs) off();\n this.offs = [];\n clearInterval(this.timer);\n this.timer = undefined;\n this.sampler.release();\n this.hide();\n this.player = null;\n }\n\n /** The report, as of now. */\n report(): DiagnosticsReport {\n const player = this.player;\n if (player === null) throw new Error('mbx-diagnostics is not inside a player');\n return buildReport({\n player,\n samples: this.sampler.samples,\n marks: this.sampler.marks,\n counters: this.sampler.counters,\n history: this.sampler.history,\n support: this.support,\n });\n }\n\n private poll(): void {\n const player = this.player;\n if (player === null) return;\n this.sampler.poll(player.video, player.engine);\n if (!this.panel.hidden) this.paint();\n }\n\n private show(): void {\n if (!this.panel.hidden) return;\n this.panel.hidden = false;\n if (!this.hasAttribute('inline')) {\n this.setAttribute('open', '');\n this.toggle.setAttribute('aria-expanded', 'true');\n document.addEventListener('pointerdown', this.outside, true);\n window.addEventListener('resize', this.refit);\n this.fit();\n }\n this.paint();\n this.drawer = setInterval(() => {\n this.draw();\n }, DRAW_MS);\n if (!this.hasAttribute('inline')) this.tabs[this.tab].focus();\n }\n\n private hide(): void {\n clearInterval(this.drawer);\n this.drawer = undefined;\n if (this.panel.hidden) return;\n this.panel.hidden = true;\n this.removeAttribute('open');\n this.toggle.setAttribute('aria-expanded', 'false');\n document.removeEventListener('pointerdown', this.outside, true);\n window.removeEventListener('resize', this.refit);\n }\n\n /** The panel never leaves the picture: fitted to the room above the button, within the player's width. */\n private fit(): void {\n const player = this.player;\n if (player === null) return;\n const box = player.getBoundingClientRect();\n const host = this.getBoundingClientRect();\n const top = player.video.getBoundingClientRect().top;\n const room = host.top - top - AIR;\n this.panel.style.maxHeight = `${Math.max(120, Math.floor(room))}px`;\n const width = Math.min(PANEL_WIDTH, Math.max(200, box.width - AIR * 2));\n this.panel.style.width = `${width}px`;\n const left = Math.max(box.left + AIR, Math.min(host.right - width, box.right - AIR - width));\n this.panel.style.right = 'auto';\n this.panel.style.left = `${left - host.left}px`;\n }\n\n private select(tab: Tab): void {\n this.tab = tab;\n this.markTab();\n this.tabs[tab].focus();\n this.paint();\n this.draw();\n }\n\n private markTab(): void {\n for (const tab of TABS) {\n this.tabs[tab].setAttribute('aria-selected', String(tab === this.tab));\n this.tabs[tab].tabIndex = tab === this.tab ? 0 : -1;\n this.pages[tab].hidden = tab !== this.tab;\n }\n }\n\n private markChartTab(): void {\n for (const tab of CHART_TABS) {\n this.chartTabs[tab].setAttribute('aria-selected', String(tab === this.chartTab));\n }\n }\n\n private renderLabels(): void {\n this.toggle.setAttribute('aria-label', this.getAttribute('label') ?? 'Diagnostics');\n this.panel.setAttribute('aria-label', this.getAttribute('label') ?? 'Diagnostics');\n if (this.copied === undefined) {\n this.copy.textContent = this.getAttribute('label-copy') ?? 'Copy report';\n }\n const raw = Number(this.getAttribute('window'));\n const seconds = Number.isFinite(raw) && raw > 0 ? raw : WINDOW;\n if (!WINDOWS.includes(seconds)) {\n const option = document.createElement('option');\n option.value = String(seconds);\n option.textContent = `${seconds} s`;\n this.windowSelect.append(option);\n }\n this.windowSelect.value = String(seconds);\n }\n\n private async copyReport(): Promise<void> {\n const text = JSON.stringify(this.report(), null, 2);\n try {\n await navigator.clipboard.writeText(text);\n } catch {\n return;\n }\n this.copy.textContent = this.getAttribute('label-copied') ?? 'Copied';\n clearTimeout(this.copied);\n this.copied = setTimeout(() => {\n this.copied = undefined;\n this.renderLabels();\n }, 1500);\n }\n\n /** The colours the charts draw with, off the element's tokens. */\n private palette(): Palette {\n const computed = getComputedStyle(this);\n const token = (name: string, fallback: string): string =>\n computed.getPropertyValue(name).trim() || fallback;\n return {\n ink: token('--mbx-text', '#f2f3f5'),\n muted: token('--mbx-muted', '#9aa0a6'),\n accent: token('--mbx-accent', '#5b8cff'),\n warn: token('--mbx-chart-3', '#d9a83f'),\n series: [1, 2, 3, 4, 5].map((i) => token(`--mbx-chart-${i}`, '#888')),\n };\n }\n\n private draw(): void {\n const player = this.player;\n if (player === null || this.panel.hidden || this.tab !== 'charts') return;\n this.charts.draw({\n tab: this.chartTab,\n window: Number(this.windowSelect.value) || WINDOW,\n samples: this.sampler.samples,\n marks: this.sampler.marks,\n counters: this.sampler.counters,\n video: player.video,\n engine: player.engine,\n palette: this.palette(),\n });\n }\n\n /** The page shown, from the facts of the moment. */\n private paint(): void {\n const player = this.player;\n if (player === null || this.panel.hidden) return;\n switch (this.tab) {\n case 'playback':\n this.sections(this.pages.playback, this.playbackSections(player));\n break;\n case 'engine':\n this.sections(this.pages.engine, this.engineSections(player.engine));\n break;\n case 'browser':\n this.browser();\n break;\n default:\n break;\n }\n }\n\n private playbackSections(player: PlayerHost): Section[] {\n const video = player.video;\n const engine = player.engine;\n const quality = video.getVideoPlaybackQuality?.();\n const counters = this.sampler.counters;\n const last = this.sampler.samples[this.sampler.samples.length - 1];\n const state = video.paused ? (video.ended ? 'ended' : 'paused') : 'playing';\n const source: Pair[] = [\n ['source', player.getAttribute('src') ?? '–'],\n ['type', player.getAttribute('type') ?? '–'],\n ['handler', player.player?.session?.handler ?? '–'],\n ];\n if (engine !== null) source.push(['phase', engine.stats.snapshot().lifecycle.phase]);\n if (player.error !== null) {\n source.push(['error', `${player.error.category}: ${player.error.code}`]);\n } else if (video.error !== null) {\n source.push(['media error', `${video.error.code} ${video.error.message}`]);\n }\n const playback: Pair[] = [\n ['time', `${clock(video.currentTime)} of ${clock(video.duration)}`],\n [\n 'state',\n `${state}, ${READY_STATES[video.readyState] ?? video.readyState}, network ${NETWORK_STATES[video.networkState] ?? video.networkState}`,\n ],\n ['rate', `${video.playbackRate}×`],\n ['picture', video.videoWidth > 0 ? `${video.videoWidth}×${video.videoHeight}` : '–'],\n [\n 'frames',\n quality === undefined\n ? '–'\n : `${quality.totalVideoFrames} decoded, ${quality.droppedVideoFrames} dropped (${share(quality.droppedVideoFrames, quality.totalVideoFrames)})`,\n ],\n ['buffered', `${fixed(last?.ahead ?? 0)}s ahead: ${ranges(playbackRanges(video))}`],\n ['stalls', `${counters.stalls}, ${counters.stalledSeconds.toFixed(1)}s in total`],\n ];\n if (engine !== null) {\n const snapshot = engine.stats.snapshot();\n playback.push(\n [\n 'throughput',\n `slow ${bitrate(snapshot.stats.throughputEwma)}, fast ${bitrate(snapshot.stats.throughputFastEwma)}`,\n ],\n ['playing', rendition(engine.quality.playing)],\n ['switches', String(counters.switches)],\n );\n }\n // The engine's own figures, when its qoe stage is in the stack: they\n // count from the load, where the stalls above count from the sampling.\n const qoe = (engine as Namespaces | null)?.qoe;\n return [\n { title: 'Source', rows: source },\n { title: 'Playback', rows: playback },\n ...(qoe === undefined\n ? []\n : [\n {\n title: 'Quality of experience',\n rows: [\n ['startup', qoe.startupTime === null ? '–' : `${qoe.startupTime.toFixed(2)}s`],\n ['rebuffers', `${qoe.rebuffers}, ${qoe.rebufferDuration.toFixed(1)}s in total`],\n ['quality changes', String(qoe.switches)],\n ] satisfies Pair[],\n },\n ]),\n ];\n }\n\n private engineSections(engine: Mattebox | null): Section[] {\n if (engine === null) {\n return [\n {\n title: null,\n rows: [],\n note: 'A native session: the browser plays this, and there is no engine to ask.',\n },\n ];\n }\n const state = engine.stats.snapshot();\n const optional = engine as Namespaces;\n const live = state.live;\n const rows: Pair[] = [\n ['capabilities', [...engine.capabilities()].join(', ') || 'none'],\n ['phase', state.lifecycle.phase],\n ['buffer goal', `${state.scheduling.bufferGoal}s`],\n [\n 'throughput',\n `slow ${bitrate(state.stats.throughputEwma)}, fast ${bitrate(state.stats.throughputFastEwma)}`,\n ],\n [\n 'in flight',\n [...state.scheduling.inflight.values()].map((r) => `${r.trackId} #${r.seq}`).join(', ') ||\n 'none',\n ],\n [\n 'live',\n live === null\n ? 'VOD'\n : `window ${clock(live.span.start)} to ${clock(live.span.end)}, edge ${clock(live.edge)}${\n optional.live?.latency === null || optional.live?.latency === undefined\n ? ''\n : `, ${optional.live.latency.toFixed(1)}s behind`\n }`,\n ],\n ['trace', `${engine.stats.trace().length} entries`],\n ];\n const error = engine.error;\n if (error !== null) rows.push(['last error', `${error.category}: ${error.code}`]);\n\n const buffers: Pair[] = [...state.buffers.entries()].map(([id, buffer]) => [\n id.replace('sb:', ''),\n `${buffer.codecs}: ${ranges(buffer.ranges)}${buffer.pendingAppends > 0 ? `, ${buffer.pendingAppends} pending` : ''}`,\n ]);\n\n const tracks: Pair[] = engine.tracks.available.map((track) => {\n const active = engine.tracks.active(track.contentType)?.id === track.id;\n const name = [track.lang, track.role].filter((v) => v !== undefined).join(' · ');\n return [\n `${track.contentType}${active ? ' ●' : ''}`,\n `${track.id}${name === '' ? '' : ` (${name})`}, ${track.renditions.length} renditions`,\n ];\n });\n\n const playing = engine.quality.playing?.id ?? null;\n const active = engine.quality.active?.id ?? null;\n const allowed = new Set(engine.quality.allowed.map((r) => r.id));\n const renditions: Pair[] = engine.quality.renditions.map((r) => {\n const flags = [\n r.id === playing ? 'playing' : '',\n r.id === active && active !== playing ? 'next' : '',\n r.id === engine.quality.pinned ? 'pinned' : '',\n allowed.has(r.id) ? '' : 'capped',\n ].filter((f) => f !== '');\n const size = r.width !== undefined && r.height !== undefined ? `${r.width}×${r.height}` : '';\n const text = [\n size,\n bitrate(r.bitrate),\n r.frameRate === undefined ? '' : `${r.frameRate} fps`,\n r.codecs ?? '',\n ]\n .filter((v) => v !== '')\n .join(', ');\n return [r.id, `${text}${flags.length > 0 ? ` [${flags.join(', ')}]` : ''}`];\n });\n\n const drm: Pair[] =\n optional.drm === undefined\n ? []\n : [\n ['key system', optional.drm.keySystem ?? 'none yet'],\n [\n 'keys',\n optional.drm.sessions.length === 0\n ? 'none yet'\n : optional.drm.sessions.map((s) => `${s.keyId}: ${s.status}`).join(', '),\n ],\n ];\n\n return [\n { title: 'Engine', rows },\n {\n title: 'Source buffers',\n rows: buffers,\n note: buffers.length === 0 ? 'none yet' : undefined,\n },\n { title: 'Tracks', rows: tracks, note: tracks.length === 0 ? 'none yet' : undefined },\n {\n title: 'Renditions',\n rows: renditions,\n note: renditions.length === 0 ? 'none yet' : undefined,\n },\n ...(optional.drm === undefined ? [] : [{ title: 'DRM', rows: drm }]),\n ];\n }\n\n /**\n * Draws sections into a page, reusing what is there: a heading and a\n * list per section, a row per pair, texts replaced only where they\n * changed, so a page open for an hour neither flickers nor grows.\n */\n private sections(page: HTMLElement, sections: readonly Section[]): void {\n const wanted = sections.flatMap((section) => {\n const nodes: Array<['heading' | 'note' | 'rows', string | readonly Pair[]]> = [];\n if (section.title !== null) nodes.push(['heading', section.title]);\n if (section.note !== undefined && section.rows.length === 0)\n nodes.push(['note', section.note]);\n else nodes.push(['rows', section.rows]);\n return nodes;\n });\n while (page.childElementCount > wanted.length) page.lastElementChild?.remove();\n wanted.forEach(([kind, content], i) => {\n let node = page.children[i] as HTMLElement | undefined;\n const tag = kind === 'heading' ? 'h3' : kind === 'note' ? 'p' : 'dl';\n if (node === undefined || node.localName !== tag) {\n const fresh = el(tag, kind);\n if (node === undefined) page.append(fresh);\n else node.replaceWith(fresh);\n node = fresh;\n }\n if (typeof content === 'string') {\n if (node.textContent !== content) node.textContent = content;\n return;\n }\n // Rows: a key and a value each, as children of the list in pairs.\n while (node.childElementCount > content.length * 2) node.lastElementChild?.remove();\n content.forEach(([key, value], j) => {\n let dt = node.children[j * 2] as HTMLElement | undefined;\n let dd = node.children[j * 2 + 1] as HTMLElement | undefined;\n if (dt === undefined || dd === undefined) {\n dt = el('dt', 'key');\n dd = el('dd', 'value');\n node.append(dt, dd);\n }\n if (dt.textContent !== key) dt.textContent = key;\n if (dd.textContent !== value) dd.textContent = value;\n });\n });\n }\n\n /** The browser page: probed once, the first time it is shown, then a set of tables. */\n private browser(): void {\n const page = this.pages.browser;\n if (this.support !== null || this.probing) return;\n this.probing = true;\n setChildren(page, el('p', 'note', 'Probing the browser…'));\n void probeSupport().then((support) => {\n this.support = support;\n this.probing = false;\n this.tables(page, support);\n });\n }\n\n private tables(page: HTMLElement, support: Support): void {\n setChildren(page);\n page.append(el('h3', 'heading', 'Platform'), el('p', 'note', support.userAgent));\n const platform = el('table', 'table');\n for (const row of support.platform) {\n const tr = document.createElement('tr');\n const [text, part] = cell(row.value);\n tr.append(el('th', 'cell label', row.label), el('td', part, text));\n platform.append(tr);\n }\n page.append(platform);\n\n page.append(el('h3', 'heading', 'Codecs'));\n const codecs = el('table', 'table');\n const head = document.createElement('tr');\n for (const name of ['Codec', 'MSE fMP4', 'MSE WebM', '<video>', 'Smooth', 'Efficient']) {\n head.append(el('th', 'cell label', name));\n }\n codecs.append(head);\n for (const row of support.codecs) {\n const tr = document.createElement('tr');\n const label = el('th', 'cell label', row.label);\n label.title = row.codec;\n tr.append(label);\n for (const value of [row.mse, row.webm, row.element, row.smooth, row.efficient]) {\n const [text, part] = cell(value);\n tr.append(el('td', part, text));\n }\n codecs.append(tr);\n }\n page.append(codecs);\n\n page.append(el('h3', 'heading', 'DRM'));\n const drm = el('table', 'table');\n const drmHead = document.createElement('tr');\n for (const name of [\n 'System',\n 'Available',\n 'Level',\n 'Schemes',\n 'Persistent',\n 'Identifier',\n 'HDCP',\n ]) {\n drmHead.append(el('th', 'cell label', name));\n }\n drm.append(drmHead);\n for (const row of support.drm) {\n const tr = document.createElement('tr');\n const label = el('th', 'cell label', row.label);\n if (row.keySystem !== null) label.title = row.keySystem;\n tr.append(label);\n const values: Cell[] = [\n row.keySystem === null ? 'no' : 'yes',\n row.level,\n row.schemes,\n row.persistent,\n row.identifier,\n row.hdcp,\n ];\n for (const value of values) {\n const [text, part] = cell(value);\n tr.append(el('td', part, text));\n }\n drm.append(tr);\n }\n page.append(drm);\n }\n}\n\nfunction playbackRanges(video: HTMLVideoElement): Array<{ start: number; end: number }> {\n return Array.from({ length: video.buffered.length }, (_, i) => ({\n start: video.buffered.start(i),\n end: video.buffered.end(i),\n }));\n}\n"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- //#region \0@oxc-project+runtime@0.150.0/helpers/esm/asyncToGenerator.js
1
+ //#region \0@oxc-project+runtime@0.152.0/helpers/esm/asyncToGenerator.js
2
2
  function asyncGeneratorStep(n, t, e, r, o, a, c) {
3
3
  try {
4
4
  var i = n[a](c), u = i.value;
@@ -1,5 +1,5 @@
1
1
  import toPropertyKey from "./toPropertyKey.js";
2
- //#region \0@oxc-project+runtime@0.150.0/helpers/esm/defineProperty.js
2
+ //#region \0@oxc-project+runtime@0.152.0/helpers/esm/defineProperty.js
3
3
  function _defineProperty(e, r, t) {
4
4
  return (r = toPropertyKey(r)) in e ? Object.defineProperty(e, r, {
5
5
  value: t,
@@ -1,5 +1,5 @@
1
1
  import _defineProperty from "./defineProperty.js";
2
- //#region \0@oxc-project+runtime@0.150.0/helpers/esm/objectSpread2.js
2
+ //#region \0@oxc-project+runtime@0.152.0/helpers/esm/objectSpread2.js
3
3
  function ownKeys(e, r) {
4
4
  var t = Object.keys(e);
5
5
  if (Object.getOwnPropertySymbols) {
@@ -1,5 +1,5 @@
1
1
  import _typeof from "./typeof.js";
2
- //#region \0@oxc-project+runtime@0.150.0/helpers/esm/toPrimitive.js
2
+ //#region \0@oxc-project+runtime@0.152.0/helpers/esm/toPrimitive.js
3
3
  function toPrimitive(t, r) {
4
4
  if ("object" != _typeof(t) || !t) return t;
5
5
  var e = t[Symbol.toPrimitive];
@@ -1,6 +1,6 @@
1
1
  import _typeof from "./typeof.js";
2
2
  import toPrimitive from "./toPrimitive.js";
3
- //#region \0@oxc-project+runtime@0.150.0/helpers/esm/toPropertyKey.js
3
+ //#region \0@oxc-project+runtime@0.152.0/helpers/esm/toPropertyKey.js
4
4
  function toPropertyKey(t) {
5
5
  var i = toPrimitive(t, "string");
6
6
  return "symbol" == _typeof(i) ? i : i + "";
@@ -1,4 +1,4 @@
1
- //#region \0@oxc-project+runtime@0.150.0/helpers/esm/typeof.js
1
+ //#region \0@oxc-project+runtime@0.152.0/helpers/esm/typeof.js
2
2
  function _typeof(o) {
3
3
  "@babel/helpers - typeof";
4
4
  return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function(o) {
@@ -6,7 +6,7 @@ import { icon } from "./icon.js";
6
6
  import { buildReport } from "./report.js";
7
7
  import { createSampler } from "./sampler.js";
8
8
  import { STYLE } from "./style.js";
9
- import _asyncToGenerator from "./_virtual/_@oxc-project_runtime@0.150.0/helpers/esm/asyncToGenerator.js";
9
+ import _asyncToGenerator from "./_virtual/_@oxc-project_runtime@0.152.0/helpers/esm/asyncToGenerator.js";
10
10
  import { probeSupport } from "./support.js";
11
11
  //#region src/element.ts
12
12
  const POLL_MS = 500;
@@ -429,13 +429,25 @@ var MbxDiagnostics = class extends HTMLElement {
429
429
  const snapshot = engine.stats.snapshot();
430
430
  playback.push(["throughput", `slow ${bitrate(snapshot.stats.throughputEwma)}, fast ${bitrate(snapshot.stats.throughputFastEwma)}`], ["playing", rendition(engine.quality.playing)], ["switches", String(counters.switches)]);
431
431
  }
432
- return [{
433
- title: "Source",
434
- rows: source
435
- }, {
436
- title: "Playback",
437
- rows: playback
438
- }];
432
+ const qoe = engine === null || engine === void 0 ? void 0 : engine.qoe;
433
+ return [
434
+ {
435
+ title: "Source",
436
+ rows: source
437
+ },
438
+ {
439
+ title: "Playback",
440
+ rows: playback
441
+ },
442
+ ...qoe === void 0 ? [] : [{
443
+ title: "Quality of experience",
444
+ rows: [
445
+ ["startup", qoe.startupTime === null ? "–" : `${qoe.startupTime.toFixed(2)}s`],
446
+ ["rebuffers", `${qoe.rebuffers}, ${qoe.rebufferDuration.toFixed(1)}s in total`],
447
+ ["quality changes", String(qoe.switches)]
448
+ ]
449
+ }]
450
+ ];
439
451
  }
440
452
  engineSections(engine) {
441
453
  var _optional$live, _optional$live2, _engine$quality$playi, _engine$quality$playi2, _engine$quality$activ, _engine$quality$activ2, _optional$drm$keySyst;
@@ -107,6 +107,12 @@ function engineFacts(engine) {
107
107
  keySystem: optional.drm.keySystem,
108
108
  sessions: [...optional.drm.sessions]
109
109
  },
110
+ qoe: optional.qoe === void 0 ? null : {
111
+ startupTime: optional.qoe.startupTime,
112
+ rebuffers: optional.qoe.rebuffers,
113
+ rebufferDuration: optional.qoe.rebufferDuration,
114
+ switches: optional.qoe.switches
115
+ },
110
116
  error: error === null ? null : {
111
117
  category: error.category,
112
118
  code: error.code,
@@ -1,5 +1,5 @@
1
- import _objectSpread2 from "./_virtual/_@oxc-project_runtime@0.150.0/helpers/esm/objectSpread2.js";
2
- import _asyncToGenerator from "./_virtual/_@oxc-project_runtime@0.150.0/helpers/esm/asyncToGenerator.js";
1
+ import _objectSpread2 from "./_virtual/_@oxc-project_runtime@0.152.0/helpers/esm/objectSpread2.js";
2
+ import _asyncToGenerator from "./_virtual/_@oxc-project_runtime@0.152.0/helpers/esm/asyncToGenerator.js";
3
3
  //#region src/support.ts
4
4
  const CODECS = [
5
5
  {
@@ -1,4 +1,4 @@
1
- import _objectSpread2 from "./_virtual/_@oxc-project_runtime@0.150.0/helpers/esm/objectSpread2.js";
1
+ import _objectSpread2 from "./_virtual/_@oxc-project_runtime@0.152.0/helpers/esm/objectSpread2.js";
2
2
  //#region src/trace.ts
3
3
  /** Segments as a count, whatever their addressing. */
4
4
  function segmentCount(segments) {
package/dist/index.d.ts CHANGED
@@ -8,7 +8,7 @@
8
8
  */
9
9
  import { MbxDiagnostics } from './element.js';
10
10
  export { MbxDiagnostics } from './element.js';
11
- export type { DiagnosticsReport, EngineReport, PlaybackReport } from './report.js';
11
+ export type { DiagnosticsReport, EngineReport, PlaybackReport, QoeFigures } from './report.js';
12
12
  export type { Counters, Mark, Sample } from './sampler.js';
13
13
  export type { CodecRow, DrmRow, PlatformRow, Support } from './support.js';
14
14
  export { probeSupport } from './support.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAE9C,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,YAAY,EAAE,iBAAiB,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AACnF,YAAY,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAC3D,YAAY,EAAE,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAC3E,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAE5C,eAAO,MAAM,WAAW,oBAAoB,CAAC;AAM7C,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,qBAAqB;QAC7B,iBAAiB,EAAE,cAAc,CAAC;KACnC;CACF"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAE9C,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,YAAY,EAAE,iBAAiB,EAAE,YAAY,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAC/F,YAAY,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAC3D,YAAY,EAAE,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAC3E,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAE5C,eAAO,MAAM,WAAW,oBAAoB,CAAC;AAM7C,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,qBAAqB;QAC7B,iBAAiB,EAAE,cAAc,CAAC;KACnC;CACF"}
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../src/index.ts"],"sourcesContent":["/**\n * @mattebox/player-diagnostics: <mbx-diagnostics>, a control for the\n * player's bar, or a panel under the video, that shows what the session\n * is doing and what the browser can do, and writes a report. Importing\n * this module registers the element; that is the package's one side\n * effect. It reaches the player only through the contract a control of\n * the page's own has, and the engine through its public surface.\n */\nimport { MbxDiagnostics } from './element.js';\n\nexport { MbxDiagnostics } from './element.js';\nexport type { DiagnosticsReport, EngineReport, PlaybackReport } from './report.js';\nexport type { Counters, Mark, Sample } from './sampler.js';\nexport type { CodecRow, DrmRow, PlatformRow, Support } from './support.js';\nexport { probeSupport } from './support.js';\n\nexport const DIAGNOSTICS = 'mbx-diagnostics';\n\nif (customElements.get(DIAGNOSTICS) === undefined) {\n customElements.define(DIAGNOSTICS, MbxDiagnostics);\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'mbx-diagnostics': MbxDiagnostics;\n }\n}\n"],"mappings":";;;;;;;;;;;AAgBA,MAAa,cAAc;AAE3B,IAAI,eAAe,IAAA,iBAAe,MAAM,KAAA,GACtC,eAAe,OAAO,aAAa,cAAc"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../src/index.ts"],"sourcesContent":["/**\n * @mattebox/player-diagnostics: <mbx-diagnostics>, a control for the\n * player's bar, or a panel under the video, that shows what the session\n * is doing and what the browser can do, and writes a report. Importing\n * this module registers the element; that is the package's one side\n * effect. It reaches the player only through the contract a control of\n * the page's own has, and the engine through its public surface.\n */\nimport { MbxDiagnostics } from './element.js';\n\nexport { MbxDiagnostics } from './element.js';\nexport type { DiagnosticsReport, EngineReport, PlaybackReport, QoeFigures } from './report.js';\nexport type { Counters, Mark, Sample } from './sampler.js';\nexport type { CodecRow, DrmRow, PlatformRow, Support } from './support.js';\nexport { probeSupport } from './support.js';\n\nexport const DIAGNOSTICS = 'mbx-diagnostics';\n\nif (customElements.get(DIAGNOSTICS) === undefined) {\n customElements.define(DIAGNOSTICS, MbxDiagnostics);\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'mbx-diagnostics': MbxDiagnostics;\n }\n}\n"],"mappings":";;;;;;;;;;;AAgBA,MAAa,cAAc;AAE3B,IAAI,eAAe,IAAA,iBAAe,MAAM,KAAA,GACtC,eAAe,OAAO,aAAa,cAAc"}
package/dist/report.d.ts CHANGED
@@ -93,6 +93,8 @@ export interface EngineReport {
93
93
  readonly status: string;
94
94
  }>;
95
95
  } | null;
96
+ /** The engine's qoe stage figures for this load, or null without the stage. */
97
+ readonly qoe: QoeFigures | null;
96
98
  readonly error: {
97
99
  readonly category: string;
98
100
  readonly code: string;
@@ -125,6 +127,16 @@ export interface DiagnosticsReport {
125
127
  /** The trace entries the element kept, slimmed, oldest first, or null for a native session. */
126
128
  readonly trace: readonly unknown[] | null;
127
129
  }
130
+ /** The figures of the engine's qoe stage, as `engine.qoe` gives them. */
131
+ export interface QoeFigures {
132
+ /** Seconds from the load, or the first play if later, to the first frame playing. */
133
+ readonly startupTime: number | null;
134
+ readonly rebuffers: number;
135
+ /** Seconds spent rebuffering, the current wait included. */
136
+ readonly rebufferDuration: number;
137
+ /** Video quality changes after the first selection. */
138
+ readonly switches: number;
139
+ }
128
140
  export declare function playbackFacts(video: HTMLVideoElement): PlaybackReport;
129
141
  export declare function engineFacts(engine: Mattebox): EngineReport;
130
142
  export interface ReportSources {
@@ -1 +1 @@
1
- {"version":3,"file":"report.d.ts","sourceRoot":"","sources":["../src/report.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"report.d.ts","sourceRoot":"","sources":["../src/report.ts"],"names":[],"mappings":"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"}
package/dist/report.js CHANGED
@@ -96,6 +96,12 @@ function engineFacts(engine) {
96
96
  keySystem: optional.drm.keySystem,
97
97
  sessions: [...optional.drm.sessions]
98
98
  },
99
+ qoe: optional.qoe === void 0 ? null : {
100
+ startupTime: optional.qoe.startupTime,
101
+ rebuffers: optional.qoe.rebuffers,
102
+ rebufferDuration: optional.qoe.rebufferDuration,
103
+ switches: optional.qoe.switches
104
+ },
99
105
  error: error === null ? null : {
100
106
  category: error.category,
101
107
  code: error.code,
@@ -1 +1 @@
1
- {"version":3,"file":"report.js","names":[],"sources":["../src/report.ts"],"sourcesContent":["/**\n * The report: everything the panel shows, as one plain object a page can\n * send when something goes wrong, and the trace the engine's guide asks\n * for with every error report (chapter 12), as the element kept it: see\n * `trace.ts` for what is kept of each entry. Every field is serializable;\n * a native session has no engine part.\n */\nimport type { Mattebox } from 'mattebox';\nimport type { PlayerError, PlayerHost } from './host.js';\nimport type { Counters, Mark, Sample } from './sampler.js';\nimport type { Support } from './support.js';\n\nexport interface RangeReport {\n readonly start: number;\n readonly end: number;\n}\n\nexport interface PlaybackReport {\n readonly currentTime: number;\n readonly duration: number;\n readonly paused: boolean;\n readonly ended: boolean;\n readonly seeking: boolean;\n readonly readyState: number;\n readonly networkState: number;\n readonly playbackRate: number;\n readonly volume: number;\n readonly muted: boolean;\n readonly videoWidth: number;\n readonly videoHeight: number;\n readonly buffered: readonly RangeReport[];\n readonly seekable: readonly RangeReport[];\n readonly frames: { readonly decoded: number; readonly dropped: number } | null;\n readonly mediaError: { readonly code: number; readonly message: string } | null;\n}\n\nexport interface EngineReport {\n readonly phase: string;\n readonly capabilities: readonly string[];\n readonly throughput: { readonly slow: number; readonly fast: number };\n readonly bufferGoal: number;\n readonly buffers: ReadonlyArray<{\n readonly id: string;\n readonly codecs: string;\n readonly ranges: readonly RangeReport[];\n }>;\n readonly inflight: ReadonlyArray<{\n readonly trackId: string;\n readonly seq: number;\n readonly url: string;\n }>;\n readonly live: {\n readonly start: number;\n readonly end: number;\n readonly edge: number;\n readonly latency: number | null;\n } | null;\n readonly tracks: {\n readonly active: Readonly<Record<string, string | null>>;\n readonly available: ReadonlyArray<{\n readonly id: string;\n readonly contentType: string;\n readonly mimeType: string;\n readonly lang: string | null;\n readonly role: string | null;\n readonly renditions: number;\n }>;\n };\n readonly quality: {\n readonly playing: string | null;\n readonly active: string | null;\n readonly pinned: string | null;\n readonly allowed: readonly string[];\n readonly renditions: ReadonlyArray<{\n readonly id: string;\n readonly bitrate: number;\n readonly width: number | null;\n readonly height: number | null;\n readonly frameRate: number | null;\n readonly codecs: string | null;\n }>;\n };\n readonly drm: {\n readonly keySystem: string | null;\n readonly sessions: ReadonlyArray<{ readonly keyId: string; readonly status: string }>;\n } | null;\n readonly error: {\n readonly category: string;\n readonly code: string;\n readonly fatal: boolean;\n readonly recoverable: boolean;\n readonly context: Readonly<Record<string, unknown>> | null;\n } | null;\n}\n\nexport interface DiagnosticsReport {\n /** When the report was taken, ISO 8601. */\n readonly at: string;\n readonly userAgent: string;\n readonly source: {\n readonly url: string | null;\n readonly type: string | null;\n /** The name of the handler that won, or null before a session. */\n readonly handler: string | null;\n };\n readonly playback: PlaybackReport;\n /** The player's fatal error of the current load, or null. */\n readonly error: PlayerError | null;\n /** Null for a native session. */\n readonly engine: EngineReport | null;\n readonly counters: Counters;\n /** The last two minutes of samples, and the marks in them. */\n readonly samples: readonly Sample[];\n readonly marks: readonly Mark[];\n /** What the browser supports, when it was probed before the report. */\n readonly support: Support | null;\n /** The trace entries the element kept, slimmed, oldest first, or null for a native session. */\n readonly trace: readonly unknown[] | null;\n}\n\n/** The optional namespaces the report reads, as the player reads them: a cast, once. */\ninterface Namespaces {\n readonly live?: { readonly latency: number | null };\n readonly drm?: {\n readonly keySystem: string | null;\n readonly sessions: ReadonlyArray<{ readonly keyId: string; readonly status: string }>;\n };\n}\n\nfunction ranges(list: TimeRanges): RangeReport[] {\n return Array.from({ length: list.length }, (_, i) => ({\n start: list.start(i),\n end: list.end(i),\n }));\n}\n\nexport function playbackFacts(video: HTMLVideoElement): PlaybackReport {\n const quality = video.getVideoPlaybackQuality?.();\n return {\n currentTime: video.currentTime,\n duration: video.duration,\n paused: video.paused,\n ended: video.ended,\n seeking: video.seeking,\n readyState: video.readyState,\n networkState: video.networkState,\n playbackRate: video.playbackRate,\n volume: video.volume,\n muted: video.muted,\n videoWidth: video.videoWidth,\n videoHeight: video.videoHeight,\n buffered: ranges(video.buffered),\n seekable: ranges(video.seekable),\n frames:\n quality === undefined\n ? null\n : { decoded: quality.totalVideoFrames, dropped: quality.droppedVideoFrames },\n mediaError:\n video.error === null ? null : { code: video.error.code, message: video.error.message },\n };\n}\n\nexport function engineFacts(engine: Mattebox): EngineReport {\n const state = engine.stats.snapshot();\n const optional = engine as Namespaces;\n const error = engine.error;\n return {\n phase: state.lifecycle.phase,\n capabilities: [...engine.capabilities()],\n throughput: { slow: state.stats.throughputEwma, fast: state.stats.throughputFastEwma },\n bufferGoal: state.scheduling.bufferGoal,\n buffers: [...state.buffers.entries()].map(([id, buffer]) => ({\n id,\n codecs: buffer.codecs,\n ranges: buffer.ranges.map((range) => ({ start: range.start, end: range.end })),\n })),\n inflight: [...state.scheduling.inflight.values()].map((request) => ({\n trackId: request.trackId,\n seq: request.seq,\n url: request.url,\n })),\n live:\n state.live === null\n ? null\n : {\n start: state.live.span.start,\n end: state.live.span.end,\n edge: state.live.edge,\n latency: optional.live?.latency ?? null,\n },\n tracks: {\n active: Object.fromEntries(\n (['video', 'audio', 'text'] as const).map((type) => [\n type,\n engine.tracks.active(type)?.id ?? null,\n ]),\n ),\n available: engine.tracks.available.map((track) => ({\n id: track.id,\n contentType: track.contentType,\n mimeType: track.mimeType,\n lang: track.lang ?? null,\n role: track.role ?? null,\n renditions: track.renditions.length,\n })),\n },\n quality: {\n playing: engine.quality.playing?.id ?? null,\n active: engine.quality.active?.id ?? null,\n pinned: engine.quality.pinned,\n allowed: engine.quality.allowed.map((r) => r.id),\n renditions: engine.quality.renditions.map((r) => ({\n id: r.id,\n bitrate: r.bitrate,\n width: r.width ?? null,\n height: r.height ?? null,\n frameRate: r.frameRate ?? null,\n codecs: r.codecs,\n })),\n },\n drm:\n optional.drm === undefined\n ? null\n : { keySystem: optional.drm.keySystem, sessions: [...optional.drm.sessions] },\n error:\n error === null\n ? null\n : {\n category: error.category,\n code: error.code,\n fatal: error.fatal,\n recoverable: error.recoverable,\n context: error.context ?? null,\n },\n };\n}\n\n/** Two minutes of samples at two a second, and the marks of the same two minutes. */\nconst KEEP_SAMPLES = 240;\nconst KEEP_MS = 120_000;\n\nexport interface ReportSources {\n readonly player: PlayerHost;\n readonly samples: readonly Sample[];\n readonly marks: readonly Mark[];\n readonly counters: Counters;\n /** The trace entries kept, slimmed, oldest first. */\n readonly history: readonly unknown[];\n readonly support: Support | null;\n}\n\nexport function buildReport(sources: ReportSources): DiagnosticsReport {\n const { player } = sources;\n const engine = player.engine;\n const samples = sources.samples.slice(-KEEP_SAMPLES);\n const since = performance.now() - KEEP_MS;\n return {\n at: new Date().toISOString(),\n userAgent: navigator.userAgent,\n source: {\n url: player.getAttribute('src'),\n type: player.getAttribute('type'),\n handler: player.player?.session?.handler ?? null,\n },\n playback: playbackFacts(player.video),\n error: player.error,\n engine: engine === null ? null : engineFacts(engine),\n counters: sources.counters,\n samples,\n marks: sources.marks.filter((mark) => mark.t >= since),\n support: sources.support,\n trace: engine === null ? null : sources.history,\n };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"report.js","names":[],"sources":["../src/report.ts"],"sourcesContent":["/**\n * The report: everything the panel shows, as one plain object a page can\n * send when something goes wrong, and the trace the engine's guide asks\n * for with every error report (chapter 12), as the element kept it: see\n * `trace.ts` for what is kept of each entry. Every field is serializable;\n * a native session has no engine part.\n */\nimport type { Mattebox } from 'mattebox';\nimport type { PlayerError, PlayerHost } from './host.js';\nimport type { Counters, Mark, Sample } from './sampler.js';\nimport type { Support } from './support.js';\n\nexport interface RangeReport {\n readonly start: number;\n readonly end: number;\n}\n\nexport interface PlaybackReport {\n readonly currentTime: number;\n readonly duration: number;\n readonly paused: boolean;\n readonly ended: boolean;\n readonly seeking: boolean;\n readonly readyState: number;\n readonly networkState: number;\n readonly playbackRate: number;\n readonly volume: number;\n readonly muted: boolean;\n readonly videoWidth: number;\n readonly videoHeight: number;\n readonly buffered: readonly RangeReport[];\n readonly seekable: readonly RangeReport[];\n readonly frames: { readonly decoded: number; readonly dropped: number } | null;\n readonly mediaError: { readonly code: number; readonly message: string } | null;\n}\n\nexport interface EngineReport {\n readonly phase: string;\n readonly capabilities: readonly string[];\n readonly throughput: { readonly slow: number; readonly fast: number };\n readonly bufferGoal: number;\n readonly buffers: ReadonlyArray<{\n readonly id: string;\n readonly codecs: string;\n readonly ranges: readonly RangeReport[];\n }>;\n readonly inflight: ReadonlyArray<{\n readonly trackId: string;\n readonly seq: number;\n readonly url: string;\n }>;\n readonly live: {\n readonly start: number;\n readonly end: number;\n readonly edge: number;\n readonly latency: number | null;\n } | null;\n readonly tracks: {\n readonly active: Readonly<Record<string, string | null>>;\n readonly available: ReadonlyArray<{\n readonly id: string;\n readonly contentType: string;\n readonly mimeType: string;\n readonly lang: string | null;\n readonly role: string | null;\n readonly renditions: number;\n }>;\n };\n readonly quality: {\n readonly playing: string | null;\n readonly active: string | null;\n readonly pinned: string | null;\n readonly allowed: readonly string[];\n readonly renditions: ReadonlyArray<{\n readonly id: string;\n readonly bitrate: number;\n readonly width: number | null;\n readonly height: number | null;\n readonly frameRate: number | null;\n readonly codecs: string | null;\n }>;\n };\n readonly drm: {\n readonly keySystem: string | null;\n readonly sessions: ReadonlyArray<{ readonly keyId: string; readonly status: string }>;\n } | null;\n /** The engine's qoe stage figures for this load, or null without the stage. */\n readonly qoe: QoeFigures | null;\n readonly error: {\n readonly category: string;\n readonly code: string;\n readonly fatal: boolean;\n readonly recoverable: boolean;\n readonly context: Readonly<Record<string, unknown>> | null;\n } | null;\n}\n\nexport interface DiagnosticsReport {\n /** When the report was taken, ISO 8601. */\n readonly at: string;\n readonly userAgent: string;\n readonly source: {\n readonly url: string | null;\n readonly type: string | null;\n /** The name of the handler that won, or null before a session. */\n readonly handler: string | null;\n };\n readonly playback: PlaybackReport;\n /** The player's fatal error of the current load, or null. */\n readonly error: PlayerError | null;\n /** Null for a native session. */\n readonly engine: EngineReport | null;\n readonly counters: Counters;\n /** The last two minutes of samples, and the marks in them. */\n readonly samples: readonly Sample[];\n readonly marks: readonly Mark[];\n /** What the browser supports, when it was probed before the report. */\n readonly support: Support | null;\n /** The trace entries the element kept, slimmed, oldest first, or null for a native session. */\n readonly trace: readonly unknown[] | null;\n}\n\n/** The figures of the engine's qoe stage, as `engine.qoe` gives them. */\nexport interface QoeFigures {\n /** Seconds from the load, or the first play if later, to the first frame playing. */\n readonly startupTime: number | null;\n readonly rebuffers: number;\n /** Seconds spent rebuffering, the current wait included. */\n readonly rebufferDuration: number;\n /** Video quality changes after the first selection. */\n readonly switches: number;\n}\n\n/** The optional namespaces the report reads, as the player reads them: a cast, once. */\ninterface Namespaces {\n readonly live?: { readonly latency: number | null };\n readonly qoe?: QoeFigures;\n readonly drm?: {\n readonly keySystem: string | null;\n readonly sessions: ReadonlyArray<{ readonly keyId: string; readonly status: string }>;\n };\n}\n\nfunction ranges(list: TimeRanges): RangeReport[] {\n return Array.from({ length: list.length }, (_, i) => ({\n start: list.start(i),\n end: list.end(i),\n }));\n}\n\nexport function playbackFacts(video: HTMLVideoElement): PlaybackReport {\n const quality = video.getVideoPlaybackQuality?.();\n return {\n currentTime: video.currentTime,\n duration: video.duration,\n paused: video.paused,\n ended: video.ended,\n seeking: video.seeking,\n readyState: video.readyState,\n networkState: video.networkState,\n playbackRate: video.playbackRate,\n volume: video.volume,\n muted: video.muted,\n videoWidth: video.videoWidth,\n videoHeight: video.videoHeight,\n buffered: ranges(video.buffered),\n seekable: ranges(video.seekable),\n frames:\n quality === undefined\n ? null\n : { decoded: quality.totalVideoFrames, dropped: quality.droppedVideoFrames },\n mediaError:\n video.error === null ? null : { code: video.error.code, message: video.error.message },\n };\n}\n\nexport function engineFacts(engine: Mattebox): EngineReport {\n const state = engine.stats.snapshot();\n const optional = engine as Namespaces;\n const error = engine.error;\n return {\n phase: state.lifecycle.phase,\n capabilities: [...engine.capabilities()],\n throughput: { slow: state.stats.throughputEwma, fast: state.stats.throughputFastEwma },\n bufferGoal: state.scheduling.bufferGoal,\n buffers: [...state.buffers.entries()].map(([id, buffer]) => ({\n id,\n codecs: buffer.codecs,\n ranges: buffer.ranges.map((range) => ({ start: range.start, end: range.end })),\n })),\n inflight: [...state.scheduling.inflight.values()].map((request) => ({\n trackId: request.trackId,\n seq: request.seq,\n url: request.url,\n })),\n live:\n state.live === null\n ? null\n : {\n start: state.live.span.start,\n end: state.live.span.end,\n edge: state.live.edge,\n latency: optional.live?.latency ?? null,\n },\n tracks: {\n active: Object.fromEntries(\n (['video', 'audio', 'text'] as const).map((type) => [\n type,\n engine.tracks.active(type)?.id ?? null,\n ]),\n ),\n available: engine.tracks.available.map((track) => ({\n id: track.id,\n contentType: track.contentType,\n mimeType: track.mimeType,\n lang: track.lang ?? null,\n role: track.role ?? null,\n renditions: track.renditions.length,\n })),\n },\n quality: {\n playing: engine.quality.playing?.id ?? null,\n active: engine.quality.active?.id ?? null,\n pinned: engine.quality.pinned,\n allowed: engine.quality.allowed.map((r) => r.id),\n renditions: engine.quality.renditions.map((r) => ({\n id: r.id,\n bitrate: r.bitrate,\n width: r.width ?? null,\n height: r.height ?? null,\n frameRate: r.frameRate ?? null,\n codecs: r.codecs,\n })),\n },\n drm:\n optional.drm === undefined\n ? null\n : { keySystem: optional.drm.keySystem, sessions: [...optional.drm.sessions] },\n qoe:\n optional.qoe === undefined\n ? null\n : {\n startupTime: optional.qoe.startupTime,\n rebuffers: optional.qoe.rebuffers,\n rebufferDuration: optional.qoe.rebufferDuration,\n switches: optional.qoe.switches,\n },\n error:\n error === null\n ? null\n : {\n category: error.category,\n code: error.code,\n fatal: error.fatal,\n recoverable: error.recoverable,\n context: error.context ?? null,\n },\n };\n}\n\n/** Two minutes of samples at two a second, and the marks of the same two minutes. */\nconst KEEP_SAMPLES = 240;\nconst KEEP_MS = 120_000;\n\nexport interface ReportSources {\n readonly player: PlayerHost;\n readonly samples: readonly Sample[];\n readonly marks: readonly Mark[];\n readonly counters: Counters;\n /** The trace entries kept, slimmed, oldest first. */\n readonly history: readonly unknown[];\n readonly support: Support | null;\n}\n\nexport function buildReport(sources: ReportSources): DiagnosticsReport {\n const { player } = sources;\n const engine = player.engine;\n const samples = sources.samples.slice(-KEEP_SAMPLES);\n const since = performance.now() - KEEP_MS;\n return {\n at: new Date().toISOString(),\n userAgent: navigator.userAgent,\n source: {\n url: player.getAttribute('src'),\n type: player.getAttribute('type'),\n handler: player.player?.session?.handler ?? null,\n },\n playback: playbackFacts(player.video),\n error: player.error,\n engine: engine === null ? null : engineFacts(engine),\n counters: sources.counters,\n samples,\n marks: sources.marks.filter((mark) => mark.t >= since),\n support: sources.support,\n trace: engine === null ? null : sources.history,\n };\n}\n"],"mappings":";AA+IA,SAAS,OAAO,MAAiC;CAC/C,OAAO,MAAM,KAAK,EAAE,QAAQ,KAAK,OAAO,IAAI,GAAG,OAAO;EACpD,OAAO,KAAK,MAAM,CAAC;EACnB,KAAK,KAAK,IAAI,CAAC;CACjB,EAAE;AACJ;AAEA,SAAgB,cAAc,OAAyC;CACrE,MAAM,UAAU,MAAM,0BAA0B;CAChD,OAAO;EACL,aAAa,MAAM;EACnB,UAAU,MAAM;EAChB,QAAQ,MAAM;EACd,OAAO,MAAM;EACb,SAAS,MAAM;EACf,YAAY,MAAM;EAClB,cAAc,MAAM;EACpB,cAAc,MAAM;EACpB,QAAQ,MAAM;EACd,OAAO,MAAM;EACb,YAAY,MAAM;EAClB,aAAa,MAAM;EACnB,UAAU,OAAO,MAAM,QAAQ;EAC/B,UAAU,OAAO,MAAM,QAAQ;EAC/B,QACE,YAAY,KAAA,IACR,OACA;GAAE,SAAS,QAAQ;GAAkB,SAAS,QAAQ;EAAmB;EAC/E,YACE,MAAM,UAAU,OAAO,OAAO;GAAE,MAAM,MAAM,MAAM;GAAM,SAAS,MAAM,MAAM;EAAQ;CACzF;AACF;AAEA,SAAgB,YAAY,QAAgC;CAC1D,MAAM,QAAQ,OAAO,MAAM,SAAS;CACpC,MAAM,WAAW;CACjB,MAAM,QAAQ,OAAO;CACrB,OAAO;EACL,OAAO,MAAM,UAAU;EACvB,cAAc,CAAC,GAAG,OAAO,aAAa,CAAC;EACvC,YAAY;GAAE,MAAM,MAAM,MAAM;GAAgB,MAAM,MAAM,MAAM;EAAmB;EACrF,YAAY,MAAM,WAAW;EAC7B,SAAS,CAAC,GAAG,MAAM,QAAQ,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,aAAa;GAC3D;GACA,QAAQ,OAAO;GACf,QAAQ,OAAO,OAAO,KAAK,WAAW;IAAE,OAAO,MAAM;IAAO,KAAK,MAAM;GAAI,EAAE;EAC/E,EAAE;EACF,UAAU,CAAC,GAAG,MAAM,WAAW,SAAS,OAAO,CAAC,CAAC,CAAC,KAAK,aAAa;GAClE,SAAS,QAAQ;GACjB,KAAK,QAAQ;GACb,KAAK,QAAQ;EACf,EAAE;EACF,MACE,MAAM,SAAS,OACX,OACA;GACE,OAAO,MAAM,KAAK,KAAK;GACvB,KAAK,MAAM,KAAK,KAAK;GACrB,MAAM,MAAM,KAAK;GACjB,SAAS,SAAS,MAAM,WAAW;EACrC;EACN,QAAQ;GACN,QAAQ,OAAO,YACZ;IAAC;IAAS;IAAS;GAAM,CAAC,CAAW,KAAK,SAAS,CAClD,MACA,OAAO,OAAO,OAAO,IAAI,CAAC,EAAE,MAAM,IACpC,CAAC,CACH;GACA,WAAW,OAAO,OAAO,UAAU,KAAK,WAAW;IACjD,IAAI,MAAM;IACV,aAAa,MAAM;IACnB,UAAU,MAAM;IAChB,MAAM,MAAM,QAAQ;IACpB,MAAM,MAAM,QAAQ;IACpB,YAAY,MAAM,WAAW;GAC/B,EAAE;EACJ;EACA,SAAS;GACP,SAAS,OAAO,QAAQ,SAAS,MAAM;GACvC,QAAQ,OAAO,QAAQ,QAAQ,MAAM;GACrC,QAAQ,OAAO,QAAQ;GACvB,SAAS,OAAO,QAAQ,QAAQ,KAAK,MAAM,EAAE,EAAE;GAC/C,YAAY,OAAO,QAAQ,WAAW,KAAK,OAAO;IAChD,IAAI,EAAE;IACN,SAAS,EAAE;IACX,OAAO,EAAE,SAAS;IAClB,QAAQ,EAAE,UAAU;IACpB,WAAW,EAAE,aAAa;IAC1B,QAAQ,EAAE;GACZ,EAAE;EACJ;EACA,KACE,SAAS,QAAQ,KAAA,IACb,OACA;GAAE,WAAW,SAAS,IAAI;GAAW,UAAU,CAAC,GAAG,SAAS,IAAI,QAAQ;EAAE;EAChF,KACE,SAAS,QAAQ,KAAA,IACb,OACA;GACE,aAAa,SAAS,IAAI;GAC1B,WAAW,SAAS,IAAI;GACxB,kBAAkB,SAAS,IAAI;GAC/B,UAAU,SAAS,IAAI;EACzB;EACN,OACE,UAAU,OACN,OACA;GACE,UAAU,MAAM;GAChB,MAAM,MAAM;GACZ,OAAO,MAAM;GACb,aAAa,MAAM;GACnB,SAAS,MAAM,WAAW;EAC5B;CACR;AACF;AAIA,MAAM,UAAU;AAYhB,SAAgB,YAAY,SAA2C;CACrE,MAAM,EAAE,WAAW;CACnB,MAAM,SAAS,OAAO;CACtB,MAAM,UAAU,QAAQ,QAAQ,MAAM,IAAa;CACnD,MAAM,QAAQ,YAAY,IAAI,IAAI;CAClC,OAAO;EACL,qBAAI,IAAI,KAAK,EAAA,CAAE,YAAY;EAC3B,WAAW,UAAU;EACrB,QAAQ;GACN,KAAK,OAAO,aAAa,KAAK;GAC9B,MAAM,OAAO,aAAa,MAAM;GAChC,SAAS,OAAO,QAAQ,SAAS,WAAW;EAC9C;EACA,UAAU,cAAc,OAAO,KAAK;EACpC,OAAO,OAAO;EACd,QAAQ,WAAW,OAAO,OAAO,YAAY,MAAM;EACnD,UAAU,QAAQ;EAClB;EACA,OAAO,QAAQ,MAAM,QAAQ,SAAS,KAAK,KAAK,KAAK;EACrD,SAAS,QAAQ;EACjB,OAAO,WAAW,OAAO,OAAO,QAAQ;CAC1C;AACF"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mattebox/player-diagnostics",
3
- "version": "0.5.0",
3
+ "version": "0.6.0",
4
4
  "description": "<mbx-diagnostics>: playback stats, charts, engine state and browser support inside <mattebox-player>, and a report to send.",
5
5
  "author": "Josep Boix Requesens",
6
6
  "repository": {
@@ -50,10 +50,10 @@
50
50
  "release:ci": "semantic-release"
51
51
  },
52
52
  "devDependencies": {
53
- "@mattebox/player-core": "^0.4.0"
53
+ "@mattebox/player-core": "^0.5.0"
54
54
  },
55
55
  "peerDependencies": {
56
- "@mattebox/player": ">=0.7.0",
57
- "mattebox": "^0.8.2"
56
+ "@mattebox/player": ">=0.8.0",
57
+ "mattebox": "^0.12.0"
58
58
  }
59
59
  }