UNPKG

@plasosdk/client-sdk

Version:

Plaso教育平台的客户端SDK

331 lines (292 loc) 10.2 kB
// 创建一个变量来存储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 };