Stop videos looping (Youtube, Twitter, Tiktok, Instagram, Facebook)
// ==UserScript==
// @name Stop videos looping
// @namespace http://tampermonkey.net/
// @version 0.72
// @description Stop videos looping (Youtube, Twitter, Tiktok, Instagram, Facebook)
// @author @dmtri
// @match https://*.youtube.com/*
// @match https://*.x.com/*
// @match https://*.tiktok.com/*
// @match https://*.instagram.com/*
// @match https://*.facebook.com/*
// @license MIT
// @icon
// @grant none
// ==/UserScript==
(function () {
"use strict";
// Keep track of processed videos
const processedVideos = new WeakSet();
const init = () => {
const vids = document.querySelectorAll("video");
vids.forEach((vid) => {
if (processedVideos.has(vid)) return;
processedVideos.add(vid);
vid.removeAttribute("loop");
let arr = [];
const setupTimeout = (extra = 0) => {
let vidLen = vid.duration;
let vidCurr = vid.currentTime;
// ignore any buggy timeout triggered < 500ms
if ((vidLen - vidCurr) * 1000 < 500) return
// Ensure duration is available
if (isNaN(vid.duration) || vid.duration === Infinity) return;
console.log(vidLen > vidCurr, 'setting a timeout', (vidLen - vidCurr - 0.05) * 1000)
if (vidLen > vidCurr) {
const timeout = setTimeout(() => {
// hack: sometimes video just stops randomly, so need to stop that behavior here
vidLen = vid.duration;
vidCurr = vid.currentTime;
const remaining = (vidLen - vidCurr) * 1000
console.log(remaining)
if (remaining < 500) vid.pause();
}, (vidLen - vidCurr - 0.01) * 1000 + extra); // Adjusted to account for potential delays
arr.push(timeout);
}
};
// need this for the initial load, 1st time playing. Some extra buffer for 1st time too
vid.addEventListener('loadedmetadata', () => setupTimeout(-200));
vid.addEventListener('seeked', () => {
clearAll(arr);
setupTimeout();
});
vid.addEventListener("pause", () => {
clearAll(arr);
});
vid.addEventListener("play", () => {
setupTimeout();
});
vid.addEventListener("ended", () => {
setTimeout(() => vid.pause(), 10);
});
});
};
const clearAll = (arr) => {
arr.forEach((timeout) => {
clearTimeout(timeout);
});
arr = [];
};
const observer = new MutationObserver(init);
observer.observe(document.body, { childList: true, subtree: true });
init();
})();