Add kinda of a better user interface

This commit is contained in:
Mylloon 2023-08-01 09:51:35 +02:00
parent ff75f7ce08
commit 3394e2b5f9
Signed by: Anri
GPG key ID: A82D63DFF8D1317F
4 changed files with 65 additions and 23 deletions

View file

@ -17,7 +17,7 @@
</head> </head>
<body> <body>
<h1>Discord Video Sharing</h1> <h1>Discord Video Sharing</h1>
<p id="message"></p>
<script src="../dist/scripts/renderer.js"></script> <script src="../dist/scripts/renderer.js"></script>
</body> </body>
</html> </html>

View file

@ -1,17 +1,14 @@
import { BrowserWindow, app, dialog, ipcMain } from "electron"; import { BrowserWindow, app, dialog, ipcMain } from "electron";
import { statSync, unlink } from "fs"; import { statSync, unlink } from "fs";
import { getNewFilename, getVideoDuration } from "./utils/misc"; import { execute, getNewFilename, getVideoDuration } from "./utils/misc";
import path = require("path"); import path = require("path");
import ffmpegPath = require("ffmpeg-static"); import ffmpegPath = require("ffmpeg-static");
import child_process = require("child_process");
const moviesFilter = { const moviesFilter = {
name: "Videos", name: "Videos",
extensions: ["mp4", "mkv"], extensions: ["mp4", "mkv"],
}; };
const isWindows = process.platform === "win32";
/** Create a new window */ /** Create a new window */
const createWindow = () => { const createWindow = () => {
const win = new BrowserWindow({ const win = new BrowserWindow({
@ -29,22 +26,22 @@ const createWindow = () => {
}; };
/** Merge all audios track of a video into one */ /** Merge all audios track of a video into one */
const mergeAudio = (file: string) => { const mergeAudio = async (file: string) => {
const tmp_file = getNewFilename(file, "TMP_"); const tmpFile = getNewFilename(file, "TMP_");
const outFile = getNewFilename(file, "(merged audio) "); const outFile = getNewFilename(file, "(merged audio) ");
// Merge 2 audio // Merge 2 audio
child_process.execSync( await execute(
`${ffmpegPath} -y -i "${file}" -filter_complex "[0:a]amerge=inputs=2[a]" -ac 1 -map 0:v -map "[a]" -c:v copy "${tmp_file}"` `${ffmpegPath} -y -i "${file}" -filter_complex "[0:a]amerge=inputs=2[a]" -ac 1 -map 0:v -map "[a]" -c:v copy "${tmpFile}"`
); );
// Add merged audio as first position to original video // Add merged audio as first position to original video
child_process.execSync( await execute(
`${ffmpegPath} -y -i "${tmp_file}" -i "${file}" -map 0 -map 1:a -c:v copy "${outFile}"` `${ffmpegPath} -y -i "${tmpFile}" -i "${file}" -map 0 -map 1:a -c:v copy "${outFile}"`
); );
// Delete the temporary file // Delete the temporary file
unlink(tmp_file, (err) => { unlink(tmpFile, (err) => {
if (err) { if (err) {
throw err; throw err;
} }
@ -57,16 +54,16 @@ const mergeAudio = (file: string) => {
}; };
/* Reduce size of a file */ /* Reduce size of a file */
const reduceSize = (file: string, bitrate: number) => { const reduceSize = async (file: string, bitrate: number) => {
const audioBitrate = 400; /* keep some room */ const audioBitrate = 400; // keep some room
const videoBitrate = Math.floor(bitrate) - audioBitrate; const videoBitrate = bitrate - audioBitrate;
/* Trash the output, depends on the platform */
const nul = isWindows ? "NUL" : "/dev/null";
const finalFile = getNewFilename(file, "Compressed - "); const finalFile = getNewFilename(file, "Compressed - ");
child_process.execSync( // Trash the output, depends on the platform
const nul = process.platform === "win32" ? "NUL" : "/dev/null";
await execute(
`${ffmpegPath} -y -i "${file}" -c:v libx264 -b:v ${videoBitrate}k -pass 1 -an -f mp4 ${nul} && \ `${ffmpegPath} -y -i "${file}" -c:v libx264 -b:v ${videoBitrate}k -pass 1 -an -f mp4 ${nul} && \
${ffmpegPath} -y -i "${file}" -c:v libx264 -b:v ${videoBitrate}k -pass 2 -c:a copy -map 0:0 -map 0:1 -map 0:2 -map 0:3 -f mp4 "${finalFile}"` ${ffmpegPath} -y -i "${file}" -c:v libx264 -b:v ${videoBitrate}k -pass 2 -c:a copy -map 0:0 -map 0:1 -map 0:2 -map 0:3 -f mp4 "${finalFile}"`
); );

View file

@ -31,21 +31,53 @@ const getFile = async () => {
return file.join(""); return file.join("");
}; };
enum Mode {
Write,
Append,
}
/** Update the message to the user */
const updateMessage = (message: string, mode: Mode = Mode.Write) => {
switch (mode) {
case Mode.Write:
document.getElementById("message").innerText = message;
break;
case Mode.Append:
document.getElementById("message").innerText += message;
break;
default:
break;
}
};
/** Main function */ /** Main function */
const main = async () => { const main = async () => {
const maxSizeDiscord = 25; const maxSizeDiscord = 25;
updateMessage("Récupération du fichier...");
const file = await getFile(); const file = await getFile();
updateMessage("Mélange des pistes audios vers la piste 1...");
const newFile = await internals.mergeAudio(file); const newFile = await internals.mergeAudio(file);
let finalTitle = newFile.title; let finalTitle = newFile.title;
updateMessage(`Taille calculée : ${Math.round(newFile.size)}Mo`);
if (newFile.size > maxSizeDiscord) { if (newFile.size > maxSizeDiscord) {
/* TODO: Since this task can take time, add a progress bar to the user */
const targetSize = maxSizeDiscord - 2; const targetSize = maxSizeDiscord - 2;
// https://trac.ffmpeg.org/wiki/Encode/H.264#twopass
const bitrate = Math.floor((targetSize * 8388.608) / newFile.duration);
updateMessage(
`\nFichier trop lourd, compression en cours... (bitrate total = ${bitrate})`,
Mode.Append
);
finalTitle = await internals.reduceSize( finalTitle = await internals.reduceSize(
newFile.title, newFile.title,
// https://trac.ffmpeg.org/wiki/Encode/H.264#twopass
(targetSize * 8388.608) / newFile.duration bitrate
); );
} }
updateMessage("Fichier prêt ! :)");
await internals.confirmation(`File ok @ ${finalTitle}!`); await internals.confirmation(`File ok @ ${finalTitle}!`);
await internals.exit(); await internals.exit();
}; };

View file

@ -2,7 +2,7 @@ import ffprobe = require("ffprobe-static");
import child_process = require("child_process"); import child_process = require("child_process");
import path = require("path"); import path = require("path");
/* Create a new filename from the OG one */ /** Create a new filename from the OG one */
export const getNewFilename = (ogFile: string, part: string) => { export const getNewFilename = (ogFile: string, part: string) => {
const oldFile = path.parse(ogFile); const oldFile = path.parse(ogFile);
return path.join(oldFile.dir, `${part}`.concat(oldFile.base)); return path.join(oldFile.dir, `${part}`.concat(oldFile.base));
@ -14,3 +14,16 @@ export const getVideoDuration = (file: string) => {
const durationString = child_process.execSync(command).toString().trim(); const durationString = child_process.execSync(command).toString().trim();
return parseFloat(durationString); return parseFloat(durationString);
}; };
/** Run a command asynchronously */
export const execute = (command: string) => {
return new Promise((resolve, reject) => {
child_process.exec(command, (error, stdout, stderr) => {
if (error) {
reject(error);
} else {
resolve({ stdout, stderr });
}
});
});
};