cloudinary-video-player
Version:
Cloudinary Video Player
77 lines (60 loc) • 1.36 MB
JavaScript
/*!
* Cloudinary Video Player v3.2.1
* Built on 2025-08-12T18:54:00.175Z
* https://github.com/cloudinary/cloudinary-video-player
*/
/*
* ATTENTION: The "eval" devtool has been used (maybe by default in mode: "development").
* This devtool is neither made for production nor for readable output files.
* It uses "eval()" calls to create a separate source file in the browser devtools.
* If you are trying to read the output file, select a different devtool (https://webpack.js.org/configuration/devtool/)
* or disable the default devtool with "devtool: false".
* If you are looking for production-ready output files, see mode: "production" (https://webpack.js.org/configuration/mode/).
*/
(self["cloudinaryVideoPlayerChunkLoading"] = self["cloudinaryVideoPlayerChunkLoading"] || []).push([["adaptive-streaming"],{
/***/ "./plugins/adaptive-streaming/abr-strategies.js":
/*!******************************************************!*\
!*** ./plugins/adaptive-streaming/abr-strategies.js ***!
\******************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
"use strict";
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ ADAPTIVE_STREAMING_STRATEGY: () => (/* binding */ ADAPTIVE_STREAMING_STRATEGY),\n/* harmony export */ abrStrategies: () => (/* binding */ abrStrategies),\n/* harmony export */ hdrSupported: () => (/* binding */ hdrSupported)\n/* harmony export */ });\nconst abrStrategies = {\n fastStart: {\n capLevelToPlayerSize: true,\n ignoreDevicePixelRatio: true,\n maxDevicePixelRatio: 2,\n abrEwmaDefaultEstimate: 4194304,\n abrEwmaDefaultEstimateMax: 4194304,\n enableWorker: false,\n startLevel: 0\n },\n balanced: {\n capLevelToPlayerSize: true,\n ignoreDevicePixelRatio: true,\n maxDevicePixelRatio: 2,\n abrEwmaDefaultEstimate: 4194304,\n abrEwmaDefaultEstimateMax: 4194304,\n enableWorker: false\n },\n highQuality: {\n capLevelToPlayerSize: true,\n ignoreDevicePixelRatio: false,\n maxDevicePixelRatio: 2,\n abrEwmaDefaultEstimate: 4194304,\n abrEwmaDefaultEstimateMax: 4194304,\n enableWorker: false\n }\n};\nconst ADAPTIVE_STREAMING_STRATEGY = Object.keys(abrStrategies);\nconst hdrSupported = window.matchMedia && window.matchMedia('(dynamic-range: high)').matches;\n\n//# sourceURL=webpack://cloudinary-video-player/./plugins/adaptive-streaming/abr-strategies.js?");
/***/ }),
/***/ "./plugins/adaptive-streaming/adaptive-streaming.js":
/*!**********************************************************!*\
!*** ./plugins/adaptive-streaming/adaptive-streaming.js ***!
\**********************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
"use strict";
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* binding */ adaptiveStreamingPlugin)\n/* harmony export */ });\n/* harmony import */ var hls_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! hls.js */ \"../node_modules/hls.js/dist/hls.mjs\");\n/* harmony import */ var videojs_contrib_quality_levels__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! videojs-contrib-quality-levels */ \"../node_modules/videojs-contrib-quality-levels/dist/videojs-contrib-quality-levels.js\");\n/* harmony import */ var videojs_contrib_quality_levels__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(videojs_contrib_quality_levels__WEBPACK_IMPORTED_MODULE_1__);\n/* harmony import */ var videojs_contrib_quality_menu__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! videojs-contrib-quality-menu */ \"../node_modules/videojs-contrib-quality-menu/dist/videojs-contrib-quality-menu.es.js\");\n/* harmony import */ var _videojs_contrib_hlsjs__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./videojs-contrib-hlsjs */ \"./plugins/adaptive-streaming/videojs-contrib-hlsjs.js\");\n/* harmony import */ var _quality_levels__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./quality-levels */ \"./plugins/adaptive-streaming/quality-levels.js\");\n/* harmony import */ var _abr_strategies__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./abr-strategies */ \"./plugins/adaptive-streaming/abr-strategies.js\");\n\n\n\n\n\n\nasync function adaptiveStreamingPlugin(player, options) {\n const config = {\n ..._abr_strategies__WEBPACK_IMPORTED_MODULE_5__.abrStrategies[options.strategy],\n videoPreference: _abr_strategies__WEBPACK_IMPORTED_MODULE_5__.hdrSupported ? {\n preferHDR: true\n } : undefined\n };\n player.tech_.options_.hlsjsConfig = config;\n player.on('loadstart', () => (0,_quality_levels__WEBPACK_IMPORTED_MODULE_4__.qualityLevels)(player, options).init());\n player.qualityMenu();\n player.adaptiveStreamingLoaded = true;\n}\n\n//# sourceURL=webpack://cloudinary-video-player/./plugins/adaptive-streaming/adaptive-streaming.js?");
/***/ }),
/***/ "./plugins/adaptive-streaming/quality-levels.js":
/*!******************************************************!*\
!*** ./plugins/adaptive-streaming/quality-levels.js ***!
\******************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
"use strict";
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ qualityLevels: () => (/* binding */ qualityLevels)\n/* harmony export */ });\n/* harmony import */ var video_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! video.js */ \"../node_modules/video.js/dist/alt/video.core-exposed.js\");\n/* harmony import */ var video_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(video_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var hls_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! hls.js */ \"../node_modules/hls.js/dist/hls.mjs\");\n\n\nconst qualityLevels = (player, options) => {\n const levelToRenditionHls = level => {\n let levelUrl = Array.isArray(level.url) && level.url.length > 1 ? level.url[level.urlId] : level.url;\n let rendition = {\n id: levelUrl,\n width: level.width,\n height: level.height,\n bandwidth: level.bitrate,\n // bitrate => bandwidth\n frameRate: 0,\n enabled: enableRendition => {\n var tech = player.tech({\n IWillNotUseThisInPlugins: true\n });\n if (typeof tech.sourceHandler_ != 'undefined' && typeof tech.sourceHandler_.hls != 'undefined' && tech.sourceHandler_.hls != null) {\n const hls = tech.sourceHandler_.hls;\n const levelIndex = hls.levels.findIndex(l => (Array.isArray(l.url) && l.url.length > 1 ? l.url[l.urlId] : l.url) === levelUrl);\n if (levelIndex >= 0 && enableRendition) {\n hls.currentLevel = levelIndex;\n }\n }\n return enableRendition;\n }\n };\n return rendition;\n };\n const levelToRenditionDash = level => ({\n id: level.id,\n width: level.width,\n height: level.height,\n bandwidth: level.bandwidth,\n enabled: enableRendition => {\n const dash = player.dash;\n if (dash && dash.mediaPlayer) {\n if (enableRendition) {\n dash.mediaPlayer.updateSettings({\n streaming: {\n abr: {\n autoSwitchBitrate: {\n video: false,\n audio: false\n }\n }\n }\n });\n // Find the correct quality index by resolution\n const targetQualityIndex = findDashQualityIndex(level.width, level.height);\n if (targetQualityIndex >= 0) {\n dash.mediaPlayer.setQualityFor('video', targetQualityIndex);\n // Set audio quality if mapping exists\n if (dash.audioMapper && dash.audioMapper[targetQualityIndex] !== undefined) {\n dash.mediaPlayer.setQualityFor('audio', dash.audioMapper[targetQualityIndex]);\n }\n }\n }\n }\n return enableRendition;\n }\n });\n const getRenditionsDash = () => {\n var dash = player.dash;\n if (typeof dash != 'undefined' && dash != null && typeof dash.mediaPlayer != 'undefined' && dash.mediaPlayer != null) {\n var streamInfo = dash.mediaPlayer.getActiveStream().getStreamInfo();\n var dashAdapter = dash.mediaPlayer.getDashAdapter();\n if (dashAdapter && streamInfo) {\n const periodIdx = streamInfo.index;\n var adaptation = dashAdapter.getAdaptationForType(periodIdx, 'video', streamInfo);\n }\n return adaptation.Representation_asArray;\n }\n return [];\n };\n\n // Helper function to find DASH quality index by resolution\n const findDashQualityIndex = (targetWidth, targetHeight) => {\n var dash = player.dash;\n if (dash && dash.mediaPlayer) {\n const availableQualities = dash.mediaPlayer.getBitrateInfoListFor('video');\n const targetQuality = availableQualities.find(q => q.width === targetWidth && q.height === targetHeight);\n return targetQuality ? targetQuality.qualityIndex : -1;\n }\n return -1;\n };\n\n // Clean up quality levels and reset state for new source\n const cleanupQualityLevels = () => {\n let qualityLevels = player.qualityLevels;\n if (typeof qualityLevels === 'function') {\n qualityLevels = player.qualityLevels();\n // Clear all existing quality levels\n qualityLevels.dispose();\n debugLog('Quality levels cleaned up for new source');\n }\n\n // Clean up audio tracks from previous source\n const audioTrackList = player.audioTracks();\n if (audioTrackList && audioTrackList.length > 0) {\n // Remove all existing audio tracks\n for (let i = audioTrackList.length - 1; i >= 0; i--) {\n audioTrackList.removeTrack(audioTrackList[i]);\n }\n debugLog('Audio tracks cleaned up for new source');\n }\n\n // Clean up DASH-specific state\n const dash = player.dash;\n if (dash && dash.audioMapper) {\n delete dash.audioMapper;\n debugLog('DASH audio mapper cleaned up for new source');\n }\n\n // Reset previous resolution for qualitychanged events\n previousResolution = null;\n };\n\n // Update the QualityLevels list of renditions\n const populateLevels = (levels, abrType) => {\n // Clean up existing quality levels before adding new ones\n cleanupQualityLevels();\n let qualityLevels = player.qualityLevels;\n if (typeof qualityLevels === 'function') {\n qualityLevels = player.qualityLevels();\n debugLog('QualityLevels', qualityLevels);\n switch (abrType) {\n case 'hls':\n for (let l = 0; l < levels.length; l++) {\n let level = levels[l];\n let rendition = levelToRenditionHls(level);\n qualityLevels.addQualityLevel(rendition);\n }\n break;\n case 'dash':\n {\n // Set up audio mapping for DASH\n const dash = player.dash;\n if (!dash) break;\n const videoRates = levels;\n const audioRates = dash.mediaPlayer.getBitrateInfoListFor('audio') || [];\n const normalizeFactor = videoRates.length > 0 ? videoRates[videoRates.length - 1].bandwidth : 1;\n dash.audioMapper = videoRates.map(rate => Math.round(rate.bandwidth / normalizeFactor * (audioRates.length - 1)));\n for (let l = 0; l < levels.length; l++) {\n let level = levels[l];\n let rendition = levelToRenditionDash(level);\n qualityLevels.addQualityLevel(rendition);\n }\n break;\n }\n default:\n return;\n }\n } else {\n console.warn('QualityLevels not supported');\n }\n };\n let previousResolution = null; // for qualitychanged event data\n\n // Update the selected rendition\n const populateQualityLevelsChange = currentLevel => {\n let qualityLevels = player.qualityLevels;\n if (typeof qualityLevels === 'function') {\n qualityLevels = player.qualityLevels();\n if (qualityLevels.length == 0) {\n console.warn('ERROR - no quality levels found! Patching populate levels first');\n var tech = player.tech({\n IWillNotUseThisInPlugins: true\n });\n if (typeof tech.sourceHandler_ != 'undefined' && typeof tech.sourceHandler_.hls != 'undefined' && tech.sourceHandler_.hls != null) {\n const hls = tech.sourceHandler_.hls;\n populateLevels(hls.levels, 'hls');\n }\n }\n qualityLevels.selectedIndex_ = currentLevel;\n qualityLevels.trigger({\n type: 'change',\n selectedIndex: currentLevel\n });\n }\n };\n\n // Custom 'qualitychanged' event\n const populateQualityChangedEvent = currentLevel => {\n if (currentLevel < 0) {\n return;\n }\n let qualityLevels = player.qualityLevels;\n let level = null;\n // Using videojs-contrib-quality-levels\n if (typeof qualityLevels === 'function') {\n qualityLevels = player.qualityLevels();\n level = qualityLevels.levels_[currentLevel];\n debugLog('Custom qualitychanged', 'using videojs-contrib-quality-levels');\n } else {\n // hls.js directly\n var tech = player.tech({\n IWillNotUseThisInPlugins: true\n });\n if (typeof tech.sourceHandler_ != 'undefined' && typeof tech.sourceHandler_.hls != 'undefined' && tech.sourceHandler_.hls != null) {\n const hls = tech.sourceHandler_.hls;\n level = hls.levels[currentLevel];\n debugLog('Custom qualitychanged', 'using hls.js directly');\n if (currentLevel !== hls.currentLevel) {\n debugLog('ERROR - new level differs from hls.js');\n }\n } else {\n // dash.js directly\n var dash = player.dash;\n if (typeof dash != 'undefined' && dash != null && typeof dash.mediaPlayer != 'undefined' && dash.mediaPlayer != null) {\n let renditions = getRenditionsDash();\n level = renditions[currentLevel];\n debugLog('Custom qualitychanged', 'using dash.js directly');\n }\n }\n }\n\n // Add null check for level\n if (!level) {\n debugLog('Warning: Level is undefined in populateQualityChangedEvent', {\n currentLevel\n });\n return;\n }\n let currentRes = {\n width: level.width,\n height: level.height\n };\n if (previousResolution !== currentRes) {\n let data = {\n from: previousResolution,\n to: currentRes\n };\n // Trigger custom 'qualitychanged' event on videojs\n player.trigger({\n type: 'qualitychanged',\n eventData: data\n });\n }\n previousResolution = currentRes;\n\n // Add detailed logging of current rendition\n debugLog('Current Rendition', {\n index: currentLevel,\n resolution: `${level.width}x${level.height}`,\n bitrate: `${Math.round(level.bitrate / 1000)} kbps`,\n url: Array.isArray(level.url) ? level.url[level.urlId] : level.url,\n details: level\n });\n };\n const debugLog = (label, data) => {\n if (options.debug) {\n console.log(`%c ${label}`, 'background: #3498db; color: white; padding: 2px 4px; border-radius: 2px;', data);\n }\n };\n const logAudioTrackInfo = () => {\n var tech = player.tech({\n IWillNotUseThisInPlugins: true\n });\n if (typeof tech.sourceHandler_ != 'undefined' && typeof tech.sourceHandler_.hls != 'undefined' && tech.sourceHandler_.hls != null) {\n const hls = tech.sourceHandler_.hls;\n const audioTrackId = hls.audioTrack;\n const len = hls.audioTracks.length;\n for (let i = 0; i < len; i++) {\n if (audioTrackId === i) {\n debugLog(`audio track [${i}] ${hls.audioTracks[i].name} - enabled`, hls.audioTracks[i]);\n } else {\n debugLog(`audio track [${i}] ${hls.audioTracks[i].name} - disabled`, hls.audioTracks[i]);\n }\n }\n }\n };\n\n // Helper to synchronise Video.js AudioTrackList with hls.js active track\n const updateVjsAudioTracksEnabled = activeIndex => {\n const list = player.audioTracks();\n if (!list) return;\n for (let i = 0; i < list.length; i++) {\n list[i].enabled = i === activeIndex;\n }\n // Sync complete – log for debug\n logAudioTrackInfo();\n };\n\n // Flush buffered audio by performing a tiny seek outside current range\n const flushBufferedAudio = () => {\n try {\n const cur = player.currentTime();\n const delta = 0.5; // 500 ms gap to escape current buffer\n const target = Math.min(cur + delta, player.duration() - 0.1);\n player.currentTime(target);\n player.currentTime(cur);\n } catch (e) {\n debugLog('Error while flushing buffered audio', e);\n }\n };\n\n // Force hls.js to switch track and immediately start loading fragments for it\n const selectAudioTrack = index => {\n var tech = player.tech({\n IWillNotUseThisInPlugins: true\n });\n if (typeof tech.sourceHandler_ != 'undefined' && typeof tech.sourceHandler_.hls != 'undefined' && tech.sourceHandler_.hls != null) {\n const hls = tech.sourceHandler_.hls;\n if (hls.audioTrack === index) {\n return;\n }\n hls.audioTrack = index;\n // Quickly restart loading to fill the buffer of the new audio group\n if (hls.media) {\n try {\n hls.stopLoad();\n hls.startLoad(0);\n } catch (e) {\n debugLog('Error while reloading after audioTrack switch', e);\n }\n }\n logAudioTrackInfo();\n // will flush once switch is confirmed (AUDIO_TRACK_SWITCHED)\n hls.once(hls_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].Events.AUDIO_TRACK_SWITCHED, () => {\n flushBufferedAudio();\n });\n }\n };\n\n // Audio track handling\n const addAudioTrackVideojs = (track, hls) => {\n const vjsTrack = new (video_js__WEBPACK_IMPORTED_MODULE_0___default().AudioTrack)({\n id: `${track.type}-id_${track.id}-groupId_${track.groupId}-${track.name}`,\n kind: 'translation',\n label: track.name,\n language: track.lang,\n enabled: hls.audioTrack === hls.audioTracks.indexOf(track),\n default: track.default\n });\n\n // Add the track to the player's audio track list.\n player.audioTracks().addTrack(vjsTrack);\n };\n const initAudioTrackInfo = () => {\n var tech = player.tech({\n IWillNotUseThisInPlugins: true\n });\n if (typeof tech.sourceHandler_ != 'undefined' && typeof tech.sourceHandler_.hls != 'undefined' && tech.sourceHandler_.hls != null) {\n const hls = tech.sourceHandler_.hls;\n const len = hls.audioTracks.length;\n for (let i = 0; i < len; i++) {\n addAudioTrackVideojs(hls.audioTracks[i], hls);\n }\n }\n\n // Listen to the \"change\" event.\n var audioTrackList = player.audioTracks();\n audioTrackList.addEventListener('change', function () {\n var tech = player.tech({\n IWillNotUseThisInPlugins: true\n });\n if (typeof tech.sourceHandler_ != 'undefined' && typeof tech.sourceHandler_.hls != 'undefined' && tech.sourceHandler_.hls != null) {\n for (var i = 0; i < audioTrackList.length; i++) {\n var track = audioTrackList[i];\n if (track.enabled) {\n selectAudioTrack(i);\n return;\n }\n }\n }\n });\n };\n\n // Map hls.js events to QualityLevels\n const initQualityLevels = () => {\n var tech = player.tech({\n IWillNotUseThisInPlugins: true\n });\n if (typeof tech == 'undefined') {\n console.warn('ERROR - tech not found!');\n }\n\n // HLS\n if (typeof tech.sourceHandler_ != 'undefined' && typeof tech.sourceHandler_.hls != 'undefined' && tech.sourceHandler_.hls != null) {\n const hls = tech.sourceHandler_.hls;\n const manifestLoadedHandler = (eventName, data) => {\n debugLog(`HLS event: ${eventName}`, data);\n populateLevels(hls.levels, 'hls');\n initAudioTrackInfo();\n hls.off(hls_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].Events.MANIFEST_LOADED, manifestLoadedHandler);\n };\n\n // If manifest is already loaded, populate levels immediately.\n if (hls.levels && hls.levels.length > 0) {\n manifestLoadedHandler('MANUAL_MANIFEST_LOADED', {});\n } else {\n hls.on(hls_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].Events.MANIFEST_LOADED, manifestLoadedHandler);\n }\n hls.on(hls_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].Events.LEVEL_SWITCHED, (eventName, data) => {\n debugLog(`HLS event: ${eventName}`, data);\n populateQualityLevelsChange(data.level);\n populateQualityChangedEvent(data.level);\n });\n hls.on(hls_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].Events.AUDIO_TRACK_SWITCHED, (eventName, data) => {\n debugLog(`HLS event: ${eventName}`, data);\n // Make sure Video.js AudioTracks reflect the newly-selected HLS track\n if (typeof data.id !== 'undefined') {\n updateVjsAudioTracksEnabled(data.id);\n }\n // Ensure buffer flushed when switch originates from hls.js (e.g. default track)\n flushBufferedAudio();\n });\n hls.on(hls_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].Events.ERROR, (eventName, data) => {\n debugLog(`HLS event: ${eventName}`, data);\n if (data.fatal) {\n player.error({\n code: 4,\n // MEDIA_ERR_SRC_NOT_SUPPORTED will trigger Utils.handleCldError\n ...data\n });\n }\n });\n } else {\n // DASH\n var dash = player.dash;\n if (typeof dash != 'undefined' && dash != null && typeof dash.mediaPlayer != 'undefined' && dash.mediaPlayer != null) {\n let renditions = getRenditionsDash();\n populateLevels(renditions, 'dash');\n dash.mediaPlayer.on('qualityChangeRendered', evt => {\n const currentVideoQuality = dash.mediaPlayer.getQualityFor('video');\n const availableQualities = dash.mediaPlayer.getBitrateInfoListFor('video');\n const currentQualityInfo = availableQualities[currentVideoQuality];\n const renditionIndex = findDashQualityIndex(currentQualityInfo.width, currentQualityInfo.height);\n if (renditionIndex >= 0) {\n debugLog(`DASH event: ${evt.type}`, evt, renditions[renditionIndex]);\n populateQualityLevelsChange(renditionIndex);\n populateQualityChangedEvent(renditionIndex);\n } else {\n console.warn('Could not find matching rendition for DASH quality change');\n }\n });\n }\n }\n };\n return {\n init: initQualityLevels\n };\n};\n\n\n//# sourceURL=webpack://cloudinary-video-player/./plugins/adaptive-streaming/quality-levels.js?");
/***/ }),
/***/ "./plugins/adaptive-streaming/videojs-contrib-hlsjs.js":
/*!*************************************************************!*\
!*** ./plugins/adaptive-streaming/videojs-contrib-hlsjs.js ***!
\*************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
"use strict";
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var hls_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! hls.js */ \"../node_modules/hls.js/dist/hls.mjs\");\n\n\n\n\n/**\n * hls.js source handler\n * Source: https://github.com/Peer5/videojs-contrib-hls.js\n * @param source\n * @param tech\n * @constructor\n */\nfunction Html5HlsJS(source, tech) {\n var options = tech.options_;\n var el = tech.el();\n var duration = null;\n var hls = this.hls = new hls_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"](options.hlsjsConfig);\n\n /**\n * creates an error handler function\n * @returns {Function}\n */\n function errorHandlerFactory() {\n var _recoverDecodingErrorDate = null;\n var _recoverAudioCodecErrorDate = null;\n return function () {\n var now = Date.now();\n if (!_recoverDecodingErrorDate || now - _recoverDecodingErrorDate > 2000) {\n _recoverDecodingErrorDate = now;\n hls.recoverMediaError();\n } else if (!_recoverAudioCodecErrorDate || now - _recoverAudioCodecErrorDate > 2000) {\n _recoverAudioCodecErrorDate = now;\n hls.swapAudioCodec();\n hls.recoverMediaError();\n } else {\n console.error('Error loading media: File could not be played');\n }\n };\n }\n\n // create separate error handlers for hlsjs and the video tag\n var hlsjsErrorHandler = errorHandlerFactory();\n var videoTagErrorHandler = errorHandlerFactory();\n\n // listen to error events coming from the video tag\n el.addEventListener('error', function (e) {\n var mediaError = e.currentTarget.error;\n if (mediaError.code === mediaError.MEDIA_ERR_DECODE) {\n videoTagErrorHandler();\n } else {\n console.error('Error loading media: File could not be played');\n }\n });\n\n /**\n * Destroys the Hls instance\n */\n this.dispose = function () {\n hls.destroy();\n };\n\n /**\n * returns the duration of the stream, or Infinity if live video\n * @returns {Infinity|number}\n */\n this.duration = function () {\n return duration || el.duration || 0;\n };\n\n // update live status on level load\n hls.on(hls_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].Events.LEVEL_LOADED, function (event, data) {\n duration = data.details.live ? Infinity : data.details.totalduration;\n });\n\n // try to recover on fatal errors\n hls.on(hls_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].Events.ERROR, function (event, data) {\n if (data.fatal) {\n switch (data.type) {\n case hls_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].ErrorTypes.NETWORK_ERROR:\n hls.startLoad();\n break;\n case hls_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].ErrorTypes.MEDIA_ERROR:\n hlsjsErrorHandler();\n break;\n default:\n console.error('Error loading media: File could not be played');\n break;\n }\n }\n });\n Object.keys(hls_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].Events).forEach(function (key) {\n var eventName = hls_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].Events[key];\n hls.on(eventName, function (event, data) {\n tech.trigger(eventName, data);\n });\n });\n\n // Intercept native TextTrack calls and route to video.js directly only\n // if native text tracks are not supported on this browser.\n if (!tech.featuresNativeTextTracks) {\n Object.defineProperty(el, 'textTracks', {\n value: tech.textTracks,\n writable: false\n });\n el.addTextTrack = function () {\n return tech.addTextTrack.apply(tech, arguments);\n };\n }\n\n // attach hlsjs to videotag\n hls.attachMedia(el);\n hls.loadSource(source.src);\n}\nvar hlsTypeRE = /^application\\/(x-mpegURL|vnd\\.apple\\.mpegURL)$/i;\nvar hlsExtRE = /\\.m3u8/i;\nvar HlsSourceHandler = {\n canHandleSource: function (source) {\n if (source.skipContribHlsJs) {\n return '';\n } else if (hlsTypeRE.test(source.type)) {\n return 'probably';\n } else if (hlsExtRE.test(source.src)) {\n return 'maybe';\n } else {\n return '';\n }\n },\n handleSource: function (source, tech) {\n return new Html5HlsJS(source, tech);\n },\n canPlayType: function (type) {\n if (hlsTypeRE.test(type)) {\n return 'probably';\n }\n return '';\n }\n};\nif (hls_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].isSupported()) {\n var videojs = window.videojs;\n\n // support es6 style import\n videojs = videojs && videojs.default || videojs;\n if (videojs) {\n var html5Tech = videojs.getTech && videojs.getTech('Html5'); // videojs6 (partially on videojs5 too)\n html5Tech = html5Tech || videojs.getComponent && videojs.getComponent('Html5'); // videojs5\n\n if (html5Tech) {\n html5Tech.registerSourceHandler(HlsSourceHandler, 0);\n }\n } else {\n console.warn('videojs-contrib-hls.js: Couldn\\'t find find window.videojs nor require(\\'video.js\\')');\n }\n}\n\n//# sourceURL=webpack://cloudinary-video-player/./plugins/adaptive-streaming/videojs-contrib-hlsjs.js?");
/***/ }),
/***/ "../node_modules/videojs-contrib-quality-levels/dist/videojs-contrib-quality-levels.js":
/*!*********************************************************************************************!*\
!*** ../node_modules/videojs-contrib-quality-levels/dist/videojs-contrib-quality-levels.js ***!
\*********************************************************************************************/
/***/ (function(module, __unused_webpack_exports, __webpack_require__) {
eval("/*! @name videojs-contrib-quality-levels @version 4.1.0 @license Apache-2.0 */\n(function (global, factory) {\n true ? module.exports = factory(__webpack_require__(/*! video.js */ \"../node_modules/video.js/dist/alt/video.core-exposed.js\")) :\n 0;\n})(this, (function (videojs) { 'use strict';\n\n function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }\n\n var videojs__default = /*#__PURE__*/_interopDefaultLegacy(videojs);\n\n /**\n * A single QualityLevel.\n *\n * interface QualityLevel {\n * readonly attribute DOMString id;\n * attribute DOMString label;\n * readonly attribute long width;\n * readonly attribute long height;\n * readonly attribute long bitrate;\n * attribute boolean enabled;\n * };\n *\n * @class QualityLevel\n */\n class QualityLevel {\n /**\n * Creates a QualityLevel\n *\n * @param {Representation|Object} representation The representation of the quality level\n * @param {string} representation.id Unique id of the QualityLevel\n * @param {number=} representation.width Resolution width of the QualityLevel\n * @param {number=} representation.height Resolution height of the QualityLevel\n * @param {number} representation.bandwidth Bitrate of the QualityLevel\n * @param {number=} representation.frameRate Frame-rate of the QualityLevel\n * @param {Function} representation.enabled Callback to enable/disable QualityLevel\n */\n constructor(representation) {\n let level = this; // eslint-disable-line\n\n level.id = representation.id;\n level.label = level.id;\n level.width = representation.width;\n level.height = representation.height;\n level.bitrate = representation.bandwidth;\n level.frameRate = representation.frameRate;\n level.enabled_ = representation.enabled;\n Object.defineProperty(level, 'enabled', {\n /**\n * Get whether the QualityLevel is enabled.\n *\n * @return {boolean} True if the QualityLevel is enabled.\n */\n get() {\n return level.enabled_();\n },\n /**\n * Enable or disable the QualityLevel.\n *\n * @param {boolean} enable true to enable QualityLevel, false to disable.\n */\n set(enable) {\n level.enabled_(enable);\n }\n });\n return level;\n }\n }\n\n /**\n * A list of QualityLevels.\n *\n * interface QualityLevelList : EventTarget {\n * getter QualityLevel (unsigned long index);\n * readonly attribute unsigned long length;\n * readonly attribute long selectedIndex;\n *\n * void addQualityLevel(QualityLevel qualityLevel)\n * void removeQualityLevel(QualityLevel remove)\n * QualityLevel? getQualityLevelById(DOMString id);\n *\n * attribute EventHandler onchange;\n * attribute EventHandler onaddqualitylevel;\n * attribute EventHandler onremovequalitylevel;\n * };\n *\n * @extends videojs.EventTarget\n * @class QualityLevelList\n */\n class QualityLevelList extends videojs__default[\"default\"].EventTarget {\n /**\n * Creates a QualityLevelList.\n */\n constructor() {\n super();\n let list = this; // eslint-disable-line\n\n list.levels_ = [];\n list.selectedIndex_ = -1;\n\n /**\n * Get the index of the currently selected QualityLevel.\n *\n * @returns {number} The index of the selected QualityLevel. -1 if none selected.\n * @readonly\n */\n Object.defineProperty(list, 'selectedIndex', {\n get() {\n return list.selectedIndex_;\n }\n });\n\n /**\n * Get the length of the list of QualityLevels.\n *\n * @returns {number} The length of the list.\n * @readonly\n */\n Object.defineProperty(list, 'length', {\n get() {\n return list.levels_.length;\n }\n });\n list[Symbol.iterator] = () => list.levels_.values();\n return list;\n }\n\n /**\n * Adds a quality level to the list.\n *\n * @param {Representation|Object} representation The representation of the quality level\n * @param {string} representation.id Unique id of the QualityLevel\n * @param {number=} representation.width Resolution width of the QualityLevel\n * @param {number=} representation.height Resolution height of the QualityLevel\n * @param {number} representation.bandwidth Bitrate of the QualityLevel\n * @param {number=} representation.frameRate Frame-rate of the QualityLevel\n * @param {Function} representation.enabled Callback to enable/disable QualityLevel\n * @return {QualityLevel} the QualityLevel added to the list\n * @method addQualityLevel\n */\n addQualityLevel(representation) {\n let qualityLevel = this.getQualityLevelById(representation.id);\n\n // Do not add duplicate quality levels\n if (qualityLevel) {\n return qualityLevel;\n }\n const index = this.levels_.length;\n qualityLevel = new QualityLevel(representation);\n if (!('' + index in this)) {\n Object.defineProperty(this, index, {\n get() {\n return this.levels_[index];\n }\n });\n }\n this.levels_.push(qualityLevel);\n this.trigger({\n qualityLevel,\n type: 'addqualitylevel'\n });\n return qualityLevel;\n }\n\n /**\n * Removes a quality level from the list.\n *\n * @param {QualityLevel} qualityLevel The QualityLevel to remove from the list.\n * @return {QualityLevel|null} the QualityLevel removed or null if nothing removed\n * @method removeQualityLevel\n */\n removeQualityLevel(qualityLevel) {\n let removed = null;\n for (let i = 0, l = this.length; i < l; i++) {\n if (this[i] === qualityLevel) {\n removed = this.levels_.splice(i, 1)[0];\n if (this.selectedIndex_ === i) {\n this.selectedIndex_ = -1;\n } else if (this.selectedIndex_ > i) {\n this.selectedIndex_--;\n }\n break;\n }\n }\n if (removed) {\n this.trigger({\n qualityLevel,\n type: 'removequalitylevel'\n });\n }\n return removed;\n }\n\n /**\n * Searches for a QualityLevel with the given id.\n *\n * @param {string} id The id of the QualityLevel to find.\n * @return {QualityLevel|null} The QualityLevel with id, or null if not found.\n * @method getQualityLevelById\n */\n getQualityLevelById(id) {\n for (let i = 0, l = this.length; i < l; i++) {\n const level = this[i];\n if (level.id === id) {\n return level;\n }\n }\n return null;\n }\n\n /**\n * Resets the list of QualityLevels to empty\n *\n * @method dispose\n */\n dispose() {\n this.selectedIndex_ = -1;\n this.levels_.length = 0;\n }\n }\n\n /**\n * change - The selected QualityLevel has changed.\n * addqualitylevel - A QualityLevel has been added to the QualityLevelList.\n * removequalitylevel - A QualityLevel has been removed from the QualityLevelList.\n */\n QualityLevelList.prototype.allowedEvents_ = {\n change: 'change',\n addqualitylevel: 'addqualitylevel',\n removequalitylevel: 'removequalitylevel'\n };\n\n // emulate attribute EventHandler support to allow for feature detection\n for (const event in QualityLevelList.prototype.allowedEvents_) {\n QualityLevelList.prototype['on' + event] = null;\n }\n\n var version = \"4.1.0\";\n\n /**\n * Initialization function for the qualityLevels plugin. Sets up the QualityLevelList and\n * event handlers.\n *\n * @param {Player} player Player object.\n * @param {Object} options Plugin options object.\n * @return {QualityLevelList} a list of QualityLevels\n */\n const initPlugin = function (player, options) {\n const originalPluginFn = player.qualityLevels;\n const qualityLevelList = new QualityLevelList();\n const disposeHandler = function () {\n qualityLevelList.dispose();\n player.qualityLevels = originalPluginFn;\n player.off('dispose', disposeHandler);\n };\n player.on('dispose', disposeHandler);\n player.qualityLevels = () => qualityLevelList;\n player.qualityLevels.VERSION = version;\n return qualityLevelList;\n };\n\n /**\n * A video.js plugin.\n *\n * In the plugin function, the value of `this` is a video.js `Player`\n * instance. You cannot rely on the player being in a \"ready\" state here,\n * depending on how the plugin is invoked. This may or may not be important\n * to you; if not, remove the wait for \"ready\"!\n *\n * @param {Object} options Plugin options object\n * @return {QualityLevelList} a list of QualityLevels\n */\n const qualityLevels = function (options) {\n return initPlugin(this, videojs__default[\"default\"].obj.merge({}, options));\n };\n\n // Register the plugin with video.js.\n videojs__default[\"default\"].registerPlugin('qualityLevels', qualityLevels);\n\n // Include the version number.\n qualityLevels.VERSION = version;\n\n return qualityLevels;\n\n}));\n\n\n//# sourceURL=webpack://cloudinary-video-player/../node_modules/videojs-contrib-quality-levels/dist/videojs-contrib-quality-levels.js?");
/***/ }),
/***/ "../node_modules/videojs-contrib-quality-menu/dist/videojs-contrib-quality-menu.es.js":
/*!********************************************************************************************!*\
!*** ../node_modules/videojs-contrib-quality-menu/dist/videojs-contrib-quality-menu.es.js ***!
\********************************************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
"use strict";
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* binding */ qualityMenu)\n/* harmony export */ });\n/* harmony import */ var video_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! video.js */ \"../node_modules/video.js/dist/alt/video.core-exposed.js\");\n/* harmony import */ var video_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(video_js__WEBPACK_IMPORTED_MODULE_0__);\n/*! @name videojs-contrib-quality-menu @version 1.0.4 @license Apache-2.0 */\n\n\n/**\n * @file quality-menu-item.js\n */\nconst MenuItem = video_js__WEBPACK_IMPORTED_MODULE_0___default().getComponent('MenuItem');\nconst dom = (video_js__WEBPACK_IMPORTED_MODULE_0___default().dom) || (video_js__WEBPACK_IMPORTED_MODULE_0___default());\n\n/**\n * The quality level menu quality\n *\n * @extends MenuItem\n * @class QualityMenuItem\n */\nclass QualityMenuItem extends MenuItem {\n /**\n * Creates a QualityMenuItem\n *\n * @param {Player|Object} player\n * Main Player\n * @param {Object} [options]\n * Options for menu item\n * @param {number[]} options.levels\n * Array of indices mapping to QualityLevels in the QualityLevelList for\n * this menu item\n * @param {string} options.label\n * Label for this menu item\n * @param {string} options.controlText\n * control text for this menu item\n * @param {string} options.subLabel\n * sub label text for this menu item\n * @param {boolean} options.active\n * True if the QualityLevelList.selectedIndex is contained in the levels list\n * for this menu\n * @param {boolean} options.selected\n * True if this menu item is the selected item in the UI\n * @param {boolean} options.selectable\n * True if this menu item should be selectable in the UI\n */\n constructor(player, options = {}) {\n const selectedOption = options.selected;\n\n // We need to change options.seleted to options.active because the call to super\n // causes us to run MenuItem's constructor which calls this.selected(options.selected)\n // However, for QualityMenuItem, we change the meaning of the parameter to\n // this.selected() to be what we mean for 'active' which is True if the\n // QualityLevelList.selectedIndex is contained in the levels list for this menu\n options.selected = options.active;\n super(player, options);\n const qualityLevels = player.qualityLevels();\n this.levels_ = options.levels;\n this.selected_ = selectedOption;\n this.handleQualityChange = this.handleQualityChange.bind(this);\n this.controlText(options.controlText);\n this.on(qualityLevels, 'change', this.handleQualityChange);\n this.on('dispose', () => {\n this.off(qualityLevels, 'change', this.handleQualityChange);\n });\n }\n\n /**\n * Create the component's DOM element\n *\n * @param {string} [type]\n * Element type\n * @param {Object} [props]\n * Element properties\n * @param {Object} [attrs]\n * An object of attributes that should be set on the element\n * @return {Element}\n * The DOM element\n * @method createEl\n */\n createEl(type, props, attrs) {\n const el = super.createEl(type, props, attrs);\n const subLabel = dom.createEl('span', {\n className: 'vjs-quality-menu-item-sub-label',\n innerHTML: this.localize(this.options_.subLabel || '')\n });\n this.subLabel_ = subLabel;\n if (el) {\n el.appendChild(subLabel);\n }\n return el;\n }\n\n /**\n * Handle a click on the menu item, and set it to selected\n *\n * @method handleClick\n */\n handleClick() {\n this.updateSiblings_();\n const qualityLevels = this.player().qualityLevels();\n const currentlySelected = qualityLevels.selectedIndex;\n for (let i = 0, l = qualityLevels.length; i < l; i++) {\n // do not disable the currently selected quality until the end to prevent\n // playlist selection from selecting something new until we've enabled/disabled\n // all the quality levels\n if (i !== currentlySelected) {\n qualityLevels[i].enabled = false;\n }\n }\n for (let i = 0, l = this.levels_.length; i < l; i++) {\n qualityLevels[this.levels_[i]].enabled = true;\n }\n\n // Disable the quality level that was selected before the click if it is not\n // associated with this menu item\n if (currentlySelected !== -1 && this.levels_.indexOf(currentlySelected) === -1) {\n qualityLevels[currentlySelected].enabled = false;\n }\n }\n\n /**\n * Handle a change event from the QualityLevelList\n *\n * @method handleQualityChange\n */\n handleQualityChange() {\n const qualityLevels = this.player().qualityLevels();\n const active = this.levels_.indexOf(qualityLevels.selectedIndex) > -1;\n this.selected(active);\n }\n\n /**\n * Set this menu item as selected or not\n *\n * @param {boolean} active\n * True if the active quality level is controlled by this item\n * @method selected\n */\n selected(active) {\n if (!this.selectable) {\n return;\n }\n if (this.selected_) {\n const hasSubLabel = this.options_.subLabel;\n this.addClass('vjs-selected');\n this.el_.setAttribute('aria-checked', 'true');\n // aria-checked isn't fully supported by browsers/screen readers,\n // so indicate selected state to screen reader in the control text.\n this.controlText(this.localize(hasSubLabel ? 'selected,' : 'selected'));\n const controlBar = this.player().controlBar;\n const menuButton = controlBar.getChild('QualityMenuButton');\n if (!active) {\n // This menu item is manually selected but the current playing quality level\n // is NOT associated with this menu item. This can happen if the quality hasnt\n // changed yet or something went wrong with rendition selection such as failed\n // server responses for playlists\n menuButton.addClass('vjs-quality-menu-button-waiting');\n } else {\n menuButton.removeClass('vjs-quality-menu-button-waiting');\n }\n } else {\n this.removeClass('vjs-selected');\n this.el_.setAttribute('aria-checked', 'false');\n // Indicate un-selected state to screen reader\n // Note that a space clears out the selected state text\n this.controlText(this.options_.controlText);\n }\n }\n\n /**\n * Sets this QualityMenuItem to be selected and deselects the other items\n *\n * @method updateSiblings_\n */\n updateSiblings_() {\n const qualityLevels = this.player().qualityLevels();\n const controlBar = this.player().controlBar;\n const menuItems = controlBar.getChild('QualityMenuButton').items;\n for (let i = 0, l = menuItems.length; i < l; i++) {\n const item = menuItems[i];\n const active = item.levels_.indexOf(qualityLevels.selectedIndex) > -1;\n item.selected_ = item === this;\n item.selected(active);\n }\n }\n}\n\n/**\n * @file quality-menu-button.js\n */\nconst MenuButton = video_js__WEBPACK_IMPORTED_MODULE_0___default().getComponent('MenuButton');\n\n/**\n * Checks whether any of the QualityLevels in a QualityLevelList have resolution information\n *\n * @param {QualityLevelList} qualityLevelList\n * The list of QualityLevels\n * @return {boolean}\n * True if any levels have resolution information, false if none have\n * @function hasResolutionInfo\n */\nconst hasResolutionInfo = function (qualityLevelList) {\n return Array.from(qualityLevelList).some(level => level.height);\n};\n\n/**\n * Determines the appropriate sub label for the given lines of resolution\n *\n * @param {number} lines\n * The horizontal lines of resolution\n * @return {string}\n * sub label for given resolution\n * @function getSubLabel\n */\nconst getSubLabel = function (lines) {\n if (lines >= 2160) {\n return '4K';\n }\n if (lines >= 720) {\n return 'HD';\n }\n return '';\n};\n\n/**\n * The component for controlling the quality menu\n *\n * @extends MenuButton\n * @class QualityMenuButton\n */\nclass QualityMenuButton extends MenuButton {\n /**\n * Creates a QualityMenuButton\n *\n * @param {Player|Object} player\n * Main Player\n * @param {Object} [options]\n * Options for QualityMenuButton\n */\n constructor(player, options = {}) {\n super(player, options);\n this.el_.setAttribute('aria-label', this.localize('Quality Levels'));\n this.controlText('Quality Levels');\n if (!player.options().experimentalSvgIcons) {\n this.$('.vjs-icon-placeholder').classList.add('vjs-icon-cog');\n }\n this.setIcon('cog');\n this.qualityLevels_ = player.qualityLevels();\n this.update = this.update.bind(this);\n this.hide = this.hide.bind(this);\n this.handleQualityChange_ = this.handleQualityChange_.bind(this);\n this.firstChangeHandler_ = this.firstChangeHandler_.bind(this);\n this.enableDefaultResolution_ = this.enableDefaultResolution_.bind(this);\n this.on(this.qualityLevels_, 'addqualitylevel', this.update);\n this.on(this.qualityLevels_, 'removequalitylevel', this.update);\n this.on(this.qualityLevels_, 'change', this.handleQualityChange_);\n\n // TODO: Remove this and the `defaultResolution` option once videojs/http-streaming supports comparable functionality\n this.one(this.qualityLevels_, 'change', this.firstChangeHandler_);\n player.on('adstart', this.hide);\n player.on(['adend', 'adtimeout'], this.update);\n this.update();\n this.on('dispose', () => {\n this.off(this.qualityLevels_, 'addqualitylevel', this.update);\n this.off(this.qualityLevels_, 'removequalitylevel', this.update);\n this.off(this.qualityLevels_, 'change', this.handleQualityChange_);\n this.off(this.qualityLevels_, 'change', this.firstChangeHandler_);\n player.off('adstart', this.hide);\n player.off(['adend', 'adtimeout'], this.update);\n player.off('loadedmetadata', this.enableDefaultResolution_);\n });\n }\n\n /**\n * Allow sub components to stack CSS class names\n *\n * @return {string}\n * The constructed class name\n * @method buildWrapperCSSClass\n */\n buildWrapperCSSClass() {\n return `vjs-quality-menu-wrapper ${super.buildWrapperCSSClass()}`;\n }\n\n /**\n * Allow sub components to stack CSS class names\n *\n * @return {string}\n * The constructed class name\n * @method buildCSSClass\n */\n buildCSSClass() {\n return `vjs-quality-menu-button ${super.buildCSSClass()}`;\n }\n\n /**\n * Create the list of menu items.\n *\n * @return {Array}\n * The list of menu items\n * @method createItems\n */\n createItems