您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Automatically download HLS streams from Privacy
当前为
// ==UserScript== // @name Privacy HLS Stream Downloader // @namespace http://tampermonkey.net/ // @license GPL-3.0 // @version 2024-10-23.3 // @description Automatically download HLS streams from Privacy // @author Rvnsxmwvrx // @match https://privacy.com.br/* // @icon https://www.google.com/s2/favicons?sz=64&domain=privacy.com.br // @grant none // ==/UserScript== (function () { "use strict"; function filterHLS(urlBegin, text) { let rtn = []; for (let line of text.split("\n")) { if (line.startsWith("#")) continue; rtn.push(urlBegin + line); } let fhd = rtn.filter((e) => e.includes("1080p")); if (fhd) return fhd; let hd = rtn.filter((e) => e.includes("720p")); if (hd) return hd; return rtn[0]; return rtn; } async function downloadFiles(div, button, urls) { let count = 1 for (let url of urls) { let start = url.lastIndexOf("/"); let filename = url.substring(start); let split = url.indexOf("hls/") + 4; let urlBegin = url.substring(0, split); await fetch(url) .then((response) => response.text()) .then(async (text) => { const fileContent = text; let video = filterHLS(urlBegin, text); await helper(div, button, urlBegin, video, url); }) .catch((err) => console.error("Error downloading file:", err)); } } const maxRetries = 10; async function helper(div, button, beginUrl, url, eUrl) { fetch(url) .then((response) => response.text()) .then(async (text) => { console.log(text); console.log(url); let element = div.getElementsByClassName(eUrl)[0] let tsFiles = filterHLS(beginUrl, text); await downloadVideos(element, button, tsFiles); }) .catch((err) => console.error("Error downloading file:", err)); } async function downloadVideos(element, button, tsFiles) { const combinedBuffers = []; const end = tsFiles[0].indexOf("--") const name = tsFiles[0].substring(0, end) const oldName = button.innerText for (const tsFile of tsFiles) { let retries = 0; let response = await fetch(tsFile); while (!response.ok && retries < maxRetries) { setTimeout(()=>{}, 500) response = await fetch(tsFile); retries += 1 } const arrayBuffer = await response.arrayBuffer(); combinedBuffers.push(arrayBuffer); let percent = (combinedBuffers.length / tsFiles.length) * 100 element.innerText = "(" + percent.toPrecision(2) + ") " button.innerText = "Downloading..." } element.innerText = "(0%)" button.innerText = oldName console.log(combinedBuffers.length); const videoBlob = new Blob(combinedBuffers, { type: "video/mp2t" }); const url = URL.createObjectURL(videoBlob); const downloadLink = document.createElement("a"); downloadLink.href = url; downloadLink.download = name + ".ts"; downloadLink.textContent = "Download Combined Video"; document.body.appendChild(downloadLink); downloadLink.click(); URL.revokeObjectUrl(url); } let allVideos = new Set(); function find_docs() { let elements = document.querySelectorAll("privacy-web-mediahub-carousel"); for (let element of elements) { let mediasStr = element.getAttribute("medias"); let medias = collectObjects(mediasStr); let videos = medias .filter((e) => e.url && e.url.endsWith(".m3u8") && !allVideos.has(e.url)) .map((e) => e.url); videos.forEach((e) => allVideos.add(e)); if (videos.length < 1) continue; let start = videos[0].indexOf("hls/") + 4 let end = videos[0].indexOf("--") let buttonId = videos[0].substring(start, end) console.log(buttonId) let shadow = element.shadowRoot while(!shadow) { shadow = element.shadowRoot } let div = document.createElement("div") div.setAttribute("style", "display:flex;") let button = document.createElement("button"); if(videos.length == 1) { button.innerText = "Download Video" }else{ button.innerText = "Download " + videos.length + " Videos"; } button.setAttribute("id", buttonId) button.addEventListener("click", function () { downloadFiles(div, button, videos); }); div.appendChild(button) for(let video of videos) { let element = document.createElement("p") element.setAttribute("class", video) element.innerText = "(0%)" div.appendChild(element) } shadow.appendChild(div); } } function collectObjects(mediasStr) { let start = 0; let offset = 0; let objects = []; for (let i = 0; i < mediasStr.length; i++) { let char = mediasStr[i]; if (char == "{") { start = i; } else if (char == "}") { let objStr = mediasStr.substring(start, start + offset + 1); objects.push(JSON.parse(objStr)); offset = 0; } else { offset += 1; } } return objects; } setInterval(() => find_docs(), 1000); })();