@mux/playback-core 0.7.1-canary.0-556dabf

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.
package/CHANGELOG.md ADDED
@@ -0,0 +1,91 @@
1
+ # Change Log
2
+
3
+ All notable changes to this project will be documented in this file.
4
+ See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
+
6
+ # [0.7.0](https://github.com/muxinc/elements/compare/@mux-elements/playback-core@0.6.0...@mux-elements/playback-core@0.7.0) (2022-06-23)
7
+
8
+ ### Bug Fixes
9
+
10
+ - preload=metadata now triggers loadedmetadata ([73c49a6](https://github.com/muxinc/elements/commit/73c49a6b3b11512b3e206c27d65cdef8472e461d))
11
+
12
+ ### Features
13
+
14
+ - Handle inferred mux data env key for custom domain cases. ([eedc19e](https://github.com/muxinc/elements/commit/eedc19e2025844f99909cf3d0751811b55239329))
15
+ - **mux-video:** Add basic support for custom video domains. ([82cfb15](https://github.com/muxinc/elements/commit/82cfb15ecb9729329018c1fe999a1585bcae55c7))
16
+
17
+ # [0.6.0](https://github.com/muxinc/elements/compare/@mux-elements/playback-core@0.5.2...@mux-elements/playback-core@0.6.0) (2022-06-06)
18
+
19
+ ### Features
20
+
21
+ - **dvr:** Initial effort for DVR support. ([d58d78f](https://github.com/muxinc/elements/commit/d58d78fe6716d21ff03e5edb7d47c73e85ef4c85))
22
+
23
+ ## [0.5.2](https://github.com/muxinc/elements/compare/@mux-elements/playback-core@0.5.1...@mux-elements/playback-core@0.5.2) (2022-05-26)
24
+
25
+ ### Bug Fixes
26
+
27
+ - stop tracking non-fatal errors in Mux data ([e00316b](https://github.com/muxinc/elements/commit/e00316b2452312fdcbf955c2d7bad5c7058dde28))
28
+
29
+ ## [0.5.1](https://github.com/muxinc/elements/compare/@mux-elements/playback-core@0.5.0...@mux-elements/playback-core@0.5.1) (2022-05-23)
30
+
31
+ ### Bug Fixes
32
+
33
+ - playback core require and default file extension is .cjs.js ([3552e39](https://github.com/muxinc/elements/commit/3552e3927c3e8767292d5cabdab16dd98f6de451))
34
+
35
+ # [0.5.0](https://github.com/muxinc/elements/compare/@mux-elements/playback-core@0.4.1...@mux-elements/playback-core@0.5.0) (2022-05-20)
36
+
37
+ ### Bug Fixes
38
+
39
+ - switch cjs extension to .cjs.js ([30e83c3](https://github.com/muxinc/elements/commit/30e83c3ce0bd9bfda4817c30ffe0921e425619e4))
40
+
41
+ ### Features
42
+
43
+ - **playback-core:** Update config values for hls to be more consistent with native playback and to reasonable trim the backbuffer during playback. ([f01fd21](https://github.com/muxinc/elements/commit/f01fd21b16228458f1b4e25eebe86871956ae051))
44
+
45
+ ## [0.4.1](https://github.com/muxinc/elements/compare/@mux-elements/playback-core@0.4.0...@mux-elements/playback-core@0.4.1) (2022-05-10)
46
+
47
+ ### Bug Fixes
48
+
49
+ - make sure we only seek with a finite number ([b8369ee](https://github.com/muxinc/elements/commit/b8369eec75672aeba75edc7b2c8cc5b49df5616e))
50
+ - only seek to live on first play for non-native hls ([c842f02](https://github.com/muxinc/elements/commit/c842f02427fad8da849f74d43964f48bc8197264))
51
+
52
+ # [0.4.0](https://github.com/muxinc/elements/compare/@mux-elements/playback-core@0.3.3...@mux-elements/playback-core@0.4.0) (2022-05-03)
53
+
54
+ ### Bug Fixes
55
+
56
+ - live autoplay with preload=metadata should wait for new data ([c290067](https://github.com/muxinc/elements/commit/c290067f6b90bbc256af96974f5475a858bc1638))
57
+ - make preload attribute work with hls.js ([dfb519c](https://github.com/muxinc/elements/commit/dfb519c0aa8b281c03e3a0232589cc4b99c3ca34))
58
+ - **playback-core:** implement track/cue management in playback-core ([#201](https://github.com/muxinc/elements/issues/201)) ([35f2f91](https://github.com/muxinc/elements/commit/35f2f919e52e833c999451d1d06ff3a47bdcdc65))
59
+ - preload=metadata with autoplay ([620e994](https://github.com/muxinc/elements/commit/620e99469a2d23fb6e96485c115312edea1adb54))
60
+
61
+ ### Features
62
+
63
+ - add errorTranslator prop & muxVideo.error property ([#195](https://github.com/muxinc/elements/issues/195)) ([3afc2f0](https://github.com/muxinc/elements/commit/3afc2f0af75a5ad8ef00257a4ebc34882ff8c9ab))
64
+
65
+ ## [0.3.3](https://github.com/muxinc/elements/compare/@mux-elements/playback-core@0.3.2...@mux-elements/playback-core@0.3.3) (2022-04-22)
66
+
67
+ ### Bug Fixes
68
+
69
+ - point pkgjson#browser at mjs build for webpack 4 ([#191](https://github.com/muxinc/elements/issues/191)) ([a73a495](https://github.com/muxinc/elements/commit/a73a4951052bfc77cc24667b9bc0a05efbcbb355))
70
+
71
+ ## [0.3.2](https://github.com/muxinc/elements/compare/@mux-elements/playback-core@0.3.1...@mux-elements/playback-core@0.3.2) (2022-04-18)
72
+
73
+ ### Bug Fixes
74
+
75
+ - make mux-video errors more uniform, fix async ([#183](https://github.com/muxinc/elements/issues/183)) ([0ea4dc3](https://github.com/muxinc/elements/commit/0ea4dc3beafc7d8a6c5078087d14f3f4bac5dda7))
76
+
77
+ ## [0.3.1](https://github.com/muxinc/elements/compare/@mux-elements/playback-core@0.3.0...@mux-elements/playback-core@0.3.1) (2022-04-12)
78
+
79
+ **Note:** Version bump only for package @mux-elements/playback-core
80
+
81
+ # [0.3.0](https://github.com/muxinc/elements/compare/@mux-elements/playback-core@0.2.0...@mux-elements/playback-core@0.3.0) (2022-03-28)
82
+
83
+ ### Bug Fixes
84
+
85
+ - **playback-core:** add function to playback-core to generate init time from mux.utils.now(). ([bc26a23](https://github.com/muxinc/elements/commit/bc26a23c40b447818ecb2f0a779edffe003dcf33))
86
+ - **playback-core:** Use window polyfill in playback-core for things like CustomEvent. ([980c4b6](https://github.com/muxinc/elements/commit/980c4b63f9199b7be1aee75a42565fff65767ea8))
87
+ - prettier format all elements files ([741d607](https://github.com/muxinc/elements/commit/741d607521ca9578cfad9f0a9216a6565b4c56a1))
88
+
89
+ ### Features
90
+
91
+ - add beaconCollectionDomain option to replace beaconDomain ([a44b699](https://github.com/muxinc/elements/commit/a44b699ae3138590b9d953f693f95971694658df))
package/README.md ADDED
@@ -0,0 +1,9 @@
1
+ # Playback Core
2
+
3
+ This is a collection of utility functions directly related to the playback and Mux Data integration with various mux elements.
4
+
5
+ It is currently used by `mux-video`, `mux-video-react`, `mux-audio`, and `mux-audio-react`.
6
+
7
+ You shouldn't need use this package directly, but if you're building something custom for your application you may find it handy.
8
+
9
+ Check the `src/index.ts` file to see the functions and types that get exported.
@@ -0,0 +1,2 @@
1
+ var ae=Object.create;var k=Object.defineProperty;var se=Object.getOwnPropertyDescriptor;var ie=Object.getOwnPropertyNames;var ue=Object.getPrototypeOf,ce=Object.prototype.hasOwnProperty;var U=e=>k(e,"__esModule",{value:!0});var le=(e,t)=>{U(e);for(var r in t)k(e,r,{get:t[r],enumerable:!0})},pe=(e,t,r)=>{if(t&&typeof t=="object"||typeof t=="function")for(let n of ie(t))!ce.call(e,n)&&n!=="default"&&k(e,n,{get:()=>t[n],enumerable:!(r=se(t,n))||r.enumerable});return e},P=e=>pe(U(k(e!=null?ae(ue(e)):{},"default",e&&e.__esModule&&"default"in e?{get:()=>e.default,enumerable:!0}:{value:e,enumerable:!0})),e);var K=(e,t,r)=>{if(!t.has(e))throw TypeError("Cannot "+r)};var B=(e,t,r)=>(K(e,t,"read from private field"),r?r.call(e):t.get(e)),F=(e,t,r)=>{if(t.has(e))throw TypeError("Cannot add the same private member more than once");t instanceof WeakSet?t.add(e):t.set(e,r)},$=(e,t,r,n)=>(K(e,t,"write to private field"),n?n.call(e,r):t.set(e,r),r);le(exports,{ExtensionMimeTypeMap:()=>g,Hls:()=>T.default,MediaError:()=>c,MimeTypeShorthandMap:()=>R,StreamTypes:()=>b,allMediaTypes:()=>me,generatePlayerInitTime:()=>fe,getError:()=>ge,getStreamTypeConfig:()=>Z,getType:()=>V,inferMimeTypeFromURL:()=>Q,initialize:()=>Ee,isMuxVideoSrc:()=>te,loadMedia:()=>ne,mux:()=>D.default,setupAutoplay:()=>W,setupHls:()=>ee,setupMux:()=>re,shorthandKeys:()=>Te,teardown:()=>j,toMuxVideoURL:()=>Me,toPlaybackIdParts:()=>J});if(typeof DocumentFragment=="undefined"){class e{}globalThis.DocumentFragment=e}globalThis.customElements||(globalThis.customElements={get(e){},define(e,t,r){},upgrade(e){},whenDefined(e){return Promise.resolve(globalThis.HTMLElement)}});var h;if(!globalThis.CustomEvent){class e{constructor(r,n={}){F(this,h,void 0);$(this,h,n==null?void 0:n.detail)}get detail(){B(this,h)}initCustomEvent(r,n,o,a){}}h=new WeakMap,globalThis.CustomEvent=e}if(!globalThis.EventTarget){class e{addEventListener(){}removeEventListener(){}dispatchEvent(r){return!0}}globalThis.EventTarget=e}if(!globalThis.HTMLElement){class e extends EventTarget{}globalThis.HTMLElement=e}if(!globalThis.HTMLVideoElement){class e extends EventTarget{}globalThis.HTMLVideoElement=e}var Y,q;if(!((Y=globalThis.document)==null?void 0:Y.createElement)){let e=(q=globalThis.document)!=null?q:{};e.createElement=function(r,n){return new HTMLElement},globalThis.document=e}var D=P(require("mux-embed")),T=P(require("hls.js"));var w=P(require("hls.js")),I={ANY:"any",MUTED:"muted"},de=Object.values(I),z=e=>typeof e=="boolean"||typeof e=="string"&&de.includes(e),W=(e,t,r)=>{let n=!1,o=!1,a=z(t)?t:!!t,i=()=>{e.addEventListener("playing",()=>{n=!0},{once:!0})};if(i(),e.addEventListener("loadstart",()=>{n=!1,i(),C(e,a)},{once:!0}),e.addEventListener("loadedmetadata",()=>{r||(o=!Number.isFinite(e.duration)),C(e,a)},{once:!0}),r&&r.once(w.default.Events.LEVEL_LOADED,(u,l)=>{var p;o=(p=l.details.live)!=null?p:!1}),!a){let u=()=>{!o||((r==null?void 0:r.liveSyncPosition)?e.currentTime=r.liveSyncPosition:Number.isFinite(e.seekable.end(0))&&(e.currentTime=e.seekable.end(0)))};e.addEventListener("play",()=>{r&&e.preload==="metadata"?r.once(w.default.Events.LEVEL_UPDATED,u):r&&u()},{once:!0})}return u=>{n||(a=z(u)?u:!!u,C(e,a))}},C=(e,t)=>{if(!t)return;let r=e.muted,n=()=>e.muted=r;switch(t){case I.ANY:e.play().catch(o=>{e.muted=!0,e.play().catch(n)});break;case I.MUTED:e.muted=!0,e.play().catch(n);break;default:e.play().catch(()=>{});break}};var E=class extends Error{constructor(t,r=E.MEDIA_ERR_CUSTOM,n){super(t);var o;this.name="MediaError",this.code=r,this.fatal=n!=null?n:r>=E.MEDIA_ERR_NETWORK&&r<=E.MEDIA_ERR_ENCRYPTED,this.message||(this.message=(o=E.defaultMessages[this.code])!=null?o:"")}},c=E;c.MEDIA_ERR_ABORTED=1,c.MEDIA_ERR_NETWORK=2,c.MEDIA_ERR_DECODE=3,c.MEDIA_ERR_SRC_NOT_SUPPORTED=4,c.MEDIA_ERR_ENCRYPTED=5,c.MEDIA_ERR_CUSTOM=100,c.defaultMessages={1:"You aborted the media playback",2:"A network error caused the media download to fail.",3:"A media error caused playback to be aborted. The media could be corrupt or your browser does not support this format.",4:"An unsupported error occurred. The server or network failed, or your browser does not support this format.",5:"The media is encrypted and there are no keys to decrypt it."};var x=P(require("hls.js"));function X(e,t){t.on(x.default.Events.NON_NATIVE_TEXT_TRACKS_FOUND,(o,{tracks:a})=>{a.forEach(i=>{var l;let s=(l=i.subtitleTrack)!=null?l:i.closedCaptions,u=t.subtitleTracks.findIndex(({lang:p,name:y,type:f})=>p==(s==null?void 0:s.lang)&&y===i.label&&f.toLowerCase()===i.kind);ye(e,i.kind,i.label,s==null?void 0:s.lang,`${i.kind}${u}`)})});let r=()=>{var i;if(!t.subtitleTracks.length)return;let o=Array.from(e.textTracks).find(s=>s.id&&s.mode==="showing"&&["subtitles","captions"].includes(s.kind)),a=`${(i=t.subtitleTracks[t.subtitleTrack])==null?void 0:i.type.toLowerCase()}${t.subtitleTrack}`;if(o&&(t.subtitleTrack<0||(o==null?void 0:o.id)!==a)){let s=t.subtitleTracks.findIndex(({lang:u,name:l,type:p})=>u==o.language&&l===o.label&&p.toLowerCase()===o.kind);t.subtitleTrack=s}o&&(o==null?void 0:o.id)===a&&o.cues&&Array.from(o.cues).forEach(s=>{o.addCue(s)})};e.textTracks.addEventListener("change",r),t.on(x.default.Events.CUES_PARSED,(o,{track:a,type:i,cues:s})=>{let u=e.textTracks.getTrackById(a);if(!u)return;let l=u.mode==="disabled";l&&(u.mode="hidden"),s.forEach(p=>{var y;((y=u.cues)==null?void 0:y.getCueById(p.id))||u.addCue(p)}),l&&(u.mode="disabled")}),t.on(x.default.Events.DESTROYING,()=>{e.textTracks.removeEventListener("change",r),e.querySelectorAll("track").forEach(a=>{!(a.id&&["subtitles","captions"].includes(a.kind))||!t.subtitleTracks.some(({type:i},s)=>a.id===`${i.toLowerCase()}${s}`)||e.removeChild(a)})});let n=()=>{Array.from(e.textTracks).forEach(o=>{var a,i;if(!["subtitles","caption"].includes(o.kind)&&o.label==="thumbnails"){if(!((a=o.cues)==null?void 0:a.length)){let s=e.querySelector('track[label="thumbnails"]'),u=(i=s==null?void 0:s.getAttribute("src"))!=null?i:"";s==null||s.removeAttribute("src"),setTimeout(()=>{s==null||s.setAttribute("src",u)},0)}o.mode!=="hidden"&&(o.mode="hidden")}})};t.once(x.default.Events.MANIFEST_LOADED,n),t.once(x.default.Events.MEDIA_ATTACHED,n)}function ye(e,t,r,n,o){let a=document.createElement("track");return a.kind=t,a.label=r,n&&(a.srclang=n),o&&(a.id=o),a.track.mode="disabled",e.appendChild(a),a.track}var O=(e,t)=>e in t;var G="mux.com",fe=()=>D.default.utils.now(),b={VOD:"on-demand",ON_DEMAND:"on-demand",LIVE:"live",LL_LIVE:"ll-live",DVR:"live:dvr",LL_DVR:"ll-live:dvr"},g={M3U8:"application/vnd.apple.mpegurl",MP4:"video/mp4"},R={HLS:g.M3U8},Te=Object.keys(R),me=[...Object.values(g),"hls","HLS"],J=e=>{let t=e.indexOf("?");if(t<0)return[e];let r=e.slice(0,t),n=e.slice(t);return[r,n]},Me=(e,{domain:t=G}={})=>{if(!e)return;let[r,n=""]=J(e);return`https://stream.${t}/${r}.m3u8${n}`},Q=e=>{let t="";try{t=new URL(e).pathname}catch{console.error("invalid url")}let r=t.lastIndexOf(".");if(r<0)return"";let o=t.slice(r+1).toUpperCase();return O(o,g)?g[o]:""},V=e=>{let t=e.type;if(t){let n=t.toUpperCase();return O(n,R)?R[n]:t}let{src:r}=e;return r?Q(r):""},Z=e=>{if([b.LIVE,b.LL_LIVE].includes(e)){let t={backBufferLength:12};return e===b.LL_LIVE?{...t,maxFragLookUpTolerance:.001}:t}return{}},S=new WeakMap,ge=e=>{var t;return(t=S.get(e))==null?void 0:t.error},j=(e,t)=>{t&&(t.detachMedia(),t.destroy()),(e==null?void 0:e.mux)&&!e.mux.deleted&&(e.mux.destroy(),e.mux),e&&(e.removeEventListener("error",oe),e.removeEventListener("error",N),S.delete(e))},ee=(e,t)=>{var L,v,_;let{debug:r,preferMse:n,streamType:o,startTime:a=-1}=e,i=V(e),s=i===g.M3U8,u=!i||((L=t==null?void 0:t.canPlayType(i))!=null?L:!0),l=T.default.isSupported(),f=((_=(v=window==null?void 0:window.navigator)==null?void 0:v.userAgent)!=null?_:"").toLowerCase().indexOf("android")!==-1&&o===b.LL_LIVE;if(s&&!(!s||u&&!((n||f)&&l))&&l){let M={backBufferLength:30,renderTextTracksNatively:!1,liveDurationInfinity:!0},d=Z(o);return new T.default({debug:r,startPosition:a,...M,...d})}},te=({playbackId:e,src:t,customDomain:r})=>{if(e)return!0;if(typeof t!="string")return!1;let n=new URL(t).hostname.toLocaleLowerCase();return n.includes(G)||!!r&&n.includes(r.toLocaleLowerCase())},re=(e,t,r)=>{let{envKey:n}=e,o=te(e);if((n||o)&&t){let{playerInitTime:a,playerSoftwareName:i,playerSoftwareVersion:s,beaconCollectionDomain:u,metadata:l,debug:p}=e,y=f=>typeof f.player_error_code=="string"?!1:typeof e.errorTranslator=="function"?e.errorTranslator(f):f;D.default.monitor(t,{debug:p,beaconCollectionDomain:u,hlsjs:r,Hls:r?T.default:void 0,automaticErrorTracking:!1,errorTranslator:y,data:{...n?{env_key:n}:{},player_software_name:i,player_software_version:s,player_init_time:a,...l}})}},ne=(e,t,r)=>{var L,v,_;if(!t){console.warn("attempting to load media before mediaEl exists");return}let{preferMse:n,streamType:o}=e,a=V(e),i=a===g.M3U8,s=!a||((L=t==null?void 0:t.canPlayType(a))!=null?L:!0),u=T.default.isSupported(),y=((_=(v=window==null?void 0:window.navigator)==null?void 0:v.userAgent)!=null?_:"").toLowerCase().indexOf("android")!==-1&&o===b.LL_LIVE,f=!i||s&&!((n||y)&&u),{src:m}=e;if(t&&s&&f){if(typeof m=="string"){let{startTime:M}=e;if(t.setAttribute("src",m),M){let d=({target:A})=>{A.currentTime=M,A.removeEventListener("loadedmetadata",d)};t.addEventListener("loadedmetadata",d)}}else t.removeAttribute("src");t.addEventListener("error",oe),t.addEventListener("error",N)}else if(r&&m){switch(r.on(T.default.Events.ERROR,(M,d)=>{let A={[T.default.ErrorTypes.NETWORK_ERROR]:c.MEDIA_ERR_NETWORK,[T.default.ErrorTypes.MEDIA_ERROR]:c.MEDIA_ERR_DECODE},H=new c("",A[d.type]);H.fatal=d.fatal,H.data=d,t.dispatchEvent(new CustomEvent("error",{detail:H}))}),t.addEventListener("error",N),X(t,r),t.preload){case"none":t.addEventListener("play",()=>r.loadSource(m),{once:!0});break;case"metadata":let M=r.config.maxBufferLength,d=r.config.maxBufferSize;r.config.maxBufferLength=1,r.config.maxBufferSize=1,t.addEventListener("play",()=>{r.config.maxBufferLength=M,r.config.maxBufferSize=d},{once:!0}),r.loadSource(m);break;default:r.loadSource(m)}r.attachMedia(t)}else console.error("It looks like the video you're trying to play will not work on this system! If possible, try upgrading to the newest versions of your browser or software.")};async function oe(e){if(!e.isTrusted)return;e.stopImmediatePropagation();let t=e.target;if(!(t==null?void 0:t.error))return;let{message:r,code:n}=t.error,o=new c(r,n);if(t.src&&(n!==c.MEDIA_ERR_DECODE||n!==void 0)){let{status:a}=await fetch(t.src);o.data={response:{code:a}}}t.dispatchEvent(new CustomEvent("error",{detail:o}))}function N(e){var o;if(!(e instanceof CustomEvent)||!(e.detail instanceof c))return;let t=e.target,r=e.detail;if(!r||!r.fatal)return;let n=S.get(t);n&&(n.error=r),(o=t.mux)==null||o.emit("error",{player_error_code:r.code,player_error_message:r.message})}var Ee=(e,t,r)=>{j(t,r),S.set(t,{});let n=ee(e,t);return re(e,t,n),ne(e,t,n),n};
2
+ //# sourceMappingURL=index.cjs.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/index.ts", "../../../shared/polyfills/window.js", "../src/autoplay.ts", "../src/errors.ts", "../src/tracks.ts", "../src/util.ts"],
4
+ "sourcesContent": ["import '@mux/polyfills';\nimport mux, { Options, ErrorEvent } from 'mux-embed';\n\nimport Hls, { HlsConfig } from 'hls.js';\nimport { AutoplayTypes, setupAutoplay } from './autoplay';\nimport { MediaError } from './errors';\nimport { setupTracks } from './tracks';\nimport { isKeyOf } from './util';\nimport type { Autoplay, UpdateAutoplay } from './autoplay';\n\nexport type ValueOf<T> = T[keyof T];\nexport type Metadata = Partial<Options['data']>;\nexport type PlaybackEngine = Hls;\nexport { mux, Hls, MediaError, Autoplay, UpdateAutoplay, setupAutoplay };\n\nconst MUX_VIDEO_DOMAIN = 'mux.com';\n\nexport const generatePlayerInitTime = () => {\n return mux.utils.now();\n};\n\nexport type StreamTypes = {\n VOD: 'on-demand';\n ON_DEMAND: 'on-demand';\n LIVE: 'live';\n LL_LIVE: 'll-live';\n DVR: 'live:dvr';\n LL_DVR: 'll-live:dvr';\n};\n\nexport const StreamTypes: StreamTypes = {\n VOD: 'on-demand',\n ON_DEMAND: 'on-demand',\n LIVE: 'live',\n LL_LIVE: 'll-live',\n DVR: 'live:dvr',\n LL_DVR: 'll-live:dvr',\n};\n\nexport type ExtensionMimeTypeMap = {\n M3U8: 'application/vnd.apple.mpegurl';\n MP4: 'video/mp4';\n};\n\nexport const ExtensionMimeTypeMap: ExtensionMimeTypeMap = {\n M3U8: 'application/vnd.apple.mpegurl',\n MP4: 'video/mp4',\n};\n\nexport type MimeTypeShorthandMap = {\n HLS: ExtensionMimeTypeMap['M3U8'];\n};\n\nexport const MimeTypeShorthandMap: MimeTypeShorthandMap = {\n HLS: ExtensionMimeTypeMap.M3U8,\n};\n\nexport const shorthandKeys = Object.keys(MimeTypeShorthandMap);\n\nexport type MediaTypes =\n | ValueOf<ExtensionMimeTypeMap>\n | keyof MimeTypeShorthandMap\n /** @TODO Figure out a way to \"downgrade\" derived types below to early TS syntax (e.g. 3.4) instead of explicit versions here (CJP) */\n | 'hls';\n// | `${Lowercase<keyof MimeTypeShorthandMap>}`\n// | `${Uppercase<keyof MimeTypeShorthandMap>}`;\n\nexport const allMediaTypes = [\n ...(Object.values(ExtensionMimeTypeMap) as ValueOf<ExtensionMimeTypeMap>[]),\n /** @TODO Figure out a way to \"downgrade\" derived types below to early TS syntax (e.g. 3.4) instead of explicit versions here (CJP) */\n 'hls',\n 'HLS',\n // ...(shorthandKeys as (keyof MimeTypeShorthandMap)[]),\n // ...(shorthandKeys.map((k) => k.toUpperCase()) as `${Uppercase<keyof MimeTypeShorthandMap>}`[]),\n // ...(shorthandKeys.map((k) => k.toLowerCase()) as `${Lowercase<keyof MimeTypeShorthandMap>}`[]),\n] as MediaTypes[];\n\nexport type MuxMediaPropTypes = {\n envKey: Options['data']['env_key'];\n debug: Options['debug'] & Hls['config']['debug'];\n metadata: Partial<Options['data']>;\n customDomain: string;\n beaconCollectionDomain: Options['beaconCollectionDomain'];\n errorTranslator: Options['errorTranslator'];\n playbackId: string;\n playerInitTime: Options['data']['player_init_time'];\n preferMse: boolean;\n type: MediaTypes;\n streamType: ValueOf<StreamTypes>;\n startTime: HlsConfig['startPosition'];\n autoPlay: boolean | ValueOf<AutoplayTypes>;\n autoplay: boolean | ValueOf<AutoplayTypes>;\n};\n\nexport type HTMLMediaElementProps = Partial<Pick<HTMLMediaElement, 'src'>>;\n\nexport type MuxMediaProps = HTMLMediaElementProps & MuxMediaPropTypes;\nexport type MuxMediaPropsInternal = MuxMediaProps & {\n playerSoftwareName: Options['data']['player_software_name'];\n playerSoftwareVersion: Options['data']['player_software_version'];\n};\n\nexport const toPlaybackIdParts = (playbackIdWithOptionalParams: string): [string, string?] => {\n const qIndex = playbackIdWithOptionalParams.indexOf('?');\n if (qIndex < 0) return [playbackIdWithOptionalParams];\n const idPart = playbackIdWithOptionalParams.slice(0, qIndex);\n const queryPart = playbackIdWithOptionalParams.slice(qIndex);\n return [idPart, queryPart];\n};\n\nexport const toMuxVideoURL = (playbackId?: string, { domain = MUX_VIDEO_DOMAIN } = {}) => {\n if (!playbackId) return undefined;\n const [idPart, queryPart = ''] = toPlaybackIdParts(playbackId);\n return `https://stream.${domain}/${idPart}.m3u8${queryPart}`;\n};\n\nexport const inferMimeTypeFromURL = (url: string) => {\n let pathname = '';\n try {\n pathname = new URL(url).pathname;\n } catch (e) {\n console.error('invalid url');\n }\n\n const extDelimIdx = pathname.lastIndexOf('.');\n if (extDelimIdx < 0) return '';\n\n const ext = pathname.slice(extDelimIdx + 1);\n const upperExt = ext.toUpperCase();\n\n return isKeyOf(upperExt, ExtensionMimeTypeMap) ? ExtensionMimeTypeMap[upperExt] : '';\n};\n\nexport const getType = (props: Partial<Pick<MuxMediaProps, 'type' | 'src'>>) => {\n const type = props.type;\n\n if (type) {\n const upperType = type.toUpperCase();\n\n return isKeyOf(upperType, MimeTypeShorthandMap) ? MimeTypeShorthandMap[upperType] : type;\n }\n\n const { src } = props;\n\n if (!src) return '';\n\n return inferMimeTypeFromURL(src);\n};\n\nexport const getStreamTypeConfig = (streamType?: ValueOf<StreamTypes>) => {\n if ([StreamTypes.LIVE, StreamTypes.LL_LIVE].includes(streamType as any)) {\n const liveConfig = {\n backBufferLength: 12,\n };\n\n if (streamType === StreamTypes.LL_LIVE) {\n return {\n ...liveConfig,\n maxFragLookUpTolerance: 0.001,\n };\n }\n\n return liveConfig;\n }\n return {};\n};\n\nlet muxMediaState: WeakMap<HTMLMediaElement, { error?: MediaError }> = new WeakMap();\n\nexport const getError = (mediaEl: HTMLMediaElement) => {\n return muxMediaState.get(mediaEl)?.error;\n};\n\nexport const teardown = (mediaEl?: HTMLMediaElement | null, hls?: Pick<Hls, 'detachMedia' | 'destroy'>) => {\n if (hls) {\n hls.detachMedia();\n hls.destroy();\n }\n if (mediaEl?.mux && !mediaEl.mux.deleted) {\n mediaEl.mux.destroy();\n mediaEl.mux;\n }\n if (mediaEl) {\n mediaEl.removeEventListener('error', handleNativeError);\n mediaEl.removeEventListener('error', handleInternalError);\n muxMediaState.delete(mediaEl);\n }\n};\n\nexport const setupHls = (\n props: Partial<Pick<MuxMediaProps, 'debug' | 'preferMse' | 'streamType' | 'type' | 'src' | 'startTime'>>,\n mediaEl?: Pick<HTMLMediaElement, 'canPlayType'> | null\n) => {\n const { debug, preferMse, streamType, startTime: startPosition = -1 } = props;\n const type = getType(props);\n const hlsType = type === ExtensionMimeTypeMap.M3U8;\n\n const canUseNative = !type || (mediaEl?.canPlayType(type) ?? true);\n const hlsSupported = Hls.isSupported();\n // NOTE: Native HLS playback on Android for LL-HLS has been flaky, so we're prefering\n // MSE for those conditions for now. (CJP)\n const userAgentStr = window?.navigator?.userAgent ?? '';\n const isAndroid = userAgentStr.toLowerCase().indexOf('android') !== -1;\n const defaultPreferMse = isAndroid && streamType === StreamTypes.LL_LIVE;\n\n // We should use native playback for hls media sources if we a) can use native playback and don't also b) prefer to use MSE/hls.js if/when it's supported\n const shouldUseNative = !hlsType || (canUseNative && !((preferMse || defaultPreferMse) && hlsSupported));\n\n // 1. if we are trying to play an hls media source create hls if we should be using it \"under the hood\"\n if (hlsType && !shouldUseNative && hlsSupported) {\n const defaultConfig = {\n backBufferLength: 30,\n renderTextTracksNatively: false,\n liveDurationInfinity: true,\n };\n const streamTypeConfig = getStreamTypeConfig(streamType);\n const hls = new Hls({\n // Kind of like preload metadata, but causes spinner.\n // autoStartLoad: false,\n debug,\n startPosition,\n ...defaultConfig,\n ...streamTypeConfig,\n });\n\n return hls;\n }\n return undefined;\n};\n\nexport const isMuxVideoSrc = ({\n playbackId,\n src,\n customDomain,\n}: Partial<Pick<MuxMediaPropsInternal, 'playbackId' | 'src' | 'customDomain'>>) => {\n if (!!playbackId) return true;\n // having no playback id and no src string should never actually happen, but could\n if (typeof src !== 'string') return false;\n const hostname = new URL(src).hostname.toLocaleLowerCase();\n return hostname.includes(MUX_VIDEO_DOMAIN) || (!!customDomain && hostname.includes(customDomain.toLocaleLowerCase()));\n};\n\nexport const setupMux = (\n props: Partial<\n Pick<\n MuxMediaPropsInternal,\n | 'envKey'\n | 'playerInitTime'\n | 'beaconCollectionDomain'\n | 'errorTranslator'\n | 'metadata'\n | 'debug'\n | 'playerSoftwareName'\n | 'playerSoftwareVersion'\n | 'playbackId'\n | 'src'\n | 'customDomain'\n >\n >,\n mediaEl?: HTMLMediaElement | null,\n hlsjs?: Hls\n) => {\n const { envKey: env_key } = props;\n const inferredEnv = isMuxVideoSrc(props);\n\n if ((env_key || inferredEnv) && mediaEl) {\n const {\n playerInitTime: player_init_time,\n playerSoftwareName: player_software_name,\n playerSoftwareVersion: player_software_version,\n beaconCollectionDomain,\n metadata,\n debug,\n } = props;\n\n const muxEmbedErrorTranslator = (error: ErrorEvent) => {\n // mux-embed auto tracks fatal hls.js errors, turn it off.\n // playback-core will emit errors with a numeric code manually to mux-embed.\n if (typeof error.player_error_code === 'string') return false;\n\n if (typeof props.errorTranslator === 'function') {\n return props.errorTranslator(error);\n }\n\n return error;\n };\n\n mux.monitor(mediaEl, {\n debug,\n beaconCollectionDomain,\n hlsjs,\n Hls: hlsjs ? Hls : undefined,\n automaticErrorTracking: false,\n errorTranslator: muxEmbedErrorTranslator,\n data: {\n ...(env_key ? { env_key } : {}),\n // Metadata fields\n player_software_name,\n player_software_version,\n player_init_time,\n // Use any metadata passed in programmatically (which may override the defaults above)\n ...metadata,\n },\n });\n }\n};\n\nexport const loadMedia = (\n props: Partial<Pick<MuxMediaProps, 'preferMse' | 'src' | 'type' | 'startTime' | 'streamType' | 'autoplay'>>,\n mediaEl?: HTMLMediaElement | null,\n hls?: Pick<\n Hls,\n | 'config'\n | 'on'\n | 'once'\n | 'startLoad'\n | 'stopLoad'\n | 'recoverMediaError'\n | 'destroy'\n | 'loadSource'\n | 'attachMedia'\n | 'liveSyncPosition'\n | 'subtitleTracks'\n | 'subtitleTrack'\n >\n) => {\n if (!mediaEl) {\n console.warn('attempting to load media before mediaEl exists');\n return;\n }\n const { preferMse, streamType } = props;\n const type = getType(props);\n const hlsType = type === ExtensionMimeTypeMap.M3U8;\n\n const canUseNative = !type || (mediaEl?.canPlayType(type) ?? true);\n const hlsSupported = Hls.isSupported();\n const userAgentStr = window?.navigator?.userAgent ?? '';\n // NOTE: Native HLS playback on Android for LL-HLS has been flaky, so we're prefering\n // MSE for those conditions for now. (CJP)\n const isAndroid = userAgentStr.toLowerCase().indexOf('android') !== -1;\n const defaultPreferMse = isAndroid && streamType === StreamTypes.LL_LIVE;\n\n // We should use native playback for hls media sources if we a) can use native playback and don't also b) prefer to use MSE/hls.js if/when it's supported\n const shouldUseNative = !hlsType || (canUseNative && !((preferMse || defaultPreferMse) && hlsSupported));\n\n const { src } = props;\n if (mediaEl && canUseNative && shouldUseNative) {\n if (typeof src === 'string') {\n const { startTime } = props;\n mediaEl.setAttribute('src', src);\n if (startTime) {\n const setStartTimeOnLoad = ({ target }: HTMLMediaElementEventMap['loadedmetadata']) => {\n (target as HTMLMediaElement).currentTime = startTime;\n (target as HTMLMediaElement).removeEventListener('loadedmetadata', setStartTimeOnLoad);\n };\n\n mediaEl.addEventListener('loadedmetadata', setStartTimeOnLoad);\n }\n } else {\n mediaEl.removeAttribute('src');\n }\n\n mediaEl.addEventListener('error', handleNativeError);\n mediaEl.addEventListener('error', handleInternalError);\n } else if (hls && src) {\n hls.on(Hls.Events.ERROR, (_event, data) => {\n // if (data.fatal) {\n // switch (data.type) {\n // case Hls.ErrorTypes.NETWORK_ERROR:\n // // try to recover network error\n // console.error(\"fatal network error encountered, try to recover\");\n // hls.startLoad();\n // break;\n // case Hls.ErrorTypes.MEDIA_ERROR:\n // console.error(\"fatal media error encountered, try to recover\");\n // hls.recoverMediaError();\n // break;\n // default:\n // // cannot recover\n // console.error(\n // \"unrecoverable fatal error encountered, cannot recover (check logs for more info)\"\n // );\n // hls.destroy();\n // break;\n // }\n // }\n\n const errorCodeMap: Record<string, number> = {\n [Hls.ErrorTypes.NETWORK_ERROR]: MediaError.MEDIA_ERR_NETWORK,\n [Hls.ErrorTypes.MEDIA_ERROR]: MediaError.MEDIA_ERR_DECODE,\n };\n const error = new MediaError('', errorCodeMap[data.type]);\n error.fatal = data.fatal;\n error.data = data;\n mediaEl.dispatchEvent(\n new CustomEvent('error', {\n detail: error,\n })\n );\n });\n mediaEl.addEventListener('error', handleInternalError);\n\n setupTracks(mediaEl, hls);\n\n switch (mediaEl.preload) {\n case 'none':\n // when preload is none, load the source on first play\n mediaEl.addEventListener('play', () => hls.loadSource(src), { once: true });\n break;\n\n case 'metadata':\n const originalLength = hls.config.maxBufferLength;\n const originalSize = hls.config.maxBufferSize;\n\n // load the least amount of data possible\n hls.config.maxBufferLength = 1;\n hls.config.maxBufferSize = 1;\n // and once a user has player, allow for it to load data as normal\n mediaEl.addEventListener(\n 'play',\n () => {\n hls.config.maxBufferLength = originalLength;\n hls.config.maxBufferSize = originalSize;\n },\n { once: true }\n );\n hls.loadSource(src);\n break;\n\n default:\n // load source immediately for any other preload value\n hls.loadSource(src);\n }\n\n hls.attachMedia(mediaEl);\n } else {\n console.error(\n \"It looks like the video you're trying to play will not work on this system! If possible, try upgrading to the newest versions of your browser or software.\"\n );\n }\n};\n\nasync function handleNativeError(event: Event) {\n // Return if the event was created or modified by a script or dispatched\n // via EventTarget.dispatchEvent() preventing an infinite loop.\n if (!event.isTrusted) return;\n\n // Stop immediate propagation of the native error event, re-dispatch below!\n event.stopImmediatePropagation();\n\n const mediaEl = event.target as HTMLMediaElement;\n // Safari sometimes throws an error event with a null error.\n if (!mediaEl?.error) return;\n\n const { message, code } = mediaEl.error;\n const error = new MediaError(message, code);\n\n if (mediaEl.src && (code !== MediaError.MEDIA_ERR_DECODE || code !== undefined)) {\n // Attempt to get the response code from the video src url.\n const { status } = await fetch(mediaEl.src as RequestInfo);\n // Use the same hls.js data structure.\n error.data = { response: { code: status } };\n }\n\n mediaEl.dispatchEvent(\n new CustomEvent('error', {\n detail: error,\n })\n );\n}\n\n/**\n * Use a event listener instead of a function call when dispatching the Custom error\n * event so consumers are still able to disable or intercept this error event.\n * @param {Event} event\n */\nfunction handleInternalError(event: Event) {\n if (!(event instanceof CustomEvent) || !(event.detail instanceof MediaError)) return;\n\n const mediaEl = event.target as HTMLMediaElement;\n const error = event.detail;\n // Prevent tracking non-fatal errors in Mux data.\n if (!error || !error.fatal) return;\n\n const state = muxMediaState.get(mediaEl);\n if (state) state.error = error;\n\n // Only pass valid mux-embed props: player_error_code, player_error_message\n mediaEl.mux?.emit('error', {\n player_error_code: error.code,\n player_error_message: error.message,\n });\n}\n\nexport const initialize = (props: Partial<MuxMediaPropsInternal>, mediaEl?: HTMLMediaElement | null, hls?: Hls) => {\n // Automatically tear down previously initialized mux data & hls instance if it exists.\n teardown(mediaEl, hls);\n muxMediaState.set(mediaEl as HTMLMediaElement, {});\n const nextHlsInstance = setupHls(props, mediaEl);\n setupMux(props, mediaEl, nextHlsInstance);\n loadMedia(props, mediaEl, nextHlsInstance);\n return nextHlsInstance;\n};\n", "if (typeof DocumentFragment === 'undefined') {\n class DocumentFragment {}\n // @ts-ignore\n globalThis.DocumentFragment = DocumentFragment;\n}\n\nif (!globalThis.customElements) {\n globalThis.customElements = {\n get(_name) {\n return undefined;\n },\n define(_name, _constructor, _options) {},\n upgrade(_root) {},\n whenDefined(_name) {\n return Promise.resolve(globalThis.HTMLElement);\n },\n };\n}\n\nif (!globalThis.CustomEvent) {\n class CustomEvent {\n #detail;\n get detail() {\n this.#detail;\n }\n constructor(typeArg, eventInitDict = {}) {\n // super(typeArg, eventInitDict);\n this.#detail = eventInitDict?.detail;\n }\n initCustomEvent(_typeArg, _canBubbleArg, _cancelableArg, _detailArg) {}\n }\n globalThis.CustomEvent = CustomEvent;\n}\n\nif (!globalThis.EventTarget) {\n class EventTarget {\n addEventListener() {}\n removeEventListener() {}\n dispatchEvent(_event) {\n return true;\n }\n }\n\n globalThis.EventTarget = EventTarget;\n}\n\nif (!globalThis.HTMLElement) {\n class HTMLElement extends EventTarget {}\n\n // NOTE: Adding ts-ignore since `HTMLElement` typedef is much larger than what we're stubbing. Consider more robust TypeScript solution (e.g. downstream usage)\n // @ts-ignore\n globalThis.HTMLElement = HTMLElement;\n}\n\nif (!globalThis.HTMLVideoElement) {\n class HTMLVideoElement extends EventTarget {}\n\n // NOTE: Adding ts-ignore since `HTMLVideoElement` typedef is much larger than what we're stubbing. Consider more robust TypeScript solution (e.g. downstream usage)\n // @ts-ignore\n globalThis.HTMLVideoElement = HTMLVideoElement;\n}\n\nif (!globalThis.document?.createElement) {\n const document = globalThis.document ?? {};\n (document.createElement = function createElement(_tagName, _options) {\n return new HTMLElement();\n }),\n // NOTE: Adding ts-ignore since `document` typedef is much larger than what we're stubbing. Consider more robust TypeScript solution (e.g. downstream usage)\n // @ts-ignore\n (globalThis.document = document);\n}\n", "import Hls from 'hls.js';\n\ntype PlaybackEngine = Hls;\n\n// TODO add INVIEW_MUTED, INVIEW_ANY\nexport type AutoplayTypes = {\n ANY: 'any';\n MUTED: 'muted';\n};\n\nexport const AutoplayTypes: AutoplayTypes = {\n ANY: 'any',\n MUTED: 'muted',\n};\n\ntype ValueOf<T> = T[keyof T];\ntype Maybe<T> = T | null | undefined;\nexport type Autoplay = boolean | ValueOf<AutoplayTypes>;\nexport type UpdateAutoplay = (newAutoplay: Maybe<string | boolean>) => void;\n\nconst AutoplayTypeValues = Object.values(AutoplayTypes);\nexport const isAutoplayValue = (value: unknown): value is Autoplay => {\n return (\n typeof value === 'boolean' ||\n (typeof value === 'string' && AutoplayTypeValues.includes(value as ValueOf<AutoplayTypes>))\n );\n};\n\n// Given a video element, will listen to lifecycle events to determine important\n// things like whether the video is live or whether the video has played\n// and then handles autoplaying the video as appropraite.\n// It works with both the native video element or hls.js.\n// This returns a method UpdateAutoplay, that allows the user to change\n// the value of the autoplay attribute and it will react appropriately.\nexport const setupAutoplay = (\n mediaEl: HTMLMediaElement,\n maybeAutoplay: Maybe<string | boolean>,\n hls: PlaybackEngine | undefined\n) => {\n let hasPlayed = false;\n let isLive = false;\n let autoplay: Autoplay = isAutoplayValue(maybeAutoplay) ? maybeAutoplay : !!maybeAutoplay;\n\n const updateHasPlayed = () => {\n // hasPlayed\n mediaEl.addEventListener(\n 'playing',\n () => {\n hasPlayed = true;\n },\n { once: true }\n );\n };\n\n updateHasPlayed();\n\n // on `loadstart`\n // hasPlayed should default to false\n // we should try and autoplay\n mediaEl.addEventListener(\n 'loadstart',\n () => {\n hasPlayed = false;\n updateHasPlayed();\n handleAutoplay(mediaEl, autoplay);\n },\n { once: true }\n );\n\n // on `loadedmetadata` we can check whether we're live in the case of native playback\n mediaEl.addEventListener(\n 'loadedmetadata',\n () => {\n // only update isLive here if we're using native playback\n if (!hls) {\n isLive = !Number.isFinite(mediaEl.duration);\n }\n handleAutoplay(mediaEl, autoplay);\n },\n { once: true }\n );\n\n // determine if we're live for hls.js\n if (hls) {\n hls.once(Hls.Events.LEVEL_LOADED, (e: any, data: any) => {\n isLive = data.details.live ?? false;\n });\n }\n\n // When we are not auto-playing, we should seek to the live sync position\n // This will seek first play event of *any* live video including event-type,\n // which probably shouldn't seek\n if (!autoplay) {\n const handleSeek = () => {\n // don't seek if we're not live\n if (!isLive) {\n return;\n }\n // seek to either hls.js's liveSyncPosition or the native seekable end\n if (hls?.liveSyncPosition) {\n mediaEl.currentTime = hls.liveSyncPosition;\n } else {\n if (Number.isFinite(mediaEl.seekable.end(0))) {\n mediaEl.currentTime = mediaEl.seekable.end(0);\n }\n }\n };\n mediaEl.addEventListener(\n 'play',\n () => {\n if (hls && mediaEl.preload === 'metadata') {\n hls.once(Hls.Events.LEVEL_UPDATED, handleSeek);\n } else if (hls) {\n handleSeek();\n }\n },\n { once: true }\n );\n }\n\n // this method allows us to update the value of autoplay\n // and try autoplaying appropriately.\n const updateAutoplay: UpdateAutoplay = (newAutoplay) => {\n if (!hasPlayed) {\n autoplay = isAutoplayValue(newAutoplay) ? newAutoplay : !!newAutoplay;\n handleAutoplay(mediaEl, autoplay);\n }\n };\n\n return updateAutoplay;\n};\n\nexport const handleAutoplay = (mediaEl: HTMLMediaElement, autoplay: Autoplay) => {\n if (!autoplay) {\n return;\n }\n\n const oldMuted = mediaEl.muted;\n const restoreMuted = () => (mediaEl.muted = oldMuted);\n\n switch (autoplay) {\n // ANY:\n // try to play with current options\n // if it fails, mute and try playing again\n // if that fails, restore muted state and don't try playing again\n case AutoplayTypes.ANY:\n mediaEl.play().catch((error: Error) => {\n mediaEl.muted = true;\n mediaEl.play().catch(restoreMuted);\n });\n break;\n\n // MUTED:\n // mute the player and then try playing\n // if that fails, restore muted state\n case AutoplayTypes.MUTED:\n mediaEl.muted = true;\n mediaEl.play().catch(restoreMuted);\n break;\n\n // Default or if autoplay is a boolean attribute:\n // Try playing the video and catch the failed autoplay warning\n default:\n mediaEl.play().catch(() => {});\n break;\n }\n};\n", "export class MediaError extends Error {\n static MEDIA_ERR_ABORTED: number = 1;\n static MEDIA_ERR_NETWORK: number = 2;\n static MEDIA_ERR_DECODE: number = 3;\n static MEDIA_ERR_SRC_NOT_SUPPORTED: number = 4;\n static MEDIA_ERR_ENCRYPTED: number = 5;\n // @see https://docs.mux.com/guides/data/monitor-html5-video-element#customize-error-tracking-behavior\n static MEDIA_ERR_CUSTOM: number = 100;\n\n static defaultMessages: Record<number, string> = {\n 1: 'You aborted the media playback',\n 2: 'A network error caused the media download to fail.',\n 3: 'A media error caused playback to be aborted. The media could be corrupt or your browser does not support this format.',\n 4: 'An unsupported error occurred. The server or network failed, or your browser does not support this format.',\n 5: 'The media is encrypted and there are no keys to decrypt it.',\n };\n\n name: string;\n code: number;\n fatal: boolean;\n data?: any;\n\n constructor(message?: string, code: number = MediaError.MEDIA_ERR_CUSTOM, fatal?: boolean) {\n super(message);\n this.name = 'MediaError';\n this.code = code;\n this.fatal = fatal ?? (code >= MediaError.MEDIA_ERR_NETWORK && code <= MediaError.MEDIA_ERR_ENCRYPTED);\n\n if (!this.message) {\n this.message = MediaError.defaultMessages[this.code] ?? '';\n }\n }\n}\n", "import Hls from 'hls.js';\nimport type { MediaPlaylist } from 'hls.js';\n\nexport function setupTracks(\n mediaEl: HTMLMediaElement,\n hls: Pick<Hls, 'on' | 'once' | 'subtitleTracks' | 'subtitleTrack'>\n) {\n hls.on(Hls.Events.NON_NATIVE_TEXT_TRACKS_FOUND, (_type, { tracks }) => {\n tracks.forEach((trackObj) => {\n const baseTrackObj = trackObj.subtitleTrack ?? trackObj.closedCaptions;\n const idx = hls.subtitleTracks.findIndex(({ lang, name, type }) => {\n return lang == baseTrackObj?.lang && name === trackObj.label && type.toLowerCase() === trackObj.kind;\n });\n\n createTextTrack(\n mediaEl,\n trackObj.kind as TextTrackKind,\n trackObj.label,\n baseTrackObj?.lang,\n `${trackObj.kind}${idx}`\n );\n });\n });\n\n const changeHandler = () => {\n if (!hls.subtitleTracks.length) return;\n\n const showingTrack = Array.from(mediaEl.textTracks).find((textTrack) => {\n return textTrack.id && textTrack.mode === 'showing' && ['subtitles', 'captions'].includes(textTrack.kind);\n });\n\n // If hls.subtitleTrack is -1 or its id changed compared to the one that is showing load the new subtitle track.\n const hlsTrackId = `${hls.subtitleTracks[hls.subtitleTrack]?.type.toLowerCase()}${hls.subtitleTrack}`;\n if (showingTrack && (hls.subtitleTrack < 0 || showingTrack?.id !== hlsTrackId)) {\n const idx = hls.subtitleTracks.findIndex(({ lang, name, type }) => {\n return lang == showingTrack.language && name === showingTrack.label && type.toLowerCase() === showingTrack.kind;\n });\n // After the subtitleTrack is set here, hls.js will load the playlist and CUES_PARSED events will be fired below.\n hls.subtitleTrack = idx;\n }\n\n if (showingTrack && showingTrack?.id === hlsTrackId) {\n // Refresh the cues after a texttrack mode change to fix a Chrome bug causing the captions not to render.\n if (showingTrack.cues) {\n Array.from(showingTrack.cues).forEach((cue) => {\n showingTrack.addCue(cue);\n });\n }\n }\n };\n\n mediaEl.textTracks.addEventListener('change', changeHandler);\n\n hls.on(Hls.Events.CUES_PARSED, (_type, { track, type, cues }) => {\n const textTrack = mediaEl.textTracks.getTrackById(track);\n if (!textTrack) return;\n\n const disabled = textTrack.mode === 'disabled';\n if (disabled) {\n textTrack.mode = 'hidden';\n }\n\n cues.forEach((cue: VTTCue) => {\n if (textTrack.cues?.getCueById(cue.id)) return;\n textTrack.addCue(cue);\n });\n\n if (disabled) {\n textTrack.mode = 'disabled';\n }\n });\n\n hls.on(Hls.Events.DESTROYING, () => {\n mediaEl.textTracks.removeEventListener('change', changeHandler);\n\n const trackEls = mediaEl.querySelectorAll('track');\n trackEls.forEach((trackEl) => {\n if (!(trackEl.id && ['subtitles', 'captions'].includes(trackEl.kind))) return;\n if (!hls.subtitleTracks.some(({ type }, idx) => trackEl.id === `${type.toLowerCase()}${idx}`)) return;\n\n mediaEl.removeChild(trackEl);\n });\n });\n\n const forceHiddenThumbnails = () => {\n // Keeping this a forEach in case we want to expand the scope of this.\n Array.from(mediaEl.textTracks).forEach((track) => {\n if (['subtitles', 'caption'].includes(track.kind)) return;\n if (track.label !== 'thumbnails') return;\n if (!track.cues?.length) {\n const trackEl = mediaEl.querySelector('track[label=\"thumbnails\"]');\n // Force a reload of the cues if they've been removed\n const src = trackEl?.getAttribute('src') ?? '';\n trackEl?.removeAttribute('src');\n setTimeout(() => {\n trackEl?.setAttribute('src', src);\n }, 0);\n }\n // Force hidden mode if it's not hidden\n if (track.mode !== 'hidden') {\n track.mode = 'hidden';\n }\n });\n };\n\n // hls.js will forcibly clear all cues from tracks on manifest loads or media attaches.\n // This ensures that we re-load them after it's done that.\n hls.once(Hls.Events.MANIFEST_LOADED, forceHiddenThumbnails);\n hls.once(Hls.Events.MEDIA_ATTACHED, forceHiddenThumbnails);\n}\n\nfunction createTextTrack(\n mediaEl: HTMLMediaElement,\n kind: TextTrackKind,\n label: string,\n lang?: string,\n id?: string\n): TextTrack | undefined {\n const trackEl = document.createElement('track');\n trackEl.kind = kind;\n trackEl.label = label;\n if (lang) {\n // This attribute must be present if the element's kind attribute is in the subtitles state.\n trackEl.srclang = lang;\n }\n if (id) {\n trackEl.id = id;\n }\n trackEl.track.mode = 'disabled';\n mediaEl.appendChild(trackEl);\n return trackEl.track;\n}\n", "type KeyTypes = string | number | symbol;\n\n// Type Guard to determine if a given key is actually a key of some object of type T\nexport const isKeyOf = <T = any>(k: KeyTypes, o: T): k is keyof T => {\n return k in o;\n};\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
package/dist/index.mjs ADDED
@@ -0,0 +1,2 @@
1
+ var I=(e,t,r)=>{if(!t.has(e))throw TypeError("Cannot "+r)};var C=(e,t,r)=>(I(e,t,"read from private field"),r?r.call(e):t.get(e)),O=(e,t,r)=>{if(t.has(e))throw TypeError("Cannot add the same private member more than once");t instanceof WeakSet?t.add(e):t.set(e,r)},V=(e,t,r,n)=>(I(e,t,"write to private field"),n?n.call(e,r):t.set(e,r),r);if(typeof DocumentFragment=="undefined"){class e{}globalThis.DocumentFragment=e}globalThis.customElements||(globalThis.customElements={get(e){},define(e,t,r){},upgrade(e){},whenDefined(e){return Promise.resolve(globalThis.HTMLElement)}});var _;if(!globalThis.CustomEvent){class e{constructor(r,n={}){O(this,_,void 0);V(this,_,n==null?void 0:n.detail)}get detail(){C(this,_)}initCustomEvent(r,n,o,a){}}_=new WeakMap,globalThis.CustomEvent=e}if(!globalThis.EventTarget){class e{addEventListener(){}removeEventListener(){}dispatchEvent(r){return!0}}globalThis.EventTarget=e}if(!globalThis.HTMLElement){class e extends EventTarget{}globalThis.HTMLElement=e}if(!globalThis.HTMLVideoElement){class e extends EventTarget{}globalThis.HTMLVideoElement=e}var N,U;if(!((N=globalThis.document)==null?void 0:N.createElement)){let e=(U=globalThis.document)!=null?U:{};e.createElement=function(r,n){return new HTMLElement},globalThis.document=e}import $ from"mux-embed";import M from"hls.js";import K from"hls.js";var D={ANY:"any",MUTED:"muted"},W=Object.values(D),B=e=>typeof e=="boolean"||typeof e=="string"&&W.includes(e),X=(e,t,r)=>{let n=!1,o=!1,a=B(t)?t:!!t,i=()=>{e.addEventListener("playing",()=>{n=!0},{once:!0})};if(i(),e.addEventListener("loadstart",()=>{n=!1,i(),R(e,a)},{once:!0}),e.addEventListener("loadedmetadata",()=>{r||(o=!Number.isFinite(e.duration)),R(e,a)},{once:!0}),r&&r.once(K.Events.LEVEL_LOADED,(u,c)=>{var p;o=(p=c.details.live)!=null?p:!1}),!a){let u=()=>{!o||((r==null?void 0:r.liveSyncPosition)?e.currentTime=r.liveSyncPosition:Number.isFinite(e.seekable.end(0))&&(e.currentTime=e.seekable.end(0)))};e.addEventListener("play",()=>{r&&e.preload==="metadata"?r.once(K.Events.LEVEL_UPDATED,u):r&&u()},{once:!0})}return u=>{n||(a=B(u)?u:!!u,R(e,a))}},R=(e,t)=>{if(!t)return;let r=e.muted,n=()=>e.muted=r;switch(t){case D.ANY:e.play().catch(o=>{e.muted=!0,e.play().catch(n)});break;case D.MUTED:e.muted=!0,e.play().catch(n);break;default:e.play().catch(()=>{});break}};var g=class extends Error{constructor(t,r=g.MEDIA_ERR_CUSTOM,n){super(t);var o;this.name="MediaError",this.code=r,this.fatal=n!=null?n:r>=g.MEDIA_ERR_NETWORK&&r<=g.MEDIA_ERR_ENCRYPTED,this.message||(this.message=(o=g.defaultMessages[this.code])!=null?o:"")}},l=g;l.MEDIA_ERR_ABORTED=1,l.MEDIA_ERR_NETWORK=2,l.MEDIA_ERR_DECODE=3,l.MEDIA_ERR_SRC_NOT_SUPPORTED=4,l.MEDIA_ERR_ENCRYPTED=5,l.MEDIA_ERR_CUSTOM=100,l.defaultMessages={1:"You aborted the media playback",2:"A network error caused the media download to fail.",3:"A media error caused playback to be aborted. The media could be corrupt or your browser does not support this format.",4:"An unsupported error occurred. The server or network failed, or your browser does not support this format.",5:"The media is encrypted and there are no keys to decrypt it."};import A from"hls.js";function F(e,t){t.on(A.Events.NON_NATIVE_TEXT_TRACKS_FOUND,(o,{tracks:a})=>{a.forEach(i=>{var c;let s=(c=i.subtitleTrack)!=null?c:i.closedCaptions,u=t.subtitleTracks.findIndex(({lang:p,name:y,type:f})=>p==(s==null?void 0:s.lang)&&y===i.label&&f.toLowerCase()===i.kind);G(e,i.kind,i.label,s==null?void 0:s.lang,`${i.kind}${u}`)})});let r=()=>{var i;if(!t.subtitleTracks.length)return;let o=Array.from(e.textTracks).find(s=>s.id&&s.mode==="showing"&&["subtitles","captions"].includes(s.kind)),a=`${(i=t.subtitleTracks[t.subtitleTrack])==null?void 0:i.type.toLowerCase()}${t.subtitleTrack}`;if(o&&(t.subtitleTrack<0||(o==null?void 0:o.id)!==a)){let s=t.subtitleTracks.findIndex(({lang:u,name:c,type:p})=>u==o.language&&c===o.label&&p.toLowerCase()===o.kind);t.subtitleTrack=s}o&&(o==null?void 0:o.id)===a&&o.cues&&Array.from(o.cues).forEach(s=>{o.addCue(s)})};e.textTracks.addEventListener("change",r),t.on(A.Events.CUES_PARSED,(o,{track:a,type:i,cues:s})=>{let u=e.textTracks.getTrackById(a);if(!u)return;let c=u.mode==="disabled";c&&(u.mode="hidden"),s.forEach(p=>{var y;((y=u.cues)==null?void 0:y.getCueById(p.id))||u.addCue(p)}),c&&(u.mode="disabled")}),t.on(A.Events.DESTROYING,()=>{e.textTracks.removeEventListener("change",r),e.querySelectorAll("track").forEach(a=>{!(a.id&&["subtitles","captions"].includes(a.kind))||!t.subtitleTracks.some(({type:i},s)=>a.id===`${i.toLowerCase()}${s}`)||e.removeChild(a)})});let n=()=>{Array.from(e.textTracks).forEach(o=>{var a,i;if(!["subtitles","caption"].includes(o.kind)&&o.label==="thumbnails"){if(!((a=o.cues)==null?void 0:a.length)){let s=e.querySelector('track[label="thumbnails"]'),u=(i=s==null?void 0:s.getAttribute("src"))!=null?i:"";s==null||s.removeAttribute("src"),setTimeout(()=>{s==null||s.setAttribute("src",u)},0)}o.mode!=="hidden"&&(o.mode="hidden")}})};t.once(A.Events.MANIFEST_LOADED,n),t.once(A.Events.MEDIA_ATTACHED,n)}function G(e,t,r,n,o){let a=document.createElement("track");return a.kind=t,a.label=r,n&&(a.srclang=n),o&&(a.id=o),a.track.mode="disabled",e.appendChild(a),a.track}var S=(e,t)=>e in t;var Y="mux.com",Ae=()=>$.utils.now(),h={VOD:"on-demand",ON_DEMAND:"on-demand",LIVE:"live",LL_LIVE:"ll-live",DVR:"live:dvr",LL_DVR:"ll-live:dvr"},E={M3U8:"application/vnd.apple.mpegurl",MP4:"video/mp4"},H={HLS:E.M3U8},he=Object.keys(H),ke=[...Object.values(E),"hls","HLS"],J=e=>{let t=e.indexOf("?");if(t<0)return[e];let r=e.slice(0,t),n=e.slice(t);return[r,n]},Pe=(e,{domain:t=Y}={})=>{if(!e)return;let[r,n=""]=J(e);return`https://stream.${t}/${r}.m3u8${n}`},Q=e=>{let t="";try{t=new URL(e).pathname}catch{console.error("invalid url")}let r=t.lastIndexOf(".");if(r<0)return"";let o=t.slice(r+1).toUpperCase();return S(o,E)?E[o]:""},q=e=>{let t=e.type;if(t){let n=t.toUpperCase();return S(n,H)?H[n]:t}let{src:r}=e;return r?Q(r):""},Z=e=>{if([h.LIVE,h.LL_LIVE].includes(e)){let t={backBufferLength:12};return e===h.LL_LIVE?{...t,maxFragLookUpTolerance:.001}:t}return{}},k=new WeakMap,De=e=>{var t;return(t=k.get(e))==null?void 0:t.error},j=(e,t)=>{t&&(t.detachMedia(),t.destroy()),(e==null?void 0:e.mux)&&!e.mux.deleted&&(e.mux.destroy(),e.mux),e&&(e.removeEventListener("error",z),e.removeEventListener("error",w),k.delete(e))},ee=(e,t)=>{var x,b,L;let{debug:r,preferMse:n,streamType:o,startTime:a=-1}=e,i=q(e),s=i===E.M3U8,u=!i||((x=t==null?void 0:t.canPlayType(i))!=null?x:!0),c=M.isSupported(),f=((L=(b=window==null?void 0:window.navigator)==null?void 0:b.userAgent)!=null?L:"").toLowerCase().indexOf("android")!==-1&&o===h.LL_LIVE;if(s&&!(!s||u&&!((n||f)&&c))&&c){let m={backBufferLength:30,renderTextTracksNatively:!1,liveDurationInfinity:!0},d=Z(o);return new M({debug:r,startPosition:a,...m,...d})}},te=({playbackId:e,src:t,customDomain:r})=>{if(e)return!0;if(typeof t!="string")return!1;let n=new URL(t).hostname.toLocaleLowerCase();return n.includes(Y)||!!r&&n.includes(r.toLocaleLowerCase())},re=(e,t,r)=>{let{envKey:n}=e,o=te(e);if((n||o)&&t){let{playerInitTime:a,playerSoftwareName:i,playerSoftwareVersion:s,beaconCollectionDomain:u,metadata:c,debug:p}=e,y=f=>typeof f.player_error_code=="string"?!1:typeof e.errorTranslator=="function"?e.errorTranslator(f):f;$.monitor(t,{debug:p,beaconCollectionDomain:u,hlsjs:r,Hls:r?M:void 0,automaticErrorTracking:!1,errorTranslator:y,data:{...n?{env_key:n}:{},player_software_name:i,player_software_version:s,player_init_time:a,...c}})}},ne=(e,t,r)=>{var x,b,L;if(!t){console.warn("attempting to load media before mediaEl exists");return}let{preferMse:n,streamType:o}=e,a=q(e),i=a===E.M3U8,s=!a||((x=t==null?void 0:t.canPlayType(a))!=null?x:!0),u=M.isSupported(),y=((L=(b=window==null?void 0:window.navigator)==null?void 0:b.userAgent)!=null?L:"").toLowerCase().indexOf("android")!==-1&&o===h.LL_LIVE,f=!i||s&&!((n||y)&&u),{src:T}=e;if(t&&s&&f){if(typeof T=="string"){let{startTime:m}=e;if(t.setAttribute("src",T),m){let d=({target:v})=>{v.currentTime=m,v.removeEventListener("loadedmetadata",d)};t.addEventListener("loadedmetadata",d)}}else t.removeAttribute("src");t.addEventListener("error",z),t.addEventListener("error",w)}else if(r&&T){switch(r.on(M.Events.ERROR,(m,d)=>{let v={[M.ErrorTypes.NETWORK_ERROR]:l.MEDIA_ERR_NETWORK,[M.ErrorTypes.MEDIA_ERROR]:l.MEDIA_ERR_DECODE},P=new l("",v[d.type]);P.fatal=d.fatal,P.data=d,t.dispatchEvent(new CustomEvent("error",{detail:P}))}),t.addEventListener("error",w),F(t,r),t.preload){case"none":t.addEventListener("play",()=>r.loadSource(T),{once:!0});break;case"metadata":let m=r.config.maxBufferLength,d=r.config.maxBufferSize;r.config.maxBufferLength=1,r.config.maxBufferSize=1,t.addEventListener("play",()=>{r.config.maxBufferLength=m,r.config.maxBufferSize=d},{once:!0}),r.loadSource(T);break;default:r.loadSource(T)}r.attachMedia(t)}else console.error("It looks like the video you're trying to play will not work on this system! If possible, try upgrading to the newest versions of your browser or software.")};async function z(e){if(!e.isTrusted)return;e.stopImmediatePropagation();let t=e.target;if(!(t==null?void 0:t.error))return;let{message:r,code:n}=t.error,o=new l(r,n);if(t.src&&(n!==l.MEDIA_ERR_DECODE||n!==void 0)){let{status:a}=await fetch(t.src);o.data={response:{code:a}}}t.dispatchEvent(new CustomEvent("error",{detail:o}))}function w(e){var o;if(!(e instanceof CustomEvent)||!(e.detail instanceof l))return;let t=e.target,r=e.detail;if(!r||!r.fatal)return;let n=k.get(t);n&&(n.error=r),(o=t.mux)==null||o.emit("error",{player_error_code:r.code,player_error_message:r.message})}var Re=(e,t,r)=>{j(t,r),k.set(t,{});let n=ee(e,t);return re(e,t,n),ne(e,t,n),n};export{E as ExtensionMimeTypeMap,M as Hls,l as MediaError,H as MimeTypeShorthandMap,h as StreamTypes,ke as allMediaTypes,Ae as generatePlayerInitTime,De as getError,Z as getStreamTypeConfig,q as getType,Q as inferMimeTypeFromURL,Re as initialize,te as isMuxVideoSrc,ne as loadMedia,$ as mux,X as setupAutoplay,ee as setupHls,re as setupMux,he as shorthandKeys,j as teardown,Pe as toMuxVideoURL,J as toPlaybackIdParts};
2
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../shared/polyfills/window.js", "../src/index.ts", "../src/autoplay.ts", "../src/errors.ts", "../src/tracks.ts", "../src/util.ts"],
4
+ "sourcesContent": ["if (typeof DocumentFragment === 'undefined') {\n class DocumentFragment {}\n // @ts-ignore\n globalThis.DocumentFragment = DocumentFragment;\n}\n\nif (!globalThis.customElements) {\n globalThis.customElements = {\n get(_name) {\n return undefined;\n },\n define(_name, _constructor, _options) {},\n upgrade(_root) {},\n whenDefined(_name) {\n return Promise.resolve(globalThis.HTMLElement);\n },\n };\n}\n\nif (!globalThis.CustomEvent) {\n class CustomEvent {\n #detail;\n get detail() {\n this.#detail;\n }\n constructor(typeArg, eventInitDict = {}) {\n // super(typeArg, eventInitDict);\n this.#detail = eventInitDict?.detail;\n }\n initCustomEvent(_typeArg, _canBubbleArg, _cancelableArg, _detailArg) {}\n }\n globalThis.CustomEvent = CustomEvent;\n}\n\nif (!globalThis.EventTarget) {\n class EventTarget {\n addEventListener() {}\n removeEventListener() {}\n dispatchEvent(_event) {\n return true;\n }\n }\n\n globalThis.EventTarget = EventTarget;\n}\n\nif (!globalThis.HTMLElement) {\n class HTMLElement extends EventTarget {}\n\n // NOTE: Adding ts-ignore since `HTMLElement` typedef is much larger than what we're stubbing. Consider more robust TypeScript solution (e.g. downstream usage)\n // @ts-ignore\n globalThis.HTMLElement = HTMLElement;\n}\n\nif (!globalThis.HTMLVideoElement) {\n class HTMLVideoElement extends EventTarget {}\n\n // NOTE: Adding ts-ignore since `HTMLVideoElement` typedef is much larger than what we're stubbing. Consider more robust TypeScript solution (e.g. downstream usage)\n // @ts-ignore\n globalThis.HTMLVideoElement = HTMLVideoElement;\n}\n\nif (!globalThis.document?.createElement) {\n const document = globalThis.document ?? {};\n (document.createElement = function createElement(_tagName, _options) {\n return new HTMLElement();\n }),\n // NOTE: Adding ts-ignore since `document` typedef is much larger than what we're stubbing. Consider more robust TypeScript solution (e.g. downstream usage)\n // @ts-ignore\n (globalThis.document = document);\n}\n", "import '@mux/polyfills';\nimport mux, { Options, ErrorEvent } from 'mux-embed';\n\nimport Hls, { HlsConfig } from 'hls.js';\nimport { AutoplayTypes, setupAutoplay } from './autoplay';\nimport { MediaError } from './errors';\nimport { setupTracks } from './tracks';\nimport { isKeyOf } from './util';\nimport type { Autoplay, UpdateAutoplay } from './autoplay';\n\nexport type ValueOf<T> = T[keyof T];\nexport type Metadata = Partial<Options['data']>;\nexport type PlaybackEngine = Hls;\nexport { mux, Hls, MediaError, Autoplay, UpdateAutoplay, setupAutoplay };\n\nconst MUX_VIDEO_DOMAIN = 'mux.com';\n\nexport const generatePlayerInitTime = () => {\n return mux.utils.now();\n};\n\nexport type StreamTypes = {\n VOD: 'on-demand';\n ON_DEMAND: 'on-demand';\n LIVE: 'live';\n LL_LIVE: 'll-live';\n DVR: 'live:dvr';\n LL_DVR: 'll-live:dvr';\n};\n\nexport const StreamTypes: StreamTypes = {\n VOD: 'on-demand',\n ON_DEMAND: 'on-demand',\n LIVE: 'live',\n LL_LIVE: 'll-live',\n DVR: 'live:dvr',\n LL_DVR: 'll-live:dvr',\n};\n\nexport type ExtensionMimeTypeMap = {\n M3U8: 'application/vnd.apple.mpegurl';\n MP4: 'video/mp4';\n};\n\nexport const ExtensionMimeTypeMap: ExtensionMimeTypeMap = {\n M3U8: 'application/vnd.apple.mpegurl',\n MP4: 'video/mp4',\n};\n\nexport type MimeTypeShorthandMap = {\n HLS: ExtensionMimeTypeMap['M3U8'];\n};\n\nexport const MimeTypeShorthandMap: MimeTypeShorthandMap = {\n HLS: ExtensionMimeTypeMap.M3U8,\n};\n\nexport const shorthandKeys = Object.keys(MimeTypeShorthandMap);\n\nexport type MediaTypes =\n | ValueOf<ExtensionMimeTypeMap>\n | keyof MimeTypeShorthandMap\n /** @TODO Figure out a way to \"downgrade\" derived types below to early TS syntax (e.g. 3.4) instead of explicit versions here (CJP) */\n | 'hls';\n// | `${Lowercase<keyof MimeTypeShorthandMap>}`\n// | `${Uppercase<keyof MimeTypeShorthandMap>}`;\n\nexport const allMediaTypes = [\n ...(Object.values(ExtensionMimeTypeMap) as ValueOf<ExtensionMimeTypeMap>[]),\n /** @TODO Figure out a way to \"downgrade\" derived types below to early TS syntax (e.g. 3.4) instead of explicit versions here (CJP) */\n 'hls',\n 'HLS',\n // ...(shorthandKeys as (keyof MimeTypeShorthandMap)[]),\n // ...(shorthandKeys.map((k) => k.toUpperCase()) as `${Uppercase<keyof MimeTypeShorthandMap>}`[]),\n // ...(shorthandKeys.map((k) => k.toLowerCase()) as `${Lowercase<keyof MimeTypeShorthandMap>}`[]),\n] as MediaTypes[];\n\nexport type MuxMediaPropTypes = {\n envKey: Options['data']['env_key'];\n debug: Options['debug'] & Hls['config']['debug'];\n metadata: Partial<Options['data']>;\n customDomain: string;\n beaconCollectionDomain: Options['beaconCollectionDomain'];\n errorTranslator: Options['errorTranslator'];\n playbackId: string;\n playerInitTime: Options['data']['player_init_time'];\n preferMse: boolean;\n type: MediaTypes;\n streamType: ValueOf<StreamTypes>;\n startTime: HlsConfig['startPosition'];\n autoPlay: boolean | ValueOf<AutoplayTypes>;\n autoplay: boolean | ValueOf<AutoplayTypes>;\n};\n\nexport type HTMLMediaElementProps = Partial<Pick<HTMLMediaElement, 'src'>>;\n\nexport type MuxMediaProps = HTMLMediaElementProps & MuxMediaPropTypes;\nexport type MuxMediaPropsInternal = MuxMediaProps & {\n playerSoftwareName: Options['data']['player_software_name'];\n playerSoftwareVersion: Options['data']['player_software_version'];\n};\n\nexport const toPlaybackIdParts = (playbackIdWithOptionalParams: string): [string, string?] => {\n const qIndex = playbackIdWithOptionalParams.indexOf('?');\n if (qIndex < 0) return [playbackIdWithOptionalParams];\n const idPart = playbackIdWithOptionalParams.slice(0, qIndex);\n const queryPart = playbackIdWithOptionalParams.slice(qIndex);\n return [idPart, queryPart];\n};\n\nexport const toMuxVideoURL = (playbackId?: string, { domain = MUX_VIDEO_DOMAIN } = {}) => {\n if (!playbackId) return undefined;\n const [idPart, queryPart = ''] = toPlaybackIdParts(playbackId);\n return `https://stream.${domain}/${idPart}.m3u8${queryPart}`;\n};\n\nexport const inferMimeTypeFromURL = (url: string) => {\n let pathname = '';\n try {\n pathname = new URL(url).pathname;\n } catch (e) {\n console.error('invalid url');\n }\n\n const extDelimIdx = pathname.lastIndexOf('.');\n if (extDelimIdx < 0) return '';\n\n const ext = pathname.slice(extDelimIdx + 1);\n const upperExt = ext.toUpperCase();\n\n return isKeyOf(upperExt, ExtensionMimeTypeMap) ? ExtensionMimeTypeMap[upperExt] : '';\n};\n\nexport const getType = (props: Partial<Pick<MuxMediaProps, 'type' | 'src'>>) => {\n const type = props.type;\n\n if (type) {\n const upperType = type.toUpperCase();\n\n return isKeyOf(upperType, MimeTypeShorthandMap) ? MimeTypeShorthandMap[upperType] : type;\n }\n\n const { src } = props;\n\n if (!src) return '';\n\n return inferMimeTypeFromURL(src);\n};\n\nexport const getStreamTypeConfig = (streamType?: ValueOf<StreamTypes>) => {\n if ([StreamTypes.LIVE, StreamTypes.LL_LIVE].includes(streamType as any)) {\n const liveConfig = {\n backBufferLength: 12,\n };\n\n if (streamType === StreamTypes.LL_LIVE) {\n return {\n ...liveConfig,\n maxFragLookUpTolerance: 0.001,\n };\n }\n\n return liveConfig;\n }\n return {};\n};\n\nlet muxMediaState: WeakMap<HTMLMediaElement, { error?: MediaError }> = new WeakMap();\n\nexport const getError = (mediaEl: HTMLMediaElement) => {\n return muxMediaState.get(mediaEl)?.error;\n};\n\nexport const teardown = (mediaEl?: HTMLMediaElement | null, hls?: Pick<Hls, 'detachMedia' | 'destroy'>) => {\n if (hls) {\n hls.detachMedia();\n hls.destroy();\n }\n if (mediaEl?.mux && !mediaEl.mux.deleted) {\n mediaEl.mux.destroy();\n mediaEl.mux;\n }\n if (mediaEl) {\n mediaEl.removeEventListener('error', handleNativeError);\n mediaEl.removeEventListener('error', handleInternalError);\n muxMediaState.delete(mediaEl);\n }\n};\n\nexport const setupHls = (\n props: Partial<Pick<MuxMediaProps, 'debug' | 'preferMse' | 'streamType' | 'type' | 'src' | 'startTime'>>,\n mediaEl?: Pick<HTMLMediaElement, 'canPlayType'> | null\n) => {\n const { debug, preferMse, streamType, startTime: startPosition = -1 } = props;\n const type = getType(props);\n const hlsType = type === ExtensionMimeTypeMap.M3U8;\n\n const canUseNative = !type || (mediaEl?.canPlayType(type) ?? true);\n const hlsSupported = Hls.isSupported();\n // NOTE: Native HLS playback on Android for LL-HLS has been flaky, so we're prefering\n // MSE for those conditions for now. (CJP)\n const userAgentStr = window?.navigator?.userAgent ?? '';\n const isAndroid = userAgentStr.toLowerCase().indexOf('android') !== -1;\n const defaultPreferMse = isAndroid && streamType === StreamTypes.LL_LIVE;\n\n // We should use native playback for hls media sources if we a) can use native playback and don't also b) prefer to use MSE/hls.js if/when it's supported\n const shouldUseNative = !hlsType || (canUseNative && !((preferMse || defaultPreferMse) && hlsSupported));\n\n // 1. if we are trying to play an hls media source create hls if we should be using it \"under the hood\"\n if (hlsType && !shouldUseNative && hlsSupported) {\n const defaultConfig = {\n backBufferLength: 30,\n renderTextTracksNatively: false,\n liveDurationInfinity: true,\n };\n const streamTypeConfig = getStreamTypeConfig(streamType);\n const hls = new Hls({\n // Kind of like preload metadata, but causes spinner.\n // autoStartLoad: false,\n debug,\n startPosition,\n ...defaultConfig,\n ...streamTypeConfig,\n });\n\n return hls;\n }\n return undefined;\n};\n\nexport const isMuxVideoSrc = ({\n playbackId,\n src,\n customDomain,\n}: Partial<Pick<MuxMediaPropsInternal, 'playbackId' | 'src' | 'customDomain'>>) => {\n if (!!playbackId) return true;\n // having no playback id and no src string should never actually happen, but could\n if (typeof src !== 'string') return false;\n const hostname = new URL(src).hostname.toLocaleLowerCase();\n return hostname.includes(MUX_VIDEO_DOMAIN) || (!!customDomain && hostname.includes(customDomain.toLocaleLowerCase()));\n};\n\nexport const setupMux = (\n props: Partial<\n Pick<\n MuxMediaPropsInternal,\n | 'envKey'\n | 'playerInitTime'\n | 'beaconCollectionDomain'\n | 'errorTranslator'\n | 'metadata'\n | 'debug'\n | 'playerSoftwareName'\n | 'playerSoftwareVersion'\n | 'playbackId'\n | 'src'\n | 'customDomain'\n >\n >,\n mediaEl?: HTMLMediaElement | null,\n hlsjs?: Hls\n) => {\n const { envKey: env_key } = props;\n const inferredEnv = isMuxVideoSrc(props);\n\n if ((env_key || inferredEnv) && mediaEl) {\n const {\n playerInitTime: player_init_time,\n playerSoftwareName: player_software_name,\n playerSoftwareVersion: player_software_version,\n beaconCollectionDomain,\n metadata,\n debug,\n } = props;\n\n const muxEmbedErrorTranslator = (error: ErrorEvent) => {\n // mux-embed auto tracks fatal hls.js errors, turn it off.\n // playback-core will emit errors with a numeric code manually to mux-embed.\n if (typeof error.player_error_code === 'string') return false;\n\n if (typeof props.errorTranslator === 'function') {\n return props.errorTranslator(error);\n }\n\n return error;\n };\n\n mux.monitor(mediaEl, {\n debug,\n beaconCollectionDomain,\n hlsjs,\n Hls: hlsjs ? Hls : undefined,\n automaticErrorTracking: false,\n errorTranslator: muxEmbedErrorTranslator,\n data: {\n ...(env_key ? { env_key } : {}),\n // Metadata fields\n player_software_name,\n player_software_version,\n player_init_time,\n // Use any metadata passed in programmatically (which may override the defaults above)\n ...metadata,\n },\n });\n }\n};\n\nexport const loadMedia = (\n props: Partial<Pick<MuxMediaProps, 'preferMse' | 'src' | 'type' | 'startTime' | 'streamType' | 'autoplay'>>,\n mediaEl?: HTMLMediaElement | null,\n hls?: Pick<\n Hls,\n | 'config'\n | 'on'\n | 'once'\n | 'startLoad'\n | 'stopLoad'\n | 'recoverMediaError'\n | 'destroy'\n | 'loadSource'\n | 'attachMedia'\n | 'liveSyncPosition'\n | 'subtitleTracks'\n | 'subtitleTrack'\n >\n) => {\n if (!mediaEl) {\n console.warn('attempting to load media before mediaEl exists');\n return;\n }\n const { preferMse, streamType } = props;\n const type = getType(props);\n const hlsType = type === ExtensionMimeTypeMap.M3U8;\n\n const canUseNative = !type || (mediaEl?.canPlayType(type) ?? true);\n const hlsSupported = Hls.isSupported();\n const userAgentStr = window?.navigator?.userAgent ?? '';\n // NOTE: Native HLS playback on Android for LL-HLS has been flaky, so we're prefering\n // MSE for those conditions for now. (CJP)\n const isAndroid = userAgentStr.toLowerCase().indexOf('android') !== -1;\n const defaultPreferMse = isAndroid && streamType === StreamTypes.LL_LIVE;\n\n // We should use native playback for hls media sources if we a) can use native playback and don't also b) prefer to use MSE/hls.js if/when it's supported\n const shouldUseNative = !hlsType || (canUseNative && !((preferMse || defaultPreferMse) && hlsSupported));\n\n const { src } = props;\n if (mediaEl && canUseNative && shouldUseNative) {\n if (typeof src === 'string') {\n const { startTime } = props;\n mediaEl.setAttribute('src', src);\n if (startTime) {\n const setStartTimeOnLoad = ({ target }: HTMLMediaElementEventMap['loadedmetadata']) => {\n (target as HTMLMediaElement).currentTime = startTime;\n (target as HTMLMediaElement).removeEventListener('loadedmetadata', setStartTimeOnLoad);\n };\n\n mediaEl.addEventListener('loadedmetadata', setStartTimeOnLoad);\n }\n } else {\n mediaEl.removeAttribute('src');\n }\n\n mediaEl.addEventListener('error', handleNativeError);\n mediaEl.addEventListener('error', handleInternalError);\n } else if (hls && src) {\n hls.on(Hls.Events.ERROR, (_event, data) => {\n // if (data.fatal) {\n // switch (data.type) {\n // case Hls.ErrorTypes.NETWORK_ERROR:\n // // try to recover network error\n // console.error(\"fatal network error encountered, try to recover\");\n // hls.startLoad();\n // break;\n // case Hls.ErrorTypes.MEDIA_ERROR:\n // console.error(\"fatal media error encountered, try to recover\");\n // hls.recoverMediaError();\n // break;\n // default:\n // // cannot recover\n // console.error(\n // \"unrecoverable fatal error encountered, cannot recover (check logs for more info)\"\n // );\n // hls.destroy();\n // break;\n // }\n // }\n\n const errorCodeMap: Record<string, number> = {\n [Hls.ErrorTypes.NETWORK_ERROR]: MediaError.MEDIA_ERR_NETWORK,\n [Hls.ErrorTypes.MEDIA_ERROR]: MediaError.MEDIA_ERR_DECODE,\n };\n const error = new MediaError('', errorCodeMap[data.type]);\n error.fatal = data.fatal;\n error.data = data;\n mediaEl.dispatchEvent(\n new CustomEvent('error', {\n detail: error,\n })\n );\n });\n mediaEl.addEventListener('error', handleInternalError);\n\n setupTracks(mediaEl, hls);\n\n switch (mediaEl.preload) {\n case 'none':\n // when preload is none, load the source on first play\n mediaEl.addEventListener('play', () => hls.loadSource(src), { once: true });\n break;\n\n case 'metadata':\n const originalLength = hls.config.maxBufferLength;\n const originalSize = hls.config.maxBufferSize;\n\n // load the least amount of data possible\n hls.config.maxBufferLength = 1;\n hls.config.maxBufferSize = 1;\n // and once a user has player, allow for it to load data as normal\n mediaEl.addEventListener(\n 'play',\n () => {\n hls.config.maxBufferLength = originalLength;\n hls.config.maxBufferSize = originalSize;\n },\n { once: true }\n );\n hls.loadSource(src);\n break;\n\n default:\n // load source immediately for any other preload value\n hls.loadSource(src);\n }\n\n hls.attachMedia(mediaEl);\n } else {\n console.error(\n \"It looks like the video you're trying to play will not work on this system! If possible, try upgrading to the newest versions of your browser or software.\"\n );\n }\n};\n\nasync function handleNativeError(event: Event) {\n // Return if the event was created or modified by a script or dispatched\n // via EventTarget.dispatchEvent() preventing an infinite loop.\n if (!event.isTrusted) return;\n\n // Stop immediate propagation of the native error event, re-dispatch below!\n event.stopImmediatePropagation();\n\n const mediaEl = event.target as HTMLMediaElement;\n // Safari sometimes throws an error event with a null error.\n if (!mediaEl?.error) return;\n\n const { message, code } = mediaEl.error;\n const error = new MediaError(message, code);\n\n if (mediaEl.src && (code !== MediaError.MEDIA_ERR_DECODE || code !== undefined)) {\n // Attempt to get the response code from the video src url.\n const { status } = await fetch(mediaEl.src as RequestInfo);\n // Use the same hls.js data structure.\n error.data = { response: { code: status } };\n }\n\n mediaEl.dispatchEvent(\n new CustomEvent('error', {\n detail: error,\n })\n );\n}\n\n/**\n * Use a event listener instead of a function call when dispatching the Custom error\n * event so consumers are still able to disable or intercept this error event.\n * @param {Event} event\n */\nfunction handleInternalError(event: Event) {\n if (!(event instanceof CustomEvent) || !(event.detail instanceof MediaError)) return;\n\n const mediaEl = event.target as HTMLMediaElement;\n const error = event.detail;\n // Prevent tracking non-fatal errors in Mux data.\n if (!error || !error.fatal) return;\n\n const state = muxMediaState.get(mediaEl);\n if (state) state.error = error;\n\n // Only pass valid mux-embed props: player_error_code, player_error_message\n mediaEl.mux?.emit('error', {\n player_error_code: error.code,\n player_error_message: error.message,\n });\n}\n\nexport const initialize = (props: Partial<MuxMediaPropsInternal>, mediaEl?: HTMLMediaElement | null, hls?: Hls) => {\n // Automatically tear down previously initialized mux data & hls instance if it exists.\n teardown(mediaEl, hls);\n muxMediaState.set(mediaEl as HTMLMediaElement, {});\n const nextHlsInstance = setupHls(props, mediaEl);\n setupMux(props, mediaEl, nextHlsInstance);\n loadMedia(props, mediaEl, nextHlsInstance);\n return nextHlsInstance;\n};\n", "import Hls from 'hls.js';\n\ntype PlaybackEngine = Hls;\n\n// TODO add INVIEW_MUTED, INVIEW_ANY\nexport type AutoplayTypes = {\n ANY: 'any';\n MUTED: 'muted';\n};\n\nexport const AutoplayTypes: AutoplayTypes = {\n ANY: 'any',\n MUTED: 'muted',\n};\n\ntype ValueOf<T> = T[keyof T];\ntype Maybe<T> = T | null | undefined;\nexport type Autoplay = boolean | ValueOf<AutoplayTypes>;\nexport type UpdateAutoplay = (newAutoplay: Maybe<string | boolean>) => void;\n\nconst AutoplayTypeValues = Object.values(AutoplayTypes);\nexport const isAutoplayValue = (value: unknown): value is Autoplay => {\n return (\n typeof value === 'boolean' ||\n (typeof value === 'string' && AutoplayTypeValues.includes(value as ValueOf<AutoplayTypes>))\n );\n};\n\n// Given a video element, will listen to lifecycle events to determine important\n// things like whether the video is live or whether the video has played\n// and then handles autoplaying the video as appropraite.\n// It works with both the native video element or hls.js.\n// This returns a method UpdateAutoplay, that allows the user to change\n// the value of the autoplay attribute and it will react appropriately.\nexport const setupAutoplay = (\n mediaEl: HTMLMediaElement,\n maybeAutoplay: Maybe<string | boolean>,\n hls: PlaybackEngine | undefined\n) => {\n let hasPlayed = false;\n let isLive = false;\n let autoplay: Autoplay = isAutoplayValue(maybeAutoplay) ? maybeAutoplay : !!maybeAutoplay;\n\n const updateHasPlayed = () => {\n // hasPlayed\n mediaEl.addEventListener(\n 'playing',\n () => {\n hasPlayed = true;\n },\n { once: true }\n );\n };\n\n updateHasPlayed();\n\n // on `loadstart`\n // hasPlayed should default to false\n // we should try and autoplay\n mediaEl.addEventListener(\n 'loadstart',\n () => {\n hasPlayed = false;\n updateHasPlayed();\n handleAutoplay(mediaEl, autoplay);\n },\n { once: true }\n );\n\n // on `loadedmetadata` we can check whether we're live in the case of native playback\n mediaEl.addEventListener(\n 'loadedmetadata',\n () => {\n // only update isLive here if we're using native playback\n if (!hls) {\n isLive = !Number.isFinite(mediaEl.duration);\n }\n handleAutoplay(mediaEl, autoplay);\n },\n { once: true }\n );\n\n // determine if we're live for hls.js\n if (hls) {\n hls.once(Hls.Events.LEVEL_LOADED, (e: any, data: any) => {\n isLive = data.details.live ?? false;\n });\n }\n\n // When we are not auto-playing, we should seek to the live sync position\n // This will seek first play event of *any* live video including event-type,\n // which probably shouldn't seek\n if (!autoplay) {\n const handleSeek = () => {\n // don't seek if we're not live\n if (!isLive) {\n return;\n }\n // seek to either hls.js's liveSyncPosition or the native seekable end\n if (hls?.liveSyncPosition) {\n mediaEl.currentTime = hls.liveSyncPosition;\n } else {\n if (Number.isFinite(mediaEl.seekable.end(0))) {\n mediaEl.currentTime = mediaEl.seekable.end(0);\n }\n }\n };\n mediaEl.addEventListener(\n 'play',\n () => {\n if (hls && mediaEl.preload === 'metadata') {\n hls.once(Hls.Events.LEVEL_UPDATED, handleSeek);\n } else if (hls) {\n handleSeek();\n }\n },\n { once: true }\n );\n }\n\n // this method allows us to update the value of autoplay\n // and try autoplaying appropriately.\n const updateAutoplay: UpdateAutoplay = (newAutoplay) => {\n if (!hasPlayed) {\n autoplay = isAutoplayValue(newAutoplay) ? newAutoplay : !!newAutoplay;\n handleAutoplay(mediaEl, autoplay);\n }\n };\n\n return updateAutoplay;\n};\n\nexport const handleAutoplay = (mediaEl: HTMLMediaElement, autoplay: Autoplay) => {\n if (!autoplay) {\n return;\n }\n\n const oldMuted = mediaEl.muted;\n const restoreMuted = () => (mediaEl.muted = oldMuted);\n\n switch (autoplay) {\n // ANY:\n // try to play with current options\n // if it fails, mute and try playing again\n // if that fails, restore muted state and don't try playing again\n case AutoplayTypes.ANY:\n mediaEl.play().catch((error: Error) => {\n mediaEl.muted = true;\n mediaEl.play().catch(restoreMuted);\n });\n break;\n\n // MUTED:\n // mute the player and then try playing\n // if that fails, restore muted state\n case AutoplayTypes.MUTED:\n mediaEl.muted = true;\n mediaEl.play().catch(restoreMuted);\n break;\n\n // Default or if autoplay is a boolean attribute:\n // Try playing the video and catch the failed autoplay warning\n default:\n mediaEl.play().catch(() => {});\n break;\n }\n};\n", "export class MediaError extends Error {\n static MEDIA_ERR_ABORTED: number = 1;\n static MEDIA_ERR_NETWORK: number = 2;\n static MEDIA_ERR_DECODE: number = 3;\n static MEDIA_ERR_SRC_NOT_SUPPORTED: number = 4;\n static MEDIA_ERR_ENCRYPTED: number = 5;\n // @see https://docs.mux.com/guides/data/monitor-html5-video-element#customize-error-tracking-behavior\n static MEDIA_ERR_CUSTOM: number = 100;\n\n static defaultMessages: Record<number, string> = {\n 1: 'You aborted the media playback',\n 2: 'A network error caused the media download to fail.',\n 3: 'A media error caused playback to be aborted. The media could be corrupt or your browser does not support this format.',\n 4: 'An unsupported error occurred. The server or network failed, or your browser does not support this format.',\n 5: 'The media is encrypted and there are no keys to decrypt it.',\n };\n\n name: string;\n code: number;\n fatal: boolean;\n data?: any;\n\n constructor(message?: string, code: number = MediaError.MEDIA_ERR_CUSTOM, fatal?: boolean) {\n super(message);\n this.name = 'MediaError';\n this.code = code;\n this.fatal = fatal ?? (code >= MediaError.MEDIA_ERR_NETWORK && code <= MediaError.MEDIA_ERR_ENCRYPTED);\n\n if (!this.message) {\n this.message = MediaError.defaultMessages[this.code] ?? '';\n }\n }\n}\n", "import Hls from 'hls.js';\nimport type { MediaPlaylist } from 'hls.js';\n\nexport function setupTracks(\n mediaEl: HTMLMediaElement,\n hls: Pick<Hls, 'on' | 'once' | 'subtitleTracks' | 'subtitleTrack'>\n) {\n hls.on(Hls.Events.NON_NATIVE_TEXT_TRACKS_FOUND, (_type, { tracks }) => {\n tracks.forEach((trackObj) => {\n const baseTrackObj = trackObj.subtitleTrack ?? trackObj.closedCaptions;\n const idx = hls.subtitleTracks.findIndex(({ lang, name, type }) => {\n return lang == baseTrackObj?.lang && name === trackObj.label && type.toLowerCase() === trackObj.kind;\n });\n\n createTextTrack(\n mediaEl,\n trackObj.kind as TextTrackKind,\n trackObj.label,\n baseTrackObj?.lang,\n `${trackObj.kind}${idx}`\n );\n });\n });\n\n const changeHandler = () => {\n if (!hls.subtitleTracks.length) return;\n\n const showingTrack = Array.from(mediaEl.textTracks).find((textTrack) => {\n return textTrack.id && textTrack.mode === 'showing' && ['subtitles', 'captions'].includes(textTrack.kind);\n });\n\n // If hls.subtitleTrack is -1 or its id changed compared to the one that is showing load the new subtitle track.\n const hlsTrackId = `${hls.subtitleTracks[hls.subtitleTrack]?.type.toLowerCase()}${hls.subtitleTrack}`;\n if (showingTrack && (hls.subtitleTrack < 0 || showingTrack?.id !== hlsTrackId)) {\n const idx = hls.subtitleTracks.findIndex(({ lang, name, type }) => {\n return lang == showingTrack.language && name === showingTrack.label && type.toLowerCase() === showingTrack.kind;\n });\n // After the subtitleTrack is set here, hls.js will load the playlist and CUES_PARSED events will be fired below.\n hls.subtitleTrack = idx;\n }\n\n if (showingTrack && showingTrack?.id === hlsTrackId) {\n // Refresh the cues after a texttrack mode change to fix a Chrome bug causing the captions not to render.\n if (showingTrack.cues) {\n Array.from(showingTrack.cues).forEach((cue) => {\n showingTrack.addCue(cue);\n });\n }\n }\n };\n\n mediaEl.textTracks.addEventListener('change', changeHandler);\n\n hls.on(Hls.Events.CUES_PARSED, (_type, { track, type, cues }) => {\n const textTrack = mediaEl.textTracks.getTrackById(track);\n if (!textTrack) return;\n\n const disabled = textTrack.mode === 'disabled';\n if (disabled) {\n textTrack.mode = 'hidden';\n }\n\n cues.forEach((cue: VTTCue) => {\n if (textTrack.cues?.getCueById(cue.id)) return;\n textTrack.addCue(cue);\n });\n\n if (disabled) {\n textTrack.mode = 'disabled';\n }\n });\n\n hls.on(Hls.Events.DESTROYING, () => {\n mediaEl.textTracks.removeEventListener('change', changeHandler);\n\n const trackEls = mediaEl.querySelectorAll('track');\n trackEls.forEach((trackEl) => {\n if (!(trackEl.id && ['subtitles', 'captions'].includes(trackEl.kind))) return;\n if (!hls.subtitleTracks.some(({ type }, idx) => trackEl.id === `${type.toLowerCase()}${idx}`)) return;\n\n mediaEl.removeChild(trackEl);\n });\n });\n\n const forceHiddenThumbnails = () => {\n // Keeping this a forEach in case we want to expand the scope of this.\n Array.from(mediaEl.textTracks).forEach((track) => {\n if (['subtitles', 'caption'].includes(track.kind)) return;\n if (track.label !== 'thumbnails') return;\n if (!track.cues?.length) {\n const trackEl = mediaEl.querySelector('track[label=\"thumbnails\"]');\n // Force a reload of the cues if they've been removed\n const src = trackEl?.getAttribute('src') ?? '';\n trackEl?.removeAttribute('src');\n setTimeout(() => {\n trackEl?.setAttribute('src', src);\n }, 0);\n }\n // Force hidden mode if it's not hidden\n if (track.mode !== 'hidden') {\n track.mode = 'hidden';\n }\n });\n };\n\n // hls.js will forcibly clear all cues from tracks on manifest loads or media attaches.\n // This ensures that we re-load them after it's done that.\n hls.once(Hls.Events.MANIFEST_LOADED, forceHiddenThumbnails);\n hls.once(Hls.Events.MEDIA_ATTACHED, forceHiddenThumbnails);\n}\n\nfunction createTextTrack(\n mediaEl: HTMLMediaElement,\n kind: TextTrackKind,\n label: string,\n lang?: string,\n id?: string\n): TextTrack | undefined {\n const trackEl = document.createElement('track');\n trackEl.kind = kind;\n trackEl.label = label;\n if (lang) {\n // This attribute must be present if the element's kind attribute is in the subtitles state.\n trackEl.srclang = lang;\n }\n if (id) {\n trackEl.id = id;\n }\n trackEl.track.mode = 'disabled';\n mediaEl.appendChild(trackEl);\n return trackEl.track;\n}\n", "type KeyTypes = string | number | symbol;\n\n// Type Guard to determine if a given key is actually a key of some object of type T\nexport const isKeyOf = <T = any>(k: KeyTypes, o: T): k is keyof T => {\n return k in o;\n};\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }