- 选择文件夹/单文件 → SenseVoice 转录 → LLM 修正 → 多路线翻译 → 双语 SRT - 路线:直译中文 / 英转中 / 仅转录 - 并发流水线:转录(可调) + LLM 并发(可调),降噪拆锁并发 - 断点续跑:.subtitle-work/ 中间产物,三阶段独立续跑 + 翻译段级续跑 - 去重:history 跟随视频文件夹,防重复任务保护 - 实时进度:SSE 推送 + 耗时显示 + 子任务状态 + 重新生成按钮 - 时间戳调优:VAD silence_schedule + noisereduce 降噪 + 完整性校验
56 lines
1.6 KiB
Python
56 lines
1.6 KiB
Python
# -*- coding: utf-8 -*-
|
||
"""
|
||
subtitle-studio 后台启动器(无阻塞)
|
||
用 subprocess.Popen 启动 uvicorn,shell 调用立即返回
|
||
日志写到 logs/server.log
|
||
用法: python start_server.py [port]
|
||
"""
|
||
import sys, os, subprocess, time, threading
|
||
|
||
PYTHON = sys.executable
|
||
PROJECT_ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||
APP_DIR = os.path.join(PROJECT_ROOT, "src")
|
||
LOG_DIR = os.path.join(PROJECT_ROOT, "logs")
|
||
PORT = sys.argv[1] if len(sys.argv) > 1 else "8788"
|
||
|
||
os.makedirs(LOG_DIR, exist_ok=True)
|
||
log_path = os.path.join(LOG_DIR, "server.log")
|
||
|
||
|
||
def is_running(port):
|
||
"""端口是否已被监听"""
|
||
try:
|
||
import socket
|
||
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
|
||
s.settimeout(1)
|
||
return s.connect_ex(("127.0.0.1", int(port))) == 0
|
||
except Exception:
|
||
return False
|
||
|
||
|
||
def main():
|
||
if is_running(PORT):
|
||
print(f"subtitle-studio 已在运行: http://127.0.0.1:{PORT}")
|
||
return
|
||
|
||
# 打开日志文件(追加模式)
|
||
logf = open(log_path, 'a', encoding='utf-8', buffering=1)
|
||
|
||
# 真正的异步启动:不等待,不继承句柄
|
||
proc = subprocess.Popen(
|
||
[PYTHON, "-m", "uvicorn", "substudio.main:app",
|
||
"--host", "127.0.0.1", "--port", PORT, "--app-dir", APP_DIR],
|
||
cwd=PROJECT_ROOT,
|
||
stdout=logf,
|
||
stderr=subprocess.STDOUT,
|
||
creationflags=subprocess.CREATE_NO_WINDOW,
|
||
)
|
||
print(f"已启动 subtitle-studio (PID {proc.pid})")
|
||
print(f"服务地址: http://127.0.0.1:{PORT}")
|
||
print(f"日志: {log_path}")
|
||
# 不等待进程,直接返回
|
||
|
||
|
||
if __name__ == "__main__":
|
||
main()
|