feat: 日语转写(翻译前归档)也作为产物放到视频旁
翻译前的日语转写只有中间态,重跑字幕或回看译文时无据可查;把它按语言归档到 视频旁,与中文译文、双目字幕并列。 - `learn-translate` 的 `final_outputs` 增加 `ja_srt: asr.srt_uri`(清洗后的转写)。 - `_sidecar_product_name` 改为**按 final_outputs 别名**映射语言后缀 (`ja_srt`→`.JA.srt`、`cn_srt`→`.CN.srt`、`ass`→`.CN_dual_eye.ass`),未登记别名 时按扩展名兜底。此前两份 `.srt` 都映射成 `.CN.srt` 会互相覆盖(真实日志: "产物已放视频旁: movie.CN.srt, movie.CN.srt")。 - 任务管理的产物列补"日语 SRT"下载链接。 - 测试:按别名区分语言变体 + 端到端验证两份产物都落地且不覆盖。
This commit is contained in:
+18
-6
@@ -149,16 +149,28 @@ def list_sidecar_subtitles(video: Path) -> list[Path]:
|
||||
return sorted(found)
|
||||
|
||||
|
||||
def _sidecar_product_name(video: Path, source: Path) -> str:
|
||||
# final_outputs 别名 → 视频旁文件名后缀:日语转写与中文译文同为 `.srt`,
|
||||
# 只按扩展名映射会让两份产物撞名互相覆盖,必须按别名区分语言。
|
||||
_PRODUCT_SUFFIXES = {
|
||||
"ja_srt": ".JA.srt",
|
||||
"cn_srt": ".CN.srt",
|
||||
"ass": ".CN_dual_eye.ass",
|
||||
}
|
||||
|
||||
|
||||
def _sidecar_product_name(video: Path, source: Path, alias: str | None = None) -> str:
|
||||
"""把最终产物映射为放在视频旁时的标准字幕文件名。
|
||||
|
||||
对齐媒体库既有约定(文件名稳定、无时间戳,媒体库可按视频主名自动匹配):
|
||||
- 日语转写(`ja_srt`)→ `<视频名>.JA.srt`;
|
||||
- 中文 `.srt` 产物 → `<视频名>.CN.srt`;
|
||||
- 双目 `.ass` 产物 → `<视频名>.CN_dual_eye.ass`;
|
||||
- 其余扩展名的最终产物保留原文件名(含时间戳),避免误改语义。
|
||||
注:当前内置字幕工作流(learn-translate / zh-direct)在视频旁放置的 `.srt/.ass` 即
|
||||
中文字幕与双目字幕;若未来出现"非中文 .srt"类产物需在此按产物来源区分。
|
||||
|
||||
别名来自 `final_outputs` 的键,未登记别名时按扩展名兜底(历史工作流兼容)。
|
||||
"""
|
||||
if alias in _PRODUCT_SUFFIXES:
|
||||
return f"{video.stem}{_PRODUCT_SUFFIXES[alias]}"
|
||||
suffix = source.suffix.lower()
|
||||
if suffix == ".srt":
|
||||
return f"{video.stem}.CN.srt"
|
||||
@@ -600,8 +612,8 @@ class BatchWorker:
|
||||
def _place_products(self, run_id: str, video: Path, definition: WorkflowDefinition) -> list[str]:
|
||||
"""把最终产物文件复制到视频所在目录(视频旁),返回放置的文件名。
|
||||
|
||||
只为 `final_outputs` 声明的最终产物放置副本:字幕流水线的产物即中文
|
||||
`.srt` 与双目 `.ass`,按库内约定命名(见 _sidecar_product_name),
|
||||
只为 `final_outputs` 声明的最终产物放置副本:字幕流水线的产物即日语
|
||||
转写 `.srt`、中文 `.srt` 与双目 `.ass`,按库内约定命名(见 _sidecar_product_name),
|
||||
文件名稳定且含视频主名——媒体库按主名匹配字幕,下次批量扫描也会命中
|
||||
"已有字幕"规则跳过该视频。同名目标直接覆盖:可能是上一次运行/旧工作流
|
||||
留下的旧内容,应以本次产物为准。
|
||||
@@ -615,7 +627,7 @@ class BatchWorker:
|
||||
source = Path(artifact["uri"])
|
||||
if not source.is_file():
|
||||
raise ValueError(f"missing final artifact file: {alias} ({source})")
|
||||
target = video.parent / _sidecar_product_name(video, source)
|
||||
target = video.parent / _sidecar_product_name(video, source, alias)
|
||||
products.append((source, target))
|
||||
placed: list[str] = []
|
||||
for source, target in products:
|
||||
|
||||
Reference in New Issue
Block a user