1 line
8.3 KiB
Plaintext
Executable File
1 line
8.3 KiB
Plaintext
Executable File
{"version":3,"file":"hls-provider-66ccc1f9.mjs","sources":["../../../common/resources/client/player/providers/hls-provider.tsx"],"sourcesContent":["import {useCallback, useContext, useEffect, useRef, useState} from 'react';\nimport {PlayerStoreContext} from '@common/player/player-context';\nimport {usePlayerStore} from '@common/player/hooks/use-player-store';\nimport Hls, {LevelLoadedData} from 'hls.js';\nimport {useHtmlMediaInternalState} from '@common/player/providers/html-media/use-html-media-internal-state';\nimport {useHtmlMediaEvents} from '@common/player/providers/html-media/use-html-media-events';\nimport {useHtmlMediaApi} from '@common/player/providers/html-media/use-html-media-api';\nimport {HlsMediaItem} from '@common/player/media-item';\nimport {AudioTrack} from '@common/player/state/player-state';\n\nexport default function HlsProvider() {\n const store = useContext(PlayerStoreContext);\n const cuedMedia = usePlayerStore(s => s.cuedMedia) as HlsMediaItem;\n\n // html medial element state\n const videoRef = useRef<HTMLVideoElement>(null!);\n const htmlMediaState = useHtmlMediaInternalState(videoRef);\n const htmlMediaEvents = useHtmlMediaEvents(htmlMediaState);\n const htmlMediaApi = useHtmlMediaApi(htmlMediaState);\n\n // need both so we can \"loadSource\" when hls is ready, while keeping other callbacks stable\n const hls = useRef<Hls | undefined>();\n const [hlsReady, setHlsReady] = useState(false);\n\n const destroyHls = useCallback(() => {\n if (hls) {\n hls.current?.destroy();\n hls.current = undefined;\n setHlsReady(false);\n }\n }, []);\n\n const setupHls = useCallback(() => {\n if (!Hls.isSupported()) {\n store.getState().emit('error', {fatal: true});\n return;\n }\n\n const hlsInstance = new Hls({\n startLevel: -1,\n });\n\n hlsInstance.on(Hls.Events.ERROR, (event: any, data: any) => {\n if (data.fatal) {\n switch (data.type) {\n case Hls.ErrorTypes.NETWORK_ERROR:\n hlsInstance.startLoad();\n break;\n case Hls.ErrorTypes.MEDIA_ERROR:\n hlsInstance.recoverMediaError();\n break;\n default:\n destroyHls();\n break;\n }\n }\n\n store.getState().emit('error', {sourceEvent: data, fatal: data.fatal});\n });\n\n hlsInstance.on(Hls.Events.MANIFEST_PARSED, () => {\n if (!hlsInstance.levels?.length) return;\n\n store.getState().emit('playbackQualities', {\n qualities: ['auto', ...hlsInstance.levels.map(levelToPlaybackQuality)],\n });\n\n store.getState().emit('playbackQualityChange', {quality: 'auto'});\n });\n\n hlsInstance.on(Hls.Events.AUDIO_TRACK_SWITCHED, (eventType, data) => {\n const track = store.getState().audioTracks.find(t => t.id === data.id);\n if (track) {\n store.getState().emit('currentAudioTrackChange', {trackId: track.id});\n }\n });\n\n hlsInstance.on(\n Hls.Events.LEVEL_LOADED,\n (eventType: string, data: LevelLoadedData) => {\n if (!store.getState().providerReady) {\n const {type, live, totalduration: duration} = data.details;\n const inferredStreamType = live\n ? type === 'EVENT' && Number.isFinite(duration)\n ? 'live:dvr'\n : 'live'\n : 'on-demand';\n store.getState().emit('streamTypeChange', {\n streamType:\n (store.getState().cuedMedia as HlsMediaItem)?.streamType ||\n inferredStreamType,\n });\n store.getState().emit('durationChange', {duration});\n\n const audioTracks: AudioTrack[] = hlsInstance.audioTracks.map(\n track => ({\n id: track.id,\n label: track.name,\n language: track.lang || '',\n kind: 'main',\n })\n );\n store.getState().emit('audioTracks', {tracks: audioTracks});\n }\n }\n );\n\n hlsInstance.attachMedia(videoRef.current);\n\n hls.current = hlsInstance;\n // trigger initial load source\n setHlsReady(true);\n }, [destroyHls, store]);\n\n // setup and destroy hls on mount and unmount\n useEffect(() => {\n setupHls();\n return () => {\n destroyHls();\n };\n }, [setupHls, destroyHls]);\n\n // load source via hls when media src changes and hls is ready\n useEffect(() => {\n if (\n hls.current &&\n cuedMedia?.src &&\n (hls.current as any).url !== cuedMedia?.src\n ) {\n hls.current.loadSource(cuedMedia.src);\n }\n }, [cuedMedia?.src, hlsReady]);\n\n useEffect(() => {\n if (!hlsReady) return;\n store.setState({\n providerApi: {\n ...htmlMediaApi,\n setCurrentAudioTrack: (trackId: number) => {\n if (!hls.current) return;\n hls.current.audioTrack = trackId;\n },\n setPlaybackQuality: (quality: string) => {\n if (!hls.current) return;\n hls.current.currentLevel = hls.current.levels.findIndex(\n level => levelToPlaybackQuality(level) === quality\n );\n store.getState().emit('playbackQualityChange', {quality});\n },\n },\n });\n }, [htmlMediaApi, store, hlsReady]);\n\n return (\n <video\n className=\"h-full w-full\"\n ref={videoRef}\n playsInline\n poster={cuedMedia?.poster}\n {...htmlMediaEvents}\n />\n );\n}\n\nconst levelToPlaybackQuality = (level: any) => {\n return level === -1 ? 'auto' : `${level.height}p`;\n};\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAUA,SAAwB,cAAc;AAC9B,QAAA,QAAQ,WAAW,kBAAkB;AAC3C,QAAM,YAAY,eAAe,CAAK,MAAA,EAAE,SAAS;AAG3C,QAAA,WAAW,OAAyB,IAAK;AACzC,QAAA,iBAAiB,0BAA0B,QAAQ;AACnD,QAAA,kBAAkB,mBAAmB,cAAc;AACnD,QAAA,eAAe,gBAAgB,cAAc;AAGnD,QAAM,MAAM;AACZ,QAAM,CAAC,UAAU,WAAW,IAAI,SAAS,KAAK;AAExC,QAAA,aAAa,YAAY,MAAM;;AACnC,QAAI,KAAK;AACP,gBAAI,YAAJ,mBAAa;AACb,UAAI,UAAU;AACd,kBAAY,KAAK;AAAA,IACnB;AAAA,EACF,GAAG,CAAE,CAAA;AAEC,QAAA,WAAW,YAAY,MAAM;AAC7B,QAAA,CAAC,IAAI,eAAe;AACtB,YAAM,WAAW,KAAK,SAAS,EAAC,OAAO,MAAK;AAC5C;AAAA,IACF;AAEM,UAAA,cAAc,IAAI,IAAI;AAAA,MAC1B,YAAY;AAAA,IAAA,CACb;AAED,gBAAY,GAAG,IAAI,OAAO,OAAO,CAAC,OAAY,SAAc;AAC1D,UAAI,KAAK,OAAO;AACd,gBAAQ,KAAK,MAAM;AAAA,UACjB,KAAK,IAAI,WAAW;AAClB,wBAAY,UAAU;AACtB;AAAA,UACF,KAAK,IAAI,WAAW;AAClB,wBAAY,kBAAkB;AAC9B;AAAA,UACF;AACa;AACX;AAAA,QACJ;AAAA,MACF;AAEM,YAAA,SAAA,EAAW,KAAK,SAAS,EAAC,aAAa,MAAM,OAAO,KAAK,MAAM,CAAA;AAAA,IAAA,CACtE;AAED,gBAAY,GAAG,IAAI,OAAO,iBAAiB,MAAM;;AAC3C,UAAA,GAAC,iBAAY,WAAZ,mBAAoB;AAAQ;AAE3B,YAAA,SAAA,EAAW,KAAK,qBAAqB;AAAA,QACzC,WAAW,CAAC,QAAQ,GAAG,YAAY,OAAO,IAAI,sBAAsB,CAAC;AAAA,MAAA,CACtE;AAED,YAAM,WAAW,KAAK,yBAAyB,EAAC,SAAS,QAAO;AAAA,IAAA,CACjE;AAED,gBAAY,GAAG,IAAI,OAAO,sBAAsB,CAAC,WAAW,SAAS;AAC7D,YAAA,QAAQ,MAAM,SAAA,EAAW,YAAY,KAAK,CAAK,MAAA,EAAE,OAAO,KAAK,EAAE;AACrE,UAAI,OAAO;AACH,cAAA,WAAW,KAAK,2BAA2B,EAAC,SAAS,MAAM,IAAG;AAAA,MACtE;AAAA,IAAA,CACD;AAEW,gBAAA;AAAA,MACV,IAAI,OAAO;AAAA,MACX,CAAC,WAAmB,SAA0B;;AAC5C,YAAI,CAAC,MAAM,SAAS,EAAE,eAAe;AACnC,gBAAM,EAAC,MAAM,MAAM,eAAe,aAAY,KAAK;AAC7C,gBAAA,qBAAqB,OACvB,SAAS,WAAW,OAAO,SAAS,QAAQ,IAC1C,aACA,SACF;AACE,gBAAA,SAAA,EAAW,KAAK,oBAAoB;AAAA,YACxC,cACG,WAAM,SAAS,EAAE,cAAjB,mBAA6C,eAC9C;AAAA,UAAA,CACH;AACD,gBAAM,WAAW,KAAK,kBAAkB,EAAC,UAAS;AAE5C,gBAAA,cAA4B,YAAY,YAAY;AAAA,YACxD,CAAU,WAAA;AAAA,cACR,IAAI,MAAM;AAAA,cACV,OAAO,MAAM;AAAA,cACb,UAAU,MAAM,QAAQ;AAAA,cACxB,MAAM;AAAA,YAAA;AAAA,UACR;AAEF,gBAAM,WAAW,KAAK,eAAe,EAAC,QAAQ,aAAY;AAAA,QAC5D;AAAA,MACF;AAAA,IAAA;AAGU,gBAAA,YAAY,SAAS,OAAO;AAExC,QAAI,UAAU;AAEd,gBAAY,IAAI;AAAA,EAAA,GACf,CAAC,YAAY,KAAK,CAAC;AAGtB,YAAU,MAAM;AACL;AACT,WAAO,MAAM;AACA;IAAA;AAAA,EACb,GACC,CAAC,UAAU,UAAU,CAAC;AAGzB,YAAU,MAAM;AAEZ,QAAA,IAAI,YACJ,uCAAW,QACV,IAAI,QAAgB,SAAQ,uCAAW,MACxC;AACI,UAAA,QAAQ,WAAW,UAAU,GAAG;AAAA,IACtC;AAAA,EACC,GAAA,CAAC,uCAAW,KAAK,QAAQ,CAAC;AAE7B,YAAU,MAAM;AACd,QAAI,CAAC;AAAU;AACf,UAAM,SAAS;AAAA,MACb,aAAa;AAAA,QACX,GAAG;AAAA,QACH,sBAAsB,CAAC,YAAoB;AACzC,cAAI,CAAC,IAAI;AAAS;AAClB,cAAI,QAAQ,aAAa;AAAA,QAC3B;AAAA,QACA,oBAAoB,CAAC,YAAoB;AACvC,cAAI,CAAC,IAAI;AAAS;AAClB,cAAI,QAAQ,eAAe,IAAI,QAAQ,OAAO;AAAA,YAC5C,CAAA,UAAS,uBAAuB,KAAK,MAAM;AAAA,UAAA;AAE7C,gBAAM,WAAW,KAAK,yBAAyB,EAAC,SAAQ;AAAA,QAC1D;AAAA,MACF;AAAA,IAAA,CACD;AAAA,EACA,GAAA,CAAC,cAAc,OAAO,QAAQ,CAAC;AAGhC,SAAA;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,WAAU;AAAA,MACV,KAAK;AAAA,MACL,aAAW;AAAA,MACX,QAAQ,uCAAW;AAAA,MAClB,GAAG;AAAA,IAAA;AAAA,EAAA;AAGV;AAEA,MAAM,yBAAyB,CAAC,UAAe;AAC7C,SAAO,UAAU,KAAK,SAAS,GAAG,MAAM,MAAM;AAChD;"} |