您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Wait for the .ts link to be generated via XHR, retrieve the segments, and merge them into an .mp4 file
// ==UserScript== // @name Video Auto Loader & Downloader (XHR Intercept) // @namespace https://beerscloud.com/ // @version 1.0 // @description Wait for the .ts link to be generated via XHR, retrieve the segments, and merge them into an .mp4 file // @author ChatGPT // @match *://beerscloud.com/iframe/* // @match *://sharecloudy.com/iframe/* // @grant GM_xmlhttpRequest // @grant GM_download // @run-at document-end // ==/UserScript== (function () { // URL du fichier version.json sur GitHub const versionUrl = "https://raw.githubusercontent.com/ProbablyXS/auto-video-downloader-ts-merge/main/version.json"; // Fonction pour vérifier si une mise à jour est disponible async function checkForUpdates() { try { let response = await fetch(versionUrl); if (response.ok) { let data = await response.json(); const remoteVersion = data.version; const updateUrl = data.url; // Vérifie si la version distante est plus récente if (remoteVersion !== localVersion) { notifyUserOfUpdate(remoteVersion, updateUrl); } } } catch (error) { console.error('Erreur lors de la vérification des mises à jour:', error); } } // Fonction pour afficher une notification à l'utilisateur function notifyUserOfUpdate(remoteVersion, updateUrl) { GM_notification({ title: "Nouvelle mise à jour disponible!", text: `Une nouvelle version (${remoteVersion}) est disponible pour ce script. Cliquez ici pour voir les détails.`, highlight: true, onclick: function () { window.open(updateUrl, '_blank'); } }); } // Vérifie les mises à jour au démarrage du script checkForUpdates(); 'use strict'; let tsLink = null; // To store the .ts file link let tsLinks = new Set(); // To store the .ts video segments let isTsLinkAvailable = false; // Flag to check if the .ts link is detected let foundSegments = 0; // Counter for the found segments let downloadedSegments = 0; // Counter for the downloaded segments let startTime = 0; // Start time for the download let statusBox = null; // Status box for tracking information let timeRemainingText = null; // Display for the remaining time // Add a button to manually start the process function createDownloadButton() { let button = document.createElement("button"); button.textContent = "Start Download"; button.style.position = "fixed"; button.style.top = "20px"; button.style.left = "20px"; button.style.zIndex = "9999"; button.style.padding = "10px 20px"; button.style.backgroundColor = "#28a745"; button.style.color = "#fff"; button.style.border = "none"; button.style.borderRadius = "5px"; button.style.cursor = "pointer"; button.addEventListener("click", function () { showStatusBox(); // Show the status box checkTsLinkAvailability(); // Start the link checking and downloading button.remove(); // Remove the button after it's clicked }); document.body.appendChild(button); } // Show the status box function showStatusBox() { if (!statusBox) { statusBox = document.createElement("div"); statusBox.style.position = "fixed"; statusBox.style.top = "60px"; statusBox.style.left = "20px"; statusBox.style.zIndex = "9999"; statusBox.style.padding = "10px"; statusBox.style.backgroundColor = "black"; statusBox.style.color = "white"; statusBox.style.fontSize = "20px"; // Enlarged font size statusBox.style.borderRadius = "5px"; document.body.appendChild(statusBox); } updateStatusBox(); // Update the status } // Display the remaining time in minutes function updateTimeRemaining() { if (!timeRemainingText) { timeRemainingText = document.createElement("div"); timeRemainingText.style.position = "fixed"; timeRemainingText.style.top = "110px"; timeRemainingText.style.left = "20px"; timeRemainingText.style.zIndex = "9999"; timeRemainingText.style.padding = "10px"; timeRemainingText.style.backgroundColor = "black"; timeRemainingText.style.color = "white"; timeRemainingText.style.fontSize = "16px"; // Font size timeRemainingText.style.borderRadius = "5px"; document.body.appendChild(timeRemainingText); } const elapsedTime = (Date.now() - startTime) / 1000; // Elapsed time in seconds const remainingSegments = foundSegments - downloadedSegments; // Remaining segments const downloadSpeed = downloadedSegments / elapsedTime; // Download speed in segments per second if (downloadSpeed > 0) { const estimatedTimeRemaining = (remainingSegments / downloadSpeed / 60).toFixed(2); // Estimate of remaining time in minutes timeRemainingText.textContent = `Estimated remaining time: ${estimatedTimeRemaining} minutes`; } else { timeRemainingText.textContent = `Calculating remaining time...`; } } // Update the status box content function updateStatusBox() { statusBox.textContent = `Segments found: ${foundSegments} | Downloaded: ${downloadedSegments}`; updateTimeRemaining(); // Update the remaining time } // Intercept all XHR requests (function interceptXHR() { const originalSend = XMLHttpRequest.prototype.send; XMLHttpRequest.prototype.send = function (...args) { this.addEventListener('load', function () { if (this.responseURL && this.responseURL.endsWith('.ts')) { tsLink = this.responseURL; // Capture the .ts link isTsLinkAvailable = true; } }); originalSend.apply(this, args); }; })(); // Function to check the validity of a .ts segment (sends a HEAD request) async function checkTSUrl(url) { try { let response = await fetch(url, { method: "HEAD" }); return response.ok; } catch (error) { return false; } } // Function to download and merge the .ts segments async function downloadAndMergeTS() { if (!tsLink) { alert("❌ No .ts link found!"); return; } let maxConcurrentDownloads = 10; let activeDownloads = 0; let mergedBlobParts = []; // List to store the segment data let tsUrlBase = tsLink.replace(/(\d+)\.ts$/, ''); // Extract the base URL of the .ts link let i = 1; let segmentUrl; let isValid = true; // Start the timer startTime = Date.now(); while (isValid) { segmentUrl = `${tsUrlBase}${i}.ts`; // Generate the URL with the index isValid = await checkTSUrl(segmentUrl); // Check if the segment is valid if (isValid) { tsLinks.add(segmentUrl); // Add to the list of segments to download foundSegments++; // Increment the found segments counter updateStatusBox(); // Update the status display i++; } else { break; // Stop when an invalid segment is encountered } } if (tsLinks.size === 0) return; // Function to download a segment const downloadSegment = (tsUrl) => { activeDownloads++; GM_xmlhttpRequest({ method: "GET", url: tsUrl, responseType: "arraybuffer", onload: (response) => { if (response.status === 200) { mergedBlobParts.push(response.response); // Add the segment to the Blob downloadedSegments++; // Increment the downloaded segments counter updateStatusBox(); // Update the status display } activeDownloads--; processQueue(); // Check if more downloads can start }, onerror: () => { activeDownloads--; processQueue(); // Check if more downloads can start } }); }; // Function to manage the download queue const processQueue = () => { if (activeDownloads < maxConcurrentDownloads && tsLinks.size > 0) { const tsUrl = tsLinks.values().next().value; // Get the next .ts link tsLinks.delete(tsUrl); // Remove the segment from the list downloadSegment(tsUrl); // Start downloading the segment } }; processQueue(); // Start downloading the segments // Wait for all downloads to finish while (activeDownloads > 0) { await new Promise(resolve => setTimeout(resolve, 50)); } // Merge the downloaded segments into a single MP4 file let finalBlob = new Blob(mergedBlobParts, { type: "video/mp4" }); let finalUrl = URL.createObjectURL(finalBlob); let a = document.createElement("a"); a.href = finalUrl; a.download = "video_merged.mp4"; document.body.appendChild(a); a.click(); document.body.removeChild(a); alert("📂 Download complete!"); } // Continuously check the availability of the .ts link function checkTsLinkAvailability() { foundSegments = 0; // Reset the counters downloadedSegments = 0; updateStatusBox(); // Update the status display if (isTsLinkAvailable) { downloadAndMergeTS(); // Start the download if the .ts link is available } else { setTimeout(checkTsLinkAvailability, 2000); // Check every 2 seconds } } // Create the download button createDownloadButton(); })();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址