11import type * as HLS from 'hls.js' ;
22import { effect , peek } from 'maverick.js' ;
3- import { camelToKebabCase , DOMEvent , listenEvent } from 'maverick.js/std' ;
3+ import { camelToKebabCase , DOMEvent , isString , listenEvent } from 'maverick.js/std' ;
44
5+ import type { MediaSrc } from '../../core/api/types' ;
56import { QualitySymbol } from '../../core/quality/symbols' ;
67import { TextTrackSymbol } from '../../core/tracks/text/symbols' ;
78import { TextTrack } from '../../core/tracks/text/text-track' ;
@@ -49,6 +50,7 @@ export class HLSController {
4950 ctx . player . dispatch ( new DOMEvent ( 'hls-instance' , { detail : this . _instance } ) ) ;
5051
5152 this . _instance . attachMedia ( this . _video ) ;
53+ this . _instance . on ( ctor . Events . FRAG_LOADING , this . _onFragLoading . bind ( this ) ) ;
5254 this . _instance . on ( ctor . Events . AUDIO_TRACK_SWITCHED , this . _onAudioSwitch . bind ( this ) ) ;
5355 this . _instance . on ( ctor . Events . LEVEL_SWITCHED , this . _onLevelSwitched . bind ( this ) ) ;
5456 this . _instance . on ( ctor . Events . LEVEL_LOADED , this . _onLevelLoaded . bind ( this ) ) ;
@@ -209,20 +211,50 @@ export class HLSController {
209211 if ( data . fatal ) {
210212 switch ( data . type ) {
211213 case 'networkError' :
212- this . _instance ?. startLoad ( ) ;
214+ this . _onNetworkError ( data . error ) ;
213215 break ;
214216 case 'mediaError' :
215217 this . _instance ?. recoverMediaError ( ) ;
216218 break ;
217219 default :
218- // We can't recover here - better course of action?
219- this . _instance ?. destroy ( ) ;
220- this . _instance = null ;
220+ this . _onFatalError ( data . error ) ;
221221 break ;
222222 }
223223 }
224224 }
225225
226+ private _onFragLoading ( ) {
227+ if ( this . _retryLoadingTimer >= 0 ) this . _clearRetryTimer ( ) ;
228+ }
229+
230+ private _retryLoadingTimer = - 1 ;
231+ private _onNetworkError ( error : Error ) {
232+ this . _clearRetryTimer ( ) ;
233+
234+ this . _instance ?. startLoad ( ) ;
235+
236+ this . _retryLoadingTimer = window . setTimeout ( ( ) => {
237+ this . _retryLoadingTimer = - 1 ;
238+ this . _onFatalError ( error ) ;
239+ } , 5000 ) ;
240+ }
241+
242+ private _clearRetryTimer ( ) {
243+ clearTimeout ( this . _retryLoadingTimer ) ;
244+ this . _retryLoadingTimer = - 1 ;
245+ }
246+
247+ private _onFatalError ( error : Error ) {
248+ // We can't recover here - better course of action?
249+ this . _instance ?. destroy ( ) ;
250+ this . _instance = null ;
251+ this . _ctx . delegate . _notify ( 'error' , {
252+ message : error . message ,
253+ code : 1 ,
254+ error : error ,
255+ } ) ;
256+ }
257+
226258 private _enableAutoQuality ( ) {
227259 if ( this . _instance ) this . _instance . currentLevel = - 1 ;
228260 }
@@ -247,7 +279,14 @@ export class HLSController {
247279 }
248280 }
249281
282+ _loadSource ( src : MediaSrc ) {
283+ if ( ! isString ( src . src ) ) return ;
284+ this . _clearRetryTimer ( ) ;
285+ this . _instance ?. loadSource ( src . src ) ;
286+ }
287+
250288 _destroy ( ) {
289+ this . _clearRetryTimer ( ) ;
251290 if ( this . _ctx ) this . _ctx . qualities [ QualitySymbol . _enableAuto ] = undefined ;
252291 this . _instance ?. destroy ( ) ;
253292 this . _instance = null ;
0 commit comments