Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[VAFT] A solution to the "buffering" when ad starts #313

Open
TsukiZero opened this issue Dec 16, 2024 · 2 comments
Open

[VAFT] A solution to the "buffering" when ad starts #313

TsukiZero opened this issue Dec 16, 2024 · 2 comments

Comments

@TsukiZero
Copy link

Here's an userscript ChatGPT cooked for me that does the trick:

// ==UserScript==
// @name         Twitch Video Loading Handler
// @namespace    http://tampermonkey.net/
// @version      1.5
// @description  Handles video loading issues on Twitch by interacting with play/pause buttons if a spinner persists, with a configurable delay before starting.
// @author       ChatGPT
// @match        *://*.twitch.tv/*
// @grant        none
// ==/UserScript==

(function () {
    'use strict';

    // Configurable delay before script starts (in milliseconds)
    const INITIAL_DELAY = 60000; // 1 minute

    // Delay the script's start by INITIAL_DELAY
    setTimeout(() => {
        let attemptCount = 0; // Track the number of attempts

        const MAX_ATTEMPTS = 5; // Maximum attempts before waiting
        const WAIT_BEFORE_RETRY = 3000; // 3 seconds between attempts
        const WAIT_AFTER_MAX_ATTEMPTS = 60000; // 1 minute after 5 failures

        function isSpinnerVisible() {
            const spinner = document.querySelector('.tw-loading-spinner');
            return spinner && spinner.offsetParent !== null; // Check if the spinner is visible
        }

        function getPlayingButton() {
            const channelPlayer = document.querySelector('#channel-player');
            return channelPlayer?.querySelector('[data-a-player-state="playing"]') || null;
        }

        function clickPlayPauseSequence() {
            const playingButton = getPlayingButton();
            if (playingButton) {
                playingButton.click(); // First click: Pause
                setTimeout(() => {
                    playingButton.click(); // Second click: Play after 10ms
                }, 10);
            }
        }

        function checkAndHandleSpinner() {
            if (isSpinnerVisible() && getPlayingButton()) {
                attemptCount++;
                if (attemptCount <= MAX_ATTEMPTS) {
                    // console.log(`Spinner visible with playing button. Attempt ${attemptCount}/${MAX_ATTEMPTS}. Retrying...`);
                    setTimeout(() => {
                        clickPlayPauseSequence();
                        setTimeout(checkAndHandleSpinner, WAIT_BEFORE_RETRY);
                    }, WAIT_BEFORE_RETRY);
                } else {
                    // console.log(`Spinner persisted after ${MAX_ATTEMPTS} attempts. Waiting 1 minute.`);
                    attemptCount = 0; // Reset attempt count
                    setTimeout(checkAndHandleSpinner, WAIT_AFTER_MAX_ATTEMPTS);
                }
            } else {
                // console.log('No spinner or playing button found. Resetting attempt count.');
                attemptCount = 0; // Reset attempt count if conditions are not met
            }
        }

        // Periodically check for the spinner after the delay
        setInterval(checkAndHandleSpinner, WAIT_BEFORE_RETRY);
    }, INITIAL_DELAY); // Use INITIAL_DELAY for start delay
})();

So far this has been doing the trick for me.

@TsukiZero TsukiZero changed the title A solution to the "buffering" when ad starts [VAFT] A solution to the "buffering" when ad starts Dec 16, 2024
@pixeltris
Copy link
Owner

Neat, I might adapt that. I guess this wont work when the video freezes but there's audio playback? As I think there's no loading wheel in those cases?

@TsukiZero
Copy link
Author

Yeah, that one is a different and odd problem. As is when video goes on but audio loops the past 5 seconds. Don't know what to do about those and they are rare to make matters worse to debug.

Also, here's a modified version of the script I had ChatGPT work on that has a finer control on attempts and delays:

// ==UserScript==
// @name         Twitch Video Loading Handler
// @namespace    http://tampermonkey.net/
// @version      1.5
// @description  Handles video loading issues on Twitch by clicking the play/pause buttons if a spinner persists, with dynamic retry intervals and a startup delay.
// @author       ChatGPT
// @match        *://*.twitch.tv/*
// @grant        none
// ==/UserScript==

(function () {
    'use strict';

    let attemptCount = 0; // Track the number of attempts
    let isProcessing = false; // Prevent overlapping executions

    const STARTUP_DELAY = 60000; // Default 1 minute (60000 ms) startup delay after page load
    const MAX_ATTEMPTS = 5; // Maximum attempts before waiting
    const FIRST_RETRY_INTERVAL = 1000; // Default 2 (2000 ms) seconds for the first attempt
    const SUBSEQUENT_RETRY_INTERVAL = 1500; // Default 3 (3000 ms) seconds for later attempts
    const WAIT_AFTER_MAX_ATTEMPTS = 60000; // Default (60000 ms) 1 minute after 5 failures

    function getRetryInterval() {
        return attemptCount === 1 ? FIRST_RETRY_INTERVAL : SUBSEQUENT_RETRY_INTERVAL;
    }

    function clickButton(selector) {
        const button = document.querySelector(selector);
        if (button) {
            button.click();
        }
    }

    function checkAndHandleSpinner() {
        if (isProcessing) return; // Prevent multiple simultaneous executions
        isProcessing = true;

        const inactivePlayer = document.querySelector('.video-player__inactive');
        if (!inactivePlayer) {
            attemptCount = 0; // Reset if no inactive player is found
            isProcessing = false;
            return;
        }

        const spinner = inactivePlayer.querySelector('.tw-loading-spinner');
        if (spinner) {
            attemptCount++;
            if (attemptCount <= MAX_ATTEMPTS) {
                // console.log(`Spinner found. Attempt ${attemptCount}/${MAX_ATTEMPTS}. Retrying play/pause...`);

                // Attempt to click the "pause" and "play" buttons
                clickButton('button[data-a-player-state="playing"]'); // Simulate pause
                setTimeout(() => {
                    clickButton('button[data-a-player-state="paused"]'); // Simulate play
                }, 100);

                setTimeout(() => {
                    isProcessing = false; // Allow next check after retry wait
                    checkAndHandleSpinner();
                }, getRetryInterval());
            } else {
                // console.log(`Spinner persisted after ${MAX_ATTEMPTS} attempts. Waiting 1 minute.`);
                attemptCount = 0; // Reset attempt count
                setTimeout(() => {
                    isProcessing = false; // Allow next check after delay
                    checkAndHandleSpinner();
                }, WAIT_AFTER_MAX_ATTEMPTS);
            }
        } else {
            // console.log('No spinner found. Resetting attempt count.');
            attemptCount = 0; // Reset attempt count if spinner is gone
            isProcessing = false;
        }
    }

    function initializeScript() {
        // Periodically check for the spinner
        setInterval(checkAndHandleSpinner, SUBSEQUENT_RETRY_INTERVAL);
    }

    // Delay script initialization
    setTimeout(initializeScript, STARTUP_DELAY);
})();

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants