import { Directive , OnInit , OnChanges , OnDestroy , Input , Output , EventEmitter , ElementRef , SimpleChanges , } from '@angular/core' ; import { Subscription } from 'rxjs' ; import { IHLSConfig , BitrateOptions , VgApiService , } from '@videogular/ngx-videogular/core' ; declare let Hls ; @ Directive ( { selector : '[vgHls]' , exportAs : 'vgHls' , } ) export class VgHlsDirective implements OnInit , OnChanges , OnDestroy { @ Input ( ) vgHls : string ; @ Input ( ) vgHlsHeaders : { [ key ] : string ; } = { } ; @ Output ( ) onGetBitrates : EventEmitter < BitrateOptions [ ] > = new EventEmitter ( ) ; vgFor : string ; target : any ; hls : any ; preload : boolean ; crossorigin : string ; config : IHLSConfig ; subscriptions : Subscription [ ] = [ ] ; constructor ( private ref , public API ) { } ngOnInit ( ) { if ( this . API . isPlayerReady ) { this . onPlayerReady ( ) ; } else { this . subscriptions . push ( this . API . playerReadyEvent . subscribe ( ( ) => this . onPlayerReady ( ) ) ) ; } } onPlayerReady ( ) { this . crossorigin = this . ref . nativeElement . getAttribute ( 'crossorigin' ) ; this . preload = this . ref . nativeElement . getAttribute ( 'preload' ) !== 'none' ; this . vgFor = this . ref . nativeElement . getAttribute ( 'vgFor' ) ; if ( this . vgFor ) { this . target = this . API . getMediaById ( this . vgFor ) ; } else { this . target = this . API . getDefaultMedia ( ) ; } this . config = { autoStartLoad : this . preload , } as IHLSConfig ; this . config . xhrSetup = ( xhr ) => { if ( this . crossorigin === 'use-credentials' ) { xhr . withCredentials = true ; } for ( const key of Object . keys ( this . vgHlsHeaders ) ) { xhr . setRequestHeader ( key , this . vgHlsHeaders [ key ] ) ; } } ; this . createPlayer ( ) ; if ( ! this . preload ) { this . subscriptions . push ( this . API . subscriptions . play . subscribe ( ( ) => { if ( this . hls ) { this . hls . startLoad ( 0 ) ; } } ) ) ; } } ngOnChanges ( changes ) { if ( changes . vgHls ?. currentValue ) { this . createPlayer ( ) ; } else if ( changes . vgHlsHeaders && changes . vgHlsHeaders . currentValue ) { } else { this . destroyPlayer ( ) ; } } createPlayer ( ) { if ( this . hls ) { this . destroyPlayer ( ) ; } if ( this . vgHls && this . vgHls . indexOf ( 'm3u8' ) > - 1 && Hls . isSupported ( ) && this . API . isPlayerReady ) { const video = this . ref . nativeElement ; this . hls = new Hls ( this . config ) ; this . hls . on ( Hls . Events . MANIFEST_PARSED , ( _event , data ) => { const videoList = [ ] ; videoList . push ( { qualityIndex : 0 , width : 0 , height : 0 , bitrate : 0 , mediaType : 'video' , label : 'AUTO' , } ) ; data . levels . forEach ( ( item , index ) => { videoList . push ( { qualityIndex : ++ index , width : item . width , height : item . height , bitrate : item . bitrate , mediaType : 'video' , label : item . name , } ) ; } ) ; this . onGetBitrates . emit ( videoList ) ; } ) ; this . hls . on ( Hls . Events . LEVEL_LOADED , ( _event , data ) => { this . target . isLive = data . details . live ; } ) ; this . hls . loadSource ( this . vgHls ) ; this . hls . attachMedia ( video ) ; } else { if ( this . target && ! ! this . target . pause ) { this . target . pause ( ) ; this . target . seekTime ( 0 ) ; this . ref . nativeElement . src = this . vgHls ; } } } setBitrate ( bitrate ) { if ( this . hls ) { this . hls . nextLevel = bitrate . qualityIndex - 1 ; } } destroyPlayer ( ) { if ( this . hls ) { this . hls . destroy ( ) ; this . hls = null ; } } ngOnDestroy ( ) { this . subscriptions . forEach ( ( s ) => s . unsubscribe ( ) ) ; this . destroyPlayer ( ) ; delete this . hls ; } }