{"version":3,"sources":["webpack:///./src/assets/player/peertube-cap-level-controller.ts","webpack:///./src/assets/player/p2p-media-loader/hls-plugin.ts","webpack:///./src/assets/player/p2p-media-loader/p2p-media-loader-plugin.ts"],"names":["hls","this","autoLevelCapping","Number","POSITIVE_INFINITY","firstLevel","media","restrictedLevels","timer","undefined","clientRect","paused","pauseCapping","resumeCapping","registerListeners","streamController","unregisterListener","config","capLevelToPlayerSize","stopCapping","on","FPS_DROP_LEVEL_CAPPING","onFpsDropLevelCapping","MEDIA_ATTACHING","onMediaAttaching","MANIFEST_PARSED","onManifestParsed","BUFFER_CODECS","onBufferCodecs","MEDIA_DETACHING","onMediaDetaching","off","event","data","isLevelAllowed","droppedLevel","push","HTMLVideoElement","video","startCapping","mediaHeight","mediaWidth","levels","length","getMaxLevel","nextLevelSwitch","capLevelIndex","validLevels","filter","level","index","getMaxLevelByMediaSize","detectPlayerSize","self","clearInterval","setInterval","bind","clientRectLast","boundsRect","width","height","getBoundingClientRect","right","left","bottom","top","getDimensions","contentScaleFactor","pixelRatio","devicePixelRatio","e","indexOf","maxLevelIndex","i","curLevel","nextLevel","hlsjsConfigHandler","options","player","srOptions_","hlsjsConfig","captionConfig","levelLabelHandler","vjs","source","tech","errorCounts","_duration","metadata","isLive","dvrDuration","edgeMargin","handlers","play","playing","textTracksChange","audioTracksChange","uiTextTrackHandled","name_","videoElement","el","options_","playerId","addEventListener","errorTxt","mediaError","currentTarget","target","error","code","MEDIA_ERR_ABORTED","MEDIA_ERR_DECODE","_handleMediaError","MEDIA_ERR_NETWORK","MEDIA_ERR_SRC_NOT_SUPPORTED","message","initialize","duration","createTimeRanges","startTime","Math","round","endTime","removeEventListener","textTracks","destroy","type","callback","hooks","splice","MEDIA_ERROR","console","info","recoverMediaError","swapAudioCodec","trigger","setTimeout","startLoad","NETWORK_ERROR","once","FRAG_LOADED","_event","fatal","details","_handleNetworkError","qualityId","bitrate","qualityLevels","selectedTrack","isAuto","_enabled","currentLevel","representation","id","bandwidth","enabled","toggle","_relayQualityChange","addQualityLevel","cleanTracklist","autoLevel","label","selected","manualLevel","forEach","quality","_levelLabel","payload","qualityData","qualitySwitchCallback","switchQuality","playerAudioTracks","audioTracks","j","audioTrack","hlsAudioTracks","addTrack","AudioTrack","toString","kind","name","lang","language","_updateSelectedAudioTrack","textTrack","track1","track2","_getTextTrackLabel","playerTextTracks","activeTrack","mode","hlsjsTracks","k","_isSameTextTrack","obj","result","objKeys","Object","keys","displayableTracks","idx","_filterDisplayableTextTracks","isAdded","jdx","hlsjsTextTrack","addRemoteTextTrack","srclang","_updateSelectedTextTrack","_handleQualityLevels","newCue","track","captionScreen","row","cue","text","VTTCue","window","TextTrackCue","r","rows","isEmpty","c","chars","ucharj","trim","configKeys","addCue","techOptions","hlsjsConfigRef","_oneLevelObjClone","includes","preload","autoplay","autoStartLoad","cueHandler","_createCueHandler","_startLoad","_notifyVideoQualities","capLevelController","ERROR","_onError","AUDIO_TRACKS_UPDATED","_onAudioTracks","_onMetaData","LEVEL_LOADED","liveSyncDuration","liveSyncDurationCount","targetduration","live","totalduration","Infinity","attachMedia","loadSource","src","_initHlsjs","registerPlugin","plugin","isSupported","warn","html5","getTech","registerSourceHandler","canHandleSource","test","handleSource","hlsProvider","dispose","Html5Hlsjs","Plugin","getPlugin","super","CONSTANTS","INFO_SCHEDULER","statsP2PBytes","pendingDownload","pendingUpload","numPeers","totalDownload","totalUpload","statsHTTPBytes","ready","initializeCore","hlsjs","initializePlugin","p2pEngine","networkInfoInterval","one","addClass","currentTime","loader","getEngine","LEVEL_SWITCHING","_","auto","autoLevelEnabled","resolutionId","SegmentError","segment","err","redundancyUrlManager","removeBySegmentUrl","requestUrl","countBaseUrls","runStats","PieceBytesDownloaded","method","size","elem","PieceBytesUploaded","PeerConnect","PeerClose","p2pDownloadSpeed","arraySum","p2pUploadSpeed","httpDownloadSpeed","httpUploadSpeed","http","downloadSpeed","uploadSpeed","downloaded","uploaded","p2p","reduce","a","b"],"mappings":"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","file":"10.chunk.js?v=2600","sourcesContent":["//@ts-nocheck\r\n\r\nimport { Events } from 'hls.js/src/events';\r\nimport type { Level } from 'hls.js/src/types/level';\r\nimport type {\r\n ManifestParsedData,\r\n BufferCodecsData,\r\n MediaAttachingData,\r\n FPSDropLevelCappingData,\r\n} from 'hls.js/src/types/events';\r\nimport type { ComponentAPI } from 'hls.js/src/types/component-api';\r\nimport type Hls from 'hls.js';\r\n\r\n\r\nclass CapLevelController implements ComponentAPI {\r\n public autoLevelCapping: number;\r\n public firstLevel: number;\r\n public media: HTMLVideoElement | null;\r\n public restrictedLevels: Array;\r\n public timer: number | undefined;\r\n public paused: Boolean\r\n\r\n private hls: Hls;\r\n private streamController?: any;\r\n public clientRect: { width: number; height: number } | null;\r\n public clientRectLast: { width: number; height: number } | null;\r\n\r\n constructor(hls: Hls) {\r\n this.hls = hls;\r\n this.autoLevelCapping = Number.POSITIVE_INFINITY;\r\n this.firstLevel = -1;\r\n this.media = null;\r\n this.restrictedLevels = [];\r\n this.timer = undefined;\r\n this.clientRect = null;\r\n this.paused = true\r\n\r\n this.hls.pauseCapping = () => {\r\n this.paused = true\r\n }\r\n\r\n this.hls.resumeCapping = () => {\r\n this.paused = false\r\n }\r\n\r\n this.registerListeners();\r\n }\r\n\r\n public setStreamController(streamController: StreamController) {\r\n this.streamController = streamController;\r\n }\r\n\r\n public destroy() {\r\n this.unregisterListener();\r\n if (this.hls.config.capLevelToPlayerSize) {\r\n this.stopCapping();\r\n }\r\n this.media = null;\r\n this.clientRect = null;\r\n // @ts-ignore\r\n this.hls = this.streamController = null;\r\n }\r\n\r\n protected registerListeners() {\r\n const { hls } = this;\r\n hls.on(Events.FPS_DROP_LEVEL_CAPPING, this.onFpsDropLevelCapping, this);\r\n hls.on(Events.MEDIA_ATTACHING, this.onMediaAttaching, this);\r\n hls.on(Events.MANIFEST_PARSED, this.onManifestParsed, this);\r\n hls.on(Events.BUFFER_CODECS, this.onBufferCodecs, this);\r\n hls.on(Events.MEDIA_DETACHING, this.onMediaDetaching, this);\r\n }\r\n\r\n protected unregisterListener() {\r\n const { hls } = this;\r\n hls.off(Events.FPS_DROP_LEVEL_CAPPING, this.onFpsDropLevelCapping, this);\r\n hls.off(Events.MEDIA_ATTACHING, this.onMediaAttaching, this);\r\n hls.off(Events.MANIFEST_PARSED, this.onManifestParsed, this);\r\n hls.off(Events.BUFFER_CODECS, this.onBufferCodecs, this);\r\n hls.off(Events.MEDIA_DETACHING, this.onMediaDetaching, this);\r\n }\r\n\r\n protected onFpsDropLevelCapping(\r\n event: Events.FPS_DROP_LEVEL_CAPPING,\r\n data: FPSDropLevelCappingData\r\n ) {\r\n // Don't add a restricted level more than once\r\n if (\r\n CapLevelController.isLevelAllowed(\r\n data.droppedLevel,\r\n this.restrictedLevels\r\n )\r\n ) {\r\n this.restrictedLevels.push(data.droppedLevel);\r\n }\r\n }\r\n\r\n protected onMediaAttaching(\r\n event: Events.MEDIA_ATTACHING,\r\n data: MediaAttachingData\r\n ) {\r\n this.media = data.media instanceof HTMLVideoElement ? data.media : null;\r\n }\r\n\r\n protected onManifestParsed(\r\n event: any,\r\n data: any\r\n ) {\r\n const hls = this.hls;\r\n this.restrictedLevels = [];\r\n this.firstLevel = data.firstLevel;\r\n if (hls.config.capLevelToPlayerSize && data.video) {\r\n // Start capping immediately if the manifest has signaled video codecs\r\n this.startCapping();\r\n }\r\n }\r\n\r\n // Only activate capping when playing a video stream; otherwise, multi-bitrate audio-only streams will be restricted\r\n // to the first level\r\n protected onBufferCodecs(\r\n event: Events.BUFFER_CODECS,\r\n data: BufferCodecsData\r\n ) {\r\n const hls = this.hls;\r\n if (hls.config.capLevelToPlayerSize && data.video) {\r\n // If the manifest did not signal a video codec capping has been deferred until we're certain video is present\r\n this.startCapping();\r\n }\r\n }\r\n\r\n protected onMediaDetaching() {\r\n this.stopCapping();\r\n }\r\n\r\n detectPlayerSize() {\r\n if (this.media && this.mediaHeight > 0 && this.mediaWidth > 0) {\r\n const levels = this.hls.levels;\r\n \r\n if (levels.length) {\r\n const hls = this.hls;\r\n hls.autoLevelCapping = this.getMaxLevel(levels.length - 1);\r\n\r\n if (\r\n hls.autoLevelCapping > this.autoLevelCapping &&\r\n this.streamController\r\n ) {\r\n // if auto level capping has a higher value for the previous one, flush the buffer using nextLevelSwitch\r\n // usually happen when the user go to the fullscreen mode.\r\n this.streamController.nextLevelSwitch();\r\n }\r\n this.autoLevelCapping = hls.autoLevelCapping;\r\n }\r\n }\r\n }\r\n\r\n /*\r\n * returns level should be the one with the dimensions equal or greater than the media (player) dimensions (so the video will be downscaled)\r\n */\r\n getMaxLevel(capLevelIndex: number): number {\r\n const levels = this.hls.levels;\r\n if (!levels.length) {\r\n return -1;\r\n }\r\n\r\n const validLevels = levels.filter(\r\n (level, index) =>\r\n CapLevelController.isLevelAllowed(index, this.restrictedLevels) &&\r\n index <= capLevelIndex\r\n );\r\n\r\n\r\n\r\n this.clientRect = null;\r\n return CapLevelController.getMaxLevelByMediaSize(\r\n validLevels,\r\n this.mediaWidth,\r\n this.mediaHeight\r\n );\r\n }\r\n\r\n capp(){\r\n this.autoLevelCapping = Number.POSITIVE_INFINITY;\r\n this.hls.firstLevel = this.getMaxLevel(this.firstLevel);\r\n \r\n this.detectPlayerSize();\r\n }\r\n\r\n startCapping() {\r\n if (this.timer) {\r\n // Don't reset capping if started twice; this can happen if the manifest signals a video codec\r\n return;\r\n }\r\n this.autoLevelCapping = Number.POSITIVE_INFINITY;\r\n this.hls.firstLevel = this.getMaxLevel(this.firstLevel);\r\n self.clearInterval(this.timer);\r\n this.timer = self.setInterval(this.detectPlayerSize.bind(this), 10000);\r\n this.detectPlayerSize();\r\n }\r\n\r\n stopCapping() {\r\n this.restrictedLevels = [];\r\n this.firstLevel = -1;\r\n //this.autoLevelCapping = Number.POSITIVE_INFINITY;\r\n \r\n if (this.timer) {\r\n self.clearInterval(this.timer);\r\n this.timer = undefined;\r\n }\r\n }\r\n\r\n\r\n getDimensions(): { width: number; height: number } {\r\n\r\n if (this.paused && this.clientRectLast){\r\n return this.clientRectLast\r\n }\r\n\r\n if (this.clientRect) {\r\n return this.clientRect;\r\n }\r\n const media = this.media;\r\n const boundsRect = {\r\n width: 0,\r\n height: 0,\r\n };\r\n\r\n if (media) {\r\n const clientRect = media.getBoundingClientRect();\r\n boundsRect.width = clientRect.width;\r\n boundsRect.height = clientRect.height;\r\n if (!boundsRect.width && !boundsRect.height) {\r\n // When the media element has no width or height (equivalent to not being in the DOM),\r\n // then use its width and height attributes (media.width, media.height)\r\n boundsRect.width =\r\n clientRect.right - clientRect.left || media.width || 0;\r\n boundsRect.height =\r\n clientRect.bottom - clientRect.top || media.height || 0;\r\n }\r\n }\r\n\r\n this.clientRectLast = this.clientRect = boundsRect;\r\n \r\n return boundsRect;\r\n }\r\n\r\n get mediaWidth(): number {\r\n return this.getDimensions().width * CapLevelController.contentScaleFactor;\r\n }\r\n\r\n get mediaHeight(): number {\r\n return this.getDimensions().height * CapLevelController.contentScaleFactor;\r\n }\r\n\r\n static get contentScaleFactor(): number {\r\n let pixelRatio = 1;\r\n try {\r\n pixelRatio = self.devicePixelRatio;\r\n } catch (e) {\r\n /* no-op */\r\n }\r\n\r\n if (pixelRatio > 1.5) pixelRatio = 1.5\r\n\r\n return pixelRatio;\r\n }\r\n\r\n static isLevelAllowed(\r\n level: number,\r\n restrictedLevels: Array = []\r\n ): boolean {\r\n return restrictedLevels.indexOf(level) === -1;\r\n }\r\n\r\n static getMaxLevelByMediaSize(\r\n levels: Array,\r\n width: number,\r\n height: number\r\n ): number {\r\n if (!levels || !levels.length) {\r\n return -1;\r\n }\r\n\r\n // Levels can have the same dimensions but differing bandwidths - since levels are ordered, we can look to the next\r\n // to determine whether we've chosen the greatest bandwidth for the media's dimensions\r\n const atGreatestBandiwdth = (curLevel : any, nextLevel : any) => {\r\n if (!nextLevel) {\r\n return true;\r\n }\r\n\r\n return (\r\n curLevel.width !== nextLevel.width ||\r\n curLevel.height !== nextLevel.height\r\n );\r\n };\r\n\r\n\r\n // If we run through the loop without breaking, the media's dimensions are greater than every level, so default to\r\n // the max level\r\n let maxLevelIndex = levels.length - 1;\r\n\r\n for (let i = 0; i < levels.length; i += 1) {\r\n const level = levels[i];\r\n if (\r\n (level.width >= width || level.height >= height) &&\r\n atGreatestBandiwdth(level, levels[i + 1])\r\n ) {\r\n maxLevelIndex = i;\r\n break;\r\n }\r\n }\r\n\r\n return maxLevelIndex;\r\n }\r\n}\r\n\r\nexport default CapLevelController;\r\n","// Thanks https://github.com/streamroot/videojs-hlsjs-plugin\r\n// We duplicated this plugin to choose the hls.js version we want, because streamroot only provide a bundled file\r\n\r\n//import * as HlsjsLigt from 'hls.js/dist/hls.light.js'\r\n\r\nimport * as Hlsjs from 'hls.js'\r\n\r\nimport videojs from 'video.js'\r\nimport { HlsjsConfigHandlerOptions, QualityLevelRepresentation, QualityLevels, VideoJSTechHLS } from '../peertube-videojs-typings'\r\nimport CapLevelController from '../peertube-cap-level-controller'\r\ntype ErrorCounts = {\r\n [ type: string ]: number\r\n}\r\n\r\ntype Metadata = {\r\n levels: Hlsjs.Level[]\r\n}\r\n\r\ntype Fmp4Data = {\r\n audio: Array,\r\n video : Array,\r\n audiovideo : Array\r\n}\r\n\r\n\r\n\r\ntype CustomAudioTrack = Hlsjs.MediaPlaylist & { name?: string, lang?: string }\r\n\r\nconst registerSourceHandler = function (vjs: typeof videojs) {\r\n if (!Hlsjs.default.isSupported()) {\r\n console.warn('Hls.js is not supported in this browser!')\r\n return\r\n }\r\n\r\n const html5 = vjs.getTech('Html5')\r\n\r\n if (!html5) {\r\n console.error('Not supported version if video.js')\r\n return\r\n }\r\n\r\n // FIXME: typings\r\n (html5 as any).registerSourceHandler({\r\n canHandleSource: function (source: videojs.Tech.SourceObject) {\r\n const hlsTypeRE = /^application\\/x-mpegURL|application\\/vnd\\.apple\\.mpegurl$/i\r\n const hlsExtRE = /\\.m3u8/i\r\n\r\n if (hlsTypeRE.test(source.type)) return 'probably'\r\n if (hlsExtRE.test(source.src)) return 'maybe'\r\n\r\n return ''\r\n },\r\n\r\n handleSource: function (source: videojs.Tech.SourceObject, tech: VideoJSTechHLS) {\r\n if (tech.hlsProvider) {\r\n\r\n tech.hlsProvider.dispose()\r\n }\r\n\r\n tech.hlsProvider = new Html5Hlsjs(vjs, source, tech)\r\n\r\n return tech.hlsProvider\r\n }\r\n }, 0);\r\n\r\n // FIXME: typings\r\n (vjs as any).Html5Hlsjs = Html5Hlsjs\r\n}\r\n\r\nfunction hlsjsConfigHandler (this: videojs.Player, options: HlsjsConfigHandlerOptions) {\r\n const player = this\r\n\r\n if (!options) return\r\n\r\n if (!player.srOptions_) {\r\n player.srOptions_ = {}\r\n }\r\n\r\n if (!player.srOptions_.hlsjsConfig) {\r\n player.srOptions_.hlsjsConfig = options.hlsjsConfig\r\n }\r\n\r\n if (!player.srOptions_.captionConfig) {\r\n player.srOptions_.captionConfig = options.captionConfig\r\n }\r\n\r\n if (options.levelLabelHandler && !player.srOptions_.levelLabelHandler) {\r\n player.srOptions_.levelLabelHandler = options.levelLabelHandler\r\n }\r\n}\r\n\r\nconst registerConfigPlugin = function (vjs: typeof videojs) {\r\n // Used in Brightcove since we don't pass options directly there\r\n const registerVjsPlugin = vjs.registerPlugin || vjs.plugin\r\n registerVjsPlugin('hlsjs', hlsjsConfigHandler)\r\n}\r\n\r\nclass Html5Hlsjs {\r\n private static readonly hooks: { [id: string]: Function[] } = {}\r\n\r\n private readonly videoElement: HTMLVideoElement\r\n private readonly errorCounts: ErrorCounts = {}\r\n private readonly player: videojs.Player\r\n private readonly tech: videojs.Tech\r\n private readonly source: videojs.Tech.SourceObject\r\n private readonly vjs: typeof videojs\r\n\r\n private hls: Hlsjs.default & { manualLevel?: number, audioTrack?: any, audioTracks?: CustomAudioTrack[] } // FIXME: typings\r\n private hlsjsConfig: Partial = null\r\n\r\n private _duration: number = null\r\n private metadata: Metadata = null\r\n private isLive: boolean = null\r\n private dvrDuration: number = null\r\n private edgeMargin: number = null\r\n\r\n private handlers: { [ id in 'play' | 'playing' | 'textTracksChange' | 'audioTracksChange' ]: EventListener } = {\r\n play: null,\r\n playing: null,\r\n textTracksChange: null,\r\n audioTracksChange: null\r\n }\r\n\r\n private uiTextTrackHandled = false\r\n\r\n constructor (vjs: typeof videojs, source: videojs.Tech.SourceObject, tech: videojs.Tech) {\r\n this.vjs = vjs\r\n this.source = source\r\n\r\n this.tech = tech;\r\n (this.tech as any).name_ = 'Hlsjs'\r\n\r\n this.videoElement = tech.el() as HTMLVideoElement\r\n this.player = vjs((tech.options_ as any).playerId)\r\n\r\n this.videoElement.addEventListener('error', event => {\r\n let errorTxt: string\r\n const mediaError = ((event.currentTarget || event.target) as HTMLVideoElement).error\r\n\r\n if (!mediaError) return\r\n\r\n switch (mediaError.code) {\r\n case mediaError.MEDIA_ERR_ABORTED:\r\n errorTxt = 'You aborted the video playback'\r\n break\r\n case mediaError.MEDIA_ERR_DECODE:\r\n errorTxt = 'The video playback was aborted due to a corruption problem or because the video used features your browser did not support'\r\n this._handleMediaError(mediaError)\r\n break\r\n case mediaError.MEDIA_ERR_NETWORK:\r\n errorTxt = 'A network error caused the video download to fail part-way'\r\n break\r\n case mediaError.MEDIA_ERR_SRC_NOT_SUPPORTED:\r\n errorTxt = 'The video could not be loaded, either because the server or network failed or because the format is not supported'\r\n break\r\n\r\n default:\r\n errorTxt = mediaError.message\r\n }\r\n\r\n })\r\n\r\n this.initialize()\r\n }\r\n\r\n duration () {\r\n return this._duration || this.videoElement.duration || 0\r\n }\r\n\r\n seekable () {\r\n if (this.hls.media) {\r\n if (!this.isLive) {\r\n return this.vjs.createTimeRanges(0, this.hls.media.duration)\r\n }\r\n\r\n // Video.js doesn't seem to like floating point timeranges\r\n const startTime = Math.round(this.hls.media.duration - this.dvrDuration)\r\n const endTime = Math.round(this.hls.media.duration - this.edgeMargin)\r\n\r\n return this.vjs.createTimeRanges(startTime, endTime)\r\n }\r\n\r\n return this.vjs.createTimeRanges()\r\n }\r\n\r\n // See comment for `initialize` method.\r\n dispose () {\r\n this.videoElement.removeEventListener('play', this.handlers.play)\r\n this.videoElement.removeEventListener('playing', this.handlers.playing)\r\n\r\n this.player.textTracks().removeEventListener('change', this.handlers.textTracksChange)\r\n this.uiTextTrackHandled = false\r\n\r\n this.hls.destroy()\r\n\r\n this.handlers = null\r\n }\r\n\r\n static addHook (type: string, callback: Function) {\r\n Html5Hlsjs.hooks[ type ] = this.hooks[ type ] || []\r\n Html5Hlsjs.hooks[ type ].push(callback)\r\n }\r\n\r\n static removeHook (type: string, callback: Function) {\r\n if (Html5Hlsjs.hooks[ type ] === undefined) return false\r\n\r\n const index = Html5Hlsjs.hooks[ type ].indexOf(callback)\r\n if (index === -1) return false\r\n\r\n Html5Hlsjs.hooks[ type ].splice(index, 1)\r\n\r\n return true\r\n }\r\n\r\n private _executeHooksFor (type: string) {\r\n if (Html5Hlsjs.hooks[ type ] === undefined) {\r\n return\r\n }\r\n\r\n // ES3 and IE < 9\r\n for (let i = 0; i < Html5Hlsjs.hooks[ type ].length; i++) {\r\n Html5Hlsjs.hooks[ type ][ i ](this.player, this.hls)\r\n }\r\n }\r\n\r\n private _handleMediaError (error: any) {\r\n\r\n\r\n if (this.errorCounts[ Hlsjs.ErrorTypes.MEDIA_ERROR ] === 1) {\r\n console.info('trying to recover media error')\r\n this.hls.recoverMediaError()\r\n return\r\n }\r\n\r\n if (this.errorCounts[ Hlsjs.ErrorTypes.MEDIA_ERROR ] === 2) {\r\n console.info('2nd try to recover media error (by swapping audio codec')\r\n this.hls.swapAudioCodec()\r\n this.hls.recoverMediaError()\r\n return\r\n }\r\n\r\n if (this.errorCounts[ Hlsjs.ErrorTypes.MEDIA_ERROR ] > 2) {\r\n console.info('bubbling media error up to VIDEOJS')\r\n\r\n this.hls.recoverMediaError()\r\n\r\n //this.hls.destroy()\r\n\r\n //this.tech.error = () => error\r\n //this.tech.trigger('error')\r\n\r\n return\r\n }\r\n }\r\n\r\n private _handleNotFatalError (error : any){\r\n this.tech.trigger('error')\r\n }\r\n\r\n private _handleNetworkError (error: any) {\r\n\r\n setTimeout(() => this.hls.startLoad(), 1000)\r\n\r\n if (this.errorCounts[ Hlsjs.ErrorTypes.NETWORK_ERROR] <= 1) {\r\n console.info('trying to recover network error', error)\r\n\r\n // Wait 1 second and retry\r\n setTimeout(() => this.hls.startLoad(), 1000)\r\n\r\n // Reset error count on success\r\n this.hls.once(Hlsjs.Events.FRAG_LOADED, () => {\r\n this.errorCounts[ Hlsjs.ErrorTypes.NETWORK_ERROR] = 0\r\n })\r\n\r\n return\r\n }\r\n\r\n console.info('bubbling network error up to VIDEOJS')\r\n // this.hls.destroy()\r\n this.tech.error = () => error\r\n this.tech.trigger('error')\r\n }\r\n\r\n private _onError (_event: any, data: Hlsjs.ErrorData) {\r\n\r\n const error: { message: string, code?: number } = {\r\n message: `HLS.js error: ${data.type} - fatal: ${data.fatal} - ${data.details}`\r\n }\r\n\r\n if (!data.fatal) {\r\n return\r\n }\r\n \r\n // increment/set error count\r\n if (this.errorCounts[ data.type ]) this.errorCounts[ data.type ] += 1\r\n else this.errorCounts[ data.type ] = 1\r\n\r\n if (data.type === Hlsjs.ErrorTypes.NETWORK_ERROR) {\r\n error.code = 2\r\n this._handleNetworkError(error)\r\n } else if (data.type === Hlsjs.ErrorTypes.MEDIA_ERROR && data.details !== 'manifestIncompatibleCodecsError') {\r\n error.code = 3\r\n this._handleMediaError(error)\r\n } else {\r\n // this.hls.destroy()\r\n this.tech.error = () => error as any\r\n this.tech.trigger('error')\r\n }\r\n }\r\n\r\n private switchQuality (qualityId: number) {\r\n this.hls.nextLevel = qualityId\r\n }\r\n\r\n private _levelLabel (level: Hlsjs.Level) {\r\n if (this.player.srOptions_.levelLabelHandler) {\r\n return this.player.srOptions_.levelLabelHandler(level)\r\n }\r\n\r\n if (level.height) return level.height + 'p'\r\n if (level.width) return Math.round(level.width * 9 / 16) + 'p'\r\n if (level.bitrate) return (level.bitrate / 1000) + 'kbps'\r\n\r\n return 0\r\n }\r\n\r\n private _relayQualityChange (qualityLevels: QualityLevels) {\r\n\r\n // Determine if it is \"Auto\" (all tracks enabled)\r\n let isAuto = true\r\n\r\n for (let i = 0; i < qualityLevels.length; i++) {\r\n if (!qualityLevels[ i ]._enabled) {\r\n isAuto = false\r\n break\r\n }\r\n }\r\n\r\n // Interact with ME\r\n if (isAuto) {\r\n this.hls.currentLevel = -1\r\n return\r\n }\r\n\r\n // Find ID of highest enabled track\r\n let selectedTrack: number\r\n\r\n for (selectedTrack = qualityLevels.length - 1; selectedTrack >= 0; selectedTrack--) {\r\n if (qualityLevels[ selectedTrack ]._enabled) {\r\n break\r\n }\r\n }\r\n\r\n this.hls.currentLevel = selectedTrack\r\n }\r\n\r\n private _handleQualityLevels () {\r\n if (!this.metadata) return\r\n\r\n const qualityLevels = this.player.qualityLevels && this.player.qualityLevels()\r\n if (!qualityLevels) return\r\n\r\n for (let i = 0; i < this.metadata.levels.length; i++) {\r\n const details = this.metadata.levels[ i ]\r\n const representation: QualityLevelRepresentation = {\r\n id: i,\r\n width: details.width,\r\n height: details.height,\r\n bandwidth: details.bitrate,\r\n bitrate: details.bitrate,\r\n _enabled: true\r\n }\r\n\r\n const self = this\r\n representation.enabled = function (this: QualityLevels, level: number, toggle?: boolean) {\r\n // Brightcove switcher works TextTracks-style (enable tracks that it wants to ABR on)\r\n if (typeof toggle === 'boolean') {\r\n\r\n this[ level ]._enabled = toggle\r\n self._relayQualityChange(this)\r\n }\r\n\r\n return this[ level ]._enabled\r\n }\r\n\r\n qualityLevels.addQualityLevel(representation)\r\n }\r\n }\r\n\r\n private _notifyVideoQualities () {\r\n if (!this.metadata) return\r\n const cleanTracklist = []\r\n\r\n if (this.metadata.levels.length > 1) {\r\n const autoLevel = {\r\n id: -1,\r\n label: 'auto',\r\n selected: this.hls.manualLevel === -1\r\n }\r\n cleanTracklist.push(autoLevel)\r\n }\r\n\r\n this.metadata.levels.forEach((level, index) => {\r\n // Don't write in level (shared reference with Hls.js)\r\n const quality = {\r\n id: index,\r\n selected: index === this.hls.manualLevel,\r\n label: this._levelLabel(level)\r\n }\r\n\r\n cleanTracklist.push(quality)\r\n })\r\n\r\n const payload = {\r\n qualityData: { video: cleanTracklist },\r\n qualitySwitchCallback: this.switchQuality.bind(this)\r\n }\r\n\r\n this.tech.trigger('loadedqualitydata', payload)\r\n\r\n // Self-de-register so we don't raise the payload multiple times\r\n this.videoElement.removeEventListener('playing', this.handlers.playing)\r\n }\r\n\r\n private _updateSelectedAudioTrack () {\r\n const playerAudioTracks = this.tech.audioTracks()\r\n for (let j = 0; j < playerAudioTracks.length; j++) {\r\n // FIXME: typings\r\n if ((playerAudioTracks[ j ] as any).enabled) {\r\n this.hls.audioTrack = j\r\n break\r\n }\r\n }\r\n }\r\n\r\n private _onAudioTracks () {\r\n const hlsAudioTracks = this.hls.audioTracks\r\n const playerAudioTracks = this.tech.audioTracks()\r\n\r\n if (hlsAudioTracks.length > 1 && playerAudioTracks.length === 0) {\r\n // Add Hls.js audio tracks if not added yet\r\n for (let i = 0; i < hlsAudioTracks.length; i++) {\r\n playerAudioTracks.addTrack(new this.vjs.AudioTrack({\r\n id: i.toString(),\r\n kind: 'alternative',\r\n label: hlsAudioTracks[ i ].name || hlsAudioTracks[ i ].lang,\r\n language: hlsAudioTracks[ i ].lang,\r\n enabled: i === this.hls.audioTrack\r\n }))\r\n }\r\n\r\n // Handle audio track change event\r\n this.handlers.audioTracksChange = this._updateSelectedAudioTrack.bind(this)\r\n playerAudioTracks.addEventListener('change', this.handlers.audioTracksChange)\r\n }\r\n }\r\n\r\n private _getTextTrackLabel (textTrack: TextTrack) {\r\n // Label here is readable label and is optional (used in the UI so if it is there it should be different)\r\n return textTrack.label ? textTrack.label : textTrack.language\r\n }\r\n\r\n private _isSameTextTrack (track1: TextTrack, track2: TextTrack) {\r\n return this._getTextTrackLabel(track1) === this._getTextTrackLabel(track2)\r\n && track1.kind === track2.kind\r\n }\r\n\r\n private _updateSelectedTextTrack () {\r\n const playerTextTracks = this.player.textTracks()\r\n let activeTrack: TextTrack = null\r\n\r\n for (let j = 0; j < playerTextTracks.length; j++) {\r\n if (playerTextTracks[ j ].mode === 'showing') {\r\n activeTrack = playerTextTracks[ j ]\r\n break\r\n }\r\n }\r\n\r\n const hlsjsTracks = this.videoElement.textTracks\r\n for (let k = 0; k < hlsjsTracks.length; k++) {\r\n if (hlsjsTracks[ k ].kind === 'subtitles' || hlsjsTracks[ k ].kind === 'captions') {\r\n hlsjsTracks[ k ].mode = activeTrack && this._isSameTextTrack(hlsjsTracks[ k ], activeTrack)\r\n ? 'showing'\r\n : 'disabled'\r\n }\r\n }\r\n }\r\n\r\n private _startLoad () {\r\n this.hls.startLoad(-1)\r\n this.videoElement.removeEventListener('play', this.handlers.play)\r\n }\r\n\r\n private _oneLevelObjClone (obj: object) {\r\n const result = {}\r\n const objKeys = Object.keys(obj)\r\n for (let i = 0; i < objKeys.length; i++) {\r\n result[ objKeys[ i ] ] = obj[ objKeys[ i ] ]\r\n }\r\n\r\n return result\r\n }\r\n\r\n private _filterDisplayableTextTracks (textTracks: TextTrackList) {\r\n const displayableTracks = []\r\n\r\n // Filter out tracks that is displayable (captions or subtitles)\r\n for (let idx = 0; idx < textTracks.length; idx++) {\r\n if (textTracks[ idx ].kind === 'subtitles' || textTracks[ idx ].kind === 'captions') {\r\n displayableTracks.push(textTracks[ idx ])\r\n }\r\n }\r\n\r\n return displayableTracks\r\n }\r\n\r\n private _updateTextTrackList () {\r\n const displayableTracks = this._filterDisplayableTextTracks(this.videoElement.textTracks)\r\n const playerTextTracks = this.player.textTracks()\r\n\r\n // Add stubs to make the caption switcher shows up\r\n // Adding the Hls.js text track in will make us have double captions\r\n for (let idx = 0; idx < displayableTracks.length; idx++) {\r\n let isAdded = false\r\n\r\n for (let jdx = 0; jdx < playerTextTracks.length; jdx++) {\r\n if (this._isSameTextTrack(displayableTracks[ idx ], playerTextTracks[ jdx ])) {\r\n isAdded = true\r\n break\r\n }\r\n }\r\n\r\n if (!isAdded) {\r\n const hlsjsTextTrack = displayableTracks[ idx ]\r\n this.player.addRemoteTextTrack({\r\n kind: hlsjsTextTrack.kind as videojs.TextTrack.Kind,\r\n label: this._getTextTrackLabel(hlsjsTextTrack),\r\n language: hlsjsTextTrack.language,\r\n srclang: hlsjsTextTrack.language\r\n }, false)\r\n }\r\n }\r\n\r\n // Handle UI switching\r\n this._updateSelectedTextTrack()\r\n\r\n if (!this.uiTextTrackHandled) {\r\n this.handlers.textTracksChange = this._updateSelectedTextTrack.bind(this)\r\n playerTextTracks.addEventListener('change', this.handlers.textTracksChange)\r\n\r\n this.uiTextTrackHandled = true\r\n }\r\n }\r\n\r\n private _onMetaData (_event: any, data: Hlsjs.ManifestLoadedData) {\r\n // This could arrive before 'loadedqualitydata' handlers is registered, remember it so we can raise it later\r\n this.metadata = data as any\r\n this._handleQualityLevels()\r\n }\r\n\r\n private _createCueHandler (captionConfig: any) {\r\n return {\r\n newCue: (track: any, startTime: number, endTime: number, captionScreen: { rows: any[] }) => {\r\n let row: any\r\n let cue: VTTCue\r\n let text: string\r\n const VTTCue = (window as any).VTTCue || (window as any).TextTrackCue\r\n\r\n for (let r = 0; r < captionScreen.rows.length; r++) {\r\n row = captionScreen.rows[ r ]\r\n text = ''\r\n\r\n if (!row.isEmpty()) {\r\n for (let c = 0; c < row.chars.length; c++) {\r\n text += row.chars[ c ].ucharj\r\n }\r\n\r\n cue = new VTTCue(startTime, endTime, text.trim())\r\n\r\n // typeof null === 'object'\r\n if (captionConfig != null && typeof captionConfig === 'object') {\r\n // Copy client overridden property into the cue object\r\n const configKeys = Object.keys(captionConfig)\r\n\r\n for (let k = 0; k < configKeys.length; k++) {\r\n cue[ configKeys[ k ] ] = captionConfig[ configKeys[ k ] ]\r\n }\r\n }\r\n track.addCue(cue)\r\n if (endTime === startTime) track.addCue(new VTTCue(endTime + 5, ''))\r\n }\r\n }\r\n }\r\n }\r\n }\r\n\r\n private _initHlsjs () {\r\n const techOptions = this.tech.options_ as HlsjsConfigHandlerOptions\r\n const srOptions_ = this.player.srOptions_\r\n\r\n const hlsjsConfigRef = srOptions_ && srOptions_.hlsjsConfig || techOptions.hlsjsConfig\r\n // Hls.js will write to the reference thus change the object for later streams\r\n this.hlsjsConfig = hlsjsConfigRef ? this._oneLevelObjClone(hlsjsConfigRef) : {}\r\n\r\n if ([ '', 'auto' ].includes(this.videoElement.preload) && !this.videoElement.autoplay && this.hlsjsConfig.autoStartLoad === undefined) {\r\n this.hlsjsConfig.autoStartLoad = false\r\n }\r\n\r\n \r\n\r\n const captionConfig = srOptions_ && srOptions_.captionConfig || techOptions.captionConfig\r\n if (captionConfig) {\r\n this.hlsjsConfig.cueHandler = this._createCueHandler(captionConfig)\r\n }\r\n // If the user explicitly sets autoStartLoad to false, we're not going to enter the if block above\r\n // That's why we have a separate if block here to set the 'play' listener\r\n if (this.hlsjsConfig.autoStartLoad === false) {\r\n this.handlers.play = this._startLoad.bind(this)\r\n this.videoElement.addEventListener('play', this.handlers.play)\r\n }\r\n\r\n // _notifyVideoQualities sometimes runs before the quality picker event handler is registered -> no video switcher\r\n this.handlers.playing = this._notifyVideoQualities.bind(this)\r\n this.videoElement.addEventListener('playing', this.handlers.playing)\r\n\r\n //this.hlsjsConfig.debug = true\r\n \r\n //this.hlsjsConfig.liveSyncDurationCount = 4\r\n\r\n //this.hlsjsConfig.maxMaxBufferLength = 55\r\n //this.hlsjsConfig.backBufferLength = 90\r\n\r\n ///// liveSyncPosition\r\n /* @ts-ignore */\r\n this.hlsjsConfig.capLevelController = CapLevelController\r\n\r\n this.hls = new Hlsjs.default(this.hlsjsConfig);\r\n\r\n (this.player as any).hls = this.hls;\r\n\r\n\r\n //this._executeHooksFor('beforeinitialize')\r\n\r\n this.hls.on(Hlsjs.Events.ERROR, (event : any, data : any) => this._onError(event, data))\r\n this.hls.on(Hlsjs.Events.AUDIO_TRACKS_UPDATED, () => this._onAudioTracks())\r\n this.hls.on(Hlsjs.Events.MANIFEST_PARSED, (event : any, data : any) => this._onMetaData(event, data as any)) // FIXME: typings\r\n this.hls.on(Hlsjs.Events.LEVEL_LOADED, (event : any, data : any) => {\r\n\r\n // The DVR plugin will auto seek to \"live edge\" on start up\r\n if (this.hlsjsConfig.liveSyncDuration) {\r\n this.edgeMargin = this.hlsjsConfig.liveSyncDuration\r\n } else if (this.hlsjsConfig.liveSyncDurationCount) {\r\n this.edgeMargin = this.hlsjsConfig.liveSyncDurationCount * data.details.targetduration\r\n }\r\n\r\n this.isLive = data.details.live\r\n this.dvrDuration = data.details.totalduration\r\n this._duration = this.isLive ? Infinity : data.details.totalduration\r\n })\r\n this.hls.once(Hlsjs.Events.FRAG_LOADED, () => {\r\n // Emit custom 'loadedmetadata' event for parity with `videojs-contrib-hls`\r\n // Ref: https://github.com/videojs/videojs-contrib-hls#loadedmetadata\r\n this.tech.trigger('loadedmetadata')\r\n })\r\n\r\n this.hls.attachMedia(this.videoElement)\r\n\r\n this.hls.loadSource(this.source.src)\r\n }\r\n\r\n private initialize () {\r\n this._initHlsjs()\r\n }\r\n}\r\n\r\nexport {\r\n Html5Hlsjs,\r\n registerSourceHandler,\r\n registerConfigPlugin\r\n}\r\n","import videojs from 'video.js'\r\nimport { P2PMediaLoaderPluginOptions, PlayerNetworkInfo } from '../peertube-videojs-typings'\r\nimport { Engine, initHlsJsPlayer, initVideoJsContribHlsJsPlayer } from './core/p2p-media-loader-master/p2p-media-loader-hlsjs/lib'\r\n\r\nimport { Events, Segment } from './core/p2p-media-loader-master/p2p-media-loader-core/lib'\r\nimport { timeToInt } from '../utils'\r\nimport { registerConfigPlugin, registerSourceHandler } from './hls-plugin'\r\nimport * as Hlsjs from 'hls.js'\r\n\r\nregisterConfigPlugin(videojs)\r\nregisterSourceHandler(videojs)\r\n\r\nconst Plugin = videojs.getPlugin('plugin')\r\nclass P2pMediaLoaderPlugin extends Plugin {\r\n\r\n private readonly CONSTANTS = {\r\n INFO_SCHEDULER: 1000 // Don't change this\r\n }\r\n private readonly options: P2PMediaLoaderPluginOptions\r\n\r\n private hlsjs: Hlsjs.default\r\n private p2pEngine: Engine\r\n private statsP2PBytes = {\r\n pendingDownload: [] as number[],\r\n pendingUpload: [] as number[],\r\n numPeers: 0,\r\n totalDownload: 0,\r\n totalUpload: 0\r\n }\r\n private statsHTTPBytes = {\r\n pendingDownload: [] as number[],\r\n pendingUpload: [] as number[],\r\n totalDownload: 0,\r\n totalUpload: 0\r\n }\r\n private startTime: number\r\n\r\n private networkInfoInterval: any\r\n\r\n constructor (player: videojs.Player, options?: P2PMediaLoaderPluginOptions) {\r\n super(player)\r\n\r\n this.options = options;\r\n\r\n\r\n initVideoJsContribHlsJsPlayer(player)\r\n\r\n if(options){\r\n this.startTime = timeToInt(options.startTime)\r\n\r\n player.src({\r\n type: options.type,\r\n src: options.src\r\n })\r\n }\r\n \r\n\r\n player.ready(() => {\r\n this.initializeCore()\r\n\r\n\r\n this.hlsjs = (player as any).hls\r\n\r\n\r\n if ((videojs as any).Html5Hlsjs) {\r\n if(options) this.initializePlugin()\r\n }\r\n })\r\n }\r\n\r\n dispose () {\r\n if (this.hlsjs) this.hlsjs.destroy()\r\n if (this.p2pEngine) this.p2pEngine.destroy()\r\n\r\n clearInterval(this.networkInfoInterval)\r\n }\r\n\r\n getHLSJS () {\r\n return this.hlsjs\r\n }\r\n\r\n private initializeCore () {\r\n this.player.one('play', () => {\r\n this.player.addClass('vjs-has-big-play-button-clicked')\r\n })\r\n\r\n this.player.one('canplay', () => {\r\n if (this.startTime) {\r\n this.player.currentTime(this.startTime)\r\n }\r\n })\r\n }\r\n\r\n private initializePlugin () {\r\n initHlsJsPlayer(this.hlsjs)\r\n\r\n\r\n // FIXME: typings\r\n const options = this.player.tech(true).options_ as any\r\n this.p2pEngine = options.hlsjsConfig.loader.getEngine()\r\n\r\n this.hlsjs.on(Hlsjs.Events.LEVEL_SWITCHING, (_: any, data: any) => {\r\n this.trigger('resolutionChange', { auto: this.hlsjs.autoLevelEnabled, resolutionId: data.height })\r\n })\r\n\r\n this.p2pEngine.on(Events.SegmentError, (segment: Segment, err) => {\r\n this.options.redundancyUrlManager.removeBySegmentUrl(segment.requestUrl)\r\n })\r\n\r\n this.statsP2PBytes.numPeers = 1 + this.options.redundancyUrlManager.countBaseUrls()\r\n\r\n this.runStats()\r\n }\r\n\r\n private runStats () {\r\n this.p2pEngine.on(Events.PieceBytesDownloaded, (method: string, segment:any, size: number) => {\r\n const elem = method === 'p2p' ? this.statsP2PBytes : this.statsHTTPBytes\r\n\r\n elem.pendingDownload.push(size)\r\n elem.totalDownload += size\r\n })\r\n\r\n this.p2pEngine.on(Events.PieceBytesUploaded, (method: string, segment:any, size: number) => {\r\n const elem = method === 'p2p' ? this.statsP2PBytes : this.statsHTTPBytes\r\n\r\n elem.pendingUpload.push(size)\r\n elem.totalUpload += size\r\n })\r\n\r\n this.p2pEngine.on(Events.PeerConnect, () => this.statsP2PBytes.numPeers++)\r\n this.p2pEngine.on(Events.PeerClose, () => this.statsP2PBytes.numPeers--)\r\n\r\n this.networkInfoInterval = setInterval(() => {\r\n const p2pDownloadSpeed = this.arraySum(this.statsP2PBytes.pendingDownload)\r\n const p2pUploadSpeed = this.arraySum(this.statsP2PBytes.pendingUpload)\r\n\r\n const httpDownloadSpeed = this.arraySum(this.statsHTTPBytes.pendingDownload)\r\n const httpUploadSpeed = this.arraySum(this.statsHTTPBytes.pendingUpload)\r\n\r\n this.statsP2PBytes.pendingDownload = []\r\n this.statsP2PBytes.pendingUpload = []\r\n this.statsHTTPBytes.pendingDownload = []\r\n this.statsHTTPBytes.pendingUpload = []\r\n\r\n return this.player.trigger('p2pInfo', {\r\n source: 'p2p-media-loader',\r\n http: {\r\n downloadSpeed: httpDownloadSpeed,\r\n uploadSpeed: httpUploadSpeed,\r\n downloaded: this.statsHTTPBytes.totalDownload,\r\n uploaded: this.statsHTTPBytes.totalUpload\r\n },\r\n p2p: {\r\n downloadSpeed: p2pDownloadSpeed,\r\n uploadSpeed: p2pUploadSpeed,\r\n numPeers: this.statsP2PBytes.numPeers,\r\n downloaded: this.statsP2PBytes.totalDownload,\r\n uploaded: this.statsP2PBytes.totalUpload\r\n }\r\n\r\n\r\n } as PlayerNetworkInfo)\r\n \r\n }, this.CONSTANTS.INFO_SCHEDULER)\r\n }\r\n\r\n private arraySum (data: number[]) {\r\n return data.reduce((a: number, b: number) => a + b, 0)\r\n }\r\n}\r\n\r\nvideojs.registerPlugin('p2pMediaLoader', P2pMediaLoaderPlugin)\r\nexport { P2pMediaLoaderPlugin }\r\n"],"sourceRoot":""}