(function main() { 'use strict'; // Captions let captionsActive = false; if (data.settings.subtitles_mode === 2 || (data.settings.subtitles_mode === 1 && data.has_manual_captions)) { captionsActive = true; } // AutoPlay let autoplayActive = data.settings.autoplay_videos || false; let qualityOptions = []; let qualityDefault; // Collect uni sources (integrated) for (let src of data.uni_sources) { qualityOptions.push(src.quality_string); } // Collect pair sources (av-merge) for (let src of data.pair_sources) { qualityOptions.push(src.quality_string); } if (data.using_pair_sources) { qualityDefault = data.pair_sources[data.pair_idx].quality_string; } else if (data.uni_sources.length !== 0) { qualityDefault = data.uni_sources[data.uni_idx].quality_string; } else { qualityDefault = 'None'; } // Current av-merge instance let avMerge = null; // Change quality: handles both uni (integrated) and pair (av-merge) function changeQuality(selection) { let currentVideoTime = video.currentTime; let videoPaused = video.paused; let videoSpeed = video.playbackRate; let srcInfo; // Close previous av-merge if any if (avMerge && typeof avMerge.close === 'function') { avMerge.close(); } if (selection.type == 'uni') { srcInfo = data.uni_sources[selection.index]; video.src = srcInfo.url; avMerge = null; } else { srcInfo = data.pair_sources[selection.index]; avMerge = new AVMerge(video, srcInfo, currentVideoTime); } video.currentTime = currentVideoTime; if (!videoPaused) { video.play(); } video.playbackRate = videoSpeed; } // Fix plyr refusing to work with qualities that are strings Object.defineProperty(Plyr.prototype, 'quality', { set: function (input) { const config = this.config.quality; const options = this.options.quality; let quality = input; let updateStorage = true; if (!options.length) { return; } if (!options.includes(quality)) { return; } // Update config config.selected = quality; // Set quality this.media.quality = quality; // Save to storage if (updateStorage) { this.storage.set({ quality }); } }, }); const playerOptions = { autoplay: autoplayActive, disableContextMenu: false, captions: { active: captionsActive, language: data.settings.subtitles_language, }, controls: [ 'play-large', 'play', 'progress', 'current-time', 'duration', 'mute', 'volume', 'captions', 'settings', 'pip', 'airplay', 'fullscreen', ], iconUrl: '/youtube.com/static/modules/plyr/plyr.svg', blankVideo: '/youtube.com/static/modules/plyr/blank.webm', debug: false, storage: { enabled: false }, quality: { default: qualityDefault, options: qualityOptions, forced: true, onChange: function (quality) { if (quality == 'None') { return; } // Check if it's a uni source (integrated) if (quality.includes('(integrated)')) { for (let i = 0; i < data.uni_sources.length; i++) { if (data.uni_sources[i].quality_string == quality) { changeQuality({ type: 'uni', index: i }); return; } } } else { // It's a pair source (av-merge) for (let i = 0; i < data.pair_sources.length; i++) { if (data.pair_sources[i].quality_string == quality) { changeQuality({ type: 'pair', index: i }); return; } } } }, }, previewThumbnails: { enabled: storyboard_url !== null, src: [storyboard_url], }, settings: ['captions', 'quality', 'speed', 'loop'], tooltips: { controls: true, }, }; const video = document.getElementById('js-video-player'); const player = new Plyr(video, playerOptions); // Hide audio track selector (DASH doesn't support multi-audio) const audioContainer = document.getElementById('plyr-audio-container'); if (audioContainer) audioContainer.style.display = 'none'; // disable double click to fullscreen player.eventListeners.forEach(function(eventListener) { if(eventListener.type === 'dblclick') { eventListener.element.removeEventListener(eventListener.type, eventListener.callback, eventListener.options); } }); // Add .started property player.started = false; player.once('playing', function(){ this.started = true; }); // Set initial time if (data.time_start != 0) { video.addEventListener('loadedmetadata', function() { video.currentTime = data.time_start; }); } })();