Compare commits
19 commits
4ddd6fd98a
...
6fb90e6815
Author | SHA1 | Date | |
---|---|---|---|
6fb90e6815 | |||
a688a6293f | |||
5b0f8befed | |||
0e1153484f | |||
6970f4a718 | |||
89fac8e35f | |||
ceb9403b32 | |||
ab9ef8f46e | |||
7f6b6932fb | |||
374e1f7036 | |||
2cc0fbffcf | |||
3c18adee84 | |||
e8de0c9c73 | |||
d50236f78f | |||
1431606c75 | |||
33f45c0965 | |||
26164f4004 | |||
3321673f62 | |||
d9f7a8d4fc |
15 changed files with 508 additions and 341 deletions
|
@ -1,3 +0,0 @@
|
||||||
node_modules
|
|
||||||
npm-debug.log
|
|
||||||
cached
|
|
16
Dockerfile
16
Dockerfile
|
@ -1,16 +0,0 @@
|
||||||
FROM node:20
|
|
||||||
|
|
||||||
RUN apt-get update \
|
|
||||||
&& apt install python3 pip ffmpeg -y \
|
|
||||||
&& python3 -m pip install -U yt-dlp --break-system-packages
|
|
||||||
|
|
||||||
WORKDIR /usr/src/app
|
|
||||||
|
|
||||||
COPY package*.json ./
|
|
||||||
RUN npm install
|
|
||||||
|
|
||||||
COPY . .
|
|
||||||
|
|
||||||
EXPOSE 8080
|
|
||||||
|
|
||||||
CMD [ "node", "index.js" ]
|
|
53
README.md
53
README.md
|
@ -1,42 +1,27 @@
|
||||||
# Univerter
|
# Univerter
|
||||||
|
|
||||||
A web downloader & converter for videos with no client-sided javascript. It can be found at https://univerter.dev
|
A web downloader for Youtube videos. It can be found at https://univerter.dev
|
||||||
|
|
||||||
Currently supports a wide variety of formats and sites, but if you have any other formats you want supported, please open an issue.
|
Currently only supporting Youtube, and not many formats. For old Univerter, which supports a variety of sites, visit https://legacy.univerter.dev.
|
||||||
Formats added to Univerter must be supported by FFmpeg
|
|
||||||
Support for sites will only be added if those sites are supported by yt-dlp.
|
|
||||||
|
|
||||||
# Installation
|
# Installation
|
||||||
|
|
||||||
There are 2 main ways to install Univerter:
|
|
||||||
|
|
||||||
## Docker
|
|
||||||
|
|
||||||
The docker image can be found at https://hub.docker.com/r/bingusviolet/univerter
|
|
||||||
Port 8080 (or whatever you set the environment variable to) is exposed inside the container. It can be exposed with `-p`
|
|
||||||
Example:
|
|
||||||
```bash
|
|
||||||
docker run -p 8080:8080 bingusviolet/univerter
|
|
||||||
```
|
|
||||||
This will allow it to be found on port 8080 (E.G. `localhost:8080`)
|
|
||||||
|
|
||||||
## Node
|
## Node
|
||||||
|
|
||||||
1. Clone the repository
|
### 1. Install Dependancies
|
||||||
|
Always make sure your dependencies are up to date! Univerter's dependencies may change from time to time.
|
||||||
```bash
|
|
||||||
git clone https://github.com/Violets-puragtory/YoutubeConverter
|
|
||||||
cd YoutubeConverter
|
|
||||||
```
|
|
||||||
|
|
||||||
2. Install Dependancies
|
|
||||||
|
|
||||||
- [ffmpeg](https://github.com/FFmpeg/FFmpeg)
|
- [ffmpeg](https://github.com/FFmpeg/FFmpeg)
|
||||||
- [node](https://github.com/nodejs/node)
|
- [node](https://github.com/nodejs/node)
|
||||||
- [npm](https://github.com/npm/cli)
|
- [npm](https://github.com/npm/cli)
|
||||||
- [yt-dlp](https://github.com/yt-dlp/yt-dlp)
|
|
||||||
|
|
||||||
3. Download NodeJS Dependencies
|
### 2. Clone the repository
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git clone https://git.viois.gay/violet/Univerter
|
||||||
|
cd Univerter
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. Download NodeJS Dependencies
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
npm install
|
npm install
|
||||||
|
@ -50,22 +35,10 @@ npm start
|
||||||
|
|
||||||
# Environment Variables
|
# Environment Variables
|
||||||
|
|
||||||
`PORT`= [Preffered Port] (8080 if unspecified)
|
`PORT`= [Preffered Port] (Default is port 8080)
|
||||||
`MAX_FILESIZE` = [Max file size in MB] (Only applies to 1080p>, don't rely on this feature yet though, as it is unfinished.)
|
|
||||||
|
|
||||||
# To-Do
|
# To-Do
|
||||||
- [ ] Save settings (per session)
|
- [ ] Save settings (per session)
|
||||||
- [ ] Proper config
|
|
||||||
- [ ] Advanced options menu
|
- [ ] Advanced options menu
|
||||||
- [ ] Add option for subtitles to file
|
- [ ] Add option for subtitles to file
|
||||||
- [ ] Video Searching
|
- [ ] Video Searching
|
||||||
- [ ] Video Caching Options
|
|
||||||
- [ ] Properly cleanup unnessacary files
|
|
||||||
- [ ] Option to disable 1080p+
|
|
||||||
- [ ] Option to disable Conversion
|
|
||||||
|
|
||||||
# Instances
|
|
||||||
Here is a list of all currently public instances. If you want to add your instance to this list, please make an issue or pull request!
|
|
||||||
|
|
||||||
- https://univerter.dev (official)
|
|
||||||
- https://yt.violets-purgatory.dev (official)
|
|
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"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
124
downloader.js
Normal file
124
downloader.js
Normal file
|
@ -0,0 +1,124 @@
|
||||||
|
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,
|
||||||
|
trimAudio = req.query.trimAudio && audioFormats.includes(format) || false
|
||||||
|
|
||||||
|
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 && format.height.toString() == qualityLabel.toString() && (format.videoCodec.includes("avc1") || format.codecs.includes("avc1"))) {
|
||||||
|
// console.log(format.videoCodec)
|
||||||
|
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'
|
||||||
|
]
|
||||||
|
|
||||||
|
var bonusArgs = []
|
||||||
|
|
||||||
|
if (needsVideo) {
|
||||||
|
inputArgs = inputArgs.concat(['-i', 'pipe:5'])
|
||||||
|
mapArgs = mapArgs.concat(['-map', '1:v'])
|
||||||
|
}
|
||||||
|
|
||||||
|
if (trimAudio) {
|
||||||
|
bonusArgs = bonusArgs.concat(['-af', 'silenceremove=1:0:-50dB'])
|
||||||
|
}
|
||||||
|
|
||||||
|
var args = inputArgs.concat(mapArgs).concat(bonusArgs).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
|
||||||
|
}
|
232
index.js
232
index.js
|
@ -1,230 +1,2 @@
|
||||||
const fs = require('fs'),
|
require("./express.js")
|
||||||
path = require('path'),
|
require("./downloader.js")
|
||||||
express = require('express'),
|
|
||||||
cp = require("child_process"),
|
|
||||||
ffmpeg = require("ffmpeg-static")
|
|
||||||
|
|
||||||
const PORT = process.env.PORT || 8080
|
|
||||||
const app = express()
|
|
||||||
|
|
||||||
const MAX_FILESIZE = process.env.MAX_FILESIZE || 500
|
|
||||||
|
|
||||||
var formats = {
|
|
||||||
"mkv": "matroska"
|
|
||||||
}
|
|
||||||
|
|
||||||
var fastFormats = ["mp4", "mkv", "mp3", "wav"]
|
|
||||||
|
|
||||||
app.get("/convert", async (req, res) => {
|
|
||||||
var file = req.query.file || ""
|
|
||||||
var format = req.query.format
|
|
||||||
var url = req.query.url
|
|
||||||
|
|
||||||
var filePath = path.join(__dirname, 'downloads', file)
|
|
||||||
|
|
||||||
if (fs.existsSync(filePath)) {
|
|
||||||
var ytdlpProcess = cp.spawnSync('./yt-dlp', ['--get-filename', url])
|
|
||||||
var name = ytdlpProcess.stdout.toString()
|
|
||||||
name = name.substring(0, name.lastIndexOf("[") - 1)
|
|
||||||
res.setHeader('Content-Disposition', `attachment; filename="${encodeURIComponent(name)}.${format}"`);
|
|
||||||
|
|
||||||
const ffmpegProcess = cp.spawn(ffmpeg, [
|
|
||||||
'-i', filePath,
|
|
||||||
'-f', formats[format] || format,
|
|
||||||
'-movflags', 'frag_keyframe+empty_moov',
|
|
||||||
'-preset','ultrafast',
|
|
||||||
'-crf', '23',
|
|
||||||
'-loglevel', 'error',
|
|
||||||
'-'
|
|
||||||
], {
|
|
||||||
stdio: [
|
|
||||||
'pipe', 'pipe', 'pipe', 'pipe', 'pipe',
|
|
||||||
],
|
|
||||||
})
|
|
||||||
|
|
||||||
ffmpegProcess.stderr.setEncoding('utf-8')
|
|
||||||
// ffmpegProcess.stderr.on('data', (data) => {
|
|
||||||
// console.log(data)
|
|
||||||
// })
|
|
||||||
// These are debugging lines to watch FFMPEG output :3
|
|
||||||
|
|
||||||
ffmpegProcess.stdio[1].pipe(res)
|
|
||||||
.on('close', () => {
|
|
||||||
fs.rmSync(filePath)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
app.get("/download", async (req, res) => {
|
|
||||||
const url = req.query.url
|
|
||||||
const format = req.query.format || 'mp4'
|
|
||||||
const quality = req.query.quality || '720'
|
|
||||||
|
|
||||||
res.setHeader("X-Accel-Buffering", "no")
|
|
||||||
|
|
||||||
var fileName = Math.ceil(Math.random() * 100_000_000_000).toString()
|
|
||||||
var videoName = cp.spawnSync('./yt-dlp', ['-S', 'res:' + quality, '--get-filename', url]).stdout.toString()
|
|
||||||
|
|
||||||
videoName = videoName.substring(0, videoName.lastIndexOf('.'))
|
|
||||||
videoName = videoName.substring(0, videoName.lastIndexOf('[') - 1)
|
|
||||||
|
|
||||||
if (!["mp3", "wav", "ogx"].includes(format) && Number(quality) > 720) {
|
|
||||||
res.setHeader("Content-Type", "text/html")
|
|
||||||
|
|
||||||
var downloadHTML = fs.readFileSync(path.join(__dirname, 'resources/downloading.html')).toString()
|
|
||||||
|
|
||||||
res.write(downloadHTML.substring(0, downloadHTML.indexOf("{CONTENT}")))
|
|
||||||
|
|
||||||
var filePath = path.join(__dirname, 'downloads', fileName)
|
|
||||||
var ytdlpProcess = cp.spawn('./yt-dlp', [
|
|
||||||
url,
|
|
||||||
'-o', filePath,
|
|
||||||
'--max-filesize', MAX_FILESIZE + 'm',
|
|
||||||
'-S', 'res:' + quality,
|
|
||||||
'--no-playlist',
|
|
||||||
])
|
|
||||||
|
|
||||||
var lastDownload = 0
|
|
||||||
|
|
||||||
ytdlpProcess.stderr.setEncoding('utf-8')
|
|
||||||
ytdlpProcess.stderr.on('data', (data) => {
|
|
||||||
// console.log(data)
|
|
||||||
res.write(`<div class="error"><p>` + data + `</p></div>`)
|
|
||||||
})
|
|
||||||
|
|
||||||
var debounce = false
|
|
||||||
|
|
||||||
ytdlpProcess.stdout.setEncoding('utf-8')
|
|
||||||
ytdlpProcess.stdout.on('data', (data) => {
|
|
||||||
if (!debounce) {
|
|
||||||
if (data.includes("max-filesize")) {
|
|
||||||
debounce = true
|
|
||||||
res.write(`<p>Uh oh! The video you're trying to download is too large for this server's current settings ${MAX_FILESIZE}. Please try another server? (Visit main page and go to the codeberg for a list of instances!)</p>`)
|
|
||||||
}
|
|
||||||
else if (data.includes("[download]")) {
|
|
||||||
res.write(`<style>#downloading${lastDownload}{ display: none; }</style>`)
|
|
||||||
lastDownload += 1
|
|
||||||
res.write(`<p id="downloading${lastDownload}">` + data.substring(12) + `</p>`)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
})
|
|
||||||
|
|
||||||
var exited = false
|
|
||||||
|
|
||||||
ytdlpProcess.on('close', () => {
|
|
||||||
|
|
||||||
var files = fs.readdirSync(path.join(__dirname, 'downloads'))
|
|
||||||
for (let index = 0; index < files.length; index++) {
|
|
||||||
const file = files[index];
|
|
||||||
if (file.includes(fileName)) {
|
|
||||||
fileName = file
|
|
||||||
filePath = path.join(__dirname, 'downloads', fileName)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (exited) {
|
|
||||||
if (fs.existsSync(filePath)) {
|
|
||||||
fs.rmSync(filePath)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (fs.existsSync(filePath)) {
|
|
||||||
res.write(`<iframe src="/convert?file=${fileName}&format=${format}&url=${url}"></iframe>"`)
|
|
||||||
res.write(downloadHTML.substring(downloadHTML.indexOf("{CONTENT}") + 9) + `<meta http-equiv="Refresh" content="0; url='/'" />`, () => { res.end() })
|
|
||||||
} else {
|
|
||||||
res.write("<p>An error has occured!!! We're not exactly sure what the error is, but we cant seem to find the download file. Double check the URL, and if the URL is fine, then file an issue on codeberg. </p>")
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
res.on("error", () => {
|
|
||||||
if (fs.existsSync(filePath)) {
|
|
||||||
fs.rmSync(filePath)
|
|
||||||
}
|
|
||||||
exited = true
|
|
||||||
})
|
|
||||||
} else if (["mp3", "wav", "opus"].includes(format)) {
|
|
||||||
res.setHeader('Content-Disposition', `attachment; filename="${encodeURIComponent(videoName)}.${format}"`);
|
|
||||||
|
|
||||||
var ytdlpProcess = cp.spawn('./yt-dlp', [
|
|
||||||
url,
|
|
||||||
'-x',
|
|
||||||
'-o', '-',
|
|
||||||
'--max-filesize', MAX_FILESIZE + 'm',
|
|
||||||
'--audio-format', 'mp3',
|
|
||||||
'--no-playlist',
|
|
||||||
])
|
|
||||||
|
|
||||||
const ffmpegProcess = cp.spawn(ffmpeg, [
|
|
||||||
'-i', 'pipe:3',
|
|
||||||
'-f', formats[format] || format,
|
|
||||||
'-movflags', 'frag_keyframe+empty_moov',
|
|
||||||
'-preset','ultrafast',
|
|
||||||
'-crf', '23',
|
|
||||||
'-loglevel', 'error',
|
|
||||||
'-'
|
|
||||||
], {
|
|
||||||
stdio: [
|
|
||||||
'pipe', 'pipe', 'pipe', 'pipe', 'pipe',
|
|
||||||
],
|
|
||||||
})
|
|
||||||
|
|
||||||
ytdlpProcess.stdout.pipe(ffmpegProcess.stdio[3])
|
|
||||||
|
|
||||||
ytdlpProcess.stderr.setEncoding('utf-8')
|
|
||||||
// ytdlpProcess.stderr.on('data', (data) => {
|
|
||||||
// console.log(data)
|
|
||||||
// })
|
|
||||||
|
|
||||||
ffmpegProcess.stdio[1].pipe(res)
|
|
||||||
} else {
|
|
||||||
res.setHeader('Content-Disposition', `attachment; filename="${encodeURIComponent(videoName)}.${format}"`);
|
|
||||||
|
|
||||||
var ytdlpProcess = cp.spawn('./yt-dlp', [
|
|
||||||
url,
|
|
||||||
'-o', '-',
|
|
||||||
'--max-filesize', MAX_FILESIZE + 'm',
|
|
||||||
'-S', 'res:' + quality,
|
|
||||||
'--no-playlist',
|
|
||||||
])
|
|
||||||
|
|
||||||
const ffmpegProcess = cp.spawn(ffmpeg, [
|
|
||||||
'-i', 'pipe:3',
|
|
||||||
'-f', formats[format] || format,
|
|
||||||
'-movflags', 'frag_keyframe+empty_moov',
|
|
||||||
'-c:a', 'libmp3lame',
|
|
||||||
'-preset','ultrafast',
|
|
||||||
'-crf', '23',
|
|
||||||
'-loglevel', 'error',
|
|
||||||
'-'
|
|
||||||
], {
|
|
||||||
stdio: [
|
|
||||||
'pipe', 'pipe', 'pipe', 'pipe', 'pipe',
|
|
||||||
],
|
|
||||||
})
|
|
||||||
|
|
||||||
ytdlpProcess.stdout.pipe(ffmpegProcess.stdio[3])
|
|
||||||
|
|
||||||
ytdlpProcess.stderr.setEncoding('utf-8')
|
|
||||||
// ytdlpProcess.stderr.on('data', (data) => {
|
|
||||||
// console.log(data)
|
|
||||||
// })
|
|
||||||
|
|
||||||
ffmpegProcess.stdio[1].pipe(res)
|
|
||||||
}
|
|
||||||
|
|
||||||
})
|
|
||||||
|
|
||||||
process.on('uncaughtException', (err, origin) => {
|
|
||||||
fs.writeSync(
|
|
||||||
process.stderr.fd,
|
|
||||||
`Caught exception: ${err}\n` +
|
|
||||||
`Exception origin: ${origin}`,
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
app.use(express.static(path.join(__dirname, 'static')))
|
|
||||||
|
|
||||||
app.listen(PORT, function () {
|
|
||||||
console.log("Hosted on port " + PORT)
|
|
||||||
})
|
|
295
package-lock.json
generated
295
package-lock.json
generated
|
@ -1,14 +1,15 @@
|
||||||
{
|
{
|
||||||
"name": "univerter",
|
"name": "univerter",
|
||||||
"version": "3.2.0",
|
"version": "4.0.0",
|
||||||
"lockfileVersion": 2,
|
"lockfileVersion": 2,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "univerter",
|
"name": "univerter",
|
||||||
"version": "3.2.0",
|
"version": "4.0.0",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@distube/ytdl-core": "^4.14.4",
|
||||||
"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"
|
||||||
|
@ -28,6 +29,26 @@
|
||||||
"node": ">=6.0.0"
|
"node": ">=6.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@distube/ytdl-core": {
|
||||||
|
"version": "4.14.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/@distube/ytdl-core/-/ytdl-core-4.14.4.tgz",
|
||||||
|
"integrity": "sha512-dHb4GW3qATIjRsS6VIhm3Pop7FdUcDFhsnyQlsPeXW7UhTPuNS0BmraKiTpFbpp0Ky+rxBQjJBfPRFsM+dT1fg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"http-cookie-agent": "^6.0.5",
|
||||||
|
"m3u8stream": "^0.8.6",
|
||||||
|
"miniget": "^4.2.3",
|
||||||
|
"sax": "^1.4.1",
|
||||||
|
"tough-cookie": "^4.1.4",
|
||||||
|
"undici": "five"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=14.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/distubejs/ytdl-core?sponsor"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@types/node": {
|
"node_modules/@types/node": {
|
||||||
"version": "10.17.60",
|
"version": "10.17.60",
|
||||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.60.tgz",
|
"resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.60.tgz",
|
||||||
|
@ -388,6 +409,65 @@
|
||||||
"url": "https://github.com/sponsors/ljharb"
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/http-cookie-agent": {
|
||||||
|
"version": "6.0.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/http-cookie-agent/-/http-cookie-agent-6.0.5.tgz",
|
||||||
|
"integrity": "sha512-sfZ8fDgDP3B1YB+teqSnAK1aPgBu8reUUGxSsndP2XnYN6cM29EURXWXZqQQiaRdor3B4QjpkUNfv21syaO4DA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"agent-base": "^7.1.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/3846masa"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"tough-cookie": "^4.0.0",
|
||||||
|
"undici": "^5.11.0 || ^6.0.0"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"undici": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/http-cookie-agent/node_modules/agent-base": {
|
||||||
|
"version": "7.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz",
|
||||||
|
"integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"debug": "^4.3.4"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 14"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/http-cookie-agent/node_modules/debug": {
|
||||||
|
"version": "4.3.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.6.tgz",
|
||||||
|
"integrity": "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"ms": "2.1.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6.0"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"supports-color": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/http-cookie-agent/node_modules/ms": {
|
||||||
|
"version": "2.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
|
||||||
|
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/http-errors": {
|
"node_modules/http-errors": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz",
|
||||||
|
@ -468,6 +548,19 @@
|
||||||
"node": ">= 0.10"
|
"node": ">= 0.10"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/m3u8stream": {
|
||||||
|
"version": "0.8.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/m3u8stream/-/m3u8stream-0.8.6.tgz",
|
||||||
|
"integrity": "sha512-LZj8kIVf9KCphiHmH7sbFQTVe4tOemb202fWwvJwR9W5ENW/1hxJN6ksAWGhQgSBSa3jyWhnjKU1Fw1GaOdbyA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"miniget": "^4.2.2",
|
||||||
|
"sax": "^1.2.4"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/media-typer": {
|
"node_modules/media-typer": {
|
||||||
"version": "0.3.0",
|
"version": "0.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
|
||||||
|
@ -519,6 +612,15 @@
|
||||||
"node": ">= 0.6"
|
"node": ">= 0.6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/miniget": {
|
||||||
|
"version": "4.2.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/miniget/-/miniget-4.2.3.tgz",
|
||||||
|
"integrity": "sha512-SjbDPDICJ1zT+ZvQwK0hUcRY4wxlhhNpHL9nJOB2MEAXRGagTljsO8MEDzQMTFf0Q8g4QNi8P9lEm/g7e+qgzA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/ms": {
|
"node_modules/ms": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
|
||||||
|
@ -589,6 +691,21 @@
|
||||||
"node": ">= 0.10"
|
"node": ">= 0.10"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/psl": {
|
||||||
|
"version": "1.9.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz",
|
||||||
|
"integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/punycode": {
|
||||||
|
"version": "2.3.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
|
||||||
|
"integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/qs": {
|
"node_modules/qs": {
|
||||||
"version": "6.11.0",
|
"version": "6.11.0",
|
||||||
"resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz",
|
"resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz",
|
||||||
|
@ -603,6 +720,12 @@
|
||||||
"url": "https://github.com/sponsors/ljharb"
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/querystringify": {
|
||||||
|
"version": "2.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz",
|
||||||
|
"integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/range-parser": {
|
"node_modules/range-parser": {
|
||||||
"version": "1.2.1",
|
"version": "1.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
|
||||||
|
@ -624,6 +747,12 @@
|
||||||
"node": ">= 6"
|
"node": ">= 6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/requires-port": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz",
|
||||||
|
"integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/safe-buffer": {
|
"node_modules/safe-buffer": {
|
||||||
"version": "5.2.1",
|
"version": "5.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
|
||||||
|
@ -648,6 +777,12 @@
|
||||||
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
|
||||||
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
|
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
|
||||||
},
|
},
|
||||||
|
"node_modules/sax": {
|
||||||
|
"version": "1.4.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/sax/-/sax-1.4.1.tgz",
|
||||||
|
"integrity": "sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg==",
|
||||||
|
"license": "ISC"
|
||||||
|
},
|
||||||
"node_modules/send": {
|
"node_modules/send": {
|
||||||
"version": "0.18.0",
|
"version": "0.18.0",
|
||||||
"resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz",
|
"resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz",
|
||||||
|
@ -732,6 +867,21 @@
|
||||||
"node": ">=0.6"
|
"node": ">=0.6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/tough-cookie": {
|
||||||
|
"version": "4.1.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.4.tgz",
|
||||||
|
"integrity": "sha512-Loo5UUvLD9ScZ6jh8beX1T6sO1w2/MpCRpEP7V280GKMVUQ0Jzar2U3UJPsrdbziLEMMhu3Ujnq//rhiFuIeag==",
|
||||||
|
"license": "BSD-3-Clause",
|
||||||
|
"dependencies": {
|
||||||
|
"psl": "^1.1.33",
|
||||||
|
"punycode": "^2.1.1",
|
||||||
|
"universalify": "^0.2.0",
|
||||||
|
"url-parse": "^1.5.3"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/type-is": {
|
"node_modules/type-is": {
|
||||||
"version": "1.6.18",
|
"version": "1.6.18",
|
||||||
"resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz",
|
"resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz",
|
||||||
|
@ -749,6 +899,24 @@
|
||||||
"resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz",
|
"resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz",
|
||||||
"integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA=="
|
"integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA=="
|
||||||
},
|
},
|
||||||
|
"node_modules/undici": {
|
||||||
|
"version": "6.19.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/undici/-/undici-6.19.4.tgz",
|
||||||
|
"integrity": "sha512-i3uaEUwNdkRq2qtTRRJb13moW5HWqviu7Vl7oYRYz++uPtGHJj+x7TGjcEuwS5Mt2P4nA0U9dhIX3DdB6JGY0g==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18.17"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/universalify": {
|
||||||
|
"version": "0.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz",
|
||||||
|
"integrity": "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 4.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/unpipe": {
|
"node_modules/unpipe": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
|
||||||
|
@ -757,6 +925,16 @@
|
||||||
"node": ">= 0.8"
|
"node": ">= 0.8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/url-parse": {
|
||||||
|
"version": "1.5.10",
|
||||||
|
"resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz",
|
||||||
|
"integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"querystringify": "^2.1.1",
|
||||||
|
"requires-port": "^1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/util-deprecate": {
|
"node_modules/util-deprecate": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
|
||||||
|
@ -791,6 +969,19 @@
|
||||||
"parse-cache-control": "^1.0.1"
|
"parse-cache-control": "^1.0.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"@distube/ytdl-core": {
|
||||||
|
"version": "4.14.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/@distube/ytdl-core/-/ytdl-core-4.14.4.tgz",
|
||||||
|
"integrity": "sha512-dHb4GW3qATIjRsS6VIhm3Pop7FdUcDFhsnyQlsPeXW7UhTPuNS0BmraKiTpFbpp0Ky+rxBQjJBfPRFsM+dT1fg==",
|
||||||
|
"requires": {
|
||||||
|
"http-cookie-agent": "^6.0.5",
|
||||||
|
"m3u8stream": "^0.8.6",
|
||||||
|
"miniget": "^4.2.3",
|
||||||
|
"sax": "^1.4.1",
|
||||||
|
"tough-cookie": "^4.1.4",
|
||||||
|
"undici": "five"
|
||||||
|
}
|
||||||
|
},
|
||||||
"@types/node": {
|
"@types/node": {
|
||||||
"version": "10.17.60",
|
"version": "10.17.60",
|
||||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.60.tgz",
|
"resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.60.tgz",
|
||||||
|
@ -1072,6 +1263,37 @@
|
||||||
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz",
|
||||||
"integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A=="
|
"integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A=="
|
||||||
},
|
},
|
||||||
|
"http-cookie-agent": {
|
||||||
|
"version": "6.0.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/http-cookie-agent/-/http-cookie-agent-6.0.5.tgz",
|
||||||
|
"integrity": "sha512-sfZ8fDgDP3B1YB+teqSnAK1aPgBu8reUUGxSsndP2XnYN6cM29EURXWXZqQQiaRdor3B4QjpkUNfv21syaO4DA==",
|
||||||
|
"requires": {
|
||||||
|
"agent-base": "^7.1.1"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"agent-base": {
|
||||||
|
"version": "7.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz",
|
||||||
|
"integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==",
|
||||||
|
"requires": {
|
||||||
|
"debug": "^4.3.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"debug": {
|
||||||
|
"version": "4.3.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.6.tgz",
|
||||||
|
"integrity": "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==",
|
||||||
|
"requires": {
|
||||||
|
"ms": "2.1.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"ms": {
|
||||||
|
"version": "2.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
|
||||||
|
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"http-errors": {
|
"http-errors": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz",
|
||||||
|
@ -1134,6 +1356,15 @@
|
||||||
"resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
|
"resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
|
||||||
"integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g=="
|
"integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g=="
|
||||||
},
|
},
|
||||||
|
"m3u8stream": {
|
||||||
|
"version": "0.8.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/m3u8stream/-/m3u8stream-0.8.6.tgz",
|
||||||
|
"integrity": "sha512-LZj8kIVf9KCphiHmH7sbFQTVe4tOemb202fWwvJwR9W5ENW/1hxJN6ksAWGhQgSBSa3jyWhnjKU1Fw1GaOdbyA==",
|
||||||
|
"requires": {
|
||||||
|
"miniget": "^4.2.2",
|
||||||
|
"sax": "^1.2.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
"media-typer": {
|
"media-typer": {
|
||||||
"version": "0.3.0",
|
"version": "0.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
|
||||||
|
@ -1167,6 +1398,11 @@
|
||||||
"mime-db": "1.52.0"
|
"mime-db": "1.52.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"miniget": {
|
||||||
|
"version": "4.2.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/miniget/-/miniget-4.2.3.tgz",
|
||||||
|
"integrity": "sha512-SjbDPDICJ1zT+ZvQwK0hUcRY4wxlhhNpHL9nJOB2MEAXRGagTljsO8MEDzQMTFf0Q8g4QNi8P9lEm/g7e+qgzA=="
|
||||||
|
},
|
||||||
"ms": {
|
"ms": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
|
||||||
|
@ -1219,6 +1455,16 @@
|
||||||
"ipaddr.js": "1.9.1"
|
"ipaddr.js": "1.9.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"psl": {
|
||||||
|
"version": "1.9.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz",
|
||||||
|
"integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag=="
|
||||||
|
},
|
||||||
|
"punycode": {
|
||||||
|
"version": "2.3.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
|
||||||
|
"integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg=="
|
||||||
|
},
|
||||||
"qs": {
|
"qs": {
|
||||||
"version": "6.11.0",
|
"version": "6.11.0",
|
||||||
"resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz",
|
"resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz",
|
||||||
|
@ -1227,6 +1473,11 @@
|
||||||
"side-channel": "^1.0.4"
|
"side-channel": "^1.0.4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"querystringify": {
|
||||||
|
"version": "2.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz",
|
||||||
|
"integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ=="
|
||||||
|
},
|
||||||
"range-parser": {
|
"range-parser": {
|
||||||
"version": "1.2.1",
|
"version": "1.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
|
||||||
|
@ -1242,6 +1493,11 @@
|
||||||
"util-deprecate": "^1.0.1"
|
"util-deprecate": "^1.0.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"requires-port": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz",
|
||||||
|
"integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ=="
|
||||||
|
},
|
||||||
"safe-buffer": {
|
"safe-buffer": {
|
||||||
"version": "5.2.1",
|
"version": "5.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
|
||||||
|
@ -1252,6 +1508,11 @@
|
||||||
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
|
||||||
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
|
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
|
||||||
},
|
},
|
||||||
|
"sax": {
|
||||||
|
"version": "1.4.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/sax/-/sax-1.4.1.tgz",
|
||||||
|
"integrity": "sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg=="
|
||||||
|
},
|
||||||
"send": {
|
"send": {
|
||||||
"version": "0.18.0",
|
"version": "0.18.0",
|
||||||
"resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz",
|
"resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz",
|
||||||
|
@ -1323,6 +1584,17 @@
|
||||||
"resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz",
|
||||||
"integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA=="
|
"integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA=="
|
||||||
},
|
},
|
||||||
|
"tough-cookie": {
|
||||||
|
"version": "4.1.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.4.tgz",
|
||||||
|
"integrity": "sha512-Loo5UUvLD9ScZ6jh8beX1T6sO1w2/MpCRpEP7V280GKMVUQ0Jzar2U3UJPsrdbziLEMMhu3Ujnq//rhiFuIeag==",
|
||||||
|
"requires": {
|
||||||
|
"psl": "^1.1.33",
|
||||||
|
"punycode": "^2.1.1",
|
||||||
|
"universalify": "^0.2.0",
|
||||||
|
"url-parse": "^1.5.3"
|
||||||
|
}
|
||||||
|
},
|
||||||
"type-is": {
|
"type-is": {
|
||||||
"version": "1.6.18",
|
"version": "1.6.18",
|
||||||
"resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz",
|
"resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz",
|
||||||
|
@ -1337,11 +1609,30 @@
|
||||||
"resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz",
|
"resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz",
|
||||||
"integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA=="
|
"integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA=="
|
||||||
},
|
},
|
||||||
|
"undici": {
|
||||||
|
"version": "6.19.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/undici/-/undici-6.19.4.tgz",
|
||||||
|
"integrity": "sha512-i3uaEUwNdkRq2qtTRRJb13moW5HWqviu7Vl7oYRYz++uPtGHJj+x7TGjcEuwS5Mt2P4nA0U9dhIX3DdB6JGY0g=="
|
||||||
|
},
|
||||||
|
"universalify": {
|
||||||
|
"version": "0.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz",
|
||||||
|
"integrity": "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg=="
|
||||||
|
},
|
||||||
"unpipe": {
|
"unpipe": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
|
||||||
"integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ=="
|
"integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ=="
|
||||||
},
|
},
|
||||||
|
"url-parse": {
|
||||||
|
"version": "1.5.10",
|
||||||
|
"resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz",
|
||||||
|
"integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==",
|
||||||
|
"requires": {
|
||||||
|
"querystringify": "^2.1.1",
|
||||||
|
"requires-port": "^1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"util-deprecate": {
|
"util-deprecate": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
|
||||||
|
|
|
@ -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,6 +23,7 @@
|
||||||
},
|
},
|
||||||
"homepage": "https://github.com/Violets-puragtory/YoutubeConverter#readme",
|
"homepage": "https://github.com/Violets-puragtory/YoutubeConverter#readme",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@distube/ytdl-core": "^4.14.4",
|
||||||
"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"
|
||||||
|
|
|
@ -8,8 +8,12 @@
|
||||||
|
|
||||||
<link rel="stylesheet" href="./style.css">
|
<link rel="stylesheet" href="./style.css">
|
||||||
|
|
||||||
|
<script src="./js/jquery.js"></script>
|
||||||
|
<script src="./js/js-cookie.js"></script>
|
||||||
|
<script src="./js/main.js"></script>
|
||||||
|
|
||||||
<meta content="Univerter" property="og:title" />
|
<meta content="Univerter" property="og:title" />
|
||||||
<meta content="Univerter is a web video downloader & converter for Youtube, TikTok, Twitter, and more." property="og:description" />
|
<meta content="Univerter is an extremely fast web downloader for Youtube videos." property="og:description" />
|
||||||
<meta content="https://univerter.dev/Images/Univerter%20Logo.png" property="og:image" />
|
<meta content="https://univerter.dev/Images/Univerter%20Logo.png" property="og:image" />
|
||||||
<meta content="#a200ff" data-react-helmet="true" name="theme-color" />
|
<meta content="#a200ff" data-react-helmet="true" name="theme-color" />
|
||||||
|
|
||||||
|
@ -20,7 +24,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">
|
||||||
|
|
||||||
|
@ -34,7 +38,7 @@
|
||||||
<option value="480">480p</option>
|
<option value="480">480p</option>
|
||||||
<option value="720" selected>720p</option>
|
<option value="720" selected>720p</option>
|
||||||
<option value="1080">1080p</option>
|
<option value="1080">1080p</option>
|
||||||
<option value="1440">1440p</option>
|
<option value="1440">1440p (2k)</option>
|
||||||
<option value="2160">2160p (4k)</option>
|
<option value="2160">2160p (4k)</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
@ -44,29 +48,26 @@
|
||||||
<select required id="format" name="format">
|
<select required id="format" name="format">
|
||||||
<option disabled>Video Formats</option>
|
<option disabled>Video Formats</option>
|
||||||
<option value="mp4">.mp4</option>
|
<option value="mp4">.mp4</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>
|
||||||
<!-- <br> -->
|
<div id="audioOnly">
|
||||||
<!-- <input style="display: inline-block" type="checkbox" id="adv"> -->
|
<input style="display: inline-block" type="checkbox" id="trim" name="trimAudio">
|
||||||
<!-- <p style="display: inline-block" for="adv">Enable Advanced options? (Beta)</p> -->
|
<p style="display: inline-block" for="trim">Trim Silence (mp3)</p>
|
||||||
|
</div>
|
||||||
|
<div id="videoAndAudio">
|
||||||
|
<!-- <input style="display: inline-block" type="checkbox" id="trim" checked>
|
||||||
|
<p style="display: inline-block" for="trim">Trim BALLS (mp4 only)</p> -->
|
||||||
|
</div>
|
||||||
|
|
||||||
<br>
|
|
||||||
<input type="submit">
|
<input type="submit">
|
||||||
</form>
|
</form>
|
||||||
<br>
|
<!-- <br> -->
|
||||||
|
|
||||||
<p>
|
<p>Inspired by <a href="https://cobalt.tools">Cobalt</a></p>
|
||||||
Powered by <a target="_blank" href="https://github.com/yt-dlp/yt-dlp/">yt-dlp</a>
|
<p>Developed by <a href="https://violets-purgatory.dev">Violet</a></p>
|
||||||
<br>
|
|
||||||
Inspired by <a href="https://cobalt.tools">Cobalt</a><br>
|
|
||||||
Check out the <a href="https://beta.univerter.dev">beta!</a> (It breaks much less!)<br>
|
|
||||||
</p>
|
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
|
|
2
static/js/jquery.js
vendored
Normal file
2
static/js/jquery.js
vendored
Normal file
File diff suppressed because one or more lines are too long
2
static/js/js-cookie.js
Normal file
2
static/js/js-cookie.js
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
/*! js-cookie v3.0.5 | MIT */
|
||||||
|
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e="undefined"!=typeof globalThis?globalThis:e||self,function(){var n=e.Cookies,o=e.Cookies=t();o.noConflict=function(){return e.Cookies=n,o}}())}(this,(function(){"use strict";function e(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var o in n)e[o]=n[o]}return e}var t=function t(n,o){function r(t,r,i){if("undefined"!=typeof document){"number"==typeof(i=e({},o,i)).expires&&(i.expires=new Date(Date.now()+864e5*i.expires)),i.expires&&(i.expires=i.expires.toUTCString()),t=encodeURIComponent(t).replace(/%(2[346B]|5E|60|7C)/g,decodeURIComponent).replace(/[()]/g,escape);var c="";for(var u in i)i[u]&&(c+="; "+u,!0!==i[u]&&(c+="="+i[u].split(";")[0]));return document.cookie=t+"="+n.write(r,t)+c}}return Object.create({set:r,get:function(e){if("undefined"!=typeof document&&(!arguments.length||e)){for(var t=document.cookie?document.cookie.split("; "):[],o={},r=0;r<t.length;r++){var i=t[r].split("="),c=i.slice(1).join("=");try{var u=decodeURIComponent(i[0]);if(o[u]=n.read(c,u),e===u)break}catch(e){}}return e?o[e]:o}},remove:function(t,n){r(t,"",e({},n,{expires:-1}))},withAttributes:function(n){return t(this.converter,e({},this.attributes,n))},withConverter:function(n){return t(e({},this.converter,n),this.attributes)}},{attributes:{value:Object.freeze(o)},converter:{value:Object.freeze(n)}})}({read:function(e){return'"'===e[0]&&(e=e.slice(1,-1)),e.replace(/(%[\dA-F]{2})+/gi,decodeURIComponent)},write:function(e){return encodeURIComponent(e).replace(/%(2[346BF]|3[AC-F]|40|5[BDE]|60|7[BCD])/g,decodeURIComponent)}},{path:"/"});return t}));
|
24
static/js/main.js
Normal file
24
static/js/main.js
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
var audioFormats = ["mp3"]
|
||||||
|
|
||||||
|
function updateOptions() {
|
||||||
|
var format = $("#format").val()
|
||||||
|
if (audioFormats.includes(format)) {
|
||||||
|
$("#audioOnly > input").attr("disabled", false)
|
||||||
|
$("#videoAndAudio > input").attr("disabled", true)
|
||||||
|
} else {
|
||||||
|
$("#audioOnly > input").attr("disabled", true)
|
||||||
|
$("#videoAndAudio > input").attr("disabled", false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$(document).ready(() => {
|
||||||
|
updateOptions()
|
||||||
|
$("#format").on("change", updateOptions)
|
||||||
|
|
||||||
|
$("#quality").val(Cookies.get("quality") || "720")
|
||||||
|
$("#trim").prop("checked", Cookies.get("trim") == "true" || false)
|
||||||
|
$("form").submit(() => {
|
||||||
|
Cookies.set("quality", $("#quality").val())
|
||||||
|
Cookies.set("trim", $("#trim").prop("checked"))
|
||||||
|
})
|
||||||
|
})
|
|
@ -76,6 +76,13 @@ body {
|
||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@media screen and (min-height: 700px) {
|
||||||
|
html,
|
||||||
|
body {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.mainDiv {
|
.mainDiv {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
/* outline: 2px white solid; */
|
/* outline: 2px white solid; */
|
||||||
|
@ -86,13 +93,6 @@ iframe {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media screen and (min-height: 500px) {
|
|
||||||
html,
|
|
||||||
body {
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
select,
|
select,
|
||||||
input {
|
input {
|
||||||
font-size: 1.3rem;
|
font-size: 1.3rem;
|
||||||
|
@ -131,10 +131,10 @@ option {
|
||||||
background-color: rgba(0, 0, 20);
|
background-color: rgba(0, 0, 20);
|
||||||
}
|
}
|
||||||
|
|
||||||
#adv {
|
input[type="checkbox"] {
|
||||||
accent-color: var(--primary-color);
|
accent-color: var(--primary-color);
|
||||||
width: 1.15rem;
|
width: 1.05rem;
|
||||||
height: 1.15rem;
|
height: 1.05rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.error {
|
.error {
|
||||||
|
|
BIN
yt-dlp
BIN
yt-dlp
Binary file not shown.
Loading…
Reference in a new issue