Files
BiliNote/backend/app/transcriber/transcriber_provider.py
huangjianwu c105342ded fix: 性能优化、前端转写器配置、任务进度丢失及 MLX Whisper 回退问题修复
### 性能优化
- 后端任务执行从串行锁改为 ThreadPoolExecutor 并发执行(默认3线程)
- 添加 GZipMiddleware 响应压缩 + Nginx gzip 配置
- 数据库连接池参数优化(pool_size=10, max_overflow=20)
- 视频帧提取并行化(ThreadPoolExecutor)
- LLM 重试配置缓存到实例,避免每次请求读 env var
- 前端路由级代码拆分(React.lazy + Suspense)
- Vite manualChunks 拆分 markdown/markmap/vendor
- MarkdownViewer 用 React.memo + useMemo 减少不必要渲染
- NoteHistory Fuse.js 实例 useMemo 缓存
- useTaskPolling 无待处理任务时跳过轮询
- 移除 antd 依赖(NoteForm Alert、modelForm Tag),改用 shadcn/ui

### 前端转写器配置(新功能)
- 新增 TranscriberConfigManager(JSON 文件存储,替代环境变量)
- 新增 GET/POST /transcriber_config API 端点
- 新增 GET /transcriber_models_status 模型下载状态查询
- 新增 POST /transcriber_download 后台模型下载触发
- 前端转写器设置页面:引擎选择、模型大小选择、模型下载管理
- deploy_status 端点同步从配置文件读取

### Bug 修复
- 修复任务进行中切换页面后进度丢失:Home.tsx status 派生逻辑补全中间状态
- 修复 MLX Whisper 静默回退 fast-whisper:移除环境变量门控,macOS 下自动尝试导入
- MLX Whisper 不可用时抛出 RuntimeError 而非静默回退
- 前端展示 MLX Whisper 可用性状态,不可用时禁用保存

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-23 14:09:34 +08:00

118 lines
4.3 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import os
import platform
from enum import Enum
from app.transcriber.groq import GroqTranscriber
from app.transcriber.whisper import WhisperTranscriber
from app.transcriber.bcut import BcutTranscriber
from app.transcriber.kuaishou import KuaishouTranscriber
from app.utils.logger import get_logger
logger = get_logger(__name__)
class TranscriberType(str, Enum):
FAST_WHISPER = "fast-whisper"
MLX_WHISPER = "mlx-whisper"
BCUT = "bcut"
KUAISHOU = "kuaishou"
GROQ = "groq"
# 在 Apple 平台尝试导入 MLX Whisper不再依赖环境变量支持前端动态切换
MLX_WHISPER_AVAILABLE = False
if platform.system() == "Darwin":
try:
from app.transcriber.mlx_whisper_transcriber import MLXWhisperTranscriber
MLX_WHISPER_AVAILABLE = True
logger.info("MLX Whisper 可用,已导入")
except ImportError:
logger.warning("MLX Whisper 导入失败,可能未安装 mlx_whisper")
logger.info('初始化转录服务提供器')
# 转录器单例缓存
_transcribers = {
TranscriberType.FAST_WHISPER: None,
TranscriberType.MLX_WHISPER: None,
TranscriberType.BCUT: None,
TranscriberType.KUAISHOU: None,
TranscriberType.GROQ: None,
}
# 公共实例初始化函数
def _init_transcriber(key: TranscriberType, cls, *args, **kwargs):
if _transcribers[key] is None:
logger.info(f'创建 {cls.__name__} 实例: {key}')
try:
_transcribers[key] = cls(*args, **kwargs)
logger.info(f'{cls.__name__} 创建成功')
except Exception as e:
logger.error(f"{cls.__name__} 创建失败: {e}")
raise
return _transcribers[key]
# 各类型获取方法
def get_groq_transcriber():
return _init_transcriber(TranscriberType.GROQ, GroqTranscriber)
def get_whisper_transcriber(model_size="base", device="cuda"):
return _init_transcriber(TranscriberType.FAST_WHISPER, WhisperTranscriber, model_size=model_size, device=device)
def get_bcut_transcriber():
return _init_transcriber(TranscriberType.BCUT, BcutTranscriber)
def get_kuaishou_transcriber():
return _init_transcriber(TranscriberType.KUAISHOU, KuaishouTranscriber)
def get_mlx_whisper_transcriber(model_size="base"):
if not MLX_WHISPER_AVAILABLE:
logger.warning("MLX Whisper 不可用,请确保在 Apple 平台且已安装 mlx_whisper")
raise ImportError("MLX Whisper 不可用")
return _init_transcriber(TranscriberType.MLX_WHISPER, MLXWhisperTranscriber, model_size=model_size)
# 通用入口
def get_transcriber(transcriber_type="fast-whisper", model_size="base", device="cuda"):
"""
获取指定类型的转录器实例
参数:
transcriber_type: 支持 "fast-whisper", "mlx-whisper", "bcut", "kuaishou", "groq"
model_size: 模型大小,适用于 whisper 类
device: 设备类型(如 cuda / cpu仅 whisper 使用
返回:
对应类型的转录器实例
"""
logger.info(f'请求转录器类型: {transcriber_type}')
try:
transcriber_enum = TranscriberType(transcriber_type)
except ValueError:
logger.warning(f'未知转录器类型 "{transcriber_type}",默认使用 fast-whisper')
transcriber_enum = TranscriberType.FAST_WHISPER
whisper_model_size = os.environ.get("WHISPER_MODEL_SIZE", model_size)
if transcriber_enum == TranscriberType.FAST_WHISPER:
return get_whisper_transcriber(whisper_model_size, device=device)
elif transcriber_enum == TranscriberType.MLX_WHISPER:
if not MLX_WHISPER_AVAILABLE:
raise RuntimeError(
"MLX Whisper 不可用:需要 macOS 平台并安装 mlx_whisper 包 (pip install mlx_whisper)。"
"请在「音频转写配置」页面切换到其他转写引擎。"
)
return get_mlx_whisper_transcriber(whisper_model_size)
elif transcriber_enum == TranscriberType.BCUT:
return get_bcut_transcriber()
elif transcriber_enum == TranscriberType.KUAISHOU:
return get_kuaishou_transcriber()
elif transcriber_enum == TranscriberType.GROQ:
return get_groq_transcriber()
# fallback
logger.warning(f'未识别转录器类型 "{transcriber_type}",使用 fast-whisper 作为默认')
return get_whisper_transcriber(whisper_model_size, device=device)