2023-08-21 11:46:48 -05:00
|
|
|
const ytdl = require('ytdl-core'),
|
|
|
|
fs = require('fs'),
|
|
|
|
path = require('path'),
|
|
|
|
express = require('express'),
|
2023-11-20 14:39:04 -06:00
|
|
|
bodyParser = require('body-parser'),
|
|
|
|
cp = require("child_process"),
|
2023-11-25 00:04:00 -06:00
|
|
|
ffmpeg = require('ffmpeg-static')
|
2023-11-20 14:39:04 -06:00
|
|
|
|
2023-05-05 11:15:22 -05:00
|
|
|
|
|
|
|
const PORT = process.env.PORT || 8080
|
|
|
|
const app = express()
|
2023-10-23 10:57:35 -05:00
|
|
|
|
2023-11-20 14:39:04 -06:00
|
|
|
var formats = {
|
|
|
|
"matroska": "mkv"
|
2023-10-23 10:57:35 -05:00
|
|
|
}
|
|
|
|
|
2023-11-20 14:39:04 -06:00
|
|
|
const characters = "abcdefghijklmnopqrstuvwxyz!@$%^*()[]_-=+ "
|
2023-05-05 11:15:22 -05:00
|
|
|
|
2023-08-24 11:00:33 -05:00
|
|
|
process.on('uncaughtException', (err, origin) => {
|
|
|
|
fs.writeSync(
|
|
|
|
process.stderr.fd,
|
|
|
|
`Caught exception: ${err}\n` +
|
|
|
|
`Exception origin: ${origin}`,
|
|
|
|
);
|
|
|
|
});
|
2023-08-23 11:35:10 -05:00
|
|
|
|
2023-08-24 11:00:33 -05:00
|
|
|
app.use(bodyParser.urlencoded({ extended: false }))
|
2023-08-23 11:35:10 -05:00
|
|
|
|
2023-11-20 14:39:04 -06:00
|
|
|
app.get("/download", async (req, res) => {
|
2023-05-08 12:52:41 -05:00
|
|
|
const url = req.query.url
|
2023-05-10 12:36:26 -05:00
|
|
|
const format = req.query.format
|
2023-05-05 11:15:22 -05:00
|
|
|
const quality = req.query.quality
|
2023-11-20 14:39:04 -06:00
|
|
|
const defin = req.query.definition
|
2023-05-10 12:36:26 -05:00
|
|
|
|
2023-10-25 22:07:48 -05:00
|
|
|
res.setHeader("X-Accel-Buffering", "no")
|
|
|
|
|
2023-08-28 08:33:16 -05:00
|
|
|
if (!ytdl.validateURL(url)) {
|
2023-10-20 18:03:54 -05:00
|
|
|
res.header("Content-Type", "text/html")
|
|
|
|
res.write(`<link rel="stylesheet" href="/style.css">`)
|
2023-10-25 16:04:42 -05:00
|
|
|
res.write(`<p>Invalid URL! Check the url for any errors! <br>URL: ${url}</p>`)
|
2023-08-24 11:00:33 -05:00
|
|
|
return
|
|
|
|
}
|
2023-10-25 18:07:54 -05:00
|
|
|
|
|
|
|
var vidinfo = await ytdl.getBasicInfo(url)
|
|
|
|
|
2023-10-25 20:53:18 -05:00
|
|
|
const ogname = vidinfo.videoDetails.title
|
|
|
|
var filename = ""
|
|
|
|
|
|
|
|
for (let index = 0; index < ogname.length; index++) {
|
|
|
|
const letter = ogname[index];
|
|
|
|
if ((characters + characters.toUpperCase()).includes(letter)) {
|
|
|
|
filename += letter
|
|
|
|
}
|
|
|
|
}
|
2023-10-25 18:07:54 -05:00
|
|
|
|
2023-11-20 14:41:17 -06:00
|
|
|
if ("mp3 ogg wav".includes(format)) {
|
2023-11-20 14:44:35 -06:00
|
|
|
console.log('audio')
|
2023-11-20 14:39:04 -06:00
|
|
|
var audio = ytdl(url, { filter: 'audioonly', quality: quality })
|
2023-11-20 14:41:17 -06:00
|
|
|
|
2023-11-20 14:44:35 -06:00
|
|
|
const ffmpegProcess = cp.spawn(ffmpeg, [
|
|
|
|
'-i', `pipe:3`,
|
|
|
|
'-c:v', 'copy',
|
|
|
|
'-c:a', 'libmp3lame',
|
|
|
|
'-crf','27',
|
|
|
|
'-preset','veryfast',
|
|
|
|
'-movflags','frag_keyframe+empty_moov',
|
|
|
|
'-f', format,
|
|
|
|
'-loglevel','error',
|
|
|
|
'-'
|
|
|
|
], {
|
|
|
|
stdio: [
|
|
|
|
'pipe', 'pipe', 'pipe', 'pipe', 'pipe',
|
|
|
|
],
|
|
|
|
})
|
|
|
|
|
|
|
|
audio.pipe(ffmpegProcess.stdio[3])
|
|
|
|
|
2023-11-20 14:41:17 -06:00
|
|
|
res.setHeader('Content-Disposition', `attachment; filename="${filename}.${formats[format] || format}"`);
|
2023-11-20 14:44:35 -06:00
|
|
|
|
|
|
|
ffmpegProcess.stdio[1].pipe(res)
|
2023-11-20 14:39:04 -06:00
|
|
|
|
|
|
|
} else if (defin == "hd") {
|
|
|
|
var video = ytdl(url, { filter: 'videoonly', quality: quality })
|
|
|
|
var audio = ytdl(url, { filter: 'audioonly', highWaterMark: 1<<25 })
|
|
|
|
|
|
|
|
const ffmpegProcess = cp.spawn(ffmpeg, [
|
|
|
|
'-i', `pipe:3`,
|
|
|
|
'-i', `pipe:4`,
|
|
|
|
'-map','0:v',
|
|
|
|
'-map','1:a',
|
|
|
|
'-c:v', 'copy',
|
|
|
|
'-c:a', 'libmp3lame',
|
|
|
|
'-crf','27',
|
|
|
|
'-preset','veryfast',
|
|
|
|
'-movflags','frag_keyframe+empty_moov',
|
|
|
|
'-f', format,
|
|
|
|
'-loglevel','error',
|
|
|
|
'-'
|
|
|
|
], {
|
|
|
|
stdio: [
|
|
|
|
'pipe', 'pipe', 'pipe', 'pipe', 'pipe',
|
|
|
|
],
|
2023-10-25 16:04:42 -05:00
|
|
|
})
|
2023-10-23 23:31:23 -05:00
|
|
|
|
2023-11-20 14:39:04 -06:00
|
|
|
video.pipe(ffmpegProcess.stdio[3])
|
|
|
|
audio.pipe(ffmpegProcess.stdio[4])
|
2023-10-23 23:31:23 -05:00
|
|
|
|
2023-11-20 14:39:04 -06:00
|
|
|
res.setHeader('Content-Disposition', `attachment; filename="${filename}.${formats[format] || format}"`);
|
|
|
|
ffmpegProcess.stdio[1].pipe(res)
|
2023-08-23 11:35:10 -05:00
|
|
|
|
2023-10-20 18:03:54 -05:00
|
|
|
} else {
|
2023-11-20 14:39:04 -06:00
|
|
|
var video = ytdl(url, { filter: 'videoandaudio', quality: quality })
|
|
|
|
|
|
|
|
const ffmpegProcess = cp.spawn(ffmpeg, [
|
|
|
|
'-i', `pipe:3`,
|
|
|
|
'-c:v', 'copy',
|
|
|
|
'-c:a', 'libmp3lame',
|
|
|
|
'-crf','27',
|
|
|
|
'-preset','veryfast',
|
|
|
|
'-movflags','frag_keyframe+empty_moov',
|
|
|
|
'-f', format,
|
|
|
|
'-loglevel','error',
|
|
|
|
'-'
|
|
|
|
], {
|
|
|
|
stdio: [
|
|
|
|
'pipe', 'pipe', 'pipe', 'pipe', 'pipe',
|
|
|
|
],
|
|
|
|
})
|
|
|
|
|
|
|
|
video.pipe(ffmpegProcess.stdio[3])
|
|
|
|
|
|
|
|
res.setHeader('Content-Disposition', `attachment; filename="${filename}.${formats[format] || format}"`);
|
|
|
|
// res.setHeader('Content-Length', fs.readFileSync(dest).length)
|
|
|
|
|
|
|
|
ffmpegProcess.stdio[1].pipe(res)
|
2023-10-20 18:03:54 -05:00
|
|
|
}
|
2023-11-20 14:39:04 -06:00
|
|
|
|
2023-10-20 18:03:54 -05:00
|
|
|
})
|
2023-05-05 11:15:22 -05:00
|
|
|
|
|
|
|
app.use(express.static(path.join(__dirname, 'static')))
|
|
|
|
|
2023-05-10 12:36:26 -05:00
|
|
|
app.listen(PORT, function () {
|
2023-05-05 11:15:22 -05:00
|
|
|
console.log("Hosted on port " + PORT)
|
|
|
|
})
|