// ==UserScript== // @name DASH Video Player Optimizer(视频协议优化DASH篇) // @namespace http://tampermonkey.net/ // @version 1.1 // @description Optimize DASH video playback on web pages with enhanced performance and ABR management // @author KiwiFruit // @match *://*/* // @grant none // @license MIT // @downloadURL none // ==/UserScript== (function() { 'use strict'; // Helper function to fetch the first segment of the DASH manifest function fetchFirstSegment(mpdUrl) { return fetch(mpdUrl) .then(response => response.text()) .then(text => { const parser = new DOMParser(); const xmlDoc = parser.parseFromString(text, "text/xml"); // Find the first Representation and SegmentTemplate/BaseURL const representation = xmlDoc.querySelector('Representation'); const segmentTemplate = representation.querySelector('SegmentTemplate'); if (segmentTemplate) { const initialization = segmentTemplate.getAttribute('initialization'); const baseUrl = xmlDoc.querySelector('BaseURL').textContent; return `${baseUrl}${initialization}`; } else { console.error('Failed to find the first segment URL.'); return null; } }) .catch(error => console.error('Error fetching first segment:', error)); } // Preload the first segment of the video using dash.js function preloadFirstSegment(videoElement, player) { const source = videoElement.querySelector('source'); if (source && source.src.endsWith('.mpd')) { fetchFirstSegment(source.src).then(segmentUrl => { if (segmentUrl) { player.initialize(videoElement, source.src, true); } }); } } // Buffer strategy optimization function optimizeBufferStrategy(player) { player.on(dashjs.MediaPlayer.events.BUFFER_EMPTY, () => { console.log('Buffer empty, pausing playback.'); player.pause(); // Dynamic buffer time based on average throughput const bufferTime = player.getAverageThroughput() < 1000000 ? 3000 : 2000; // Adjust buffer time based on average throughput setTimeout(() => { player.play(); }, bufferTime); }); player.on(dashjs.MediaPlayer.events.BUFFER_LOADED, () => { console.log('Buffer loaded, resuming playback.'); player.play(); }); } // Helper function to dynamically load external scripts function loadExternalScript(url, callback) { var script = document.createElement('script'); script.src = url; script.onload = function() { console.log(url + ' loaded successfully.'); if (callback) callback(); }; script.onerror = function() { console.error('Failed to load script: ' + url); }; document.head.appendChild(script); } // Main function to initialize optimizations function initializeOptimizations() { try { const videoElement = document.querySelector('video'); if (!videoElement || !videoElement.querySelector('source[src$=".mpd"]')) return; // Dynamically load dashjs loadExternalScript('https://cdn.jsdelivr.net/npm/dashjs@latest/dist/dash.all.min.js', () => { const player = dashjs.MediaPlayer().create(); preloadFirstSegment(videoElement, player); optimizeBufferStrategy(player); }); } catch (error) { console.error('Error initializing optimizations:', error); } } // Run the initialization when the page loads window.addEventListener('load', initializeOptimizations); // Compatibility check if ('MediaSource' in window && MediaSource.isTypeSupported('video/mp4; codecs="avc1.42E01E, mp4a.40.2"')) { initializeOptimizations(); } else { console.warn('Your browser does not support DASH or MSE.'); } })();