925b365d6a
CI/CD Pipeline / Check if frontend-only change (push) Has been skipped
CI/CD Pipeline / PR Build API Image (push) Has been skipped
CI/CD Pipeline / PR Build Web Image (push) Has been skipped
CI/CD Pipeline / PR Build Worker Image (push) Has been skipped
CI/CD Pipeline / Frontend Lint (push) Successful in 57s
CI/CD Pipeline / Validate - Type Check (mypy) (push) Successful in 1m22s
CI/CD Pipeline / Validate - Migration (alembic) (push) Successful in 1m23s
CI/CD Pipeline / Build Production API Image (push) Has been skipped
CI/CD Pipeline / Build Production Web Image (push) Has been skipped
CI/CD Pipeline / Build Production Worker Image (push) Has been skipped
CI/CD Pipeline / Build Staging Web Image (push) Successful in 1m56s
CI/CD Pipeline / Deploy Production (push) Has been skipped
CI/CD Pipeline / Validate - Code Quality (push) Failing after 2m56s
CI/CD Pipeline / Frontend Unit Tests (push) Successful in 1m21s
CI/CD Pipeline / Production Browser E2E (push) Has been skipped
CI/CD Pipeline / Integration Tests (push) Successful in 2m3s
CI/CD Pipeline / Build Staging Worker Image (push) Successful in 5m22s
CI/CD Pipeline / Unit Tests (push) Successful in 7m2s
CI/CD Pipeline / Build Staging API Image (push) Successful in 14m26s
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (push) Successful in 1m42s
CI/CD Pipeline / ACR Image Cleanup (push) Successful in 37s
CI/CD Pipeline / Staging E2E Tests (push) Successful in 3m8s
CI/CD Pipeline / Staging API Integration Tests (push) Successful in 4m7s
CI/CD Pipeline / Canary Release to Production (push) Has been skipped
90 lines
2.7 KiB
Python
Executable File
90 lines
2.7 KiB
Python
Executable File
"""ASS 字幕生成模块 — 薄包装,实际逻辑在 packages/domain/ass_subtitle_builder.py.
|
|
|
|
职责:
|
|
- 将 title / subtitle 配置转换为 ASS 字幕文件
|
|
- 文件IO 在此模块,纯逻辑已抽离到 domain
|
|
- 供 UnifiedRenderService._maybe_generate_ass 调用
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import logging
|
|
from pathlib import Path
|
|
from typing import Any
|
|
|
|
from packages.domain.ass_subtitle_builder import (
|
|
TITLE_MARGIN_BOTTOM,
|
|
TITLE_MARGIN_SIDE,
|
|
TITLE_MARGIN_TOP,
|
|
build_ass_content,
|
|
)
|
|
from packages.domain.ass_subtitle_builder import build_ass_style as _build_ass_style_base # noqa: F401 — 向后兼容
|
|
from packages.domain.ass_subtitle_builder import escape_ass_text as _escape_ass_text_base
|
|
from packages.domain.ass_subtitle_builder import format_ass_time as _format_ass_time_base
|
|
from packages.domain.ass_subtitle_builder import hex_to_ass_color as _hex_to_ass_color_base
|
|
from packages.domain.ass_subtitle_builder import position_to_ass_alignment as _position_to_ass_alignment_base
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
# 向后兼容:模块级函数保留为薄包装
|
|
def _hex_to_ass_color(hex_color: str) -> str:
|
|
return _hex_to_ass_color_base(hex_color)
|
|
|
|
|
|
def _position_to_ass_alignment(position: str) -> int:
|
|
return _position_to_ass_alignment_base(position)
|
|
|
|
|
|
def _build_ass_style(*args, **kwargs) -> str:
|
|
return _build_ass_style_base(*args, **kwargs)
|
|
|
|
|
|
def _escape_ass_text(text: str) -> str:
|
|
return _escape_ass_text_base(text)
|
|
|
|
|
|
def _format_ass_time(seconds: float) -> str:
|
|
return _format_ass_time_base(seconds)
|
|
|
|
|
|
def generate_ass_subtitles(
|
|
output_path: Path,
|
|
*,
|
|
video_width: int,
|
|
video_height: int,
|
|
video_duration: float,
|
|
title_text: str = "",
|
|
title_config: dict[str, Any] | None = None,
|
|
subtitle_text: str = "",
|
|
subtitle_config: dict[str, Any] | None = None,
|
|
) -> Path:
|
|
"""生成 ASS 字幕文件.
|
|
|
|
Args:
|
|
output_path: 输出 ASS 文件路径
|
|
video_width: 视频宽度
|
|
video_height: 视频高度
|
|
video_duration: 视频总时长(秒)
|
|
title_text: 标题文本
|
|
title_config: 标题样式配置
|
|
subtitle_text: 字幕文本
|
|
subtitle_config: 字幕样式配置
|
|
|
|
Returns:
|
|
生成的 ASS 文件路径
|
|
"""
|
|
content = build_ass_content(
|
|
video_width=video_width,
|
|
video_height=video_height,
|
|
video_duration=video_duration,
|
|
title_text=title_text,
|
|
title_config=title_config,
|
|
subtitle_text=subtitle_text,
|
|
subtitle_config=subtitle_config,
|
|
)
|
|
|
|
output_path.parent.mkdir(parents=True, exist_ok=True)
|
|
output_path.write_text(content, encoding="utf-8")
|
|
return output_path
|