Testing out yt-dlp

pull/9/head
aandrew-me 3 years ago
parent 07dad07aa8
commit 545e17e5e9

File diff suppressed because it is too large Load Diff

@ -21,7 +21,7 @@ function createWindow() {
win.loadFile("html/index.html");
win.maximize();
win.setMenu(null)
// win.setMenu(null)
win.show();
// win.webContents.openDevTools();
autoUpdater.checkForUpdatesAndNotify();

@ -9,12 +9,15 @@ const { shell, ipcRenderer, clipboard } = require("electron");
// Directories
const homedir = os.homedir();
const appdir = path.join(homedir, "ytDownloader");
const tempDir = path.join(homedir,".ytDownloader", "temp");
const tempDir = path.join(homedir, ".ytDownloader", "temp");
fs.mkdirSync(tempDir, { recursive: true });
// Download directory
let downloadDir = "";
// Global variables
let title, onlyvideo;
function getId(id) {
return document.getElementById(id);
}
@ -27,24 +30,26 @@ if (localPath) {
downloadDir = appdir;
localStorage.setItem("downloadPath", appdir);
}
fs.mkdir(downloadDir, {recursive:true}, ()=>{})
fs.mkdir(downloadDir, { recursive: true }, () => {});
// Clearing tempDir
fs.readdirSync(tempDir).forEach((f) => fs.rmdir(`${tempDir}/${f}`, {recursive:true} ,() => {}));
fs.readdirSync(tempDir).forEach((f) =>
fs.rmdir(`${tempDir}/${f}`, { recursive: true }, () => {})
);
// Collecting info from youtube
async function getVideoInfo(url) {
let info;
await ytdl
.getInfo(url)
.then((data) => {
info = data;
})
.catch((error) => {
console.log(error);
});
return info;
}
// async function getVideoInfo(url) {
// let info;
// await ytdl
// .getInfo(url)
// .then((data) => {
// info = data;
// })
// .catch((error) => {
// console.log(error);
// });
// return info;
// }
function defaultVideoToggle() {
videoToggle.style.backgroundColor = "var(--box-toggleOn)";
@ -78,109 +83,132 @@ getId("pasteUrl").addEventListener("click", () => {
async function getInfo(url) {
getId("videoFormatSelect").innerHTML = "";
getId("audioFormatSelect").innerHTML = "";
let info = await getVideoInfo(url);
if (info) {
const title = info.videoDetails.title;
const formats = info.formats;
console.log(formats);
const urlElements = document.querySelectorAll(".url");
urlElements.forEach((element) => {
element.value = url;
});
getId("hidden").style.display = "inline-block";
getId("title").innerHTML = "<b>Title</b>: " + title;
getId("videoList").style.display = "block";
videoToggle.style.backgroundColor = "rgb(67, 212, 164)";
let highestQualityLength = 0;
let audioSize = 0;
// Getting approx size of audio file
for (let format of formats) {
if (
format.hasAudio &&
!format.hasVideo &&
format.contentLength &&
format.container == "mp4"
) {
audioSize = Number(format.contentLength) / 1000000;
}
let info;
cp.exec(`yt-dlp -j ${url}`, (error, stdout, stderr) => {
try {
info = JSON.parse(stdout);
} catch (error) {
info = false;
}
for (let format of formats) {
let size = (Number(format.contentLength) / 1000000).toFixed(2);
// For videos
if (format.hasVideo && format.contentLength && !format.hasAudio) {
size = (Number(size) + Number(audioSize)).toFixed(2);
size = size + " MB";
const itag = format.itag;
const avcPattern = /^avc1[0-9a-zA-Z.]+$/g;
const av1Pattern = /^av01[0-9a-zA-Z.]+$/g;
let codec;
if (av1Pattern.test(format.codecs)) {
codec = "AV1 Codec";
} else if (avcPattern.test(format.codecs)) {
codec = "AVC Codec";
} else {
codec = format.codecs.toUpperCase() + " Codec";
}
console.log(info);
if (info) {
title = info.title;
const formats = info.formats;
console.log(formats);
const urlElements = document.querySelectorAll(".url");
const element =
"<option value='" +
itag +
"'>" +
format.qualityLabel +
" | " +
format.container +
" | " +
size +
" | " +
codec;
("</option>");
getId("videoFormatSelect").innerHTML += element;
urlElements.forEach((element) => {
element.value = url;
});
getId("hidden").style.display = "inline-block";
getId("title").innerHTML = "<b>Title</b>: " + title;
getId("videoList").style.display = "block";
videoToggle.style.backgroundColor = "rgb(67, 212, 164)";
let highestQualityLength = 0;
let audioSize = 0;
// Getting approx size of audio file
for (let format of formats) {
if (
format.audio_ext !== "none" || format.acodec !== "none" &&
format.video_ext === "none"
) {
audioSize =
Number(format.filesize || format.filesize_approx) /
1000000;
}
}
// For audios
else if (
format.hasAudio &&
!format.hasVideo &&
format.audioBitrate
) {
size = size + " MB";
const pattern = /^mp*4a[0-9.]+$/g;
let audioCodec;
const itag = format.itag;
if (pattern.test(format.audioCodec)) {
audioCodec = "m4a";
} else {
audioCodec = format.audioCodec;
for (let format of formats) {
let size = (
Number(format.filesize || format.filesize_approx) / 1000000
).toFixed(2);
// For videos
if (
format.video_ext !== "none" &&
format.audio_ext === "none"
) {
size = (Number(size) + 0 || Number(audioSize)).toFixed(2);
size = size + " MB";
const format_id = format.format_id;
const element =
"<option value='" +
format_id +
"'>" +
format.resolution +
" | " +
format.ext +
" | " +
size +
"</option>";
getId("videoFormatSelect").innerHTML += element;
}
// For audios
else if (
format.audio_ext !== "none" ||
(format.acodec !== "none" && format.video_ext === "none")
) {
size = size + " MB";
let audio_ext;
const format_id = format.format_id;
if (format.audio_ext === "webm") {
audio_ext = "opus";
} else {
audio_ext = format.audio_ext;
}
const element =
"<option value='" +
format_id +
"'>" +
format.format_note +
" | " +
audio_ext +
" | " +
size +
"</option>";
getId("audioFormatSelect").innerHTML += element;
}
// Both audio and video available
else if (
format.audio_ext !== "none" ||
(format.acodec !== "none" && format.video_ext !== "none")
) {
let size = (
Number(format.filesize || format.filesize_approx) /
1000000
).toFixed(2);
console.log("filesize " + format.filesize);
console.log("filesize_approx " + format.filesize_approx);
const element =
"<option value='" +
format.format_id +
"'>" +
format.resolution +
" | " +
format.ext +
" | " +
size +
" MB" +
"</option>";
getId("videoFormatSelect").innerHTML += element;
}
const element =
"<option value='" +
itag +
"'>" +
format.audioBitrate +
" kbps" +
" | " +
audioCodec +
" | " +
size +
"</option>";
getId("audioFormatSelect").innerHTML += element;
}
} else {
getId("loadingWrapper").style.display = "none";
getId("incorrectMsg").textContent =
"Some error has occured. Check your connection and use correct URL";
}
} else {
getId("loadingWrapper").style.display = "none";
getId("incorrectMsg").textContent =
"Some error has occured. Check your connection and use correct URL";
}
});
}
// Video download event
@ -201,36 +229,24 @@ getId("audioDownload").addEventListener("click", (event) => {
function download(type) {
const url = getId("url").value;
const newFolderName = Math.random().toFixed(10).toString().slice(2);
const newFolderPath = path.join(tempDir, newFolderName);
fs.mkdir(newFolderPath, (err) => {
if (err) {
console.log("Temp directory couldn't be created");
}
});
let itag;
let format_id;
if (type === "video") {
itag = getId("videoFormatSelect").value;
format_id = getId("videoFormatSelect").value;
} else {
itag = getId("audioFormatSelect").value;
format_id = getId("audioFormatSelect").value;
}
// Finding info of the link and downloading
findInfo(url, itag).then((info) => {
const id = info.id;
const newItem = `
const newItem = `
<div class="item" id="${newFolderName}">
<img src="../assets/images/close.png" onClick="fadeItem('${newFolderName}')" class="itemClose"}" id="${
newFolderName + ".close"
}">
newFolderName + ".close"
}">
<img src="https://img.youtube.com/vi/${id}/mqdefault.jpg" alt="thumbnail" class="itemIcon">
<div class="itemBody">
<div class="itemTitle">${info.title}</div>
<div class="itemType">${info.filetype}</div>
<div class="itemTitle">${title}</div>
<div class="itemType">${type}</div>
<input disabled type="range" value="0" class="hiddenVideoProgress" id="${
newFolderName + "vid"
}"></input>
@ -241,199 +257,23 @@ function download(type) {
</div>
</div>
`;
getId("list").innerHTML += newItem;
getId("loadingWrapper").style.display = "none";
let cancelled = false;
getId(newFolderName + ".close").addEventListener("click", () => {
if (getId(newFolderName)) {
fadeItem(newFolderName);
}
cancelled = true;
});
const format = info.format;
const extension = info.extension;
let filename = "";
// Trying to remove ambiguous characters
for (let i = 0; i < info.filename.length; i++) {
const pattern = /^[`~!@#$%^&*:;,<>?/|'"-+=\]\[]$/g;
let letter = "";
if (pattern.test(info.filename[i])) {
letter = "";
} else {
if (info.filename[i] == " ") {
letter = "_";
} else {
letter = info.filename[i];
}
}
filename += letter;
}
let audioExtension;
let videoProgress, audioProgress;
let audioTag;
getId("list").innerHTML += newItem;
getId("loadingWrapper").style.display = "none";
let cancelled = false;
if (extension == "mp4") {
audioTag = 140;
audioExtension = "m4a";
} else {
audioTag = 251;
audioExtension = "opus";
}
// If video
if (format.hasVideo) {
getId(newFolderName + "prog").textContent = "Starting...";
// Temporary audio and video files
let videoName =
Math.random().toString("16").slice(2) + "." + extension;
let audioName =
Math.random().toString("16").slice(2) + "." + audioExtension;
const arr = [
new Promise((resolve, reject) => {
if (cancelled) {
reject("cancelled");
}
// Downloading only video
const videoDownload = ytdl(url, { quality: itag });
videoDownload
.on("progress", (_, downloaded, size) => {
if (cancelled) {
console.log("Cancelled video");
videoDownload.destroy();
reject();
} else {
videoProgress = (downloaded / size) * 100;
getId(newFolderName + "vid").value =
videoProgress;
if (videoProgress != 100) {
getId(newFolderName + "prog").textContent =
"Downloading";
getId(newFolderName + "vid").style.display =
"block";
getId(newFolderName + "aud").style.display =
"block";
}
if (videoProgress == 100) {
resolve("video downloaded");
}
}
})
.pipe(
fs.createWriteStream(
path.join(newFolderPath, videoName)
)
);
}),
new Promise((resolve, reject) => {
if (cancelled) {
reject("cancelled");
}
// Downloading only audio
const audioDownload = ytdl(url, {
highWaterMark: 1 << 25,
quality: audioTag,
});
audioDownload
.on("progress", (_, downloaded, size) => {
if (cancelled) {
console.log("Cancelled audio");
audioDownload.destroy();
reject();
} else {
audioProgress = (downloaded / size) * 100;
getId(newFolderName + "aud").value =
audioProgress || 0;
if (audioProgress != 100) {
} else if (audioProgress == 100) {
resolve("audio downloaded");
}
}
})
.pipe(
fs.createWriteStream(
path.join(newFolderPath, audioName)
)
);
}),
];
Promise.all([arr[0], arr[1]])
.then((response) => {
getId(newFolderName + "aud").style.display = "none";
getId(newFolderName + "vid").style.display = "none";
cp.exec(
`"${ffmpeg}" -i "${path.join(
newFolderPath,
videoName
)}" -i "${path.join(
newFolderPath,
audioName
)}" -c copy "${path.join(downloadDir, filename)}"`,
(error, stdout, stderr) => {
if (error) {
console.log(error);
} else if (stderr) {
console.log("video saved");
// Clear temp dir
fs.readdirSync(newFolderPath).forEach((f) =>
fs.rm(`${newFolderPath}/${f}`, () => {})
);
getId(newFolderName + "prog").textContent =
"Saved successfully";
afterSave(
downloadDir,
filename,
newFolderName + "prog"
);
}
}
);
})
.catch((error) => {
console.log("Promise failed. " + error);
});
}
// If audio
else {
getId(newFolderName + "prog").textContent = "Starting...";
const audioDownloading = ytdl(url, { quality: itag });
audioDownloading
.on("progress", (_, downloaded, size) => {
if (cancelled) {
console.log("Cancelled");
audioDownloading.destroy();
fs.rm(path.join(downloadDir, filename), (err) => {
if (err) {
console.log(err);
}
});
return;
}
const progress = ((downloaded / size) * 100).toFixed(0);
getId(
newFolderName + "prog"
).textContent = `Progress: ${progress}%`;
})
.on("end", () => {
afterSave(downloadDir, filename, newFolderName + "prog");
})
.pipe(fs.createWriteStream(path.join(downloadDir, filename)));
getId(newFolderName + ".close").addEventListener("click", () => {
if (getId(newFolderName)) {
fadeItem(newFolderName);
}
cancelled = true;
});
let downloadProcess;
if (type === "video") {
// cp.spawn(`yt-dlp -f ${format_id}+best`);
downloadProcess = cp.spawn("yt-dlp", ['-f', `${format_id}+ba`])
} else {
}
}
// Removing item
@ -462,77 +302,38 @@ function afterSave(location, filename, progressId) {
body: "File saved successfully.",
icon: "../assets/images/icon.png",
});
getId(progressId).innerHTML = `<b onClick="showItem('${location}', '${filename}')">File saved. Click to Open</b>`;
getId(
progressId
).innerHTML = `<b onClick="showItem('${location}', '${filename}')">File saved. Click to Open</b>`;
}
function showItem(location, filename){
function showItem(location, filename) {
shell.showItemInFolder(path.join(location, filename));
}
// Function to find video/audio info
async function findInfo(url, itag) {
const data = await ytdl.getInfo(url);
const format = ytdl.chooseFormat(data.formats, { quality: itag });
const title = data.videoDetails.title;
const id = data.videoDetails.videoId;
let type;
let extension;
if (format.hasVideo) {
extension = format.mimeType.split("; ")[0].split("/")[1];
type = "Video";
} else {
type = "Audio";
if (format.audioCodec === "mp4a.40.2") {
extension = "m4a";
} else {
extension = format.audioCodec;
}
}
let filetype = type + "/" + extension;
let quality;
if (format.hasVideo) {
quality = format.qualityLabel;
} else {
quality = format.audioBitrate + "kbps";
}
const randomNum = Math.random().toFixed(5).toString("16").slice(2);
const filename = `${title}_${randomNum}_${quality}.${extension}`;
const info = {
format: format,
title: title,
extension: extension,
quality: quality,
filename: filename,
id: id,
filetype: filetype,
};
return info;
}
// Opening windows
function closeMenu(){
function closeMenu() {
getId("menuIcon").style.transform = "rotate(0deg)";
menuIsOpen = false;
let count = 0;
let opacity = 1;
const fade = setInterval(() => {
if (count >= 10) {
clearInterval(fade);
} else {
opacity -= 0.1;
getId("menu").style.opacity = opacity;
count++;
}
}, 50);
menuIsOpen = false;
let count = 0;
let opacity = 1;
const fade = setInterval(() => {
if (count >= 10) {
clearInterval(fade);
} else {
opacity -= 0.1;
getId("menu").style.opacity = opacity;
count++;
}
}, 50);
}
getId("preferenceWin").addEventListener("click", () => {
closeMenu()
closeMenu();
ipcRenderer.send("load-page", __dirname + "/preferences.html");
});
getId("aboutWin").addEventListener("click", () => {
closeMenu()
closeMenu();
ipcRenderer.send("load-page", __dirname + "/about.html");
});

Loading…
Cancel
Save