Files
auto-caption/src/main/utils/engine.ts
himeditator b28799b03f feat: 新增配置保存和读取、新增文档
- 添加配置数据文件保存和载入
- 添加字幕样式恢复默认的选项
- 添加用户说明文档
- 添加字幕引擎说明文档
2025-06-26 21:29:06 +08:00

122 lines
3.7 KiB
TypeScript

import { spawn, exec } from 'child_process'
import { app, BrowserWindow } from 'electron'
import { is } from '@electron-toolkit/utils'
import path from 'path'
import { addCaptionLog, controls, sendControls } from './config'
import { controlWindow } from '../control'
export class CaptionEngine {
appPath: string = ''
command: string[] = []
process: any | undefined
private getApp() {
if (controls.customized && controls.customizedApp) {
this.appPath = controls.customizedApp
this.command = [controls.customizedCommand]
}
else if (controls.engine === 'gummy') {
controls.customized = false
let gummyName = ''
if (process.platform === 'win32') {
gummyName = 'main-gummy.exe'
}
else if (process.platform === 'linux') {
gummyName = 'main-gummy'
}
else {
controlWindow.sendErrorMessage('不支持的操作系统平台:' + process.platform)
throw new Error('Unsupported platform')
}
if (is.dev) {
this.appPath = path.join(
app.getAppPath(),
'python-subprocess', 'dist', gummyName
)
}
else {
this.appPath = path.join(
process.resourcesPath,
'python-subprocess', 'dist', gummyName
)
}
this.command = []
this.command.push('-s', controls.sourceLang)
this.command.push('-t', controls.translation ? controls.targetLang : 'none')
this.command.push('-a', controls.audio ? '1' : '0')
console.log('[INFO] Engine Path:', this.appPath)
console.log('[INFO] Engine Command:', this.command)
}
}
public start(window: BrowserWindow) {
if (this.process) {
this.stop();
}
this.getApp()
try {
this.process = spawn(this.appPath, this.command)
}
catch (e) {
controlWindow.sendErrorMessage('字幕引擎启动失败:' + e)
console.error('[ERROR] Error starting subprocess:', e)
return
}
console.log('[INFO] Caption Engine Started: ', {
appPath: this.appPath,
command: this.command
})
controls.engineEnabled = true
sendControls(window)
window.webContents.send('control.engine.started')
this.process.stdout.on('data', (data) => {
const lines = data.toString().split('\n');
lines.forEach((line: string) => {
if (line.trim()) {
try {
const caption = JSON.parse(line);
addCaptionLog(caption);
} catch (e) {
controlWindow.sendErrorMessage('字幕引擎输出内容无法解析为 JSON 对象:' + e)
console.error('[ERROR] Error parsing JSON:', e);
}
}
});
});
this.process.stderr.on('data', (data) => {
controlWindow.sendErrorMessage('字幕引擎错误:' + data)
console.error(`[ERROR] Subprocess Error: ${data}`);
});
this.process.on('close', (code: any) => {
console.log(`[INFO] Subprocess exited with code ${code}`);
this.process = undefined;
controls.engineEnabled = false
sendControls(window)
});
}
public stop() {
if (this.process) {
if (process.platform === "win32" && this.process.pid) {
exec(`taskkill /pid ${this.process.pid} /t /f`, (error) => {
if (error) {
controlWindow.sendErrorMessage('字幕引擎进程关闭失败:' + error)
console.error(`[ERROR] Failed to kill process: ${error}`);
}
});
} else {
this.process.kill('SIGKILL');
}
}
this.process = undefined;
controls.engineEnabled = false;
console.log('[INFO] Caption engine process stopped');
if(controlWindow.window) sendControls(controlWindow.window);
}
}