Greasy Fork

Mediaplay缓存优化

Optimize media playback by caching video segments to minimize user waiting time and maximize cache efficiency.

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

// ==UserScript==
// @name         Mediaplay缓存优化
// @namespace    http://tampermonkey.net/
// @version      1.5
// @description  Optimize media playback by caching video segments to minimize user waiting time and maximize cache efficiency.
// @author       KiwiFruit
// @match        *://*/*
// @grant        none
// @license MIT
// ==/UserScript==
(function() {
    'use strict';

    // 初始化参数
    const N = 10; // 假设每个视频有10个片段
    const d = Array.from({ length: N }, () => Math.random()); // 下载时延模拟
    const videoQuality = 720; // 假设视频分辨率为720p
    const userPreferences = { quality: true }; // 假设用户偏好高清视频
    const D = 5; // 最大允许总时延
    const C = 3; // 缓存容量限制
    let lambda_val = 0;
    let mu_val = 0;
    const alpha = 0.1;
    const beta = 0.1;
    const tolerance = 1e-6;
    const max_iterations = 1000;

    // 动态加载延迟测量URL
    async function getLatencyCheckUrl() {
        return new Promise((resolve) => {
            setTimeout(() => {
                resolve('https://example.com/ping'); // 动态返回延迟测量URL
            }, 100); // 模拟异步加载
        });
    }

    async function measureLatency(urlForLatencyCheck, numSamples = 5) {
        const url = await getLatencyCheckUrl(); // 动态获取延迟测量URL
        let totalLatency = 0;
        for (let i = 0; i < numSamples; i++) {
            const startTime = performance.now();
            try {
                await fetch(url);
                const endTime = performance.now();
                totalLatency += endTime - startTime; // 累加延迟时间(毫秒)
            } catch (error) {
                console.error('Error measuring latency:', error);
                return null;
            }
        }
        return totalLatency / numSamples; // 返回平均延迟时间
    }

    function getNetworkSpeed(latency) {
        let networkSpeed;

        if (latency !== null) {
            if (latency > 200) {
                networkSpeed = 5; // 高延迟,较低的网络速度
            } else if (latency > 100) {
                networkSpeed = 10; // 中等延迟,中等网络速度
            } else {
                networkSpeed = 15; // 低延迟,高速网络
            }
        } else {
            // 如果延迟测量失败,则使用默认值
            networkSpeed = 15; // 默认为15Mbps
        }

        console.log(`Measured latency: ${latency} ms, using network speed: ${networkSpeed} Mbps`);
        return networkSpeed;
    }

    async function getDownloadDelay(segmentSize) {
        const urlForLatencyCheck = await getLatencyCheckUrl(); // 动态获取延迟测量URL
        const latency = await measureLatency(urlForLatencyCheck);
        const networkSpeed = getNetworkSpeed(latency); // 动态获取网络速度
        const bandwidth = networkSpeed * 1024 * 1024; // 将Mbps转换为字节每秒
        const downloadDelay = segmentSize / bandwidth; // 计算下载延迟
        console.log(`Estimated download delay: ${downloadDelay} seconds`);

        // 更新缓存逻辑
        optimizeCache(d, D, C, alpha, beta, max_iterations, tolerance, downloadDelay);
    }

    // 效用函数
    function u(x, di, videoQuality, userPreferences) {
        const qualityFactor = userPreferences.quality ? videoQuality : 1;
        return x === 1 ? (qualityFactor / Math.max(di, 0.06)) : 0; // Assuming 60ms as 0.06 seconds
    }

    // 下载时延
    function getDownloadDelayForSegment(segmentSize, networkSpeed) {
        const bandwidth = networkSpeed * 1024 * 1024; // Convert Mbps to bytes per second
        return segmentSize / bandwidth; // Calculate download delay
    }

    // 优化算法 (梯度下降法)
    function optimizeCache(d, D, C, alpha, beta, max_iterations, tolerance, averageDownloadDelay) {
        let x = new Array(N).fill(0);
        let iteration = 0;
        while (iteration < max_iterations) {
            // 梯度下降更新
            const gradLambda = d.reduce((sum, di, idx) => sum + di * x[idx], 0) - D;
            const gradMu = x.reduce((sum, xi) => sum + xi, 0) - C;
            lambda_val -= alpha * gradLambda;
            mu_val -= beta * gradMu;
            // 更新决策变量
            for (let i = 0; i < N; i++) {
                const utility = u(x[i], d[i], videoQuality, userPreferences) - lambda_val * d[i] - mu_val;
                x[i] = utility > 0 ? 1 : 0;
            }
            // 检查收敛条件
            if (Math.abs(gradLambda) < tolerance && Math.abs(gradMu) < tolerance) {
                break;
            }
            iteration++;
        }
        return x;
    }

    // 缓存策略
    function cacheSegments(mediaElement, optimalSolution, averageDownloadDelay) {
        const sources = mediaElement.querySelectorAll('source');
        sources.forEach((source, index) => {
            if (optimalSolution[index] === 1) {
                const segmentUrl = source.src;
                fetch(segmentUrl)
                    .then(response => response.blob())
                    .then(blob => {
                        // 将片段存储在内存或本地存储中
                        console.log(`Cached segment ${index}:`, blob);
                    })
                    .catch(error => console.error(`Failed to cache segment ${index}:`, error));
            }
        });
    }

    // 缓冲停止计时器
    let bufferStopTimer;
    const BUFFER_STOP_THRESHOLD_MS = 15000; // 缓冲停止阈值,单位为毫秒(例如5秒)

    function handleBufferStop(mediaElement, segmentSize) {
        clearTimeout(bufferStopTimer); // 清除之前的定时器
        bufferStopTimer = setTimeout(async () => {
            console.log('Buffer has stopped for a long time, starting latency measurements...');
            await getDownloadDelay(segmentSize);
        }, BUFFER_STOP_THRESHOLD_MS);
    }

    // 获取页面上的所有媒体元素(视频和音频)
    const mediaElements = document.querySelectorAll('video, audio');

    mediaElements.forEach(mediaElement => {
        let lastTimeUpdate = performance.now(); // 上次播放进度更新的时间

        mediaElement.addEventListener('play', async function() {
            console.log('Media element started playing:', mediaElement);
            // 启动缓存逻辑
            const optimalSolution = optimizeCache(d, D, C, alpha, beta, max_iterations, tolerance, 0);
            await cacheSegments(mediaElement, optimalSolution, 0);
        });

        mediaElement.addEventListener('waiting', function() {
            console.log('Media element waiting due to buffering:', mediaElement);
            handleBufferStop(mediaElement, 10 * 1024 * 1024); // 假设片段大小为10MB
        });

        mediaElement.addEventListener('playing', function() {
            console.log('Media element resumed playing:', mediaElement);
            clearTimeout(bufferStopTimer); // 清除定时器,因为播放已恢复
        });

        mediaElement.addEventListener('timeupdate', function() {
            const currentTime = performance.now();
            if (currentTime - lastTimeUpdate > BUFFER_STOP_THRESHOLD_MS) {
                console.log('Buffer has stopped updating for a long time, starting latency measurements...');
                getDownloadDelay(10 * 1024 * 1024);
            }
            lastTimeUpdate = currentTime;
        });

        mediaElement.addEventListener('ended', function() {
            console.log('Media element ended:', mediaElement);
            // 在结束时也可以进行延迟测量
            getDownloadDelay(10 * 1024 * 1024);
        });
    });
})();