Paste not found.
Surprise! We've been running on hardware provided by BuyVM for a few months and wanted to show them a little appreciation.
Running a paste site comes with unique challenges, ones that aren't always obvious and hard to control. As such, BuyVM offered us a home where we could worry less about the hosting side of things and focus on maintaining a clean and useful service! Go check them out and show them some love!
Submitted on September 3, 2024 at 09:18 AM

New Paste 1 (Text)

// ==UserScript==
// @name         Replace Video Links with HTML5 Player (Video.js)
// @namespace    http://tampermonkey.net/
// @version      1.3
// @description  Replace video links with HTML5 player on XenForo.com using Video.js
// @author       Your Name
// @match https://www.thecoli.com/threads/*
// @match https://thecoli.com/threads/*
// @match https://www.thecoli.com/forums/*/post-thread
// @match https://thecoli.com/forums/*/post-thread
// @match https://www.thecoli.com/conversations/*
// @grant        none
// ==/UserScript==

(function() {
  'use strict';

  // Function to load Video.js CSS and JS files if they are not already loaded
  function loadVideoJs() {
    const head = document.head || document.getElementsByTagName('head')[0];
    const style = document.createElement('link');
    style.rel = 'stylesheet';
    style.href = 'https://vjs.zencdn.net/8.16.1/video-js.css';
    head.appendChild(style);

    // Add custom Video.js styles
    const customStyle = document.createElement('style');
    customStyle.textContent = `
      .video-js {
        max-width: 100vw;
        max-height: 80vh;
        object-fit: contain;
        margin: 0 auto;
        border-radius: 5px;
        box-shadow: 0 0 10px rgba(0, 0, 0, 0.2);
      }
    `;
    head.appendChild(customStyle);

    const script = document.createElement('script');
    script.src = 'https://vjs.zencdn.net/8.16.1/video.min.js';
    head.appendChild(script);

    return new Promise(resolve => {
      script.onload = resolve;
    });
  }

  var replacedLinks = {};

  function replaceVideoLinks() {
    var links = document.querySelectorAll('a[href*=".mp4"], a[href*=".m3u8"], a[href*=".webm"]');

    links.forEach(function(link) {
      if (!replacedLinks[link.href]) {
        var videoUrl = link.href;

        // Create a new <video> element based on file type
        let videoElement;

        if (videoUrl.endsWith('.m3u8')) {
          // Use Video.js for .m3u8 links
          loadVideoJs().then(() => {
            videoElement = document.createElement('video');
            videoElement.className = 'video-js';
            videoElement.controls = true;

            const sourceElement = document.createElement('source');
            sourceElement.src = videoUrl;
            sourceElement.type = 'application/x-mpegURL';
            videoElement.appendChild(sourceElement);

            // Add playback speed control
            const speedButton = document.createElement('button');
            speedButton.textContent = 'Speed';
            speedButton.onclick = function() {
              const speeds = ['0.5', '1', '1.5', '2'];
              const currentSpeed = videoElement.playbackRate;
              const nextSpeedIndex = (speeds.indexOf(currentSpeed) + 1) % speeds.length;
              videoElement.playbackRate = speeds[nextSpeedIndex];
              speedButton.textContent = `Speed: ${speeds[nextSpeedIndex]}x`;
            };
            videoElement.controlsList = 'nodownload';
            videoElement.appendChild(speedButton);

            // Add Picture-in-Picture (PiP) button
            const pipButton = document.createElement('button');
            pipButton.textContent = 'PiP';
            pipButton.onclick = function() {
              if (document.pictureInPictureEnabled) {
                videoElement.requestPictureInPicture();
              }
            };
            videoElement.appendChild(pipButton);

            // Add closed captions
            const captionButton = document.createElement('button');
            captionButton.textContent = 'CC';
            captionButton.onclick = function() {
              videoElement.textTracks[0].mode = videoElement.textTracks[0].mode === 'disabled' ? 'showing' : 'disabled';
            };
            videoElement.appendChild(captionButton);

            link.parentNode.replaceChild(videoElement, link);

            setTimeout(() => {
              const player = window.videojs(videoElement);
              player.play();
            }, 100); // Delay initialization by 100ms to ensure DOM readiness

            replacedLinks[link.href] = true;
          });
                } else if (videoUrl.endsWith('.mp4') || videoUrl.endsWith('.webm')) {
          // Use native HTML5 player for .mp4 and .webm links
          videoElement = document.createElement('video');
          videoElement.controls = true;
          videoElement.style.maxWidth = '100vw';
          videoElement.style.maxHeight = '80vh';
          videoElement.style.objectFit = 'contain';
          videoElement.style.margin = '0 auto';
          videoElement.style.borderRadius = '5px';
          videoElement.style.boxShadow = '0 0 10px rgba(0, 0, 0, 0.2)';

          // Add playback speed control
          const speedButton = document.createElement('button');
          speedButton.textContent = 'Speed: 1x';
          speedButton.onclick = function() {
            const speeds = ['0.5', '1', '1.5', '2'];
            const currentSpeed = videoElement.playbackRate;
            const nextSpeedIndex = speeds.indexOf(currentSpeed) !== -1 ? (speeds.indexOf(currentSpeed) + 1) % speeds.length : 1;
            videoElement.playbackRate = speeds[nextSpeedIndex];
            speedButton.textContent = `Speed: ${speeds[nextSpeedIndex]}x`;
          };
          videoElement.appendChild(speedButton);

          // Add Picture-in-Picture (PiP) button
          const pipButton = document.createElement('button');
          pipButton.textContent = 'PiP';
          pipButton.onclick = function() {
            if (document.pictureInPictureEnabled) {
              videoElement.requestPictureInPicture();
            }
          };
          videoElement.appendChild(pipButton);

          // Add closed captions
          const captionButton = document.createElement('button');
          captionButton.textContent = 'CC';
          captionButton.onclick = function() {
            if (videoElement.textTracks) {
              videoElement.textTracks[0].mode = videoElement.textTracks[0].mode === 'disabled' ? 'showing' : 'disabled';
            }
          };
          videoElement.appendChild(captionButton);

          // Add keyboard navigation
          videoElement.tabIndex = 0;
          videoElement.addEventListener('keydown', function(event) {
            switch (event.key) {
              case ' ':
                videoElement.paused ? videoElement.play() : videoElement.pause();
                break;
              case 'ArrowLeft':
                videoElement.currentTime -= 10;
                break;
              case 'ArrowRight':
                videoElement.currentTime += 10;
                break;
              case 'ArrowUp':
                videoElement.volume = Math.min(videoElement.volume + 0.1, 1);
                break;
              case 'ArrowDown':
                videoElement.volume = Math.max(videoElement.volume - 0.1, 0);
                break;
            }
          });

          const sourceElement = document.createElement('source');
          sourceElement.src = videoUrl;

          if (videoUrl.endsWith('.mp4')) {
            sourceElement.type = 'video/mp4';
          } else if (videoUrl.endsWith('.webm')) {
            sourceElement.type = 'video/webm';
          }

          videoElement.appendChild(sourceElement);

          link.parentNode.replaceChild(videoElement, link);

          replacedLinks[link.href] = true;
        }
      }
    });

    requestAnimationFrame(replaceVideoLinks);
  }

  replaceVideoLinks();
})();