Functions
This commit is contained in:
parent
d9f7a8d4fc
commit
3321673f62
7 changed files with 378 additions and 1097 deletions
22
config.json
22
config.json
|
@ -1,22 +0,0 @@
|
||||||
{
|
|
||||||
"qualityOptions": [
|
|
||||||
"2160",
|
|
||||||
"1140",
|
|
||||||
"1080",
|
|
||||||
"720",
|
|
||||||
"480",
|
|
||||||
"360",
|
|
||||||
"240",
|
|
||||||
"144"
|
|
||||||
],
|
|
||||||
"formats": {
|
|
||||||
"video": [
|
|
||||||
"mp4",
|
|
||||||
"mkv"
|
|
||||||
],
|
|
||||||
"audio": [
|
|
||||||
"mp3",
|
|
||||||
"wav"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
116
downloader.js
Normal file
116
downloader.js
Normal file
|
@ -0,0 +1,116 @@
|
||||||
|
const expressManager = require("./express.js"),
|
||||||
|
path = require("path"),
|
||||||
|
fs = require("fs"),
|
||||||
|
ytdl = require("@distube/ytdl-core"),
|
||||||
|
ffmpeg = require("ffmpeg-static"),
|
||||||
|
cp = require("child_process")
|
||||||
|
|
||||||
|
var qualityLabels = [
|
||||||
|
"144",
|
||||||
|
"240",
|
||||||
|
"360",
|
||||||
|
"480",
|
||||||
|
"720",
|
||||||
|
"1080",
|
||||||
|
"1440",
|
||||||
|
"2160"
|
||||||
|
]
|
||||||
|
|
||||||
|
var audioFormats = [
|
||||||
|
"mp3"
|
||||||
|
]
|
||||||
|
|
||||||
|
expressManager.app.get("/download", async (req, res) => {
|
||||||
|
var url = req.query.url,
|
||||||
|
quality = req.query.quality,
|
||||||
|
format = req.query.format
|
||||||
|
|
||||||
|
if (ytdl.validateURL(url) && qualityLabels.includes(quality)) {
|
||||||
|
var needsVideo = !audioFormats.includes(format)
|
||||||
|
|
||||||
|
var info = await ytdl.getInfo(url)
|
||||||
|
|
||||||
|
res.setHeader("Content-Disposition", `attachment; filename*="${info.videoDetails.title.replace(/[^a-z0-9 ]/gi, '')}.${format}"`)
|
||||||
|
|
||||||
|
var audioFormat = ytdl.chooseFormat(info.formats, { filter: (format) => {
|
||||||
|
return format.hasAudio && !format.hasVideo
|
||||||
|
} })
|
||||||
|
|
||||||
|
var videoFormat = undefined
|
||||||
|
|
||||||
|
var qualityLabel = quality
|
||||||
|
while (videoFormat == undefined) {
|
||||||
|
for (let i = 0; i < info.formats.length; i++) {
|
||||||
|
const format = info.formats[i];
|
||||||
|
if (format.hasVideo && !format.hasAudio && format.height.toString() == qualityLabel.toString()) {
|
||||||
|
videoFormat = format
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (qualityLabels.indexOf(qualityLabel) - 1 < 0) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
qualityLabel = qualityLabels[qualityLabels.indexOf(qualityLabel) - 1]
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!videoFormat) {
|
||||||
|
videoFormat = ytdl.chooseFormat(info.formats, { filter: "videoonly" })
|
||||||
|
}
|
||||||
|
|
||||||
|
var baseArgs = [
|
||||||
|
// Remove ffmpeg's console spamming
|
||||||
|
'-loglevel', 'error',
|
||||||
|
// // Set inputs
|
||||||
|
// '-i', 'pipe:4',
|
||||||
|
// '-i', 'pipe:5',
|
||||||
|
// Map audio & video from streams
|
||||||
|
// '-map', '0:a',
|
||||||
|
// '-map', '1:v',
|
||||||
|
// Keep encoding
|
||||||
|
'-c:v', 'copy',
|
||||||
|
'-movflags','frag_keyframe+empty_moov',
|
||||||
|
'-f', format,
|
||||||
|
// Define output file
|
||||||
|
'-',
|
||||||
|
]
|
||||||
|
|
||||||
|
var inputArgs = [
|
||||||
|
'-i', 'pipe:4'
|
||||||
|
]
|
||||||
|
|
||||||
|
var mapArgs = [
|
||||||
|
'-map', '0:a'
|
||||||
|
]
|
||||||
|
|
||||||
|
if (needsVideo) {
|
||||||
|
inputArgs = inputArgs.concat(['-i', 'pipe:5'])
|
||||||
|
mapArgs = mapArgs.concat(['-map', '1:v'])
|
||||||
|
}
|
||||||
|
|
||||||
|
var args = inputArgs.concat(mapArgs).concat(baseArgs)
|
||||||
|
|
||||||
|
const ffmpegProcess = cp.spawn(ffmpeg, args, {
|
||||||
|
windowsHide: true,
|
||||||
|
stdio: [
|
||||||
|
/* Standard: stdin, stdout, stderr */
|
||||||
|
'pipe', 'pipe', 'pipe',
|
||||||
|
/* Custom: pipe:3, pipe:4, pipe:5 */
|
||||||
|
'pipe', 'pipe', 'pipe',
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
ffmpegProcess.stdio[1].pipe(res)
|
||||||
|
|
||||||
|
var audio = ytdl(url, { format: audioFormat || "audioonly" })
|
||||||
|
audio.pipe(ffmpegProcess.stdio[4])
|
||||||
|
|
||||||
|
if (needsVideo) {
|
||||||
|
var video = ytdl(url, { format: videoFormat || "videoonly" })
|
||||||
|
video.pipe(ffmpegProcess.stdio[5])
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
res.send("Invalid URL!")
|
||||||
|
}
|
||||||
|
})
|
18
express.js
Normal file
18
express.js
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
const express = require("express"),
|
||||||
|
path = require("path")
|
||||||
|
|
||||||
|
const PORT = process.env.PORT || 8080
|
||||||
|
|
||||||
|
var staticPath = path.join(__dirname, "static")
|
||||||
|
|
||||||
|
var app = express()
|
||||||
|
|
||||||
|
app.use(express.static(staticPath))
|
||||||
|
|
||||||
|
app.listen(PORT, () => {
|
||||||
|
console.log("Univerter now listening on PORT: " + PORT)
|
||||||
|
})
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
app
|
||||||
|
}
|
7
index.js
7
index.js
|
@ -1,5 +1,2 @@
|
||||||
const fs = require("fs"),
|
require("./express.js")
|
||||||
ytdl = require("youtube-dl-exec")
|
require("./downloader.js")
|
||||||
|
|
||||||
|
|
||||||
ytdl('http://www.youtube.com/watch?v=aqz-KE-bpKQ')
|
|
1301
package-lock.json
generated
1301
package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "univerter",
|
"name": "univerter",
|
||||||
"version": "3.2.0",
|
"version": "4.0.0",
|
||||||
"description": "A web youtube converter for converting videos to mp4, mp3, and other supported formats",
|
"description": "A web youtube converter for converting videos to mp4, mp3, and other supported formats",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
@ -23,10 +23,9 @@
|
||||||
},
|
},
|
||||||
"homepage": "https://github.com/Violets-puragtory/YoutubeConverter#readme",
|
"homepage": "https://github.com/Violets-puragtory/YoutubeConverter#readme",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@distube/ytdl-core": "^4.13.5",
|
||||||
"child_process": "^1.0.2",
|
"child_process": "^1.0.2",
|
||||||
"express": "^4.18.2",
|
"express": "^4.18.2",
|
||||||
"ffmpeg-static": "^5.2.0",
|
"ffmpeg-static": "^5.2.0"
|
||||||
"youtube-dl-exec": "^3.0.7",
|
|
||||||
"ytdl-core": "^4.11.5"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
<div class="mainDiv">
|
<div class="mainDiv">
|
||||||
<h1>Univerter<hr></h1>
|
<h1>Univerter<hr></h1>
|
||||||
|
|
||||||
<form action="/download" method="get">
|
<form action="/download" method="get" target="_blank">
|
||||||
<p style="margin-bottom: 1px;">Video URL:</p>
|
<p style="margin-bottom: 1px;">Video URL:</p>
|
||||||
<input required type="url" id="url" placeholder="Enter URL" name="url">
|
<input required type="url" id="url" placeholder="Enter URL" name="url">
|
||||||
|
|
||||||
|
@ -47,8 +47,6 @@
|
||||||
<option value="mkv">.mkv</option>
|
<option value="mkv">.mkv</option>
|
||||||
<option disabled>Audio Formats</option>
|
<option disabled>Audio Formats</option>
|
||||||
<option value="mp3" selected>.mp3</option>
|
<option value="mp3" selected>.mp3</option>
|
||||||
<option value="wav">.wav</option>
|
|
||||||
<option value="opus">.ogx</option>
|
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
Loading…
Reference in a new issue