2024-06-29 11:19:50 +00:00
|
|
|
const WebSocket = require('ws')
|
2024-03-29 14:32:12 +00:00
|
|
|
const metadata = require('./metadata.js')
|
2024-06-29 09:22:55 +00:00
|
|
|
|
2024-03-29 14:32:12 +00:00
|
|
|
async function downloadVideo(url, ws, id) {
|
|
|
|
return new Promise(async (resolve, reject) => {
|
2024-06-29 11:50:59 +00:00
|
|
|
let quality = '480p'
|
2024-03-29 14:32:12 +00:00
|
|
|
const video = await metadata.getVideoMetadata(id)
|
2024-03-30 10:11:49 +00:00
|
|
|
if (video.error) {
|
2024-03-30 13:32:37 +00:00
|
|
|
return resolve({
|
2024-03-30 10:11:49 +00:00
|
|
|
message: `Failed to request Youtube with error ${video.error}. Please retry...`,
|
|
|
|
fail: true
|
|
|
|
})
|
|
|
|
}
|
2024-06-29 11:48:25 +00:00
|
|
|
if (video.basic_info.duration >= 900) quality = '360p' // 15 minutes
|
2024-03-30 10:11:49 +00:00
|
|
|
|
2024-07-03 06:50:54 +00:00
|
|
|
quality = await getVideoQuality(video, quality)
|
|
|
|
|
2024-06-29 11:19:50 +00:00
|
|
|
let isDownloading = true
|
2024-06-29 11:48:25 +00:00
|
|
|
const downloader = new WebSocket(`ws://${process.env.METADATA.replace('http://', '')}/download/${id}/${quality}`)
|
2024-06-29 11:19:50 +00:00
|
|
|
downloader.on('message', async function message(data) {
|
|
|
|
const text = data.toString()
|
|
|
|
if (text == 'done') {
|
|
|
|
isDownloading = false
|
2024-03-30 13:32:37 +00:00
|
|
|
return resolve({
|
2024-06-29 09:22:55 +00:00
|
|
|
fail: false
|
2024-03-29 14:32:12 +00:00
|
|
|
})
|
2024-06-29 11:19:50 +00:00
|
|
|
} else {
|
2024-06-29 11:26:41 +00:00
|
|
|
ws.send(`DATA - ${text}`)
|
2024-03-29 14:32:12 +00:00
|
|
|
}
|
|
|
|
})
|
|
|
|
|
2024-06-29 11:19:50 +00:00
|
|
|
downloader.on('close', function close(code, reason) {
|
|
|
|
if (!isDownloading) return
|
2024-06-29 09:22:55 +00:00
|
|
|
|
2024-06-29 11:19:50 +00:00
|
|
|
return resolve({
|
|
|
|
fail: true,
|
|
|
|
message: 'The metadata server unexpectedly closed the websocket. Please try again.'
|
|
|
|
})
|
|
|
|
})
|
|
|
|
})
|
2024-03-29 18:30:04 +00:00
|
|
|
}
|
|
|
|
|
2024-07-03 06:50:54 +00:00
|
|
|
async function getVideoQuality(json, quality) {
|
|
|
|
const adaptiveFormats = json['streaming_data']['adaptive_formats'];
|
|
|
|
let video = adaptiveFormats.find(f => f.quality_label === quality && !f.has_audio);
|
|
|
|
|
|
|
|
// If the specified quality isn't available, find the lowest quality video
|
|
|
|
if (!video) {
|
|
|
|
video = adaptiveFormats.filter(f => !f.has_audio).reduce((prev, current) => {
|
|
|
|
if (!prev || parseInt(current.quality_label) < parseInt(prev.quality_label)) {
|
|
|
|
return current;
|
|
|
|
}
|
|
|
|
return prev;
|
|
|
|
}, null);
|
|
|
|
}
|
|
|
|
|
|
|
|
return video ? video.quality_label : null;
|
|
|
|
}
|
|
|
|
|
2023-03-03 16:44:40 +00:00
|
|
|
module.exports = { downloadVideo }
|