Video compressor updates
This commit is contained in:
parent
33f4a71c9b
commit
99b61f8976
@ -406,10 +406,10 @@ body {
|
||||
padding: 12px 15px;
|
||||
background-color: var(--select);
|
||||
border: none;
|
||||
border-radius: 10px;
|
||||
border-radius: 12px;
|
||||
cursor: pointer;
|
||||
font-size: large;
|
||||
margin: 8px;
|
||||
margin-bottom: 8px;
|
||||
outline: none;
|
||||
max-width: min(400px, 100%);
|
||||
font-family: "JetBrains";
|
||||
@ -726,15 +726,16 @@ body::-webkit-scrollbar-thumb {
|
||||
|
||||
|
||||
/* Compressor styles */
|
||||
#compressor_body {
|
||||
text-align: left;
|
||||
#compressor-header {
|
||||
text-align: center;
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.container {
|
||||
max-width: 800px;
|
||||
margin: 0 auto;
|
||||
margin: 0 auto 10px auto;
|
||||
background: var(--box-main);
|
||||
padding: 2rem;
|
||||
padding: 30px;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
@ -754,15 +755,55 @@ body::-webkit-scrollbar-thumb {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.compress-select {
|
||||
font-family: "Ubuntu";
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.drop-zone.dragover {
|
||||
border-color: #2196F3;
|
||||
background-color: #f5fbff;
|
||||
background-color: var(--box-toggleOn);
|
||||
}
|
||||
|
||||
#settings-group-container {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.output-folder-conf {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
#output-folder-box {
|
||||
background-color: var(--item-bg);
|
||||
margin-bottom: 12px;
|
||||
padding: 15px;
|
||||
border-radius: 8px;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
#output-folder-input {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
.folder-input-checkbox {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
#output-suffix {
|
||||
cursor: text;
|
||||
}
|
||||
|
||||
.settings-group {
|
||||
margin-bottom: 1.5rem;
|
||||
margin-bottom: 10px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 46%;
|
||||
}
|
||||
|
||||
.compress-label {
|
||||
@ -774,19 +815,21 @@ body::-webkit-scrollbar-thumb {
|
||||
}
|
||||
|
||||
#compression-status {
|
||||
margin-top: 2rem;
|
||||
max-width: 800px;
|
||||
margin: 20px auto 0 auto;
|
||||
border-top: 1px solid var(--item-bg);
|
||||
padding-top: 1rem;
|
||||
padding-top: 20px;
|
||||
}
|
||||
|
||||
.status-item {
|
||||
padding: 15px;
|
||||
margin: 5px;
|
||||
padding: 16px;
|
||||
margin: 6px auto;
|
||||
border-radius: 4px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
flex-direction: row;
|
||||
background-color: var(--item-bg);
|
||||
max-width: 800px;
|
||||
}
|
||||
|
||||
.status-item.success {
|
||||
@ -797,11 +840,6 @@ body::-webkit-scrollbar-thumb {
|
||||
color: var(--redBtn);
|
||||
}
|
||||
|
||||
.filename {
|
||||
flex: 1;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.status {
|
||||
min-width: 80px;
|
||||
text-transform: uppercase;
|
||||
@ -809,11 +847,6 @@ body::-webkit-scrollbar-thumb {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.details {
|
||||
font-size: 0.9em;
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
.fileinput-btn {
|
||||
background: var(--blueBtn);
|
||||
color: white;
|
||||
@ -822,6 +855,7 @@ body::-webkit-scrollbar-thumb {
|
||||
border-radius: 5px;
|
||||
margin: 5px 0 10px 0;
|
||||
cursor: pointer;
|
||||
border: none;
|
||||
}
|
||||
|
||||
.progressBarCompress {
|
||||
@ -832,4 +866,18 @@ body::-webkit-scrollbar-thumb {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#custom-folder-select{
|
||||
padding: 10px;
|
||||
margin-left: 0;
|
||||
display: none;
|
||||
}
|
||||
|
||||
#custom-folder-path {
|
||||
font-family: "JetBrains";
|
||||
background-color: var(--box-main);
|
||||
padding: 8px;
|
||||
border-radius: 4px;
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* End */
|
@ -5,7 +5,6 @@
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Video Compressor</title>
|
||||
<link rel="stylesheet" href="../assets/css/extra.css">
|
||||
<link rel="stylesheet" href="../assets/css/index.css">
|
||||
</head>
|
||||
|
||||
@ -16,10 +15,11 @@
|
||||
<!-- Menu -->
|
||||
<div id="menu">
|
||||
<a id="homeWin" class="menuItem">Homepage</a>
|
||||
<a id="playlistWin" class="menuItem">Download Playlist</a>
|
||||
<a id="preferenceWin" class="menuItem">Preferences</a>
|
||||
<a id="aboutWin" class="menuItem">About</a>
|
||||
<span id="themeTxt" class="menuItem">Theme:</span>
|
||||
<select name="themeToggle" id="themeToggle">
|
||||
<select class="select compress-select" name="themeToggle" id="themeToggle">
|
||||
<option id="lightTxt" value="light">Light</option>
|
||||
<option id="darkTxt" value="dark">Dark</option>
|
||||
<option id="frappeTxt" value="frappe">Frappé</option>
|
||||
@ -32,7 +32,7 @@
|
||||
</div>
|
||||
|
||||
<div class="container">
|
||||
<h1>Video Compressor</h1>
|
||||
<h1 id="compressor-header">Video Compressor</h1>
|
||||
|
||||
<div class="drop-zone">
|
||||
<p>Drag and drop files here or</p>
|
||||
@ -41,106 +41,127 @@
|
||||
<div id="selected-files">No files selected</div>
|
||||
</div>
|
||||
|
||||
<div class="settings-group">
|
||||
<label class="compress-label" for="extension">Video format</label>
|
||||
<select id="file_extension">
|
||||
<option value="unchanged">Unchanged</option>
|
||||
<option value="mp4">mp4</option>
|
||||
<option value="mkv">mkv</option>
|
||||
<option value="webm">webm</option>
|
||||
</select>
|
||||
<div id="settings-group-container">
|
||||
<div class="settings-group">
|
||||
<label class="compress-label" for="extension">Video format</label>
|
||||
<select class="select compress-select" id="file_extension">
|
||||
<option value="unchanged">Unchanged</option>
|
||||
<option value="mp4">mp4</option>
|
||||
<option value="mkv">mkv</option>
|
||||
<option value="webm">webm</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="settings-group">
|
||||
<label class="compress-label" for="encoder">Video Encoder</label>
|
||||
<select class="select compress-select" id="encoder">
|
||||
<option value="x264">x264</option>
|
||||
<option value="x265">x265</option>
|
||||
|
||||
<option class="qsv_opt" value="qsv">x264 (Intel QSV Hardware Acceleration)</option>
|
||||
<option class="qsv_opt" value="hevc_qsv">x264 (Intel QSV Hardware Acceleration)</option>
|
||||
|
||||
<option class="amf_opt" value="amf">x264 (AMD Hardware Acceleration)</option>
|
||||
<option class="amf_opt" value="hevc_amf">x265 (AMD Hardware Acceleration)</option>
|
||||
|
||||
<option class="nvidia_opt" value="nvenc">x264 (NVIDIA Hardware Acceleration)</option>
|
||||
<option class="nvidia_opt" value="hevc_nvenc">x265 (NVIDIA Hardware Acceleration)</option>
|
||||
|
||||
<option class="vaapi_opt" value="vaapi">x264 (VA-API Hardware Acceleration)</option>
|
||||
<option class="vaapi_opt" value="hevc_vaapi">x265 (VA-API Hardware Acceleration)</option>
|
||||
|
||||
<option class="videotoolbox_opt" value="videotoolbox">x264 (VideoToolbox Hardware Acceleration)</option>
|
||||
<option class="videotoolbox_opt" value="hevc_videotoolbox">x265 (VideoToolbox Hardware Acceleration)</option>
|
||||
|
||||
|
||||
<option value="copy">Copy video</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="settings-group">
|
||||
<label class="compress-label" for="compression-speed">Compression Speed</label>
|
||||
<select class="select compress-select" id="compression-speed">
|
||||
<option value="fast">Fast</option>
|
||||
<option selected value="medium">Medium</option>
|
||||
<option value="slow">Slow</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="settings-group">
|
||||
<label class="compress-label" for="video-quality">Video Quality
|
||||
</label>
|
||||
<select class="select compress-select" id="video-quality">
|
||||
<option value="18">18 (Best quality)</option>
|
||||
<option value="19">19</option>
|
||||
<option value="20">20</option>
|
||||
<option value="21">21</option>
|
||||
<option value="22">22</option>
|
||||
<option selected value="23">23 (Medium size, good quality)</option>
|
||||
<option value="24">24</option>
|
||||
<option value="25">25</option>
|
||||
<option value="26">26</option>
|
||||
<option value="27">27</option>
|
||||
<option value="28">28 (Smaller file size, decent quality)</option>
|
||||
<option value="29">29</option>
|
||||
<option value="30">30</option>
|
||||
<option value="31">31</option>
|
||||
<option value="32">32</option>
|
||||
<option value="33">33</option>
|
||||
<option value="34">34</option>
|
||||
<option value="35">35</option>
|
||||
<option value="36">36</option>
|
||||
<option value="37">37</option>
|
||||
<option value="38">38</option>
|
||||
<option value="39">39</option>
|
||||
<option value="40">40</option>
|
||||
<option value="41">41</option>
|
||||
<option value="42">42</option>
|
||||
<option value="43">43</option>
|
||||
<option value="44">44</option>
|
||||
<option value="45">45</option>
|
||||
<option value="46">46</option>
|
||||
<option value="47">47</option>
|
||||
<option value="48">48</option>
|
||||
<option value="49">49</option>
|
||||
<option value="50">50</option>
|
||||
<option value="51">51 (Worst quality)</option>
|
||||
</select>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="settings-group">
|
||||
<label class="compress-label" for="audio-format">Audio Format</label>
|
||||
<select class="select compress-select" id="audio-format">
|
||||
<option value="copy">Unchanged</option>
|
||||
<option value="aac">aac</option>
|
||||
<option value="mp3">mp3</option>
|
||||
<option value="opus">opus</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="settings-group">
|
||||
<div class="compress-label">Output suffix</div>
|
||||
<input type="text" name="suffix" id="output-suffix" class="select compress-select" placeholder="No suffix needs different output folder" value="_compressed">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="settings-group">
|
||||
<label class="compress-label" for="encoder">Video Encoder</label>
|
||||
<select id="encoder">
|
||||
<option value="x264">x264</option>
|
||||
<option value="x265">x265</option>
|
||||
<div id="output-folder-box">
|
||||
<div class="output-folder-conf">
|
||||
<span class="compress-label">Output in same folder</span>
|
||||
<input checked type="checkbox" name="output-folder" id="output-folder-input">
|
||||
|
||||
<option class="qsv_opt" value="qsv">x264 (Intel QSV Hardware Acceleration)</option>
|
||||
<option class="qsv_opt" value="hevc_qsv">x264 (Intel QSV Hardware Acceleration)</option>
|
||||
|
||||
<option class="amf_opt" value="amf">x264 (AMD Hardware Acceleration)</option>
|
||||
<option class="amf_opt" value="hevc_amf">x265 (AMD Hardware Acceleration)</option>
|
||||
|
||||
<option class="nvidia_opt" value="nvenc">x264 (NVIDIA Hardware Acceleration)</option>
|
||||
<option class="nvidia_opt" value="hevc_nvenc">x265 (NVIDIA Hardware Acceleration)</option>
|
||||
|
||||
<option class="vaapi_opt" value="vaapi">x264 (VA-API Hardware Acceleration)</option>
|
||||
<option class="vaapi_opt" value="hevc_vaapi">x265 (VA-API Hardware Acceleration)</option>
|
||||
|
||||
<option class="videotoolbox_opt" value="videotoolbox">x264 (VideoToolbox Hardware Acceleration)</option>
|
||||
<option class="videotoolbox_opt" value="hevc_videotoolbox">x265 (VideoToolbox Hardware Acceleration)</option>
|
||||
|
||||
|
||||
<option value="copy">Copy video</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="settings-group">
|
||||
<label class="compress-label" for="compression-speed">Compression Speed</label>
|
||||
<select id="compression-speed">
|
||||
<option value="fast">Fast</option>
|
||||
<option selected value="medium">Medium</option>
|
||||
<option value="slow">Slow</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="settings-group">
|
||||
<label class="compress-label" for="video-quality">Video Quality
|
||||
</label>
|
||||
<select id="video-quality">
|
||||
<option value="18">18 (Best quality)</option>
|
||||
<option value="19">19</option>
|
||||
<option value="20">20</option>
|
||||
<option value="21">21</option>
|
||||
<option value="22">22</option>
|
||||
<option selected value="23">23 (Medium size, good quality)</option>
|
||||
<option value="24">24</option>
|
||||
<option value="25">25</option>
|
||||
<option value="26">26</option>
|
||||
<option value="27">27</option>
|
||||
<option value="28">28 (Smaller file size, decent quality)</option>
|
||||
<option value="29">29</option>
|
||||
<option value="30">30</option>
|
||||
<option value="31">31</option>
|
||||
<option value="32">32</option>
|
||||
<option value="33">33</option>
|
||||
<option value="34">34</option>
|
||||
<option value="35">35</option>
|
||||
<option value="36">36</option>
|
||||
<option value="37">37</option>
|
||||
<option value="38">38</option>
|
||||
<option value="39">39</option>
|
||||
<option value="40">40</option>
|
||||
<option value="41">41</option>
|
||||
<option value="42">42</option>
|
||||
<option value="43">43</option>
|
||||
<option value="44">44</option>
|
||||
<option value="45">45</option>
|
||||
<option value="46">46</option>
|
||||
<option value="47">47</option>
|
||||
<option value="48">48</option>
|
||||
<option value="49">49</option>
|
||||
<option value="50">50</option>
|
||||
<option value="51">51 (Worst quality)</option>
|
||||
</select>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="settings-group">
|
||||
<label class="compress-label" for="audio-format">Audio Format</label>
|
||||
<select id="audio-format">
|
||||
<option value="copy">Unchanged</option>
|
||||
<option value="aac">aac</option>
|
||||
<option value="mp3">mp3</option>
|
||||
<option value="opus">opus</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="output-folder-conf">
|
||||
<button class="blueBtn" id="custom-folder-select">Select Custom Folder</button>
|
||||
<span id="custom-folder-path"></span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="button-group">
|
||||
<button class="blueBtn" id="compress-btn">Start Compression</button>
|
||||
<button class="advancedToggle" id="cancel-btn">Cancel (not finished)</button>
|
||||
<button class="advancedToggle" id="cancel-btn">Cancel</button>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div id="compression-status"></div>
|
||||
|
@ -47,7 +47,7 @@
|
||||
<a id="playlistWin" class="menuItem">Download Playlist</a>
|
||||
<!-- <a id="newPlaylistWin" class="menuItem">New Playlist</a> -->
|
||||
<a id="preferenceWin" class="menuItem">Preferences</a>
|
||||
<a id="compressorWin" class="menuItem">Compressor</a>
|
||||
<a id="compressorWin" class="menuItem">Compressor</a>
|
||||
<a id="aboutWin" class="menuItem">About</a>
|
||||
<span id="themeTxt" class="menuItem">Theme:</span>
|
||||
<select name="themeToggle" id="themeToggle">
|
||||
|
@ -47,6 +47,7 @@
|
||||
<!-- Menu -->
|
||||
<div id="menu">
|
||||
<a id="homeWin" class="menuItem">Homepage</a>
|
||||
<a id="compressorWin" class="menuItem">Compressor</a>
|
||||
<a id="preferenceWin" class="menuItem">Preferences</a>
|
||||
<a id="aboutWin" class="menuItem">About</a>
|
||||
<span id="themeTxt" class="menuItem">Theme:</span>
|
||||
|
25
main.js
25
main.js
@ -266,6 +266,16 @@ ipcMain.on("select-location-secondary", () => {
|
||||
}
|
||||
});
|
||||
|
||||
ipcMain.on("get-directory", () => {
|
||||
const location = dialog.showOpenDialogSync({
|
||||
properties: ["openDirectory"],
|
||||
});
|
||||
|
||||
if (location) {
|
||||
win.webContents.send("directory-path", location);
|
||||
}
|
||||
});
|
||||
|
||||
ipcMain.on("select-config", () => {
|
||||
const location = dialog.showOpenDialogSync({
|
||||
properties: ["openFile"],
|
||||
@ -355,6 +365,21 @@ ipcMain.on("progress", (_event, percentage) => {
|
||||
}
|
||||
})
|
||||
|
||||
ipcMain.on("error_dialog", (_event, message) => {
|
||||
dialog.showMessageBox(win, {
|
||||
type: "error",
|
||||
title: "Error",
|
||||
message: message,
|
||||
buttons: [
|
||||
"Ok", "Copy error"
|
||||
]
|
||||
}).then((result) => {
|
||||
if (result.response == 1) {
|
||||
clipboard.writeText(message)
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
autoUpdater.on("update-downloaded", (_event, releaseNotes, releaseName) => {
|
||||
/**
|
||||
* @type {Electron.MessageBoxOptions}
|
||||
|
@ -21,8 +21,7 @@ getId("menuIcon").addEventListener("click", () => {
|
||||
getId("menu").style.display = "none";
|
||||
clearInterval(fade);
|
||||
} else {
|
||||
opacity -= 0.1;
|
||||
getId("menu").style.opacity = opacity;
|
||||
getId("menu").style.opacity = opacity.toFixed(3).toString();
|
||||
count++;
|
||||
}
|
||||
}, 50);
|
||||
|
@ -1,9 +1,39 @@
|
||||
const {exec} = require("child_process");
|
||||
const path = require("path");
|
||||
const {ipcRenderer} = require("electron");
|
||||
const {ipcRenderer, shell} = require("electron");
|
||||
const os = require("os");
|
||||
const si = require("systeminformation")
|
||||
|
||||
let menuIsOpen = false;
|
||||
|
||||
getId("menuIcon").addEventListener("click", () => {
|
||||
if (menuIsOpen) {
|
||||
getId("menuIcon").style.transform = "rotate(0deg)";
|
||||
menuIsOpen = false;
|
||||
let count = 0;
|
||||
let opacity = 1;
|
||||
const fade = setInterval(() => {
|
||||
if (count >= 10) {
|
||||
getId("menu").style.display = "none";
|
||||
clearInterval(fade);
|
||||
} else {
|
||||
opacity -= 0.1;
|
||||
getId("menu").style.opacity = opacity.toFixed(3).toString();
|
||||
count++;
|
||||
}
|
||||
}, 50);
|
||||
} else {
|
||||
getId("menuIcon").style.transform = "rotate(90deg)";
|
||||
menuIsOpen = true;
|
||||
|
||||
setTimeout(() => {
|
||||
getId("menu").style.display = "flex";
|
||||
getId("menu").style.opacity = "1";
|
||||
}, 150);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
let ffmpeg;
|
||||
if (os.platform() === "win32") {
|
||||
ffmpeg = `"${__dirname}\\..\\ffmpeg.exe"`;
|
||||
@ -13,6 +43,7 @@ if (os.platform() === "win32") {
|
||||
|
||||
const vaapi_device = "/dev/dri/renderD128"
|
||||
|
||||
// Checking GPU
|
||||
si.graphics().then((info) => {
|
||||
console.log({gpuInfo: info})
|
||||
const gpuDevices = info.controllers;
|
||||
@ -61,6 +92,7 @@ si.graphics().then((info) => {
|
||||
let files = [];
|
||||
let activeProcesses = new Set();
|
||||
let currentItemId = "";
|
||||
let isCancelled = false;
|
||||
|
||||
/**
|
||||
* @param {string} id
|
||||
@ -98,11 +130,15 @@ fileInput.addEventListener("change", (e) => {
|
||||
updateSelectedFiles();
|
||||
});
|
||||
|
||||
getId("custom-folder-select").addEventListener("click", (e) => {
|
||||
ipcRenderer.send("get-directory", "")
|
||||
})
|
||||
|
||||
function updateSelectedFiles() {
|
||||
const fileList = files
|
||||
.map((f) => `${f.name} (${formatBytes(f.size)})`)
|
||||
.map((f) => `${f.name} (${formatBytes(f.size)})<br/>`)
|
||||
.join("\n");
|
||||
selectedFilesDiv.textContent = fileList || "No files selected";
|
||||
selectedFilesDiv.innerHTML = fileList || "No files selected";
|
||||
}
|
||||
|
||||
// Compression Logic
|
||||
@ -120,45 +156,73 @@ async function startCompression() {
|
||||
"f" + Math.random().toFixed(10).toString().slice(2).toString();
|
||||
currentItemId = itemId;
|
||||
|
||||
const outputPath = generateOutputPath(file, settings);
|
||||
|
||||
try {
|
||||
await compressVideo(file, settings, itemId);
|
||||
updateProgress("success", "Successfully compressed", itemId);
|
||||
currentItemId = ""
|
||||
await compressVideo(file, settings, itemId, outputPath);
|
||||
|
||||
if (isCancelled) {
|
||||
isCancelled = false;
|
||||
} else {
|
||||
updateProgress("success", "", itemId);
|
||||
const fileSavedElement = document.createElement("b")
|
||||
fileSavedElement.textContent = "File saved. Click to open"
|
||||
fileSavedElement.onclick = () => {
|
||||
shell.showItemInFolder(outputPath)
|
||||
}
|
||||
getId(itemId + "_prog").appendChild(fileSavedElement)
|
||||
currentItemId = ""
|
||||
}
|
||||
} catch (error) {
|
||||
updateProgress("error", error.message, itemId);
|
||||
const errorElement = document.createElement("div")
|
||||
errorElement.onclick = () => {
|
||||
ipcRenderer.send("error_dialog", error.message)
|
||||
}
|
||||
errorElement.textContent = "Error. Click for details"
|
||||
updateProgress("error", "", itemId);
|
||||
getId(itemId + "_prog").appendChild(errorElement)
|
||||
currentItemId = ""
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function cancelCompression() {
|
||||
activeProcesses.forEach((child) => child.kill("SIGTERM"));
|
||||
activeProcesses.forEach((child) => {
|
||||
child.stdin.write("q")
|
||||
isCancelled = true;
|
||||
});
|
||||
activeProcesses.clear();
|
||||
updateProgress("", "cancelled", currentItemId);
|
||||
updateProgress("error", "Cancelled", currentItemId);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {File} file
|
||||
*/
|
||||
function generateOutputPath(file, settings) {
|
||||
console.log({settings})
|
||||
const output_extension = settings.extension
|
||||
const parsed_file = path.parse(file.path)
|
||||
|
||||
let outputDir = settings.outputPath || parsed_file.dir
|
||||
|
||||
|
||||
if (output_extension == "unchanged") {
|
||||
return path.join(parsed_file.dir, `${parsed_file.name}_compressed${parsed_file.ext}`);
|
||||
return path.join(outputDir, `${parsed_file.name}${settings.outputSuffix}${parsed_file.ext}`);
|
||||
}
|
||||
|
||||
return path.join(parsed_file.dir, `${parsed_file.name}_compressed.${output_extension}`);
|
||||
return path.join(outputDir, `${parsed_file.name}_compressed.${output_extension}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {File} file
|
||||
* @param {{ encoder: any; speed: any; videoQuality: any; audioQuality?: any; audioFormat: string, extension: string }} settings
|
||||
* @param {string} itemId
|
||||
* @param {string} outputPath
|
||||
*/
|
||||
async function compressVideo(file, settings, itemId) {
|
||||
const command = buildFFmpegCommand(file, settings);
|
||||
async function compressVideo(file, settings, itemId, outputPath) {
|
||||
const command = buildFFmpegCommand(file, settings, outputPath);
|
||||
|
||||
console.log("Command: " + command)
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
const child = exec(command, (error) => {
|
||||
@ -167,7 +231,9 @@ async function compressVideo(file, settings, itemId) {
|
||||
});
|
||||
|
||||
activeProcesses.add(child);
|
||||
child.on("exit", () => activeProcesses.delete(child));
|
||||
child.on("exit", (_code) => {
|
||||
activeProcesses.delete(child)
|
||||
});
|
||||
|
||||
let video_info = {
|
||||
duration: "",
|
||||
@ -182,6 +248,7 @@ async function compressVideo(file, settings, itemId) {
|
||||
);
|
||||
|
||||
child.stderr.on("data", (data) => {
|
||||
// console.log(data)
|
||||
const duration_match = data.match(/Duration:\s*([\d:.]+)/);
|
||||
if (duration_match) {
|
||||
video_info.duration = duration_match[1];
|
||||
@ -202,7 +269,7 @@ async function compressVideo(file, settings, itemId) {
|
||||
? timeToSeconds(progressTime[1])
|
||||
: null;
|
||||
|
||||
if (currentSeconds) {
|
||||
if (currentSeconds && !isCancelled) {
|
||||
const progress = Math.round(
|
||||
(currentSeconds / totalSeconds) * 100
|
||||
);
|
||||
@ -218,15 +285,14 @@ async function compressVideo(file, settings, itemId) {
|
||||
/**
|
||||
* @param {File} file
|
||||
* @param {{ encoder: string; speed: string; videoQuality: string; audioQuality: string; audioFormat: string }} settings
|
||||
* @param {string} outputPath
|
||||
*/
|
||||
function buildFFmpegCommand(file, settings) {
|
||||
function buildFFmpegCommand(file, settings, outputPath) {
|
||||
const inputPath = file.path;
|
||||
|
||||
const outputPath = generateOutputPath(file, settings);
|
||||
|
||||
console.log("Output path: " + outputPath)
|
||||
|
||||
const args = ["-y", "-stats", "-i", `"${inputPath}"`];
|
||||
const args = ["-hide_banner", "-y", "-stats", "-i", `"${inputPath}"`];
|
||||
|
||||
switch (settings.encoder) {
|
||||
case "copy":
|
||||
@ -320,8 +386,8 @@ function buildFFmpegCommand(file, settings) {
|
||||
"cqp",
|
||||
"-qp_i",
|
||||
parseInt(settings.videoQuality).toString(),
|
||||
"-qp_i",
|
||||
parseInt(settings.videoQuality).toString()
|
||||
"-qp_p",
|
||||
parseInt(settings.videoQuality).toString(),
|
||||
);
|
||||
break;
|
||||
case "amf":
|
||||
@ -342,7 +408,9 @@ function buildFFmpegCommand(file, settings) {
|
||||
"cqp",
|
||||
"-qp_i",
|
||||
parseInt(settings.videoQuality).toString(),
|
||||
"-qp_i",
|
||||
"-qp_p",
|
||||
parseInt(settings.videoQuality).toString(),
|
||||
"-qp_b",
|
||||
parseInt(settings.videoQuality).toString()
|
||||
);
|
||||
break;
|
||||
@ -356,6 +424,10 @@ function buildFFmpegCommand(file, settings) {
|
||||
break;
|
||||
}
|
||||
|
||||
// args.push("-vf", "scale=trunc(iw*1/2)*2:trunc(ih*1/2)*2,format=yuv420p");
|
||||
|
||||
args.push("-vf", "format=yuv420p");
|
||||
|
||||
args.push("-c:a", settings.audioFormat, `"${outputPath}"`);
|
||||
|
||||
return `${ffmpeg} ${args.join(" ")}`;
|
||||
@ -363,7 +435,7 @@ function buildFFmpegCommand(file, settings) {
|
||||
|
||||
/**
|
||||
*
|
||||
* @returns {{ encoder: string; speed: string; videoQuality: string; audioQuality?: string; audioFormat: string, extension: string }} settings
|
||||
* @returns {{ encoder: string; speed: string; videoQuality: string; audioQuality?: string; audioFormat: string, extension: string, outputPath:string }} settings
|
||||
*/
|
||||
function getEncoderSettings() {
|
||||
return {
|
||||
@ -377,6 +449,9 @@ function getEncoderSettings() {
|
||||
audioFormat: getId("audio-format").value,
|
||||
// @ts-ignore
|
||||
extension: getId("file_extension").value,
|
||||
outputPath: getId("custom-folder-path").textContent,
|
||||
// @ts-ignore
|
||||
outputSuffix: getId("output-suffix").value,
|
||||
};
|
||||
}
|
||||
|
||||
@ -395,11 +470,17 @@ function getNvencPreset(speed) {
|
||||
*/
|
||||
function updateProgress(status, data, itemId) {
|
||||
if (status == "success" || status == "error") {
|
||||
getId(itemId).classList.remove("progress");
|
||||
getId(itemId).classList.add(status);
|
||||
const item = getId("itemId");
|
||||
|
||||
if (item) {
|
||||
getId(itemId).classList.remove("progress");
|
||||
getId(itemId).classList.add(status);
|
||||
}
|
||||
}
|
||||
|
||||
getId(itemId + "_prog").textContent = data;
|
||||
if (itemId) {
|
||||
getId(itemId + "_prog").textContent = data;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -466,8 +547,62 @@ getId("themeToggle").addEventListener("change", () => {
|
||||
localStorage.setItem("theme", getId("themeToggle").value);
|
||||
});
|
||||
|
||||
getId("output-folder-input").addEventListener("change", (e) => {
|
||||
const checked = e.target.checked;
|
||||
|
||||
if (!checked) {
|
||||
getId("custom-folder-select").style.display = "block"
|
||||
} else {
|
||||
getId("custom-folder-select").style.display = "none"
|
||||
getId("custom-folder-path").textContent = ""
|
||||
getId("custom-folder-path").style.display = "none"
|
||||
}
|
||||
})
|
||||
|
||||
const storageTheme = localStorage.getItem("theme");
|
||||
if (storageTheme) {
|
||||
document.documentElement.setAttribute("theme", storageTheme);
|
||||
getId("themeToggle").value = storageTheme;
|
||||
}
|
||||
|
||||
ipcRenderer.on("directory-path", (_event, msg) => {
|
||||
let customFolderPathItem = getId("custom-folder-path")
|
||||
|
||||
customFolderPathItem.textContent = msg;
|
||||
customFolderPathItem.style.display = "inline"
|
||||
})
|
||||
|
||||
function closeMenu() {
|
||||
getId("menuIcon").style.transform = "rotate(0deg)";
|
||||
let count = 0;
|
||||
let opacity = 1;
|
||||
const fade = setInterval(() => {
|
||||
if (count >= 10) {
|
||||
clearInterval(fade);
|
||||
} else {
|
||||
opacity -= 0.1;
|
||||
getId("menu").style.opacity = String(opacity);
|
||||
count++;
|
||||
}
|
||||
}, 50);
|
||||
}
|
||||
|
||||
// Menu
|
||||
getId("preferenceWin").addEventListener("click", () => {
|
||||
closeMenu();
|
||||
ipcRenderer.send("load-page", __dirname + "/preferences.html");
|
||||
});
|
||||
|
||||
getId("playlistWin").addEventListener("click", () => {
|
||||
closeMenu();
|
||||
ipcRenderer.send("load-win", __dirname + "/playlist.html");
|
||||
});
|
||||
|
||||
getId("aboutWin").addEventListener("click", () => {
|
||||
closeMenu();
|
||||
ipcRenderer.send("load-page", __dirname + "/about.html");
|
||||
});
|
||||
getId("homeWin").addEventListener("click", () => {
|
||||
closeMenu();
|
||||
ipcRenderer.send("load-win", __dirname + "/index.html");
|
||||
});
|
@ -309,7 +309,7 @@ function download(type) {
|
||||
getId("finishBtn").addEventListener("click", () => {
|
||||
controller.abort("user_finished")
|
||||
try {
|
||||
process.kill(downloadProcess.ytDlpProcess.pid, 'SIGHINT')
|
||||
process.kill(downloadProcess.ytDlpProcess.pid, 'SIGINT')
|
||||
} catch (_error) {}
|
||||
})
|
||||
|
||||
@ -716,6 +716,11 @@ getId("homeWin").addEventListener("click", () => {
|
||||
ipcRenderer.send("load-win", __dirname + "/index.html");
|
||||
});
|
||||
|
||||
getId("compressorWin").addEventListener("click", () => {
|
||||
closeMenu();
|
||||
ipcRenderer.send("load-win", __dirname + "/compressor.html");
|
||||
});
|
||||
|
||||
// Translations
|
||||
getId("pasteLink").textContent = i18n.__(
|
||||
"Click to paste playlist link from clipboard [Ctrl + V]"
|
||||
|
@ -1214,7 +1214,7 @@ function download(
|
||||
getId(randomId + ".close").addEventListener("click", () => {
|
||||
controller.abort()
|
||||
try {
|
||||
process.kill(downloadProcess.ytDlpProcess.pid, 'SIGHINT')
|
||||
process.kill(downloadProcess.ytDlpProcess.pid, 'SIGINT')
|
||||
} catch (_error) {}
|
||||
});
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user