Stop videos looping

Stop videos looping (Youtube, Twitter, Tiktok, Instagram)

Install this script?
Author's suggested script

You may also like YouTube Channel Hover Popup.

Install this script
// ==UserScript==
// @name         Stop videos looping
// @namespace    http://tampermonkey.net/
// @version      0.7
// @description  Stop videos looping (Youtube, Twitter, Tiktok, Instagram)
// @author       @dmtri
// @match        https://*.youtube.com/*
// @match        https://*.twitter.com/*
// @match        https://*.tiktok.com/*
// @match        https://*.instagram.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();
})();