Greasy Fork

DASH Video Player Optimizer(视频协议优化DASH篇)

Optimize DASH video playback on web pages with enhanced performance and ABR management

目前为 2025-03-12 提交的版本。查看 最新版本

// ==UserScript==
// @name         DASH Video Player Optimizer(视频协议优化DASH篇)
// @namespace    http://tampermonkey.net/
// @version      0.2
// @description  Optimize DASH video playback on web pages with enhanced performance and ABR management
// @author       KiwiFruit
// @match        *://*/*
// @grant        none
// @license MIT
// @require https://update.greasyfork.org/scripts/529588/1552013/webdashjs.js
// ==/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();
        });
    }

    // Main function to initialize optimizations
    function initializeOptimizations() {
        try {
            const videoElement = document.querySelector('video');
            if (!videoElement || !videoElement.querySelector('source[src$=".mpd"]')) return;

            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 ('dashjs' in window && '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.');
    }
})();