dsr/src/main.ts

121 lines
3.5 KiB
TypeScript
Raw Normal View History

2023-07-30 02:40:05 +02:00
import { BrowserWindow, app, dialog, ipcMain } from "electron";
2023-07-30 13:44:47 +02:00
import { unlink, statSync } from "fs";
import path = require("path");
2023-07-29 19:23:18 +02:00
import ffmpegPath = require("ffmpeg-static");
2023-07-30 01:40:06 +02:00
import child_process = require("child_process");
2023-07-30 13:44:47 +02:00
import { getVideoDurationInSeconds } from "get-video-duration";
const moviesFilter = {
name: "Videos",
extensions: ["mp4", "mkv"],
};
const isWindows = process.platform === "win32";
2023-07-28 02:46:49 +02:00
2023-07-30 00:14:20 +02:00
/** Create a new window */
2023-07-28 02:32:18 +02:00
const createWindow = () => {
const win = new BrowserWindow({
2023-07-29 19:23:18 +02:00
width: 1280,
height: 720,
webPreferences: {
preload: path.join(__dirname, "preload.js"),
},
2023-07-28 02:32:18 +02:00
});
2023-07-29 15:30:41 +02:00
win.loadFile(path.join(path.resolve(__dirname, ".."), "pages", "index.html"));
2023-07-29 19:23:18 +02:00
win.webContents.openDevTools(); // debug
2023-07-30 02:01:16 +02:00
return win;
2023-07-28 02:32:18 +02:00
};
2023-07-29 15:30:41 +02:00
2023-07-30 02:40:05 +02:00
/* Create a new filename from the OG one */
2023-07-30 01:40:06 +02:00
const getNewFilename = (ogFile: string, part: string) => {
const oldFile = path.parse(ogFile);
return path.join(oldFile.dir, `${part}`.concat(oldFile.base));
};
/** Merge all audios track of a video into one */
2023-07-30 13:44:47 +02:00
const mergeAudio = async (file: string) => {
2023-07-30 02:29:02 +02:00
const tmp_file = getNewFilename(file, "TMP_");
2023-07-30 01:40:06 +02:00
const outFile = getNewFilename(file, "(merged audio) ");
2023-07-30 02:29:02 +02:00
// Merge 2 audio
child_process.execSync(
2023-07-30 13:44:47 +02:00
`${ffmpegPath} -y -i "${file}" -filter_complex "[0:a]amerge=inputs=2[a]" -ac 1 -map 0:v -map "[a]" -c:v copy "${tmp_file}"`
2023-07-30 02:29:02 +02:00
);
// Add merged audio as first position to original video
child_process.execSync(
2023-07-30 13:44:47 +02:00
`${ffmpegPath} -y -i "${tmp_file}" -i "${file}" -map 0 -map 1:a -c:v copy "${outFile}"`
2023-07-30 01:40:06 +02:00
);
2023-07-30 02:01:16 +02:00
2023-07-30 02:29:02 +02:00
// Delete the temporary file
unlink(tmp_file, (err) => {
if (err) {
throw err;
}
2023-07-30 02:03:40 +02:00
});
2023-07-30 13:44:47 +02:00
const duration = await getVideoDurationInSeconds(outFile);
const stats = statSync(outFile);
return { title: outFile, size: stats.size / 1024 / 1024, duration };
};
/* Reduce size of a file */
const reduceSize = (file: string, bitrate: number) => {
2023-07-30 14:05:26 +02:00
const audioBitrate = 400; /* keep some room */
2023-07-30 13:44:47 +02:00
const videoBitrate = Math.floor(bitrate) - audioBitrate;
/* Trash the output, depends on the platform */
const nul = isWindows ? "NUL" : "/dev/null";
/* AND operator, depends on the platform */
const and = isWindows ? "^" : "&&";
const finalFile = getNewFilename(file, "Compressed - ");
child_process.execSync(
`${ffmpegPath} -y -i "${file}" -c:v libx264 -b:v ${videoBitrate}k -pass 1 -an -f null ${nul} ${and} \
2023-07-30 14:05:26 +02:00
${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 "${finalFile}"`
2023-07-30 13:44:47 +02:00
);
2023-07-30 13:46:07 +02:00
// Delete the old file
unlink(file, (err) => {
if (err) {
throw err;
}
});
2023-07-30 13:44:47 +02:00
return finalFile;
2023-07-30 01:40:06 +02:00
};
2023-07-30 02:40:05 +02:00
/* Ready to create the window */
2023-07-28 02:32:18 +02:00
app.whenReady().then(() => {
2023-07-30 02:01:16 +02:00
const win = createWindow();
/** Ask user a file */
const askFile = async () => {
return dialog.showOpenDialogSync(win, {
filters: [moviesFilter],
properties: ["openFile", "dontAddToRecent"],
});
};
/** Send confirmation to user */
const confirmation = async (message: string) => {
dialog.showMessageBoxSync(win, { message });
};
2023-07-30 00:14:20 +02:00
/* Context bridge */
2023-07-29 20:20:55 +02:00
ipcMain.handle("argv", () => process.argv);
2023-07-30 00:14:20 +02:00
ipcMain.handle("allowedExtensions", () => moviesFilter);
2023-07-30 01:40:06 +02:00
ipcMain.handle("askFile", () => askFile());
ipcMain.handle("mergeAudio", (_, file: string) => mergeAudio(file));
2023-07-30 13:44:47 +02:00
ipcMain.handle("reduceSize", (_, file: string, bitrate: number) =>
reduceSize(file, bitrate)
);
2023-07-30 01:40:06 +02:00
ipcMain.handle("exit", async () => app.quit());
2023-07-30 02:01:16 +02:00
ipcMain.handle("confirmation", async (_, text: string) => confirmation(text));
2023-07-28 02:32:18 +02:00
});