{"version":3,"sources":["webpack://mediasite-player/../GitLabRunner/builds/MaDYF1-sx/0/espial/mediasite/server/mvp/Mediasite/Server/Player/Player/src/plugins/conditional/multistream/middleware.js","webpack://mediasite-player/../GitLabRunner/builds/MaDYF1-sx/0/espial/mediasite/server/mvp/Mediasite/Server/Player/Player/src/plugins/conditional/multistream/stream-player.js","webpack://mediasite-player/../GitLabRunner/builds/MaDYF1-sx/0/espial/mediasite/server/mvp/Mediasite/Server/Player/Player/GitLabRunner/builds/MaDYF1-sx/0/espial/mediasite/server/mvp/Mediasite/Server/Player/Player/GitLabRunner/builds/MaDYF1-sx/0/espial/mediasite/server/mvp/Mediasite/Server/Player/Player/GitLabRunner/builds/MaDYF1-sx/0/espial/mediasite/server/mvp/Mediasite/Server/Player/Player/src/plugins/conditional/multistream.css","webpack://mediasite-player/../GitLabRunner/builds/MaDYF1-sx/0/espial/mediasite/server/mvp/Mediasite/Server/Player/Player/src/plugins/conditional/multistream.js","webpack://mediasite-player/../GitLabRunner/builds/MaDYF1-sx/0/espial/mediasite/server/mvp/Mediasite/Server/Player/Player/GitLabRunner/builds/MaDYF1-sx/0/espial/mediasite/server/mvp/Mediasite/Server/Player/Player/GitLabRunner/builds/MaDYF1-sx/0/espial/mediasite/server/mvp/Mediasite/Server/Player/Player/src/plugins/conditional/multistream.css"],"names":["multistreamMiddleware","player","play","terminated","value","usingPlugin","multistream","handlePlayerPlaying","clamp","val","min","max","Math","CACHE_FRIENDLY_IMAGE_SIZES","StreamPlayer","videojs","constructor","options","super","stream","this","videojsPlayer","slideMapping","lastSync","isLive","initStream","streamType","ContentStreamType","setupSlides","setupVideo","element","el","style","left","x","top","y","width","height","document","createElement","setAttribute","log","JSON","stringify","appendChild","newPlayer","controls","fill","fluid","userActions","hotkeys","crossOrigin","preload","muted","errorRetries","on","error","code","MediaErrorType","setTimeout","reset","src","items","load","tech","addClass","trigger","then","paused","pause","catch","className","slides","live","enableDvr","slice","i","length","slide","nextSlide","time","nextTime","Infinity","id","timedEvents","add","duration","type","handleSlideStart","bind","handleSlideEnd","slideUrl","buildGenericSlideUrl","number","start","end","url","addSlide","lastSlideId","Object","keys","find","slideId","lastSlide","sequence","newDuration","update","slideNumber","playbackTicket","reporting","playbackTicketQuery","fullImageSrc","slideBaseUrl","toString","padStart","srcset","map","size","join","concat","imageEl","querySelector","hidden","currentTime","values","some","syncPlayback","playerTime","playbackRate","Promise","resolve","reject","Date","now","SEEK_THRESHOLD","offset","diff","abs","diffMs","round","one","streamPlaybackRate","adjustedPlaybackRate","getAttribute","priority","_container","WeakMap","_streamPlayers","_currentTimeWhenBufferingStarted","_firstPlay","_compositeAspect","_compositionList","_currentCompositionIndex","_primarySourceId","MultistreamPlugin","init","set","container","smartZoomIndex","layout","children","indexOf","getChild","addChild","smartzoom","aspect","get","target","settings","enablePIP","setBackgroundColor","color","setProperty","setBackgroundImage","setMainStreamSize","setElementSize","setStreamElementSize","rect","fudgedHeight","list","incrementCompositionIndex","newIndex","currentCompositionIndex","compositionList","uuid","streamPlayers","playerComponent","waiting","streamPlayer","syncAllPlayers","getAllStreams","getSlideStream","streams","remove","existingPlayers","seekPromises","mainTime","mainPlaybackRate","push","any","all","event","dimensionsMatch","region","X","Y","Width","Height","applyNewCompositionMap","composition","VisualCompositions","smartZoom","isZoomed","hasClass","nextRegionStreamId","VisualItems","forEach","item","idx","comps","layoutInfo","TargetRect","streamId","streamElement","SourceId","primarySourceId","moveRegion","lastFocused","dataset","zoomTargetIndex","nextVisCompItem","s","nextRegion","parentNode","unzoom","activeRegion","parse","zoom","dispose","hasSmartzoom","removeRegion","removeChild","addRegion","___CSS_LOADER_EXPORT___","module"],"mappings":"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","file":"multistream.a12d4bca12ac0d376086.js","sourcesContent":["export function multistreamMiddleware(player) {\r\n // Middleware like this gets invoked in the same call stack as the user event that triggered it.\r\n // iOS Safari doesn't normally allow programmatic calls to play() unless triggered through a\r\n // user interaction event listener at least once (and/or if the video is muted).\r\n return {\r\n play: function (terminated, value) {\r\n if (player.usingPlugin('multistream')) {\r\n player.multistream()?.handlePlayerPlaying();\r\n }\r\n\r\n return value;\r\n }\r\n }\r\n}\r\n","import videojs from 'video.js';\r\n\r\nimport { ContentStreamType, MediaErrorType } from \"../../../api/presentation\";\r\n\r\nfunction clamp(val, min, max) {\r\n return Math.min(Math.max(val, min), max);\r\n}\r\n\r\nconst SEEK_THRESHOLD = 1;\r\nconst PLAYBACK_RATE_THRESHOLD = .05;\r\nconst MAX_PLAYBACK_RATE_ADJUSTMENT = .2;\r\nconst CACHE_FRIENDLY_IMAGE_SIZES = [64, 128, 256, 512, 768];\r\nconst TEMP_FULL_SIZE_IMAGE_RES = 1024;\r\nconst MAX_ERROR_RETRIES = 100;\r\nconst RETRY_DELAY = 2000;\r\n\r\nexport default class StreamPlayer extends videojs.getComponent('Component') {\r\n constructor(player, options) {\r\n super(player, options);\r\n\r\n const { stream } = options;\r\n this.stream = stream;\r\n this.videojsPlayer = null;\r\n this.slideMapping = {};\r\n this.lastSync = 0;\r\n this.isLive = player.usingPlugin('live');\r\n }\r\n\r\n initStream() {\r\n const stream = this.stream;\r\n if (stream.streamType === ContentStreamType.Slide) {\r\n this.setupSlides();\r\n }\r\n else {\r\n this.setupVideo();\r\n }\r\n\r\n const element = this.el();\r\n element.style.left = `${stream.x * 100}%`;\r\n element.style.top = `${stream.y * 100}%`;\r\n element.style.width = `${stream.width * 100}%`;\r\n element.style.height = `${stream.height * 100}%`;\r\n }\r\n\r\n setupVideo() {\r\n const stream = this.stream;\r\n const element = document.createElement('video');\r\n element.setAttribute('playsinline', 'playsinline');\r\n\r\n this.player().multistream().log(`Initializing video stream with configuration: ${JSON.stringify(stream)}`);\r\n \r\n this.el().appendChild(element);\r\n const newPlayer = videojs(element, {\r\n controls: false,\r\n fill: false,\r\n fluid: true,\r\n userActions: {\r\n hotkeys: false\r\n },\r\n crossOrigin: 'anonymous',\r\n preload: 'auto',\r\n muted: true\r\n });\r\n\r\n //If the manifest call fails for a stream, it is likely because we are calling it before the server is ready\r\n //In this case attempt to recall the manifest and reload the stream-player. Limit to 5 tries to avoid overcalling.\r\n //For some reason this error manifests with two different error codes, so try for both.\r\n //Needs to exist here and in live plugin, because error behavior is different for multistream and single stream presentations.\r\n let errorRetries = 0;\r\n newPlayer.on('error', () => {\r\n const error = newPlayer.error();\r\n if ((error.code === MediaErrorType.NetworkError || error.code === MediaErrorType.SrcNotSupported) && errorRetries < MAX_ERROR_RETRIES) {\r\n this.setTimeout(() => {\r\n newPlayer.reset();\r\n newPlayer.src(stream.items);\r\n newPlayer.load();\r\n newPlayer.play();\r\n errorRetries++;\r\n }, RETRY_DELAY);\r\n }\r\n });\r\n newPlayer.tech(true).addClass('mediasite-player__multistream-display');\r\n\r\n this.on(newPlayer, ['seeked', 'loadeddata', 'waiting', 'playing', 'timeupdate'], this.trigger);\r\n\r\n newPlayer.src(stream.items);\r\n newPlayer.play() // Needed for iOS Safari to start loading\r\n .then(() => {\r\n if (this.player().paused()) {\r\n newPlayer.pause();\r\n }\r\n }).catch(() => { });\r\n this.videojsPlayer = newPlayer;\r\n }\r\n\r\n setupSlides() {\r\n const stream = this.stream;\r\n const element = document.createElement('img');\r\n element.className = 'mediasite-player__multistream-display';\r\n\r\n //If stream is non DVR live, only load last 50 slides to reduce loading times\r\n const slides = (this.isLive === true && this.player().live()?.enableDvr === false) ? stream.items.slice(-50) : stream.items;\r\n this.player().multistream().log(`Initializing slide stream with configuration: ${JSON.stringify(slides)}`);\r\n\r\n this.el().appendChild(element);\r\n\r\n // Add a timed event for each slide\r\n const slideMapping = {};\r\n for (let i = 0; i < slides.length; i++) {\r\n const slide = slides[i];\r\n const nextSlide = slides[i + 1];\r\n const time = slide.time / 1000; // API returns slide times in milliseconds\r\n const nextTime = nextSlide ? nextSlide.time / 1000 : Infinity;\r\n\r\n const id = this.player().timedEvents().add(\r\n {\r\n time,\r\n duration: nextTime - time,\r\n type: 'hidden'\r\n },\r\n this.handleSlideStart.bind(this),\r\n this.handleSlideEnd.bind(this)\r\n );\r\n\r\n const slideUrl = this.buildGenericSlideUrl(id);\r\n\r\n slideMapping[id] = {\r\n number: slide.number,\r\n start: time,\r\n end: nextTime,\r\n // url needed for iframe API getSlides\r\n url: slideUrl\r\n };\r\n }\r\n this.slideMapping = slideMapping;\r\n\r\n // temp: for testing only. TODO: trigger event on image load\r\n this.setTimeout(() => {\r\n this.trigger('loadeddata');\r\n }, 1000);\r\n }\r\n\r\n addSlide(slide) {\r\n const lastSlideId = Object.keys(this.slideMapping).find(slideId => {\r\n return this.slideMapping[slideId].end === Infinity;\r\n })\r\n const lastSlide = this.slideMapping[lastSlideId]\r\n\r\n if (lastSlide?.number >= slide.sequence) {\r\n //The first getLiveEvents call after page load gets all slide events from presentation start to current time\r\n //To save time and space, we must filter out slides that have already been added\r\n return\r\n }\r\n else if (lastSlide != null) {\r\n const newDuration = (slide.time / 1000) - lastSlide.start; // API returns slide times in milliseconds\r\n //Update last stored slide timed event duration from Infinity to time until start of new slide\r\n this.player().timedEvents().update(lastSlideId, { duration: newDuration })\r\n //Update last stored slide end from Infinity to start of new slide\r\n this.slideMapping[lastSlideId].end = slide.time / 1000;\r\n }\r\n\r\n const time = slide.time / 1000; // API returns slide times in milliseconds\r\n const nextTime = Infinity;\r\n const id = this.player().timedEvents().add(\r\n {\r\n time,\r\n duration: nextTime - time,\r\n type: 'hidden'\r\n },\r\n this.handleSlideStart.bind(this),\r\n this.handleSlideEnd.bind(this)\r\n );\r\n this.slideMapping[id] = {\r\n number: slide.sequence,\r\n start: time,\r\n end: nextTime\r\n };\r\n }\r\n\r\n handleSlideStart(id) {\r\n // TODO: use filename template from API; request appropriate width/height for current layout\r\n const stream = this.stream;\r\n const { number: slideNumber } = this.slideMapping[id];\r\n const playbackTicket = this.player().reporting().playbackTicket;\r\n const playbackTicketQuery = playbackTicket ? '?playbackticket=' + playbackTicket : '';\r\n const fullImageSrc = `${stream.slideBaseUrl}slide_${slideNumber.toString().padStart(4, '0')}.jpg${playbackTicketQuery} ${TEMP_FULL_SIZE_IMAGE_RES}w`;\r\n const srcset = CACHE_FRIENDLY_IMAGE_SIZES.map(size => {\r\n // Estimate the screen size at which the image is the given width in the layout\r\n return `${stream.slideBaseUrl}slide_${slideNumber.toString().padStart(4, '0')}_${size}_0.jpg${playbackTicketQuery} ${size}w`;\r\n }).join(', ').concat(', ', fullImageSrc);\r\n\r\n // Note: We could be even more specific if we take the aspect ratio of the composite into account. In landscape composites, for example:\r\n // When we're horizontally constrained, the image changes sizes when the screen changes widths.\r\n // When we're vertically constrained, the image will always be the same size (figure out the image's width in vh units).\r\n\r\n const imageEl = this.el().querySelector('img');\r\n imageEl.srcset = srcset;\r\n imageEl.hidden = false;\r\n }\r\n\r\n handleSlideEnd(id) {\r\n const currentTime = this.player().currentTime();\r\n const anotherSlideIsActive = Object.values(this.slideMapping).some(({ start, end }) => {\r\n return (start <= currentTime) && (currentTime <= end);\r\n });\r\n\r\n if (!anotherSlideIsActive) {\r\n const imageEl = this.el().querySelector('img');\r\n imageEl.srcset = '';\r\n imageEl.hidden = true;\r\n }\r\n }\r\n\r\n buildGenericSlideUrl(slideNumber) {\r\n const stream = this.stream;\r\n const playbackTicket = this.player().reporting().playbackTicket;\r\n const playbackTicketQuery = playbackTicket ? '?playbackticket=' + playbackTicket : '';\r\n const fullImageSrc = `${stream.slideBaseUrl}slide_${slideNumber.toString().padStart(4, '0')}.jpg${playbackTicketQuery}`;\r\n\r\n return fullImageSrc;\r\n }\r\n\r\n play() {\r\n return this.videojsPlayer?.play().catch(() => {});\r\n }\r\n\r\n pause() {\r\n this.videojsPlayer?.pause();\r\n }\r\n\r\n syncPlayback(playerTime, playbackRate) {\r\n return new Promise((resolve, reject) => {\r\n const currentTime = Date.now();\r\n if (this.videojsPlayer && (currentTime - this.lastSync > SEEK_THRESHOLD * 1000)) {\r\n this.lastSync = currentTime;\r\n if (this.videojsPlayer.paused()) {\r\n this.videojsPlayer.play().catch(() => {});\r\n }\r\n\r\n const streamPlayerTime = this.currentTime;\r\n const offset = streamPlayerTime - playerTime;\r\n const diff = Math.abs(offset);\r\n const diffMs = Math.round(diff * 1000);\r\n\r\n if (diff > SEEK_THRESHOLD) {\r\n // Stream is too far out of sync. Seek to catch up.\r\n this.videojsPlayer.one('seeked', resolve);\r\n this.player().multistream().log(`Secondary stream out of sync by ${diffMs}ms. Seeking to correct the difference...`);\r\n this.currentTime = playerTime;\r\n }\r\n else {\r\n // Within 1 second of sync. Adjust stream playback rate.\r\n this.videojsPlayer.one('timeupdate', resolve);\r\n if (diff > PLAYBACK_RATE_THRESHOLD) {\r\n const streamPlaybackRate = this.videojsPlayer.playbackRate();\r\n const adjustedPlaybackRate = clamp(playbackRate - offset, playbackRate - MAX_PLAYBACK_RATE_ADJUSTMENT, playbackRate + MAX_PLAYBACK_RATE_ADJUSTMENT);\r\n\r\n if (streamPlaybackRate !== adjustedPlaybackRate) {\r\n this.player().multistream().log(`Secondary stream out of sync by ${diffMs}ms. Adjusting playback rate to ${adjustedPlaybackRate}...`);\r\n this.playbackRate = clamp(adjustedPlaybackRate, .25, 2);\r\n }\r\n }\r\n else {\r\n // Close enough to being in sync. Reset playbackRate to 1.0.\r\n if (this.playbackRate !== 1) {\r\n this.player().multistream().log(`Secondary stream close enough to being in sync. Adjusting playback rate to ${this.player().playbackRate()} to match main stream...`);\r\n this.playbackRate = 1;\r\n }\r\n }\r\n }\r\n }\r\n else {\r\n resolve();\r\n }\r\n });\r\n }\r\n\r\n get priority() {\r\n return this.getAttribute('data-stream-priority')\r\n }\r\n set priority(priority) {\r\n const element = this.videojsPlayer?.tech(true) || this.el().querySelector('img');\r\n this.setAttribute('data-stream-priority', priority);\r\n element.setAttribute('data-stream-priority', priority);\r\n }\r\n\r\n get currentTime() {\r\n return this.videojsPlayer?.currentTime();\r\n }\r\n set currentTime(currentTime) {\r\n if (this.videojsPlayer) {\r\n this.videojsPlayer.currentTime(currentTime);\r\n }\r\n else {\r\n this.trigger('seeked');\r\n }\r\n }\r\n\r\n get playbackRate() {\r\n return this.videojsPlayer?.playbackRate();\r\n }\r\n set playbackRate(playbackRate) {\r\n this.videojsPlayer?.playbackRate(playbackRate);\r\n }\r\n}\r\n","import api from \"!../../../node_modules/style-loader/dist/runtime/injectStylesIntoStyleTag.js\";\n import content from \"!!../../../node_modules/css-loader/dist/cjs.js!../../../node_modules/postcss-loader/dist/cjs.js!./multistream.css\";\n\nvar options = {};\n\noptions.insert = \"head\";\noptions.singleton = false;\n\nvar update = api(content, options);\n\n\n\nexport default content.locals || {};","import videojs from 'video.js';\r\nimport { v4 as uuid } from 'uuid';\r\nimport { multistreamMiddleware } from './multistream/middleware.js';\r\nimport StreamPlayer from './multistream/stream-player.js';\r\n\r\nimport './multistream.css';\r\n\r\nconst _container = new WeakMap();\r\nconst _streamPlayers = new WeakMap();\r\nconst _currentTimeWhenBufferingStarted = new WeakMap();\r\nconst _firstPlay = new WeakMap();\r\nconst _compositeAspect = new WeakMap();\r\nconst _compositionList = new WeakMap();\r\nconst _currentCompositionIndex = new WeakMap();\r\nconst _primarySourceId = new WeakMap();\r\n\r\n/**\r\n * The Multistream module.
\r\n * Note: this module is optional and might not be available on every MediasitePlayer instance.\r\n * @member {MultistreamPlugin|undefined} multistream\r\n * @memberof MediasitePlayer#\r\n */\r\n\r\n/**\r\n * Provides support for playing back legacy presentations with multiple synchronized video & slide streams that haven't been converted to the new composited form yet.\r\n * @hideconstructor\r\n * @extends {external:\"videojs.Plugin\"}\r\n **/\r\nclass MultistreamPlugin extends videojs.getPlugin('plugin') {\r\n constructor(player, options) {\r\n super(player, options);\r\n this.log('Loaded multistream plugin.');\r\n\r\n // Use custom middleware to intercept play() calls triggered through a user interaction event listener (needed for iOS Safari playback)\r\n videojs.use('*', multistreamMiddleware);\r\n }\r\n\r\n /**\r\n * Initializes the Multistream plugin.\r\n */\r\n init() {\r\n const player = this.player;\r\n\r\n // Listen for events from the main player\r\n this.on(player, 'seeking', this.#handlePlayerSeeking);\r\n this.on(player, 'timeupdate', this.#handlePlayerTimeupdate);\r\n this.on(player, 'pause', this.#handlePlayerPause);\r\n this.on(player, 'ratechange', this.#handlePlayerRatechange);\r\n\r\n _streamPlayers.set(this, []);\r\n _currentTimeWhenBufferingStarted.set(this, 0);\r\n _firstPlay.set(this, true);\r\n _currentCompositionIndex.set(this, 0);\r\n\r\n // Create a container and move the main video element into it\r\n const Component = videojs.getComponent('component');\r\n const container = new Component(player);\r\n container.addClass('mediasite-player__multistream-container');\r\n // BAD: This plugin should not be using getChild to get a something that belongs to another plugin.\r\n const smartZoomIndex = this.player.layout().children().indexOf(this.player.getChild('SmartZoom'));\r\n player.layout().addChild(container, null, smartZoomIndex);\r\n _container.set(this, container);\r\n\r\n container.addChild(player.tech(true));\r\n\r\n // Set smartzoom to target the multistream container instead of the main video element and set a default aspect ratio\r\n _compositeAspect.set(this, 1);\r\n player.smartzoom().aspect = _compositeAspect.get(this);\r\n player.smartzoom().target = container.el();\r\n\r\n //TODO: Reexamine expected behavior for multistream picture in picture\r\n //For now, disable Picture in Picture for multistream presentations\r\n player.settings().enablePIP = false;\r\n }\r\n\r\n /**\r\n * Sets the color of the canvas behind the mult-streams.\r\n * @param {color} color A valid CSS value for the background color \r\n */\r\n setBackgroundColor(color) {\r\n const container = _container.get(this);\r\n container.el().style.setProperty('--multistream-background-color', color);\r\n }\r\n\r\n /**\r\n * Sets the image url of the canvas behind the mult-streams.\r\n * @param {string} url A valid image url to be rendered as the background\r\n */\r\n setBackgroundImage(url) {\r\n const container = _container.get(this);\r\n container.el().style.setProperty('--multistream-background-url', `url('${url}')`);\r\n }\r\n\r\n /**\r\n * Sets the size and position of the main stream within the composition.\r\n * @param {number} x A number between 0.0 and 1.0.\r\n * @param {number} y A number between 0.0 and 1.0.\r\n * @param {number} width A number between 0.0 and 1.0.\r\n * @param {number} height A number between 0.0 and 1.0.\r\n */\r\n setMainStreamSize(x, y, width, height) {\r\n const element = this.player.tech(true).el();\r\n this.setElementSize(element, x, y, width, height);\r\n\r\n this.#addSmartZoomRegion('multistream-main', {\r\n x: x,\r\n y: y,\r\n width,\r\n height,\r\n });\r\n }\r\n\r\n /**\r\n * Sets the size and position of a stream element given the rect param.\r\n * @param {HTMLElement} element The element to set the size of.\r\n * @param {object} rect A rect object with x, y, width, and height properties.\r\n */\r\n setStreamElementSize(element, rect) {\r\n this.setElementSize(element, rect.left, rect.top, rect.width, rect.height);\r\n }\r\n\r\n /**\r\n * Sets the size and position of a stream element given x, y, width, and height.\r\n * @param {HTMLElement} element The element to set the size of.\r\n * @param {number} x A number between 0.0 and 1.0.\r\n * @param {number} y A number between 0.0 and 1.0.\r\n * @param {number} width A number between 0.0 and 1.0.\r\n * @param {number} height A number between 0.0 and 1.0.\r\n */\r\n setElementSize(element, x, y, width, height) {\r\n // Main stream with zero height is likely an audio-only stream, but also the source of audio for the presentation.\r\n // Adjust the element height to be non-zero.\r\n const fudgedHeight = (height === 0) ? 0.01 : height;\r\n\r\n element.style.left = `${x * 100}%`;\r\n element.style.top = `${y * 100}%`;\r\n element.style.width = `${width * 100}%`;\r\n element.style.height = `${fudgedHeight * 100}%`;\r\n }\r\n\r\n /**\r\n * The aspect ratio of the composition.\r\n * @type {number}\r\n */\r\n get aspect() {\r\n return _compositeAspect.get(this);\r\n }\r\n\r\n set aspect(aspect) {\r\n _compositeAspect.set(this, aspect);\r\n this.player.smartzoom().aspect = aspect;\r\n }\r\n\r\n /**\r\n * The list of possible composition maps.\r\n * @type {Array}\r\n */\r\n get compositionList() {\r\n return _compositionList.get(this);\r\n }\r\n\r\n set compositionList(list) {\r\n _compositionList.set(this, list);\r\n }\r\n\r\n /**\r\n * The SourceId for the primary stream.\r\n * @type {string}\r\n */\r\n get primarySourceId() {\r\n return _primarySourceId.get(this);\r\n }\r\n\r\n set primarySourceId(id) {\r\n _primarySourceId.set(this, id);\r\n }\r\n\r\n /**\r\n * An index that determines which composition map to use.\r\n * @type {number}\r\n */\r\n get currentCompositionIndex() {\r\n return _currentCompositionIndex.get(this);\r\n }\r\n\r\n /**\r\n * Increment currentCompositionIndex or return to 0\r\n */\r\n incrementCompositionIndex() {\r\n const newIndex = (this.currentCompositionIndex + 1) % this.compositionList.length;\r\n _currentCompositionIndex.set(this, newIndex);\r\n }\r\n\r\n /**\r\n * Adds a stream to the composition.\r\n * @param {import('../../api/presentation.js').MediaStream} stream\r\n */\r\n add(stream) {\r\n return new Promise((resolve, reject) => {\r\n const id = uuid();\r\n const container = _container.get(this);\r\n const streamPlayers = _streamPlayers.get(this);\r\n\r\n //TODO: Remove once Chromium bug has been fixed - https://issues.chromium.org/issues/353552554\r\n //In Chromium, if multiple videos have same dimensions then sometimes hovering over them causes flickering\r\n //between the two videos to occur. In the case of balanced streams we will make one stream .1% smaller to avoid bug.\r\n //Always make the right stream the slightly smaller stream so the streams still always line up in the center and to avoid\r\n //situations where both streams are set smaller\r\n if (stream.width === 0.5 && stream.height === 0.5 && stream.x === 0.5) {\r\n stream.width = 0.499;\r\n stream.height = 0.499;\r\n }\r\n\r\n const playerComponent = new StreamPlayer(this.player, { stream });\r\n playerComponent.addClass('mediasite-player__multistream-stream-player');\r\n container.addChild(playerComponent);\r\n playerComponent.initStream();\r\n playerComponent.priority = stream.priority;\r\n\r\n _streamPlayers.set(this, [...streamPlayers, { id, waiting: false, streamPlayer: playerComponent }]);\r\n\r\n this.#addSmartZoomRegion(id, {\r\n x: stream.x,\r\n y: stream.y,\r\n width: stream.width,\r\n height: stream.height\r\n });\r\n \r\n playerComponent.one('loadeddata', () => {\r\n this.syncAllPlayers().then(resolve);\r\n });\r\n });\r\n }\r\n\r\n #addSmartZoomRegion(id, rect) {\r\n if (rect.width <= 0 || rect.height <= 0) {\r\n // A region with zero area makes exactly zero sense. Let's get out of here.\r\n return;\r\n }\r\n\r\n this.player.smartzoom().addRegion({\r\n left: rect.x,\r\n top: rect.y,\r\n width: rect.width,\r\n height: rect.height,\r\n id\r\n });\r\n }\r\n\r\n /**\r\n * Return the array of stream players.\r\n */\r\n getAllStreams() {\r\n return _streamPlayers.get(this);\r\n }\r\n\r\n getSlideStream() {\r\n const streams = _streamPlayers.get(this);\r\n return streams?.find(stream => {\r\n return stream.streamPlayer.stream.streamType === 2;\r\n })?.streamPlayer\r\n }\r\n\r\n remove(src) {\r\n // Todo: enable removing a multistream player\r\n // Find the player with this src\r\n // Remove it from the DOM\r\n // Dispose of it\r\n }\r\n\r\n /**\r\n * Synchronizes all secondary players to the main stream.\r\n * @returns {Promise} A promise that is resolved when all streams have finished seeking.\r\n */\r\n syncAllPlayers() {\r\n const existingPlayers = _streamPlayers.get(this);\r\n const seekPromises = [];\r\n const mainTime = this.player.currentTime();\r\n const mainPlaybackRate = this.player.playbackRate();\r\n\r\n for (const { streamPlayer, waiting } of existingPlayers) {\r\n seekPromises.push(new Promise((resolve, reject) => {\r\n streamPlayer.any(['seeked', 'playing', 'timeupdate'], resolve);\r\n }));\r\n streamPlayer.currentTime = mainTime;\r\n streamPlayer.playbackRate = mainPlaybackRate;\r\n }\r\n\r\n return Promise.all(seekPromises);\r\n }\r\n\r\n /**\r\n * A boolean indicating if there are any streams in the composition that are currently waiting.\r\n * @type {boolean}\r\n */\r\n get waiting() {\r\n const streamPlayers = _streamPlayers.get(this);\r\n return streamPlayers.some(({ waiting }) => waiting);\r\n }\r\n\r\n /**\r\n * @private\r\n * @param {Event} event\r\n */\r\n #handlePlayerSeeking(event) {\r\n if (this.waiting && !_firstPlay.get(this)) {\r\n // Still waiting for a stream to buffer - we should cancel seeking\r\n this.player.currentTime(_currentTimeWhenBufferingStarted.get(this));\r\n }\r\n else {\r\n this.syncAllPlayers().then(() => { });\r\n }\r\n }\r\n\r\n /**\r\n * @private\r\n * @param {Event} event\r\n */\r\n #handlePlayerTimeupdate(event) {\r\n if (!(this.player.paused() || this.waiting)) {\r\n const streamPlayers = _streamPlayers.get(this);\r\n const playerTime = this.player.currentTime();\r\n const playbackRate = this.player.playbackRate();\r\n\r\n for (const { streamPlayer } of streamPlayers) {\r\n streamPlayer.syncPlayback(playerTime, playbackRate);\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * NOTE: DO NOT REMOVE! This method is used by the multistream middleware that is attached in the plugin constructor.\r\n * @private\r\n * @param {Event} event\r\n */\r\n handlePlayerPlaying(event) {\r\n if (this.waiting && !_firstPlay.get(this)) {\r\n // Still waiting for a stream to buffer - we should cancel playback\r\n this.player.pause();\r\n this.player.setTimeout(() => {\r\n this.player.tech(true).trigger('waiting');\r\n }, 0);\r\n }\r\n else {\r\n _firstPlay.set(this, false);\r\n const streamPlayers = _streamPlayers.get(this);\r\n for (const { streamPlayer } of streamPlayers) {\r\n streamPlayer.play();\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * @private\r\n * @param {Event} event\r\n */\r\n #handlePlayerPause(event) {\r\n const streamPlayers = _streamPlayers.get(this);\r\n for (const { streamPlayer, waiting } of streamPlayers) {\r\n if (!waiting) {\r\n streamPlayer.pause();\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * @private\r\n * @param {Event} event\r\n */\r\n #handlePlayerRatechange(event) {\r\n this.log('Playback rate changed for primary stream. Updating all secondary streams to match...');\r\n const streamPlayers = _streamPlayers.get(this);\r\n for (const { streamPlayer } of streamPlayers) {\r\n streamPlayer.playbackRate = this.player.playbackRate();\r\n }\r\n }\r\n\r\n dimensionsMatch(rect, region) {\r\n return rect.X === region.left && rect.Y === region.top && rect.Width === region.width && rect.Height === region.height;\r\n }\r\n\r\n /**\r\n * Cycles the positions of the stream players in the composition.\r\n */\r\n applyNewCompositionMap() {\r\n const composition = this.compositionList[this.currentCompositionIndex].VisualCompositions[0];\r\n const streams = this.getAllStreams();\r\n const smartZoom = this.player.smartzoom();\r\n const isZoomed = this.player.hasClass('mediasite-player--smartzoom-zoomed');\r\n //let zoomTargetSourceId = null;\r\n let nextRegionStreamId = null;\r\n\r\n //Cycle through all items in the composition and assign the visual item's size and position to the stream element\r\n composition.VisualItems.forEach((item, idx, comps) => {\r\n const layoutInfo = {\r\n left: item.TargetRect.X,\r\n top: item.TargetRect.Y,\r\n width: item.TargetRect.Width,\r\n height: item.TargetRect.Height\r\n };\r\n\r\n //Determine if the stream is the main stream or a secondary stream\r\n let streamId, streamElement;\r\n if (item.SourceId === this.primarySourceId) {\r\n streamId = 'multistream-main';\r\n streamElement = this.player.tech(true).el();\r\n } else {\r\n //Find the player stream matching the composition source\r\n const stream = streams.find(stream => stream.streamPlayer.stream.id === item.SourceId);\r\n //Some visual items may not be represented in a movable stream, like backgrounds\r\n if (!stream) {\r\n return;\r\n }\r\n streamId = stream.id;\r\n streamElement = stream.streamPlayer.el();\r\n }\r\n\r\n //Move the smart zoom container and the stream element to new position with new dimensions\r\n smartZoom.moveRegion(streamId, layoutInfo);\r\n this.setStreamElementSize(streamElement, layoutInfo);\r\n\r\n if (isZoomed && streamId === smartZoom.lastFocused.dataset.id) {\r\n let zoomTargetIndex = idx + 1;\r\n while (!nextRegionStreamId) {\r\n const nextVisCompItem = comps[zoomTargetIndex % comps.length];\r\n nextRegionStreamId = nextVisCompItem.SourceId === this.primarySourceId ? 'multistream-main' :\r\n streams.find(s => s.streamPlayer.stream.id === nextVisCompItem.SourceId)?.id;\r\n if (zoomTargetIndex > comps.length) {\r\n break;\r\n }\r\n zoomTargetIndex++;\r\n }\r\n }\r\n });\r\n\r\n if (nextRegionStreamId) {\r\n const nextRegion = smartZoom.lastFocused.parentNode.querySelector(`.mediasite-player__smartzoom-region[data-id=\"${nextRegionStreamId}\"]`);\r\n smartZoom.unzoom(true);\r\n smartZoom.activeRegion = JSON.parse(nextRegion.dataset.region);\r\n const { left, top, width, height } = smartZoom.activeRegion;\r\n smartZoom.lastFocused = nextRegion;\r\n smartZoom.zoom(left, top, width, height);\r\n }\r\n }\r\n\r\n dispose() {\r\n const tech = this.player.tech(true);\r\n this.player.layout().addChild(tech, {}, 0);\r\n\r\n const element = tech.el();\r\n element.style.left = null;\r\n element.style.top = null;\r\n element.style.width = null;\r\n element.style.height = null;\r\n\r\n const container = _container.get(this);\r\n const streamPlayers = _streamPlayers.get(this);\r\n\r\n if (!streamPlayers) {\r\n super.dispose();\r\n return;\r\n }\r\n\r\n const hasSmartzoom = this.player?.usingPlugin('smartzoom');\r\n for (const { streamPlayer, id } of streamPlayers) {\r\n if (hasSmartzoom) {\r\n this.player.smartzoom().removeRegion(id);\r\n }\r\n \r\n container.removeChild(streamPlayer);\r\n streamPlayer.dispose();\r\n }\r\n\r\n if (hasSmartzoom) {\r\n this.player.smartzoom().removeRegion('multistream-main');\r\n }\r\n \r\n this.player.layout().removeChild(container);\r\n container.dispose();\r\n\r\n super.dispose();\r\n }\r\n}\r\n\r\nexport { MultistreamPlugin };\r\n","// Imports\nimport ___CSS_LOADER_API_SOURCEMAP_IMPORT___ from \"../../../node_modules/css-loader/dist/runtime/cssWithMappingToString.js\";\nimport ___CSS_LOADER_API_IMPORT___ from \"../../../node_modules/css-loader/dist/runtime/api.js\";\nvar ___CSS_LOADER_EXPORT___ = ___CSS_LOADER_API_IMPORT___(___CSS_LOADER_API_SOURCEMAP_IMPORT___);\n// Module\n___CSS_LOADER_EXPORT___.push([module.id, \":root {\\r\\n --multistream-rows: auto;\\r\\n --multistream-columns: auto;\\r\\n --multistream-areas: \\\"primary\\\";\\r\\n --multistream-background-color: #000;\\r\\n --multistream-background-url: none;\\r\\n}\\r\\n\\r\\n.mediasite-player__multistream-container {\\r\\n position: absolute;\\r\\n top: 0;\\r\\n left: 0;\\r\\n width: 100%;\\r\\n height: 100%;\\r\\n grid-area: video;\\r\\n background-color: var(--multistream-background-color);\\r\\n background-image: var(--multistream-background-url);\\r\\n background-repeat: no-repeat;\\r\\n background-position: center;\\r\\n background-size: 100% 100%; /*This stretches the background image to fit no matter the size of the image. This matches how the transcoder handles its videos*/\\r\\n}\\r\\n\\r\\n.mediasite-player--multistream *[data-stream-priority=\\\"1\\\"] {\\r\\n grid-area: primary;\\r\\n}\\r\\n\\r\\n.mediasite-player--multistream *[data-stream-priority=\\\"2\\\"] {\\r\\n grid-area: secondary;\\r\\n}\\r\\n\\r\\n.mediasite-player--multistream *[data-stream-priority=\\\"3\\\"] {\\r\\n grid-area: tertiary;\\r\\n}\\r\\n\\r\\n.mediasite-player--multistream *[data-stream-priority=\\\"4\\\"] {\\r\\n grid-area: quaternary;\\r\\n}\\r\\n\\r\\n/* 2 streams */\\r\\n.mediasite-player--multistream[data-multistream-count=\\\"2\\\"] *[data-stream-priority=\\\"1\\\"] {\\r\\n object-position: center right;\\r\\n}\\r\\n\\r\\n.mediasite-player--multistream[data-multistream-count=\\\"2\\\"] *[data-stream-priority=\\\"2\\\"] {\\r\\n object-position: center left;\\r\\n}\\r\\n\\r\\n/* 3 streams */\\r\\n.mediasite-player--multistream[data-multistream-count=\\\"3\\\"] *[data-stream-priority=\\\"1\\\"] {\\r\\n object-position: center right;\\r\\n}\\r\\n\\r\\n.mediasite-player--multistream[data-multistream-count=\\\"3\\\"] *[data-stream-priority=\\\"2\\\"] {\\r\\n object-position: bottom left;\\r\\n}\\r\\n\\r\\n.mediasite-player--multistream[data-multistream-count=\\\"3\\\"] *[data-stream-priority=\\\"3\\\"] {\\r\\n object-position: top left;\\r\\n}\\r\\n\\r\\n/* 4 streams */\\r\\n.mediasite-player--multistream[data-multistream-count=\\\"4\\\"] *[data-stream-priority=\\\"1\\\"] {\\r\\n object-position: bottom right;\\r\\n}\\r\\n\\r\\n.mediasite-player--multistream[data-multistream-count=\\\"4\\\"] *[data-stream-priority=\\\"2\\\"] {\\r\\n object-position: bottom left;\\r\\n}\\r\\n\\r\\n.mediasite-player--multistream[data-multistream-count=\\\"4\\\"] *[data-stream-priority=\\\"3\\\"] {\\r\\n object-position: top right;\\r\\n}\\r\\n\\r\\n.mediasite-player--multistream[data-multistream-count=\\\"4\\\"] *[data-stream-priority=\\\"3\\\"] {\\r\\n object-position: top left;\\r\\n}\\r\\n\\r\\n.mediasite-player--multistream .mediasite-player__multistream-stream-player {\\r\\n width: 100%;\\r\\n height: 100%;\\r\\n padding-top: 0;\\r\\n}\\r\\n\\r\\n.mediasite-player__multistream-stream-player {\\r\\n pointer-events: none;\\r\\n position: absolute;\\r\\n object-fit: contain;\\r\\n overflow: hidden;\\r\\n}\\r\\n\\r\\n.mediasite-player__multistream-stream-player > img {\\r\\n width: 100%;\\r\\n height: 100%;\\r\\n object-fit: contain;\\r\\n}\\r\\n\\r\\n.mediasite-player__multistream-container > img {\\r\\n width: unset;\\r\\n object-fit: contain;\\r\\n}\\r\\n\\r\\n.mediasite-player__multistream-stream-player .vjs-loading-spinner {\\r\\n display: none;\\r\\n}\\r\\n\", \"\",{\"version\":3,\"sources\":[\"webpack://./../../../../../GitLabRunner/builds/MaDYF1-sx/0/espial/mediasite/server/mvp/Mediasite/Server/Player/Player/src/plugins/conditional/multistream.css\"],\"names\":[],\"mappings\":\"AAAA;IACI,wBAAwB;IACxB,2BAA2B;IAC3B,8BAA8B;IAC9B,oCAAoC;IACpC,kCAAkC;AACtC;;AAEA;IACI,kBAAkB;IAClB,MAAM;IACN,OAAO;IACP,WAAW;IACX,YAAY;IACZ,gBAAgB;IAChB,qDAAqD;IACrD,mDAAmD;IACnD,4BAA4B;IAC5B,2BAA2B;IAC3B,0BAA0B,EAAE,iIAAiI;AACjK;;AAEA;IACI,kBAAkB;AACtB;;AAEA;IACI,oBAAoB;AACxB;;AAEA;IACI,mBAAmB;AACvB;;AAEA;IACI,qBAAqB;AACzB;;AAEA,cAAc;AACd;IACI,6BAA6B;AACjC;;AAEA;IACI,4BAA4B;AAChC;;AAEA,cAAc;AACd;IACI,6BAA6B;AACjC;;AAEA;IACI,4BAA4B;AAChC;;AAEA;IACI,yBAAyB;AAC7B;;AAEA,cAAc;AACd;IACI,6BAA6B;AACjC;;AAEA;IACI,4BAA4B;AAChC;;AAEA;IACI,0BAA0B;AAC9B;;AAEA;IACI,yBAAyB;AAC7B;;AAEA;IACI,WAAW;IACX,YAAY;IACZ,cAAc;AAClB;;AAEA;IACI,oBAAoB;IACpB,kBAAkB;IAClB,mBAAmB;IACnB,gBAAgB;AACpB;;AAEA;IACI,WAAW;IACX,YAAY;IACZ,mBAAmB;AACvB;;AAEA;IACI,YAAY;IACZ,mBAAmB;AACvB;;AAEA;IACI,aAAa;AACjB\",\"sourcesContent\":[\":root {\\r\\n --multistream-rows: auto;\\r\\n --multistream-columns: auto;\\r\\n --multistream-areas: \\\"primary\\\";\\r\\n --multistream-background-color: #000;\\r\\n --multistream-background-url: none;\\r\\n}\\r\\n\\r\\n.mediasite-player__multistream-container {\\r\\n position: absolute;\\r\\n top: 0;\\r\\n left: 0;\\r\\n width: 100%;\\r\\n height: 100%;\\r\\n grid-area: video;\\r\\n background-color: var(--multistream-background-color);\\r\\n background-image: var(--multistream-background-url);\\r\\n background-repeat: no-repeat;\\r\\n background-position: center;\\r\\n background-size: 100% 100%; /*This stretches the background image to fit no matter the size of the image. This matches how the transcoder handles its videos*/\\r\\n}\\r\\n\\r\\n.mediasite-player--multistream *[data-stream-priority=\\\"1\\\"] {\\r\\n grid-area: primary;\\r\\n}\\r\\n\\r\\n.mediasite-player--multistream *[data-stream-priority=\\\"2\\\"] {\\r\\n grid-area: secondary;\\r\\n}\\r\\n\\r\\n.mediasite-player--multistream *[data-stream-priority=\\\"3\\\"] {\\r\\n grid-area: tertiary;\\r\\n}\\r\\n\\r\\n.mediasite-player--multistream *[data-stream-priority=\\\"4\\\"] {\\r\\n grid-area: quaternary;\\r\\n}\\r\\n\\r\\n/* 2 streams */\\r\\n.mediasite-player--multistream[data-multistream-count=\\\"2\\\"] *[data-stream-priority=\\\"1\\\"] {\\r\\n object-position: center right;\\r\\n}\\r\\n\\r\\n.mediasite-player--multistream[data-multistream-count=\\\"2\\\"] *[data-stream-priority=\\\"2\\\"] {\\r\\n object-position: center left;\\r\\n}\\r\\n\\r\\n/* 3 streams */\\r\\n.mediasite-player--multistream[data-multistream-count=\\\"3\\\"] *[data-stream-priority=\\\"1\\\"] {\\r\\n object-position: center right;\\r\\n}\\r\\n\\r\\n.mediasite-player--multistream[data-multistream-count=\\\"3\\\"] *[data-stream-priority=\\\"2\\\"] {\\r\\n object-position: bottom left;\\r\\n}\\r\\n\\r\\n.mediasite-player--multistream[data-multistream-count=\\\"3\\\"] *[data-stream-priority=\\\"3\\\"] {\\r\\n object-position: top left;\\r\\n}\\r\\n\\r\\n/* 4 streams */\\r\\n.mediasite-player--multistream[data-multistream-count=\\\"4\\\"] *[data-stream-priority=\\\"1\\\"] {\\r\\n object-position: bottom right;\\r\\n}\\r\\n\\r\\n.mediasite-player--multistream[data-multistream-count=\\\"4\\\"] *[data-stream-priority=\\\"2\\\"] {\\r\\n object-position: bottom left;\\r\\n}\\r\\n\\r\\n.mediasite-player--multistream[data-multistream-count=\\\"4\\\"] *[data-stream-priority=\\\"3\\\"] {\\r\\n object-position: top right;\\r\\n}\\r\\n\\r\\n.mediasite-player--multistream[data-multistream-count=\\\"4\\\"] *[data-stream-priority=\\\"3\\\"] {\\r\\n object-position: top left;\\r\\n}\\r\\n\\r\\n.mediasite-player--multistream .mediasite-player__multistream-stream-player {\\r\\n width: 100%;\\r\\n height: 100%;\\r\\n padding-top: 0;\\r\\n}\\r\\n\\r\\n.mediasite-player__multistream-stream-player {\\r\\n pointer-events: none;\\r\\n position: absolute;\\r\\n object-fit: contain;\\r\\n overflow: hidden;\\r\\n}\\r\\n\\r\\n.mediasite-player__multistream-stream-player > img {\\r\\n width: 100%;\\r\\n height: 100%;\\r\\n object-fit: contain;\\r\\n}\\r\\n\\r\\n.mediasite-player__multistream-container > img {\\r\\n width: unset;\\r\\n object-fit: contain;\\r\\n}\\r\\n\\r\\n.mediasite-player__multistream-stream-player .vjs-loading-spinner {\\r\\n display: none;\\r\\n}\\r\\n\"],\"sourceRoot\":\"\"}]);\n// Exports\nexport default ___CSS_LOADER_EXPORT___;\n"],"sourceRoot":""}