From 858091eb60a3f36a2e7f8e28421089b9f51d7d5b Mon Sep 17 00:00:00 2001 From: localhost Date: Sat, 29 Jun 2024 13:19:50 +0200 Subject: [PATCH] sigma patch --- package.json | 3 +- utils/ytdlp.js | 153 ++++++------------------------------------------- yarn.lock | 5 ++ 3 files changed, 25 insertions(+), 136 deletions(-) diff --git a/package.json b/package.json index 3195202..8d3fb65 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,8 @@ "readable-to-ms": "^1.0.3", "rolling-rate-limiter": "^0.4.2", "wget-improved": "^3.4.0", - "winston": "^3.8.2" + "winston": "^3.8.2", + "ws": "^8.17.1" }, "devDependencies": { "prisma": "4.9.0" diff --git a/utils/ytdlp.js b/utils/ytdlp.js index 488147e..ca9a7e1 100644 --- a/utils/ytdlp.js +++ b/utils/ytdlp.js @@ -1,13 +1,5 @@ -const wget = require('wget-improved') -const DOMPurify = require('isomorphic-dompurify') +const WebSocket = require('ws') const metadata = require('./metadata.js') -const hr = require('@tsmx/human-readable') - -const ffmpeg = require('fluent-ffmpeg') -const ffmpegStatic = require('ffmpeg-static') -const fs = require('node:fs') - -ffmpeg.setFfmpegPath(ffmpegStatic) async function downloadVideo(url, ws, id) { return new Promise(async (resolve, reject) => { @@ -21,138 +13,29 @@ async function downloadVideo(url, ws, id) { } if (video.basic_info.duration >= 900) quality = '360' // 15 minutes - const downloadJson = await metadata.getVideoDownload(video, quality) - - let size = '' - let startTime = Date.now() - let prevBytes = 0 - let speed = 0 - const alreadyPrecentages = [] - - const target = Array.isArray(downloadJson.url) ? downloadJson.url[0] : downloadJson.url - const download = wget.download(target, `./videos/${id}.mp4`, { - proxy: { - protocol: 'http', - host: 'gluetun', - port: '8888', - headers: { - 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36', - accept: '*/*', - origin: 'https://www.youtube.com', - referer: 'https://www.youtube.com', - DNT: '?1' - } - } - }) - - download.on('start', fileSize => { - size = fileSize - if (ws) ws.send(`DATA - Download has started in ${quality}p`) - }) - - download.on('progress', progress => { - if (alreadyPrecentages.includes((progress*100).toFixed(0))) return - alreadyPrecentages.push((progress*100).toFixed(0)) - - const currentTime = Date.now() - const elapsedTime = (currentTime - startTime) / 1000 - const currentBytes = progress * size - const bytesDownloaded = currentBytes - prevBytes - speed = bytesDownloaded / elapsedTime - prevBytes = currentBytes - - const speedInMBps = speed / 1048576 - const remainingBytes = size - currentBytes - const remainingTime = remainingBytes / speed - - if (ws) ws.send(`DATA - [download] ${(progress*100).toFixed(2)}% of ${hr.fromBytes(size)} at ${speedInMBps.toFixed(2)} MB/s ETA ${secondsToTime(remainingTime.toFixed(0))}`) - }) - - download.on('error', err => { - if (ws) ws.send(`DATA - ${DOMPurify.sanitize(err)}`) - }) - - download.on('end', output => { - if (output !== 'Finished writing to disk') { - return resolve({ - fail: true - }) - } - - if (Array.isArray(downloadJson.url)) { // this means video is separate - ws.send(`DATA - Downloading the video has finished, downloading audio.`); - - const audioDownload = wget.download(downloadJson.url[1], `./videos/${id}_audio.mp4`, { - proxy: { - protocol: 'http', - host: 'gluetun', - port: '8888', - headers: { - 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36', - accept: '*/*', - origin: 'https://www.youtube.com', - referer: 'https://www.youtube.com', - DNT: '?1' - } - } - }) - audioDownload.on('end', async (audioOutput) => { - if (audioOutput !== 'Finished writing to disk') { - return resolve({ fail: true }); - } - - fs.renameSync(`./videos/${id}.mp4`, `./videos/${id}_video.mp4`); - try { - await mergeIt(`./videos/${id}_audio.mp4`, `./videos/${id}_video.mp4`, `./videos/${id}.mp4`); - ws.send(`DATA - Merging succeeded.`) - - fs.rmSync(`./videos/${id}_audio.mp4`) - fs.rmSync(`./videos/${id}_video.mp4`) - - return resolve({ fail: false }); - } catch (error) { - console.error('Merging error:', error); - return resolve({ fail: true }); - } - }); - - audioDownload.on('error', (err) => { - console.error('Audio download error:', err); - return resolve({ fail: true }); - }); - } else { - ws.send(`DATA - Download has finished`) + let isDownloading = true + const downloader = new WebSocket(`ws://${process.env.METADATA.replace('http://', '')}/download/${id}/${quality}p`) + downloader.on('message', async function message(data) { + const text = data.toString() + if (text == 'done') { + isDownloading = false return resolve({ fail: false }) + } else { + ws.send(text) } }) + + downloader.on('close', function close(code, reason) { + if (!isDownloading) return + + return resolve({ + fail: true, + message: 'The metadata server unexpectedly closed the websocket. Please try again.' + }) + }) }) } -function mergeIt(audioPath, videoPath, outputPath) { - return new Promise((resolve, reject) => { - ffmpeg() - .addInput(videoPath) - .addInput(audioPath) - .outputOptions('-c:v copy') - .outputOptions('-c:a aac') - .output(outputPath) - .on('end', () => { - resolve('Merging finished!'); - }) - .on('error', (err) => { - reject(new Error('An error occurred: ' + err.message)); - }) - .run(); - }); -} - -function secondsToTime(seconds) { - const minutes = Math.floor(seconds / 60); - const remainingSeconds = seconds % 60; - const formattedSeconds = remainingSeconds < 10 ? '0' + remainingSeconds : remainingSeconds; - return `${minutes}:${formattedSeconds}`; -} - module.exports = { downloadVideo } \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index 0173919..fed345b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1502,6 +1502,11 @@ ws@^8.11.0: resolved "https://registry.yarnpkg.com/ws/-/ws-8.12.1.tgz#c51e583d79140b5e42e39be48c934131942d4a8f" integrity sha512-1qo+M9Ba+xNhPB+YTWUlK6M17brTut5EXbcBaMRN5pH5dFrXz7lzz1ChFSUq3bOUl8yEvSenhHmYUNJxFzdJew== +ws@^8.17.1: + version "8.17.1" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.17.1.tgz#9293da530bb548febc95371d90f9c878727d919b" + integrity sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ== + xml-name-validator@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-4.0.0.tgz#79a006e2e63149a8600f15430f0a4725d1524835"