mirror of
https://github.com/HiMeditator/auto-caption.git
synced 2026-02-24 19:04:43 +08:00
feat(engine): 优化字幕引擎、提升程序健壮性
- 优化服务器启动流程,增加异常处理 - 主程序和字幕引擎的 WebSocket 端口号改为随机生成
This commit is contained in:
19
README.md
19
README.md
@@ -122,7 +122,7 @@ npm install
|
|||||||
|
|
||||||
### 构建字幕引擎
|
### 构建字幕引擎
|
||||||
|
|
||||||
首先进入 `engine` 文件夹,执行如下指令创建虚拟环境:
|
首先进入 `engine` 文件夹,执行如下指令创建虚拟环境(需要使用大于等于 Python 3.10 的 Python 运行环境):
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# in ./engine folder
|
# in ./engine folder
|
||||||
@@ -160,11 +160,10 @@ pip install samplerate --only-binary=:all:
|
|||||||
然后使用 `pyinstaller` 构建项目:
|
然后使用 `pyinstaller` 构建项目:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
pyinstaller ./main-gummy.spec
|
pyinstaller ./main.spec
|
||||||
pyinstaller ./main-vosk.spec
|
|
||||||
```
|
```
|
||||||
|
|
||||||
注意 `main-vosk.spec` 文件中 `vosk` 库的路径可能不正确,需要根据实际状况配置。
|
注意 `main.spec` 文件中 `vosk` 库的路径可能不正确,需要根据实际状况配置。
|
||||||
|
|
||||||
```
|
```
|
||||||
# Windows
|
# Windows
|
||||||
@@ -197,13 +196,9 @@ npm run build:linux
|
|||||||
```yml
|
```yml
|
||||||
extraResources:
|
extraResources:
|
||||||
# For Windows
|
# For Windows
|
||||||
- from: ./engine/dist/main-gummy.exe
|
- from: ./engine/dist/main.exe
|
||||||
to: ./engine/main-gummy.exe
|
to: ./engine/main.exe
|
||||||
- from: ./engine/dist/main-vosk.exe
|
|
||||||
to: ./engine/main-vosk.exe
|
|
||||||
# For macOS and Linux
|
# For macOS and Linux
|
||||||
# - from: ./engine/dist/main-gummy
|
# - from: ./engine/dist/main
|
||||||
# to: ./engine/main-gummy
|
# to: ./engine/main
|
||||||
# - from: ./engine/dist/main-vosk
|
|
||||||
# to: ./engine/main-vosk
|
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -236,13 +236,13 @@
|
|||||||
|
|
||||||
### `control.engine.started`
|
### `control.engine.started`
|
||||||
|
|
||||||
**介绍:** 引擎启动成功
|
**介绍:** 引擎启动成功,参数为引擎的进程 ID
|
||||||
|
|
||||||
**发起方:** 后端
|
**发起方:** 后端
|
||||||
|
|
||||||
**接收方:** 前端控制窗口
|
**接收方:** 前端控制窗口
|
||||||
|
|
||||||
**数据类型:** 无数据
|
**数据类型:** `number`
|
||||||
|
|
||||||
### `control.engine.stopped`
|
### `control.engine.stopped`
|
||||||
|
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ if __name__ == "__main__":
|
|||||||
parser.add_argument('-e', '--caption_engine', default='gummy', help='Caption engine: gummy or vosk')
|
parser.add_argument('-e', '--caption_engine', default='gummy', help='Caption engine: gummy or vosk')
|
||||||
parser.add_argument('-a', '--audio_type', default=0, help='Audio stream source: 0 for output, 1 for input')
|
parser.add_argument('-a', '--audio_type', default=0, help='Audio stream source: 0 for output, 1 for input')
|
||||||
parser.add_argument('-c', '--chunk_rate', default=20, help='Number of audio stream chunks collected per second')
|
parser.add_argument('-c', '--chunk_rate', default=20, help='Number of audio stream chunks collected per second')
|
||||||
parser.add_argument('-p', '--port', default=7070, help='The port to run the server on, 0 for no server')
|
parser.add_argument('-p', '--port', default=8080, help='The port to run the server on, 0 for no server')
|
||||||
# gummy
|
# gummy
|
||||||
parser.add_argument('-s', '--source_language', default='en', help='Source language code')
|
parser.add_argument('-s', '--source_language', default='en', help='Source language code')
|
||||||
parser.add_argument('-t', '--target_language', default='zh', help='Target language code')
|
parser.add_argument('-t', '--target_language', default='zh', help='Target language code')
|
||||||
|
|||||||
@@ -26,8 +26,13 @@ def handle_client(client_socket):
|
|||||||
|
|
||||||
def start_server(port: int):
|
def start_server(port: int):
|
||||||
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||||
server.bind(('localhost', port))
|
try:
|
||||||
server.listen(1)
|
server.bind(('localhost', port))
|
||||||
|
server.listen(1)
|
||||||
|
except Exception as e:
|
||||||
|
stderr(str(e))
|
||||||
|
stdout_cmd('kill')
|
||||||
|
return
|
||||||
stdout_cmd('connect')
|
stdout_cmd('connect')
|
||||||
|
|
||||||
client, addr = server.accept()
|
client, addr = server.accept()
|
||||||
|
|||||||
871
package-lock.json
generated
871
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "auto-caption",
|
"name": "auto-caption",
|
||||||
"productName": "Auto Caption",
|
"productName": "Auto Caption",
|
||||||
"version": "0.5.1",
|
"version": "0.6.0",
|
||||||
"description": "A cross-platform subtitle display software.",
|
"description": "A cross-platform subtitle display software.",
|
||||||
"main": "./out/main/index.js",
|
"main": "./out/main/index.js",
|
||||||
"author": "himeditator",
|
"author": "himeditator",
|
||||||
@@ -13,7 +13,7 @@
|
|||||||
"typecheck:web": "vue-tsc --noEmit -p tsconfig.web.json --composite false",
|
"typecheck:web": "vue-tsc --noEmit -p tsconfig.web.json --composite false",
|
||||||
"typecheck": "npm run typecheck:node && npm run typecheck:web",
|
"typecheck": "npm run typecheck:node && npm run typecheck:web",
|
||||||
"start": "electron-vite preview",
|
"start": "electron-vite preview",
|
||||||
"dev": "chcp 65001 && electron-vite dev",
|
"dev": "electron-vite dev",
|
||||||
"build": "npm run typecheck && electron-vite build",
|
"build": "npm run typecheck && electron-vite build",
|
||||||
"postinstall": "electron-builder install-app-deps",
|
"postinstall": "electron-builder install-app-deps",
|
||||||
"build:unpack": "npm run build && electron-builder --dir",
|
"build:unpack": "npm run build && electron-builder --dir",
|
||||||
|
|||||||
@@ -85,12 +85,13 @@ class ControlWindow {
|
|||||||
|
|
||||||
ipcMain.handle('control.engine.info', async () => {
|
ipcMain.handle('control.engine.info', async () => {
|
||||||
const info: EngineInfo = {
|
const info: EngineInfo = {
|
||||||
pid: 0, ppid: 0, cpu: 0, mem: 0, elapsed: 0
|
pid: 0, ppid: 0, port: 0, cpu: 0, mem: 0, elapsed: 0
|
||||||
}
|
}
|
||||||
if(captionEngine.processStatus !== 'running') return info
|
if(captionEngine.status !== 'running') return info
|
||||||
const stats = await pidusage(captionEngine.process.pid)
|
const stats = await pidusage(captionEngine.process.pid)
|
||||||
info.pid = stats.pid
|
info.pid = stats.pid
|
||||||
info.ppid = stats.ppid
|
info.ppid = stats.ppid
|
||||||
|
info.port = captionEngine.port
|
||||||
info.cpu = stats.cpu
|
info.cpu = stats.cpu
|
||||||
info.mem = stats.memory
|
info.mem = stats.memory
|
||||||
info.elapsed = stats.elapsed
|
info.elapsed = stats.elapsed
|
||||||
|
|||||||
@@ -58,6 +58,7 @@ export interface FullConfig {
|
|||||||
export interface EngineInfo {
|
export interface EngineInfo {
|
||||||
pid: number,
|
pid: number,
|
||||||
ppid: number,
|
ppid: number,
|
||||||
|
port:number,
|
||||||
cpu: number,
|
cpu: number,
|
||||||
mem: number,
|
mem: number,
|
||||||
elapsed: number
|
elapsed: number
|
||||||
|
|||||||
@@ -121,9 +121,9 @@ class AllConfig {
|
|||||||
Log.info('Set Controls:', this.controls)
|
Log.info('Set Controls:', this.controls)
|
||||||
}
|
}
|
||||||
|
|
||||||
public sendControls(window: BrowserWindow) {
|
public sendControls(window: BrowserWindow, info = true) {
|
||||||
window.webContents.send('control.controls.set', this.controls)
|
window.webContents.send('control.controls.set', this.controls)
|
||||||
Log.info(`Send Controls to #${window.id}:`, this.controls)
|
if(info) Log.info(`Send Controls to #${window.id}:`, this.controls)
|
||||||
}
|
}
|
||||||
|
|
||||||
public updateCaptionLog(log: CaptionItem) {
|
public updateCaptionLog(log: CaptionItem) {
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ export class CaptionEngine {
|
|||||||
command: string[] = []
|
command: string[] = []
|
||||||
process: any | undefined
|
process: any | undefined
|
||||||
client: net.Socket | undefined
|
client: net.Socket | undefined
|
||||||
|
port: number = 8080
|
||||||
status: 'running' | 'starting' | 'stopping' | 'stopped' = 'stopped'
|
status: 'running' | 'starting' | 'stopping' | 'stopped' = 'stopped'
|
||||||
|
|
||||||
private getApp(): boolean {
|
private getApp(): boolean {
|
||||||
@@ -20,6 +21,8 @@ export class CaptionEngine {
|
|||||||
Log.info('Using customized caption engine')
|
Log.info('Using customized caption engine')
|
||||||
this.appPath = allConfig.controls.customizedApp
|
this.appPath = allConfig.controls.customizedApp
|
||||||
this.command = allConfig.controls.customizedCommand.split(' ')
|
this.command = allConfig.controls.customizedCommand.split(' ')
|
||||||
|
this.port = Math.floor(Math.random() * (65535 - 1024 + 1)) + 1024
|
||||||
|
this.command.push('-p', this.port.toString())
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if(allConfig.controls.engine === 'gummy' &&
|
if(allConfig.controls.engine === 'gummy' &&
|
||||||
@@ -30,19 +33,34 @@ export class CaptionEngine {
|
|||||||
}
|
}
|
||||||
this.command = []
|
this.command = []
|
||||||
if (is.dev) {
|
if (is.dev) {
|
||||||
this.appPath = path.join(
|
if(process.platform === "win32") {
|
||||||
app.getAppPath(), 'engine',
|
this.appPath = path.join(
|
||||||
'subenv', 'Scripts', 'python.exe'
|
app.getAppPath(), 'engine',
|
||||||
)
|
'subenv', 'Scripts', 'python.exe'
|
||||||
this.command.push(path.join(
|
)
|
||||||
app.getAppPath(), 'engine', 'main.py'
|
this.command.push(path.join(
|
||||||
))
|
app.getAppPath(), 'engine', 'main.py'
|
||||||
// this.appPath = path.join(app.getAppPath(), 'engine', 'dist', 'main.exe')
|
))
|
||||||
|
// this.appPath = path.join(app.getAppPath(), 'engine', 'dist', 'main.exe')
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.appPath = path.join(
|
||||||
|
app.getAppPath(), 'engine',
|
||||||
|
'subenv', 'bin', 'python3'
|
||||||
|
)
|
||||||
|
this.command.push(path.join(
|
||||||
|
app.getAppPath(), 'engine', 'main.py'
|
||||||
|
))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
this.appPath = path.join(process.resourcesPath, 'engine', 'main.exe')
|
this.appPath = path.join(process.resourcesPath, 'engine', 'main.exe')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.command.push('-a', allConfig.controls.audio ? '1' : '0')
|
||||||
|
this.port = Math.floor(Math.random() * (65535 - 1024 + 1)) + 1024
|
||||||
|
this.command.push('-p', this.port.toString())
|
||||||
|
|
||||||
if(allConfig.controls.engine === 'gummy') {
|
if(allConfig.controls.engine === 'gummy') {
|
||||||
this.command.push('-e', 'gummy')
|
this.command.push('-e', 'gummy')
|
||||||
this.command.push('-s', allConfig.controls.sourceLang)
|
this.command.push('-s', allConfig.controls.sourceLang)
|
||||||
@@ -50,14 +68,13 @@ export class CaptionEngine {
|
|||||||
'-t', allConfig.controls.translation ?
|
'-t', allConfig.controls.translation ?
|
||||||
allConfig.controls.targetLang : 'none'
|
allConfig.controls.targetLang : 'none'
|
||||||
)
|
)
|
||||||
this.command.push('-a', allConfig.controls.audio ? '1' : '0')
|
|
||||||
if(allConfig.controls.API_KEY) {
|
if(allConfig.controls.API_KEY) {
|
||||||
this.command.push('-k', allConfig.controls.API_KEY)
|
this.command.push('-k', allConfig.controls.API_KEY)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if(allConfig.controls.engine === 'vosk'){
|
else if(allConfig.controls.engine === 'vosk'){
|
||||||
this.command.push('-e', 'vosk')
|
this.command.push('-e', 'vosk')
|
||||||
this.command.push('-a', allConfig.controls.audio ? '1' : '0')
|
|
||||||
this.command.push('-m', `"${allConfig.controls.modelPath}"`)
|
this.command.push('-m', `"${allConfig.controls.modelPath}"`)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -67,15 +84,15 @@ export class CaptionEngine {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public connect() {
|
public connect() {
|
||||||
|
Log.info('Connecting to caption engine server...')
|
||||||
if(this.client) { Log.warn('Client already exists, ignoring...') }
|
if(this.client) { Log.warn('Client already exists, ignoring...') }
|
||||||
Log.info('Connecting to caption engine server...');
|
this.client = net.createConnection({ port: this.port }, () => {
|
||||||
this.client = net.createConnection({ port: 7070 }, () => {
|
|
||||||
Log.info('Connected to caption engine server');
|
Log.info('Connected to caption engine server');
|
||||||
});
|
});
|
||||||
this.status = 'running'
|
this.status = 'running'
|
||||||
allConfig.controls.engineEnabled = true
|
allConfig.controls.engineEnabled = true
|
||||||
if(controlWindow.window){
|
if(controlWindow.window){
|
||||||
allConfig.sendControls(controlWindow.window)
|
allConfig.sendControls(controlWindow.window, false)
|
||||||
controlWindow.window.webContents.send(
|
controlWindow.window.webContents.send(
|
||||||
'control.engine.started',
|
'control.engine.started',
|
||||||
this.process.pid
|
this.process.pid
|
||||||
@@ -95,7 +112,7 @@ export class CaptionEngine {
|
|||||||
|
|
||||||
public start() {
|
public start() {
|
||||||
if (this.status !== 'stopped') {
|
if (this.status !== 'stopped') {
|
||||||
Log.warn('Casption engine is not stopped, current status:', this.status)
|
Log.warn('Caption engine is not stopped, current status:', this.status)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if(!this.getApp()){ return }
|
if(!this.getApp()){ return }
|
||||||
@@ -134,7 +151,7 @@ export class CaptionEngine {
|
|||||||
this.client = undefined
|
this.client = undefined
|
||||||
allConfig.controls.engineEnabled = false
|
allConfig.controls.engineEnabled = false
|
||||||
if(controlWindow.window){
|
if(controlWindow.window){
|
||||||
allConfig.sendControls(controlWindow.window)
|
allConfig.sendControls(controlWindow.window, false)
|
||||||
controlWindow.window.webContents.send('control.engine.stopped')
|
controlWindow.window.webContents.send('control.engine.stopped')
|
||||||
}
|
}
|
||||||
this.status = 'stopped'
|
this.status = 'stopped'
|
||||||
@@ -144,7 +161,7 @@ export class CaptionEngine {
|
|||||||
|
|
||||||
public stop() {
|
public stop() {
|
||||||
if(this.status !== 'running'){
|
if(this.status !== 'running'){
|
||||||
Log.warn('Engine is not running, current status:', this.status)
|
Log.warn('Trying to stop engine which is not running, current status:', this.status)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
this.sendCommand('stop')
|
this.sendCommand('stop')
|
||||||
@@ -158,15 +175,14 @@ export class CaptionEngine {
|
|||||||
|
|
||||||
public kill(){
|
public kill(){
|
||||||
if(this.status !== 'running'){
|
if(this.status !== 'running'){
|
||||||
Log.warn('Engine is not running, current status:', this.status)
|
Log.warn('Trying to kill engine which is not running, current status:', this.status)
|
||||||
return
|
}
|
||||||
|
Log.warn('Trying to kill engine process, PID:', this.process.pid)
|
||||||
|
if(this.client){
|
||||||
|
this.client.destroy()
|
||||||
|
this.client = undefined
|
||||||
}
|
}
|
||||||
if (this.process.pid) {
|
if (this.process.pid) {
|
||||||
Log.warn('Trying to kill engine process, PID:', this.process.pid)
|
|
||||||
if(this.client){
|
|
||||||
this.client.destroy()
|
|
||||||
this.client = undefined
|
|
||||||
}
|
|
||||||
let cmd = `kill ${this.process.pid}`;
|
let cmd = `kill ${this.process.pid}`;
|
||||||
if (process.platform === "win32") {
|
if (process.platform === "win32") {
|
||||||
cmd = `taskkill /pid ${this.process.pid} /t /f`
|
cmd = `taskkill /pid ${this.process.pid} /t /f`
|
||||||
@@ -183,7 +199,7 @@ function handleEngineData(data: any) {
|
|||||||
}
|
}
|
||||||
else if(data.command === 'kill') {
|
else if(data.command === 'kill') {
|
||||||
if(captionEngine.status !== 'stopped') {
|
if(captionEngine.status !== 'stopped') {
|
||||||
Log.warn('Error occurred, trying to kill Gummy engine...')
|
Log.warn('Error occurred, trying to kill caption engine...')
|
||||||
captionEngine.kill()
|
captionEngine.kill()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -197,7 +213,7 @@ function handleEngineData(data: any) {
|
|||||||
Log.info('Engine Info:', data.content)
|
Log.info('Engine Info:', data.content)
|
||||||
}
|
}
|
||||||
else if(data.command === 'usage') {
|
else if(data.command === 'usage') {
|
||||||
Log.info('Gummy Engine Usage: ', data.content)
|
Log.info('Engine Usage: ', data.content)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Log.warn('Unknown command:', data)
|
Log.warn('Unknown command:', data)
|
||||||
|
|||||||
@@ -18,6 +18,10 @@
|
|||||||
<div class="engine-status-title">ppid</div>
|
<div class="engine-status-title">ppid</div>
|
||||||
<div>{{ ppid }}</div>
|
<div>{{ ppid }}</div>
|
||||||
</a-col>
|
</a-col>
|
||||||
|
<a-col :flex="1" :title="$t('status.port')" style="cursor:pointer;">
|
||||||
|
<div class="engine-status-title">port</div>
|
||||||
|
<div>{{ port }}</div>
|
||||||
|
</a-col>
|
||||||
<a-col :flex="1" :title="$t('status.cpu')" style="cursor:pointer;">
|
<a-col :flex="1" :title="$t('status.cpu')" style="cursor:pointer;">
|
||||||
<div class="engine-status-title">cpu</div>
|
<div class="engine-status-title">cpu</div>
|
||||||
<div>{{ cpu.toFixed(1) }}%</div>
|
<div>{{ cpu.toFixed(1) }}%</div>
|
||||||
@@ -79,7 +83,7 @@
|
|||||||
<p class="about-desc">{{ $t('status.about.desc') }}</p>
|
<p class="about-desc">{{ $t('status.about.desc') }}</p>
|
||||||
<a-divider />
|
<a-divider />
|
||||||
<div class="about-info">
|
<div class="about-info">
|
||||||
<p><b>{{ $t('status.about.version') }}</b><a-tag color="green">v0.5.1</a-tag></p>
|
<p><b>{{ $t('status.about.version') }}</b><a-tag color="green">v0.6.0</a-tag></p>
|
||||||
<p>
|
<p>
|
||||||
<b>{{ $t('status.about.author') }}</b>
|
<b>{{ $t('status.about.author') }}</b>
|
||||||
<a
|
<a
|
||||||
@@ -133,10 +137,11 @@ const pending = ref(false)
|
|||||||
const captionLog = useCaptionLogStore()
|
const captionLog = useCaptionLogStore()
|
||||||
const { captionData } = storeToRefs(captionLog)
|
const { captionData } = storeToRefs(captionLog)
|
||||||
const engineControl = useEngineControlStore()
|
const engineControl = useEngineControlStore()
|
||||||
const { engineEnabled, engine, customized } = storeToRefs(engineControl)
|
const { engineEnabled, engine, customized, errorSignal } = storeToRefs(engineControl)
|
||||||
|
|
||||||
const pid = ref(0)
|
const pid = ref(0)
|
||||||
const ppid = ref(0)
|
const ppid = ref(0)
|
||||||
|
const port = ref(0)
|
||||||
const cpu = ref(0)
|
const cpu = ref(0)
|
||||||
const mem = ref(0)
|
const mem = ref(0)
|
||||||
const elapsed = ref(0)
|
const elapsed = ref(0)
|
||||||
@@ -163,6 +168,7 @@ function getEngineInfo() {
|
|||||||
window.electron.ipcRenderer.invoke('control.engine.info').then((data: EngineInfo) => {
|
window.electron.ipcRenderer.invoke('control.engine.info').then((data: EngineInfo) => {
|
||||||
pid.value = data.pid
|
pid.value = data.pid
|
||||||
ppid.value = data.ppid
|
ppid.value = data.ppid
|
||||||
|
port.value = data.port
|
||||||
cpu.value = data.cpu
|
cpu.value = data.cpu
|
||||||
mem.value = data.mem
|
mem.value = data.mem
|
||||||
elapsed.value = data.elapsed
|
elapsed.value = data.elapsed
|
||||||
@@ -172,6 +178,11 @@ function getEngineInfo() {
|
|||||||
watch(engineEnabled, () => {
|
watch(engineEnabled, () => {
|
||||||
pending.value = false
|
pending.value = false
|
||||||
})
|
})
|
||||||
|
|
||||||
|
watch(errorSignal, () => {
|
||||||
|
pending.value = false
|
||||||
|
errorSignal.value = false
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
|||||||
@@ -22,6 +22,8 @@ export default {
|
|||||||
"stopped": "Caption Engine Stopped",
|
"stopped": "Caption Engine Stopped",
|
||||||
"stoppedInfo": "The caption engine has stopped. You can click the 'Start Caption Engine' button to restart it.",
|
"stoppedInfo": "The caption engine has stopped. You can click the 'Start Caption Engine' button to restart it.",
|
||||||
"error": "An error occurred",
|
"error": "An error occurred",
|
||||||
|
"engineError": "The subtitle engine encountered an error and requested a forced exit.",
|
||||||
|
"wsError": "The WebSocket connection between the main program and the subtitle engine was not successfully established.",
|
||||||
"engineChange": "Cpation Engine Configuration Changed",
|
"engineChange": "Cpation Engine Configuration Changed",
|
||||||
"changeInfo": "If the caption engine is already running, you need to restart it for the changes to take effect.",
|
"changeInfo": "If the caption engine is already running, you need to restart it for the changes to take effect.",
|
||||||
"styleChange": "Caption Style Changed",
|
"styleChange": "Caption Style Changed",
|
||||||
@@ -95,6 +97,7 @@ export default {
|
|||||||
"pid": "Process ID",
|
"pid": "Process ID",
|
||||||
"ppid": "Parent Process ID",
|
"ppid": "Parent Process ID",
|
||||||
"cpu": "CPU Usage",
|
"cpu": "CPU Usage",
|
||||||
|
"port": "WebSocket Port Number",
|
||||||
"mem": "Memory Usage",
|
"mem": "Memory Usage",
|
||||||
"elapsed": "Running Time",
|
"elapsed": "Running Time",
|
||||||
"customized": "Customized",
|
"customized": "Customized",
|
||||||
@@ -116,7 +119,7 @@ export default {
|
|||||||
"projLink": "Project Link",
|
"projLink": "Project Link",
|
||||||
"manual": "User Manual",
|
"manual": "User Manual",
|
||||||
"engineDoc": "Caption Engine Manual",
|
"engineDoc": "Caption Engine Manual",
|
||||||
"date": "July 17, 2025"
|
"date": "July 29, 2025"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
log: {
|
log: {
|
||||||
|
|||||||
@@ -22,6 +22,8 @@ export default {
|
|||||||
"stopped": "字幕エンジンが停止しました",
|
"stopped": "字幕エンジンが停止しました",
|
||||||
"stoppedInfo": "字幕エンジンが停止しました。再起動するには「字幕エンジンを開始」ボタンをクリックしてください。",
|
"stoppedInfo": "字幕エンジンが停止しました。再起動するには「字幕エンジンを開始」ボタンをクリックしてください。",
|
||||||
"error": "エラーが発生しました",
|
"error": "エラーが発生しました",
|
||||||
|
"engineError": "字幕エンジンにエラーが発生し、強制終了が要求されました。",
|
||||||
|
"wsError": "メインプログラムと字幕エンジン間の WebSocket 接続が確立されませんでした。",
|
||||||
"engineChange": "字幕エンジンの設定が変更されました",
|
"engineChange": "字幕エンジンの設定が変更されました",
|
||||||
"changeInfo": "字幕エンジンがすでに起動している場合、変更を有効にするには再起動が必要です。",
|
"changeInfo": "字幕エンジンがすでに起動している場合、変更を有効にするには再起動が必要です。",
|
||||||
"styleChange": "字幕のスタイルが変更されました",
|
"styleChange": "字幕のスタイルが変更されました",
|
||||||
@@ -94,6 +96,7 @@ export default {
|
|||||||
"engineStatus": "字幕エンジンの状態",
|
"engineStatus": "字幕エンジンの状態",
|
||||||
"pid": "プロセス ID",
|
"pid": "プロセス ID",
|
||||||
"ppid": "親プロセス ID",
|
"ppid": "親プロセス ID",
|
||||||
|
"port": "WebSocket ポート番号",
|
||||||
"cpu": "CPU 使用率",
|
"cpu": "CPU 使用率",
|
||||||
"mem": "メモリ使用量",
|
"mem": "メモリ使用量",
|
||||||
"elapsed": "稼働時間",
|
"elapsed": "稼働時間",
|
||||||
@@ -116,7 +119,7 @@ export default {
|
|||||||
"projLink": "プロジェクトリンク",
|
"projLink": "プロジェクトリンク",
|
||||||
"manual": "ユーザーマニュアル",
|
"manual": "ユーザーマニュアル",
|
||||||
"engineDoc": "字幕エンジンマニュアル",
|
"engineDoc": "字幕エンジンマニュアル",
|
||||||
"date": "2025 年 7 月 17 日"
|
"date": "2025 年 7 月 29 日"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
log: {
|
log: {
|
||||||
|
|||||||
@@ -22,6 +22,8 @@ export default {
|
|||||||
"stopped": "字幕引擎停止",
|
"stopped": "字幕引擎停止",
|
||||||
"stoppedInfo": "字幕引擎已经停止,可点击“启动字幕引擎”按钮重新启动",
|
"stoppedInfo": "字幕引擎已经停止,可点击“启动字幕引擎”按钮重新启动",
|
||||||
"error": "发生错误",
|
"error": "发生错误",
|
||||||
|
"engineError": "字幕引擎发生错误并请求强制退出",
|
||||||
|
"wsError": "主程序与字幕引擎的 WebSocket 未成功连接",
|
||||||
"engineChange": "字幕引擎配置已更改",
|
"engineChange": "字幕引擎配置已更改",
|
||||||
"changeInfo": "如果字幕引擎已经启动,需要重启字幕引擎修改才会生效",
|
"changeInfo": "如果字幕引擎已经启动,需要重启字幕引擎修改才会生效",
|
||||||
"styleChange": "字幕样式已修改",
|
"styleChange": "字幕样式已修改",
|
||||||
@@ -94,6 +96,7 @@ export default {
|
|||||||
"engineStatus": "字幕引擎状态",
|
"engineStatus": "字幕引擎状态",
|
||||||
"pid": "进程ID",
|
"pid": "进程ID",
|
||||||
"ppid": "父进程ID",
|
"ppid": "父进程ID",
|
||||||
|
"port": "WebSocket 端口号",
|
||||||
"cpu": "CPU使用率",
|
"cpu": "CPU使用率",
|
||||||
"mem": "内存使用量",
|
"mem": "内存使用量",
|
||||||
"elapsed": "运行时间",
|
"elapsed": "运行时间",
|
||||||
@@ -116,7 +119,7 @@ export default {
|
|||||||
"projLink": "项目链接",
|
"projLink": "项目链接",
|
||||||
"manual": "用户手册",
|
"manual": "用户手册",
|
||||||
"engineDoc": "字幕引擎手册",
|
"engineDoc": "字幕引擎手册",
|
||||||
"date": "2025 年 7 月 17 日"
|
"date": "2025 年 7 月 29 日"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
log: {
|
log: {
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ export const useEngineControlStore = defineStore('engineControl', () => {
|
|||||||
const customizedCommand = ref<string>('')
|
const customizedCommand = ref<string>('')
|
||||||
|
|
||||||
const changeSignal = ref<boolean>(false)
|
const changeSignal = ref<boolean>(false)
|
||||||
|
const errorSignal = ref<boolean>(false)
|
||||||
|
|
||||||
function sendControlsChange() {
|
function sendControlsChange() {
|
||||||
const controls: Controls = {
|
const controls: Controls = {
|
||||||
@@ -47,7 +48,22 @@ export const useEngineControlStore = defineStore('engineControl', () => {
|
|||||||
window.electron.ipcRenderer.send('control.controls.change', controls)
|
window.electron.ipcRenderer.send('control.controls.change', controls)
|
||||||
}
|
}
|
||||||
|
|
||||||
function setControls(controls: Controls) {
|
function setControls(controls: Controls, set = false) {
|
||||||
|
if(set && !engineEnabled.value && !controls.engineEnabled) {
|
||||||
|
errorSignal.value = true
|
||||||
|
notification.open({
|
||||||
|
message: t('noti.error'),
|
||||||
|
description: t("noti.engineError"),
|
||||||
|
duration: null,
|
||||||
|
icon: () => h(ExclamationCircleOutlined, { style: 'color: #ff4d4f' })
|
||||||
|
});
|
||||||
|
notification.open({
|
||||||
|
message: t('noti.error'),
|
||||||
|
description: t("noti.wsError"),
|
||||||
|
duration: null,
|
||||||
|
icon: () => h(ExclamationCircleOutlined, { style: 'color: #ff4d4f' })
|
||||||
|
});
|
||||||
|
}
|
||||||
sourceLang.value = controls.sourceLang
|
sourceLang.value = controls.sourceLang
|
||||||
targetLang.value = controls.targetLang
|
targetLang.value = controls.targetLang
|
||||||
engine.value = controls.engine
|
engine.value = controls.engine
|
||||||
@@ -71,7 +87,7 @@ export const useEngineControlStore = defineStore('engineControl', () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
window.electron.ipcRenderer.on('control.controls.set', (_, controls: Controls) => {
|
window.electron.ipcRenderer.on('control.controls.set', (_, controls: Controls) => {
|
||||||
setControls(controls)
|
setControls(controls, true)
|
||||||
})
|
})
|
||||||
|
|
||||||
window.electron.ipcRenderer.on('control.engine.started', (_, args) => {
|
window.electron.ipcRenderer.on('control.engine.started', (_, args) => {
|
||||||
@@ -125,5 +141,6 @@ export const useEngineControlStore = defineStore('engineControl', () => {
|
|||||||
sendControlsChange, // 发送最新控制消息到后端
|
sendControlsChange, // 发送最新控制消息到后端
|
||||||
emptyModelPathErr, // 模型路径为空时显示警告
|
emptyModelPathErr, // 模型路径为空时显示警告
|
||||||
changeSignal, // 配置改变信号
|
changeSignal, // 配置改变信号
|
||||||
|
errorSignal, // 错误信号
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -58,6 +58,7 @@ export interface FullConfig {
|
|||||||
export interface EngineInfo {
|
export interface EngineInfo {
|
||||||
pid: number,
|
pid: number,
|
||||||
ppid: number,
|
ppid: number,
|
||||||
|
port:number,
|
||||||
cpu: number,
|
cpu: number,
|
||||||
mem: number,
|
mem: number,
|
||||||
elapsed: number
|
elapsed: number
|
||||||
|
|||||||
@@ -36,7 +36,6 @@ const { leftBarWidth, antdTheme } = storeToRefs(generalSettingStore)
|
|||||||
background-color: var(--control-background);
|
background-color: var(--control-background);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
.caption-control {
|
.caption-control {
|
||||||
height: 100vh;
|
height: 100vh;
|
||||||
border-right: 1px solid var(--tag-color);
|
border-right: 1px solid var(--tag-color);
|
||||||
|
|||||||
Reference in New Issue
Block a user