feat: 优化学习视频转写与字幕清洗
This commit is contained in:
+22
-7
@@ -1,7 +1,7 @@
|
||||
"""faster-whisper ASR 节点。
|
||||
|
||||
单体版中作为进程内节点模块,由调度器直接调用。模型权重默认优先从本地
|
||||
目录加载,避免从远端下载,仅在本地找不到模型时才回退到远端 large-v3。
|
||||
目录加载,避免从远端下载,仅在本地找不到模型时才回退到远端 large-v2。
|
||||
CUDA 动态库通过 ctypes 在进程内预加载,替代分布式版的 LD_LIBRARY_PATH 注入。
|
||||
"""
|
||||
|
||||
@@ -60,13 +60,13 @@ def _load_cuda_libraries() -> None:
|
||||
def _local_model_candidates() -> list[Path]:
|
||||
"""返回本地模型候选目录:单体根目录 model/ 优先,其次 nodes/ 同级 model/。
|
||||
|
||||
单体根目录 model/ 对应仓库根下的 model/faster-whisper-large-v3,
|
||||
单体根目录 model/ 对应仓库根下的 model/faster-whisper-large-v2,
|
||||
nodes/ 同级 model/ 允许部署时把权重随代码目录一起携带。
|
||||
"""
|
||||
monolith_root = Path(__file__).resolve().parent.parent
|
||||
return [
|
||||
monolith_root / "model" / "faster-whisper-large-v3",
|
||||
monolith_root / "nodes" / "model" / "faster-whisper-large-v3",
|
||||
monolith_root / "model" / "faster-whisper-large-v2",
|
||||
monolith_root / "nodes" / "model" / "faster-whisper-large-v2",
|
||||
]
|
||||
|
||||
|
||||
@@ -75,7 +75,7 @@ def resolve_model_path(
|
||||
env: dict | None = None,
|
||||
candidates: list[Path] | None = None,
|
||||
) -> str:
|
||||
"""按 参数 > 环境变量 > 本地候选目录 > 远端 large-v3 的顺序解析模型路径。
|
||||
"""按 参数 > 环境变量 > 本地候选目录 > 远端 large-v2 的顺序解析模型路径。
|
||||
|
||||
本地优先是默认行为:只要候选目录存在且包含 model.bin 就使用本地权重,
|
||||
避免从 Hugging Face 下载;远端下载仅在全部本地候选缺失时作为兜底。
|
||||
@@ -99,7 +99,7 @@ def resolve_model_path(
|
||||
# model.bin 是 CTranslate2 权重的必需文件,存在才认为模型完整。
|
||||
if candidate.is_dir() and (candidate / "model.bin").is_file():
|
||||
return str(candidate)
|
||||
return "large-v3"
|
||||
return "large-v2"
|
||||
|
||||
def format_timestamp(seconds: float) -> str:
|
||||
"""把秒数格式化为 SRT 时间戳,例如 01:00:00,500。"""
|
||||
@@ -232,6 +232,8 @@ def invoke(request: InvokeRequest) -> InvokeResponse:
|
||||
# 把真话当非语音剔除(实测 savr-1054 全片仅召回 115 条),开启后强制
|
||||
# 无 VAD 整段解码(vad_filter=False 且跳过自动 VAD 分析)以召回弱语音,
|
||||
# 代价是无语音段会产生长时套话幻觉,由下方日语幻觉清洗兜底移除。
|
||||
# 另:decode_full 救回的弱语音中混有纯语气词碎片(あ/ん?等),由
|
||||
# short_moan_max_chars(默认 3,0=关闭)参数控制短呻吟整条删除。
|
||||
# task 默认 transcribe,中文直出模型可传 translate 直接翻译为目标语言。
|
||||
# condition_on_previous_text 默认 False:长音频下开启会导致重复/漂移,
|
||||
# 关闭后每个 30s 窗口独立解码,是 faster-whisper 官方建议的长音频方案。
|
||||
@@ -305,10 +307,23 @@ def invoke(request: InvokeRequest) -> InvokeResponse:
|
||||
# 剔除**(序号/时间轴/文本全删、剩余重编号),不留下 '-' 占位污染下游
|
||||
# (占位会渲染进 ASS 成减号、翻译/过滤都要额外处理);短时(≤15s)相同词
|
||||
# 可能是剧情真实道晚安,保留。见 nodes/subtitle_cleanup.py。
|
||||
# 其次(2026-09 用户决策):decode_full 也会把呻吟/BGM 混叠的弱语音整段
|
||||
# 救回,其中混有大量**纯语气词碎片**(あ…/ん?/はぁ…/あ!あ!/んふふ 等),
|
||||
# 这类噪声影响字幕观感;在此按'全部字符∈纯呻吟集合 且 有效假名≤max_chars'
|
||||
# 判据**整条删除**(remove_short_moan_entries),真实短对话(そこ/やばい/
|
||||
# ねえ/やだ)天然不命中。仅 decode_full 生效,demo 等 VAD 链路不受影响;
|
||||
# 参数 short_moan_max_chars 可调(默认 3,设 0 关闭)。
|
||||
if decode_full:
|
||||
from nodes.subtitle_cleanup import clean_japanese_hallucinations
|
||||
from nodes.subtitle_cleanup import (
|
||||
clean_japanese_hallucinations,
|
||||
remove_short_moan_entries,
|
||||
)
|
||||
|
||||
body = clean_japanese_hallucinations("\n".join(lines))
|
||||
body = remove_short_moan_entries(
|
||||
body,
|
||||
max_chars=int(request.params.get("short_moan_max_chars", 3)),
|
||||
)
|
||||
else:
|
||||
body = "\n".join(lines)
|
||||
output_path = output_dir / "transcript.srt"
|
||||
|
||||
Reference in New Issue
Block a user