@mux/playback-core 0.8.1-canary.7-b1efffb → 0.9.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.
- package/CHANGELOG.md +7 -0
- package/LICENSE +9 -0
- package/dist/index.cjs.js +1 -1
- package/dist/index.cjs.js.map +2 -2
- package/dist/index.mjs +1 -1
- package/dist/index.mjs.map +2 -2
- package/dist/playback-core.js +3 -3
- package/dist/playback-core.js.map +2 -2
- package/dist/playback-core.mjs +3 -3
- package/dist/playback-core.mjs.map +2 -2
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/types/index.d.ts +2 -1
- package/dist/types/tracks.d.ts +2 -0
- package/dist/types-ts3.4/index.d.ts +2 -1
- package/dist/types-ts3.4/tracks.d.ts +2 -0
- package/package.json +3 -2
- package/src/index.ts +2 -2
- package/src/tracks.ts +16 -9
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,13 @@
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
5
|
|
|
6
|
+
# [0.9.0](https://github.com/muxinc/elements/compare/@mux/playback-core@0.8.0...@mux/playback-core@0.9.0) (2022-07-21)
|
|
7
|
+
|
|
8
|
+
### Features
|
|
9
|
+
|
|
10
|
+
- **playback-core, mux-player:** Add support to removeTextTrack. Remove all identified tracks on hls destroy. Add methods to mux-player. ([d090b06](https://github.com/muxinc/elements/commit/d090b060a8b8b3772e74762176af9881299bf894))
|
|
11
|
+
- **playback-core:** prefer remove() and append() for elements. ([90bbbcb](https://github.com/muxinc/elements/commit/90bbbcbccf74bc30be56ad8c84b3db1d00ab6665))
|
|
12
|
+
|
|
6
13
|
# 0.8.0 (2022-07-05)
|
|
7
14
|
|
|
8
15
|
### Bug Fixes
|
package/LICENSE
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2021 Mux, Inc.
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
6
|
+
|
|
7
|
+
The above copyright notice and this permission notice (including the next paragraph) shall be included in all copies or substantial portions of the Software.
|
|
8
|
+
|
|
9
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
package/dist/index.cjs.js
CHANGED
|
@@ -1,2 +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};
|
|
1
|
+
var ie=Object.create;var h=Object.defineProperty;var ce=Object.getOwnPropertyDescriptor;var ue=Object.getOwnPropertyNames;var le=Object.getPrototypeOf,de=Object.prototype.hasOwnProperty;var K=e=>h(e,"__esModule",{value:!0});var pe=(e,t)=>{K(e);for(var r in t)h(e,r,{get:t[r],enumerable:!0})},ye=(e,t,r)=>{if(t&&typeof t=="object"||typeof t=="function")for(let n of ue(t))!de.call(e,n)&&n!=="default"&&h(e,n,{get:()=>t[n],enumerable:!(r=ce(t,n))||r.enumerable});return e},P=e=>ye(K(h(e!=null?ie(le(e)):{},"default",e&&e.__esModule&&"default"in e?{get:()=>e.default,enumerable:!0}:{value:e,enumerable:!0})),e);var B=(e,t,r)=>{if(!t.has(e))throw TypeError("Cannot "+r)};var F=(e,t,r)=>(B(e,t,"read from private field"),r?r.call(e):t.get(e)),q=(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)},Y=(e,t,r,n)=>(B(e,t,"write to private field"),n?n.call(e,r):t.set(e,r),r);pe(exports,{ExtensionMimeTypeMap:()=>g,Hls:()=>T.default,MediaError:()=>u,MimeTypeShorthandMap:()=>R,StreamTypes:()=>L,addTextTrack:()=>C,allMediaTypes:()=>Me,generatePlayerInitTime:()=>Te,getError:()=>Ee,getStreamTypeConfig:()=>ee,getType:()=>N,inferMimeTypeFromURL:()=>j,initialize:()=>xe,isMuxVideoSrc:()=>ne,loadMedia:()=>ae,mux:()=>D.default,removeTextTrack:()=>J,setupAutoplay:()=>X,setupHls:()=>re,setupMux:()=>oe,shorthandKeys:()=>me,teardown:()=>te,toMuxVideoURL:()=>ge,toPlaybackIdParts:()=>Z});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 k;if(!globalThis.CustomEvent){class e{constructor(r,n={}){q(this,k,void 0);Y(this,k,n==null?void 0:n.detail)}get detail(){F(this,k)}initCustomEvent(r,n,o,a){}}k=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 $,z;if(!(($=globalThis.document)==null?void 0:$.createElement)){let e=(z=globalThis.document)!=null?z:{};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"},fe=Object.values(I),W=e=>typeof e=="boolean"||typeof e=="string"&&fe.includes(e),X=(e,t,r)=>{let n=!1,o=!1,a=W(t)?t:!!t,c=()=>{e.addEventListener("playing",()=>{n=!0},{once:!0})};if(c(),e.addEventListener("loadstart",()=>{n=!1,c(),O(e,a)},{once:!0}),e.addEventListener("loadedmetadata",()=>{r||(o=!Number.isFinite(e.duration)),O(e,a)},{once:!0}),r&&r.once(w.default.Events.LEVEL_LOADED,(i,l)=>{var d;o=(d=l.details.live)!=null?d:!1}),!a){let i=()=>{!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,i):r&&i()},{once:!0})}return i=>{n||(a=W(i)?i:!!i,O(e,a))}},O=(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:"")}},u=E;u.MEDIA_ERR_ABORTED=1,u.MEDIA_ERR_NETWORK=2,u.MEDIA_ERR_DECODE=3,u.MEDIA_ERR_SRC_NOT_SUPPORTED=4,u.MEDIA_ERR_ENCRYPTED=5,u.MEDIA_ERR_CUSTOM=100,u.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 G(e,t){t.on(x.default.Events.NON_NATIVE_TEXT_TRACKS_FOUND,(o,{tracks:a})=>{a.forEach(c=>{var l;let s=(l=c.subtitleTrack)!=null?l:c.closedCaptions,i=t.subtitleTracks.findIndex(({lang:d,name:y,type:f})=>d==(s==null?void 0:s.lang)&&y===c.label&&f.toLowerCase()===c.kind);C(e,c.kind,c.label,s==null?void 0:s.lang,`${c.kind}${i}`)})});let r=()=>{var c;if(!t.subtitleTracks.length)return;let o=Array.from(e.textTracks).find(s=>s.id&&s.mode==="showing"&&["subtitles","captions"].includes(s.kind)),a=`${(c=t.subtitleTracks[t.subtitleTrack])==null?void 0:c.type.toLowerCase()}${t.subtitleTrack}`;if(o&&(t.subtitleTrack<0||(o==null?void 0:o.id)!==a)){let s=t.subtitleTracks.findIndex(({lang:i,name:l,type:d})=>i==o.language&&l===o.label&&d.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:c,cues:s})=>{let i=e.textTracks.getTrackById(a);if(!i)return;let l=i.mode==="disabled";l&&(i.mode="hidden"),s.forEach(d=>{var y;((y=i.cues)==null?void 0:y.getCueById(d.id))||i.addCue(d)}),l&&(i.mode="disabled")}),t.on(x.default.Events.DESTROYING,()=>{e.textTracks.removeEventListener("change",r),e.querySelectorAll("track[data-removeondestroy]").forEach(a=>{a.remove()})});let n=()=>{Array.from(e.textTracks).forEach(o=>{var a,c;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"]'),i=(c=s==null?void 0:s.getAttribute("src"))!=null?c:"";s==null||s.removeAttribute("src"),setTimeout(()=>{s==null||s.setAttribute("src",i)},0)}o.mode!=="hidden"&&(o.mode="hidden")}})};t.once(x.default.Events.MANIFEST_LOADED,n),t.once(x.default.Events.MEDIA_ATTACHED,n)}function C(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",a.setAttribute("data-removeondestroy",""),e.append(a),a.track}function J(e,t){let r=Array.prototype.find.call(e.querySelectorAll("track"),n=>n.track===t);r==null||r.remove()}var V=(e,t)=>e in t;var Q="mux.com",Te=()=>D.default.utils.now(),L={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},me=Object.keys(R),Me=[...Object.values(g),"hls","HLS"],Z=e=>{let t=e.indexOf("?");if(t<0)return[e];let r=e.slice(0,t),n=e.slice(t);return[r,n]},ge=(e,{domain:t=Q}={})=>{if(!e)return;let[r,n=""]=Z(e);return`https://stream.${t}/${r}.m3u8${n}`},j=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 V(o,g)?g[o]:""},N=e=>{let t=e.type;if(t){let n=t.toUpperCase();return V(n,R)?R[n]:t}let{src:r}=e;return r?j(r):""},ee=e=>{if([L.LIVE,L.LL_LIVE].includes(e)){let t={backBufferLength:12};return e===L.LL_LIVE?{...t,maxFragLookUpTolerance:.001}:t}return{}},H=new WeakMap,Ee=e=>{var t;return(t=H.get(e))==null?void 0:t.error},te=(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",se),e.removeEventListener("error",U),H.delete(e))},re=(e,t)=>{var b,v,A;let{debug:r,preferMse:n,streamType:o,startTime:a=-1}=e,c=N(e),s=c===g.M3U8,i=!c||((b=t==null?void 0:t.canPlayType(c))!=null?b:!0),l=T.default.isSupported(),f=((A=(v=window==null?void 0:window.navigator)==null?void 0:v.userAgent)!=null?A:"").toLowerCase().indexOf("android")!==-1&&o===L.LL_LIVE;if(s&&!(!s||i&&!((n||f)&&l))&&l){let M={backBufferLength:30,renderTextTracksNatively:!1,liveDurationInfinity:!0},p=ee(o);return new T.default({debug:r,startPosition:a,...M,...p})}},ne=({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(Q)||!!r&&n.includes(r.toLocaleLowerCase())},oe=(e,t,r)=>{let{envKey:n}=e,o=ne(e);if((n||o)&&t){let{playerInitTime:a,playerSoftwareName:c,playerSoftwareVersion:s,beaconCollectionDomain:i,metadata:l,debug:d}=e,y=f=>typeof f.player_error_code=="string"?!1:typeof e.errorTranslator=="function"?e.errorTranslator(f):f;D.default.monitor(t,{debug:d,beaconCollectionDomain:i,hlsjs:r,Hls:r?T.default:void 0,automaticErrorTracking:!1,errorTranslator:y,data:{...n?{env_key:n}:{},player_software_name:c,player_software_version:s,player_init_time:a,...l}})}},ae=(e,t,r)=>{var b,v,A;if(!t){console.warn("attempting to load media before mediaEl exists");return}let{preferMse:n,streamType:o}=e,a=N(e),c=a===g.M3U8,s=!a||((b=t==null?void 0:t.canPlayType(a))!=null?b:!0),i=T.default.isSupported(),y=((A=(v=window==null?void 0:window.navigator)==null?void 0:v.userAgent)!=null?A:"").toLowerCase().indexOf("android")!==-1&&o===L.LL_LIVE,f=!c||s&&!((n||y)&&i),{src:m}=e;if(t&&s&&f){if(typeof m=="string"){let{startTime:M}=e;if(t.setAttribute("src",m),M){let p=({target:_})=>{_.currentTime=M,_.removeEventListener("loadedmetadata",p)};t.addEventListener("loadedmetadata",p)}}else t.removeAttribute("src");t.addEventListener("error",se),t.addEventListener("error",U)}else if(r&&m){switch(r.on(T.default.Events.ERROR,(M,p)=>{let _={[T.default.ErrorTypes.NETWORK_ERROR]:u.MEDIA_ERR_NETWORK,[T.default.ErrorTypes.MEDIA_ERROR]:u.MEDIA_ERR_DECODE},S=new u("",_[p.type]);S.fatal=p.fatal,S.data=p,t.dispatchEvent(new CustomEvent("error",{detail:S}))}),t.addEventListener("error",U),G(t,r),t.preload){case"none":t.addEventListener("play",()=>r.loadSource(m),{once:!0});break;case"metadata":let M=r.config.maxBufferLength,p=r.config.maxBufferSize;r.config.maxBufferLength=1,r.config.maxBufferSize=1,t.addEventListener("play",()=>{r.config.maxBufferLength=M,r.config.maxBufferSize=p},{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 se(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 u(r,n);if(t.src&&(n!==u.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 U(e){var o;if(!(e instanceof CustomEvent)||!(e.detail instanceof u))return;let t=e.target,r=e.detail;if(!r||!r.fatal)return;let n=H.get(t);n&&(n.error=r),(o=t.mux)==null||o.emit("error",{player_error_code:r.code,player_error_message:r.message})}var xe=(e,t,r)=>{te(t,r),H.set(t,{});let n=re(e,t);return oe(e,t,n),ae(e,t,n),n};
|
|
2
2
|
//# sourceMappingURL=index.cjs.js.map
|
package/dist/index.cjs.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
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": "m7BAAA,
|
|
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, addTextTrack, removeTextTrack } 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, addTextTrack, removeTextTrack };\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';\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 addTextTrack(\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 // Use data attribute to identify tracks that should be removed when switching sources/destroying hls.js instance.\n const trackEls: NodeListOf<HTMLTrackElement> = mediaEl.querySelectorAll('track[data-removeondestroy]');\n trackEls.forEach((trackEl) => {\n trackEl.remove();\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\nexport function addTextTrack(\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 // Add data attribute to identify tracks that should be removed when switching sources/destroying hls.js instance.\n trackEl.setAttribute('data-removeondestroy', '');\n mediaEl.append(trackEl);\n return trackEl.track;\n}\n\nexport function removeTextTrack(mediaEl: HTMLMediaElement, track: TextTrack) {\n const trackEl: HTMLTrackElement | undefined = Array.prototype.find.call(\n mediaEl.querySelectorAll('track'),\n (trackEl: HTMLTrackElement) => trackEl.track === track\n );\n trackEl?.remove();\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
6
|
"names": []
|
|
7
7
|
}
|
package/dist/index.mjs
CHANGED
|
@@ -1,2 +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};
|
|
1
|
+
var I=(e,t,r)=>{if(!t.has(e))throw TypeError("Cannot "+r)};var O=(e,t,r)=>(I(e,t,"read from private field"),r?r.call(e):t.get(e)),C=(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 A;if(!globalThis.CustomEvent){class e{constructor(r,n={}){C(this,A,void 0);V(this,A,n==null?void 0:n.detail)}get detail(){O(this,A)}initCustomEvent(r,n,o,a){}}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 Y from"mux-embed";import M from"hls.js";import K from"hls.js";var D={ANY:"any",MUTED:"muted"},X=Object.values(D),B=e=>typeof e=="boolean"||typeof e=="string"&&X.includes(e),G=(e,t,r)=>{let n=!1,o=!1,a=B(t)?t:!!t,c=()=>{e.addEventListener("playing",()=>{n=!0},{once:!0})};if(c(),e.addEventListener("loadstart",()=>{n=!1,c(),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,(i,u)=>{var d;o=(d=u.details.live)!=null?d:!1}),!a){let i=()=>{!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,i):r&&i()},{once:!0})}return i=>{n||(a=B(i)?i:!!i,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 _ from"hls.js";function F(e,t){t.on(_.Events.NON_NATIVE_TEXT_TRACKS_FOUND,(o,{tracks:a})=>{a.forEach(c=>{var u;let s=(u=c.subtitleTrack)!=null?u:c.closedCaptions,i=t.subtitleTracks.findIndex(({lang:d,name:y,type:f})=>d==(s==null?void 0:s.lang)&&y===c.label&&f.toLowerCase()===c.kind);q(e,c.kind,c.label,s==null?void 0:s.lang,`${c.kind}${i}`)})});let r=()=>{var c;if(!t.subtitleTracks.length)return;let o=Array.from(e.textTracks).find(s=>s.id&&s.mode==="showing"&&["subtitles","captions"].includes(s.kind)),a=`${(c=t.subtitleTracks[t.subtitleTrack])==null?void 0:c.type.toLowerCase()}${t.subtitleTrack}`;if(o&&(t.subtitleTrack<0||(o==null?void 0:o.id)!==a)){let s=t.subtitleTracks.findIndex(({lang:i,name:u,type:d})=>i==o.language&&u===o.label&&d.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(_.Events.CUES_PARSED,(o,{track:a,type:c,cues:s})=>{let i=e.textTracks.getTrackById(a);if(!i)return;let u=i.mode==="disabled";u&&(i.mode="hidden"),s.forEach(d=>{var y;((y=i.cues)==null?void 0:y.getCueById(d.id))||i.addCue(d)}),u&&(i.mode="disabled")}),t.on(_.Events.DESTROYING,()=>{e.textTracks.removeEventListener("change",r),e.querySelectorAll("track[data-removeondestroy]").forEach(a=>{a.remove()})});let n=()=>{Array.from(e.textTracks).forEach(o=>{var a,c;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"]'),i=(c=s==null?void 0:s.getAttribute("src"))!=null?c:"";s==null||s.removeAttribute("src"),setTimeout(()=>{s==null||s.setAttribute("src",i)},0)}o.mode!=="hidden"&&(o.mode="hidden")}})};t.once(_.Events.MANIFEST_LOADED,n),t.once(_.Events.MEDIA_ATTACHED,n)}function q(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",a.setAttribute("data-removeondestroy",""),e.append(a),a.track}function J(e,t){let r=Array.prototype.find.call(e.querySelectorAll("track"),n=>n.track===t);r==null||r.remove()}var H=(e,t)=>e in t;var $="mux.com",ke=()=>Y.utils.now(),k={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"},S={HLS:E.M3U8},he=Object.keys(S),Pe=[...Object.values(E),"hls","HLS"],Q=e=>{let t=e.indexOf("?");if(t<0)return[e];let r=e.slice(0,t),n=e.slice(t);return[r,n]},De=(e,{domain:t=$}={})=>{if(!e)return;let[r,n=""]=Q(e);return`https://stream.${t}/${r}.m3u8${n}`},Z=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 H(o,E)?E[o]:""},z=e=>{let t=e.type;if(t){let n=t.toUpperCase();return H(n,S)?S[n]:t}let{src:r}=e;return r?Z(r):""},j=e=>{if([k.LIVE,k.LL_LIVE].includes(e)){let t={backBufferLength:12};return e===k.LL_LIVE?{...t,maxFragLookUpTolerance:.001}:t}return{}},h=new WeakMap,Re=e=>{var t;return(t=h.get(e))==null?void 0:t.error},ee=(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",W),e.removeEventListener("error",w),h.delete(e))},te=(e,t)=>{var x,L,b;let{debug:r,preferMse:n,streamType:o,startTime:a=-1}=e,c=z(e),s=c===E.M3U8,i=!c||((x=t==null?void 0:t.canPlayType(c))!=null?x:!0),u=M.isSupported(),f=((b=(L=window==null?void 0:window.navigator)==null?void 0:L.userAgent)!=null?b:"").toLowerCase().indexOf("android")!==-1&&o===k.LL_LIVE;if(s&&!(!s||i&&!((n||f)&&u))&&u){let m={backBufferLength:30,renderTextTracksNatively:!1,liveDurationInfinity:!0},p=j(o);return new M({debug:r,startPosition:a,...m,...p})}},re=({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($)||!!r&&n.includes(r.toLocaleLowerCase())},ne=(e,t,r)=>{let{envKey:n}=e,o=re(e);if((n||o)&&t){let{playerInitTime:a,playerSoftwareName:c,playerSoftwareVersion:s,beaconCollectionDomain:i,metadata:u,debug:d}=e,y=f=>typeof f.player_error_code=="string"?!1:typeof e.errorTranslator=="function"?e.errorTranslator(f):f;Y.monitor(t,{debug:d,beaconCollectionDomain:i,hlsjs:r,Hls:r?M:void 0,automaticErrorTracking:!1,errorTranslator:y,data:{...n?{env_key:n}:{},player_software_name:c,player_software_version:s,player_init_time:a,...u}})}},oe=(e,t,r)=>{var x,L,b;if(!t){console.warn("attempting to load media before mediaEl exists");return}let{preferMse:n,streamType:o}=e,a=z(e),c=a===E.M3U8,s=!a||((x=t==null?void 0:t.canPlayType(a))!=null?x:!0),i=M.isSupported(),y=((b=(L=window==null?void 0:window.navigator)==null?void 0:L.userAgent)!=null?b:"").toLowerCase().indexOf("android")!==-1&&o===k.LL_LIVE,f=!c||s&&!((n||y)&&i),{src:T}=e;if(t&&s&&f){if(typeof T=="string"){let{startTime:m}=e;if(t.setAttribute("src",T),m){let p=({target:v})=>{v.currentTime=m,v.removeEventListener("loadedmetadata",p)};t.addEventListener("loadedmetadata",p)}}else t.removeAttribute("src");t.addEventListener("error",W),t.addEventListener("error",w)}else if(r&&T){switch(r.on(M.Events.ERROR,(m,p)=>{let v={[M.ErrorTypes.NETWORK_ERROR]:l.MEDIA_ERR_NETWORK,[M.ErrorTypes.MEDIA_ERROR]:l.MEDIA_ERR_DECODE},P=new l("",v[p.type]);P.fatal=p.fatal,P.data=p,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,p=r.config.maxBufferSize;r.config.maxBufferLength=1,r.config.maxBufferSize=1,t.addEventListener("play",()=>{r.config.maxBufferLength=m,r.config.maxBufferSize=p},{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 W(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=h.get(t);n&&(n.error=r),(o=t.mux)==null||o.emit("error",{player_error_code:r.code,player_error_message:r.message})}var He=(e,t,r)=>{ee(t,r),h.set(t,{});let n=te(e,t);return ne(e,t,n),oe(e,t,n),n};export{E as ExtensionMimeTypeMap,M as Hls,l as MediaError,S as MimeTypeShorthandMap,k as StreamTypes,q as addTextTrack,Pe as allMediaTypes,ke as generatePlayerInitTime,Re as getError,j as getStreamTypeConfig,z as getType,Z as inferMimeTypeFromURL,He as initialize,re as isMuxVideoSrc,oe as loadMedia,Y as mux,J as removeTextTrack,G as setupAutoplay,te as setupHls,ne as setupMux,he as shorthandKeys,ee as teardown,De as toMuxVideoURL,Q as toPlaybackIdParts};
|
|
2
2
|
//# sourceMappingURL=index.mjs.map
|
package/dist/index.mjs.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
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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
|
|
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, addTextTrack, removeTextTrack } 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, addTextTrack, removeTextTrack };\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';\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 addTextTrack(\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 // Use data attribute to identify tracks that should be removed when switching sources/destroying hls.js instance.\n const trackEls: NodeListOf<HTMLTrackElement> = mediaEl.querySelectorAll('track[data-removeondestroy]');\n trackEls.forEach((trackEl) => {\n trackEl.remove();\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\nexport function addTextTrack(\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 // Add data attribute to identify tracks that should be removed when switching sources/destroying hls.js instance.\n trackEl.setAttribute('data-removeondestroy', '');\n mediaEl.append(trackEl);\n return trackEl.track;\n}\n\nexport function removeTextTrack(mediaEl: HTMLMediaElement, track: TextTrack) {\n const trackEl: HTMLTrackElement | undefined = Array.prototype.find.call(\n mediaEl.querySelectorAll('track'),\n (trackEl: HTMLTrackElement) => trackEl.track === track\n );\n trackEl?.remove();\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
6
|
"names": []
|
|
7
7
|
}
|