@plasosdk/client-sdk
Version:
Plaso教育平台的客户端SDK
331 lines (292 loc) • 10.2 kB
text/typescript
// 创建一个变量来存储ffmpeg模块
let ffmpegModuleInstance: any = null;
// 添加类型定义
interface FFmpegProgress {
percent: number;
}
interface FFmpegError extends Error {
code?: string;
}
type ProcessType = "mac" | "win";
interface IpcMainInvokeEvent {
sender: any;
frameId: number;
}
const init = (remoteMain: any, ffmpegModule?: any, ffmpegPath?: string) => {
//@ts-ignore
const { app, BrowserWindow, ipcMain, webContents } = require("electron");
const Store = require("electron-store");
const path = require("path");
const fs = require("fs");
const { EventEmitter } = require("events");
const emitter = new EventEmitter();
// 添加缺失的变量声明
const args = process.argv;
const manifest = require("../package.json");
const { exec } = require("child_process");
const store = new Store();
// 初始化 FFmpeg 模块
const initFFmpeg = () => {
// 如果外部传入了模块,直接使用
if (ffmpegModule && ffmpegPath) {
try {
ffmpegModule.setFfmpegPath(ffmpegPath);
ffmpegModuleInstance = ffmpegModule;
console.log("FFmpeg loaded successfully from external modules, path:", ffmpegPath);
return true;
} catch (error) {
console.error("Error setting FFmpeg path with external modules:", error);
return false;
}
}
// 否则尝试从 require 加载
try {
const ffmpegTemp = require("fluent-ffmpeg");
const ffmpegStaticPath = require("ffmpeg-static");
ffmpegTemp.setFfmpegPath(ffmpegStaticPath);
ffmpegModuleInstance = ffmpegTemp;
console.log("FFmpeg loaded successfully via require, path:", ffmpegStaticPath);
return true;
} catch (error) {
console.error("FFmpeg module loading error:", error);
console.error(
"Please ensure fluent-ffmpeg and ffmpeg-static are installed in your project, or pass them as parameters to init()"
);
return false;
}
};
// 初始化 FFmpeg
initFFmpeg();
ipcMain.on("enable-remote", (event: any, webContentsId: any) => {
const target = webContents.fromId(webContentsId);
remoteMain.enable(target); // 主进程操作:ml-citation{ref="4" data="citationList"}
});
// 你包内部收到 relaunch 命令时
function handleRelaunch(args: any) {
// ...你自己的逻辑...
// 通知外部
emitter.emit("relaunch", args);
}
// 目前使用了第三个 --- relaunch
ipcMain.on("synchronous-message", (event: any, arg: any) => {
let cmd = arg,
params = [];
if (typeof arg == "object" && !Array.isArray(arg)) {
cmd = arg.cmd;
params = arg.params;
}
switch (cmd) {
case "argv":
event.returnValue = args;
break;
case "manifest":
event.returnValue = manifest;
break;
case "relaunch":
handleRelaunch(args);
break;
case "quit":
app.exit();
break;
case "shareToQQ":
{
const shareWin = new BrowserWindow();
try {
require("@electron/remote/main").enable(shareWin.webContents);
} catch (error) {
console.error(
"Module not found",
"Please run `npm install @electron/remote` to enable remote module and update electron version to 22.0.0 or higher"
);
}
shareWin.loadURL(params);
}
break;
default:
event.returnValue = "no such command!!";
break;
}
});
ipcMain.handle("getStoreValue", (event: any, key: any) => {
return store.get(key);
});
ipcMain.handle("setStoreValue", (event: any, key: any, value: any) => {
store.set(key, value);
return true;
});
// 转换wav to mp3
ipcMain.handle(
"convert-audio",
(event: any, { inputPath, outputPath }: any) => {
console.log("Convert-audio called with:", { inputPath, outputPath });
// 检查参数
if (!inputPath || !outputPath) {
console.error("Missing required parameters");
return Promise.reject(
new Error("Missing required parameters: inputPath or outputPath")
);
}
// 检查ffmpeg是否正确加载
if (!ffmpegModuleInstance) {
console.error("FFmpeg module not loaded");
return Promise.reject(
new Error(
"FFmpeg module not loaded. Please install fluent-ffmpeg and ffmpeg-static packages."
)
);
}
// 检查输入文件是否存在
try {
if (!fs.existsSync(inputPath)) {
console.error("Input file does not exist:", inputPath);
return Promise.reject(
new Error(`Input file does not exist: ${inputPath}`)
);
}
} catch (error) {
console.error("Error checking input file:", error);
return Promise.reject(error);
}
// 确保输出目录存在
try {
const outputDir = path.dirname(outputPath);
if (!fs.existsSync(outputDir)) {
fs.mkdirSync(outputDir, { recursive: true });
console.log("Created output directory:", outputDir);
}
} catch (error) {
console.error("Error creating output directory:", error);
return Promise.reject(error);
}
console.log("Starting audio conversion...");
return new Promise((resolve, reject) => {
ffmpegModuleInstance()
.input(inputPath)
.audioCodec("libmp3lame")
.audioBitrate(192)
.toFormat("mp3")
.on("start", (commandLine: string) => {
console.log("FFmpeg process started:", commandLine);
})
.on("progress", (progress: FFmpegProgress) => {
console.log(`Processing: ${Math.floor(progress.percent)}% done`);
})
.on("end", () => {
console.log("Conversion completed successfully");
resolve(outputPath);
})
.on("error", (err: FFmpegError) => {
console.error("Conversion error:", err);
reject(err);
})
.save(outputPath);
});
}
);
// 获取进程
const getData = (type: ProcessType) => {
const cmd = type === "mac" ? "ps -Aco command" : "tasklist";
return new Promise((resolve, reject) => {
exec(cmd, (err: Error | null, stdout: string) => {
if (err) {
return console.error(err);
}
if (stdout) {
resolve(stdout);
}
});
});
};
ipcMain.handle(
"getSystemProcess",
async (event: IpcMainInvokeEvent, type: ProcessType) => {
// @ts-ignore
const data = await getData(type);
return data;
}
);
ipcMain.handle("open-new-window", (event: IpcMainInvokeEvent, params: any) => {
let parentWindow: any = null;
if (params?.parentWindowId) {
parentWindow = BrowserWindow.fromId(params.parentWindowId);
}
// 默认尺寸
let width = 800;
let height = 600;
// 如果需要和父窗口一样大
if (params?.matchParentSize && parentWindow) {
[width, height] = parentWindow.getSize();
}
const win = new BrowserWindow({
width,
height,
frame: params?.frameless ? false : true,
titleBarStyle: params?.frameless ? "hidden" : "default",
alwaysOnTop: params?.alwaysOnTop ? true : false,
parent: parentWindow,
modal: params?.modal ? true : false,
transparent: params?.transparent ? true : false,
backgroundColor: params?.transparent ? "#00ffffff" : "#ffffff", // 白色, 透明
webPreferences: {
nodeIntegration: true,
contextIsolation: false,
webviewTag: true,
webSecurity: false,
devTools: true,
},
});
win.setMenu(null);
remoteMain.enable(win.webContents);
// 居中窗口
win.center();
if (params) {
win.loadURL(params.url);
} else {
win.loadURL("about:blank");
}
if (params.debug) {
win.webContents.openDevTools();
}
// 关键:监听父窗口移动,同步子窗口位置和尺寸
if (parentWindow && !params?.modal) {
// 记录初始尺寸
const [parentInitWidth, parentInitHeight] = parentWindow.getSize();
const [childInitWidth, childInitHeight] = win.getSize();
const widthRatio = childInitWidth / parentInitWidth;
const heightRatio = childInitHeight / parentInitHeight;
const syncPositionAndSize = () => {
const [parentX, parentY] = parentWindow.getPosition();
const [parentWidth, parentHeight] = parentWindow.getSize();
let childWidth, childHeight;
if (params?.matchParentSize) {
childWidth = parentWidth;
childHeight = parentHeight;
} else {
// 按比例缩放子窗口
childWidth = Math.round(parentWidth * widthRatio);
childHeight = Math.round(parentHeight * heightRatio);
}
win.setSize(childWidth, childHeight);
// 居中于父窗口
const x = parentX + Math.round((parentWidth - childWidth) / 2);
const y = parentY + Math.round((parentHeight - childHeight) / 2);
win.setPosition(x, y);
};
parentWindow.on("move", syncPositionAndSize);
parentWindow.on("resize", syncPositionAndSize);
// 初始同步一次
syncPositionAndSize();
// 父窗口关闭时,子窗口也关闭
parentWindow.on("closed", () => {
if (!win.isDestroyed()) win.close();
});
}
// 页面加载完成后再显示窗口
win.webContents.once("did-finish-load", () => {
win.show();
});
return { windowId: win.id, webContentsId: win.webContents.id };
});
return emitter;
};
export { init };