style: auto-format with black + isort + prettier [skip ci-format-check]
CI/CD Pipeline / Build Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Has been skipped
CI/CD Pipeline / Staging API Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / Staging E2E Tests (pull_request) Has been skipped
CI/CD Pipeline / ACR Image Cleanup (pull_request) Has been skipped
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 31s
CI/CD Pipeline / Frontend Lint (pull_request) Has been skipped
CI/CD Pipeline / Frontend Unit Tests (pull_request) Has been skipped
CI/CD Pipeline / PR Build Web Image (pull_request) Has been skipped
CI/CD Pipeline / Validate - Type Check (mypy) (pull_request) Successful in 1m43s
CI/CD Pipeline / Validate - Code Quality (pull_request) Failing after 1m43s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Successful in 1m47s
CI/CD Pipeline / Validate - Migration (alembic) (pull_request) Successful in 1m49s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 1m53s
CI/CD Pipeline / Unit Tests (pull_request) Successful in 2m49s
CI/CD Pipeline / Build Production API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Deploy Production (pull_request) Has been skipped
CI/CD Pipeline / Canary Release to Production (pull_request) Has been skipped
CI/CD Pipeline / Production Browser E2E (pull_request) Has been skipped
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 3m14s
CI/CD Pipeline / Integration Tests (pull_request) Successful in 1m58s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 3m14s
CI/CD Pipeline / CI Gate (pull_request) Failing after 6s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 4m3s
AI Code Review / AI Code Review (pull_request) Failing after 6m30s
CI/CD Pipeline / Build Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Has been skipped
CI/CD Pipeline / Staging API Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / Staging E2E Tests (pull_request) Has been skipped
CI/CD Pipeline / ACR Image Cleanup (pull_request) Has been skipped
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 31s
CI/CD Pipeline / Frontend Lint (pull_request) Has been skipped
CI/CD Pipeline / Frontend Unit Tests (pull_request) Has been skipped
CI/CD Pipeline / PR Build Web Image (pull_request) Has been skipped
CI/CD Pipeline / Validate - Type Check (mypy) (pull_request) Successful in 1m43s
CI/CD Pipeline / Validate - Code Quality (pull_request) Failing after 1m43s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Successful in 1m47s
CI/CD Pipeline / Validate - Migration (alembic) (pull_request) Successful in 1m49s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 1m53s
CI/CD Pipeline / Unit Tests (pull_request) Successful in 2m49s
CI/CD Pipeline / Build Production API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Deploy Production (pull_request) Has been skipped
CI/CD Pipeline / Canary Release to Production (pull_request) Has been skipped
CI/CD Pipeline / Production Browser E2E (pull_request) Has been skipped
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 3m14s
CI/CD Pipeline / Integration Tests (pull_request) Successful in 1m58s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 3m14s
CI/CD Pipeline / CI Gate (pull_request) Failing after 6s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 4m3s
AI Code Review / AI Code Review (pull_request) Failing after 6m30s
This commit is contained in:
@@ -47,13 +47,12 @@ from video_processing.reverse_engine import ReverseConfig, ReverseEngine
|
||||
from video_processing.speed_engine import SpeedEngine
|
||||
from video_processing.sticker_engine import StickerEngine
|
||||
from video_processing.subtitle_generator import generate_ass_from_timeline
|
||||
|
||||
from packages.domain.ass_subtitle_builder import build_ass_content
|
||||
from video_processing.transition_engine import TransitionEngine
|
||||
from video_processing.trim_engine import TrimConfig, TrimEngine, extract_trim_from_clip_config
|
||||
from video_processing.tts_engine import TtsEngine
|
||||
from video_processing.watermark_engine import WatermarkConfig, WatermarkEngine
|
||||
|
||||
from packages.domain.ass_subtitle_builder import build_ass_content
|
||||
from packages.domain.render_layer_utils import LAYER_Z_INDEX as _IMPORTED_LAYER_Z_INDEX
|
||||
from packages.domain.render_layer_utils import clip_adjusted_duration as _clip_adjusted_duration_pure
|
||||
from packages.domain.render_layer_utils import clip_effective_duration as _clip_effective_duration_pure
|
||||
@@ -133,7 +132,6 @@ _PIP_SCALE = 0.25 # PiP 占主画面的比例
|
||||
# ── 统一渲染引擎 ─────────────────────────────────────────────────────────────
|
||||
|
||||
|
||||
|
||||
def _overlay_title_on_ass(
|
||||
ass_path: Path,
|
||||
*,
|
||||
|
||||
@@ -7,10 +7,11 @@
|
||||
4. ASR 失败但有标题时,降级生成标题 ASS
|
||||
"""
|
||||
|
||||
import pytest
|
||||
from pathlib import Path
|
||||
from unittest.mock import MagicMock, patch
|
||||
|
||||
import pytest
|
||||
|
||||
from apps.worker.video_processing.unified_render_service import _overlay_title_on_ass
|
||||
|
||||
|
||||
@@ -122,7 +123,7 @@ class TestMaybeGenerateAssWithTitle:
|
||||
def _make_service(self, tmp_path, plan_config, asr_service=None):
|
||||
"""创建简化的 UnifiedRenderService 实例用于测试"""
|
||||
from apps.worker.video_processing.unified_render_service import UnifiedRenderService
|
||||
|
||||
|
||||
service = object.__new__(UnifiedRenderService)
|
||||
service.plan = MagicMock()
|
||||
service.plan.id = "test_plan_001"
|
||||
@@ -138,14 +139,21 @@ class TestMaybeGenerateAssWithTitle:
|
||||
def test_asr_path_with_title_overlays_title(self, tmp_path):
|
||||
"""ASR 路径 + 有标题 → 标题叠加到 ASS 文件"""
|
||||
plan_config = {
|
||||
"title": {"text": "测试标题", "enabled": True, "position": "top", "size": 48, "font": "思源黑体", "color": "#ffffff"},
|
||||
"title": {
|
||||
"text": "测试标题",
|
||||
"enabled": True,
|
||||
"position": "top",
|
||||
"size": 48,
|
||||
"font": "思源黑体",
|
||||
"color": "#ffffff",
|
||||
},
|
||||
"subtitle": {"enabled": True, "auto_generated": True},
|
||||
}
|
||||
|
||||
|
||||
# Mock ASR service
|
||||
mock_asr = MagicMock()
|
||||
service = self._make_service(tmp_path, plan_config, asr_service=mock_asr)
|
||||
|
||||
|
||||
# Mock _generate_asr_subtitles to return a timeline with segments
|
||||
mock_timeline = MagicMock()
|
||||
mock_segment = MagicMock()
|
||||
@@ -154,10 +162,10 @@ class TestMaybeGenerateAssWithTitle:
|
||||
mock_segment.text = "ASR识别的文字"
|
||||
mock_timeline.segments = [mock_segment]
|
||||
mock_timeline.segment_count = 1
|
||||
|
||||
with patch.object(service, '_generate_asr_subtitles', return_value=mock_timeline):
|
||||
|
||||
with patch.object(service, "_generate_asr_subtitles", return_value=mock_timeline):
|
||||
result = service._maybe_generate_ass(video_duration=10.0)
|
||||
|
||||
|
||||
assert result is not None, "应生成 ASS 文件"
|
||||
content = result.read_text(encoding="utf-8")
|
||||
assert "测试标题" in content, "标题应出现在 ASS 文件中"
|
||||
@@ -169,17 +177,17 @@ class TestMaybeGenerateAssWithTitle:
|
||||
"title": {"text": "仅标题", "enabled": True, "position": "top", "size": 48},
|
||||
"subtitle": {"enabled": True, "auto_generated": True},
|
||||
}
|
||||
|
||||
|
||||
mock_asr = MagicMock()
|
||||
service = self._make_service(tmp_path, plan_config, asr_service=mock_asr)
|
||||
|
||||
|
||||
# Mock ASR returns empty timeline
|
||||
mock_timeline = MagicMock()
|
||||
mock_timeline.segments = []
|
||||
|
||||
with patch.object(service, '_generate_asr_subtitles', return_value=mock_timeline):
|
||||
|
||||
with patch.object(service, "_generate_asr_subtitles", return_value=mock_timeline):
|
||||
result = service._maybe_generate_ass(video_duration=10.0)
|
||||
|
||||
|
||||
assert result is not None, "有标题时应生成 ASS 文件"
|
||||
content = result.read_text(encoding="utf-8")
|
||||
assert "仅标题" in content, "标题应出现在 ASS 文件中"
|
||||
@@ -190,14 +198,14 @@ class TestMaybeGenerateAssWithTitle:
|
||||
"title": {"text": "降级标题", "enabled": True, "position": "top", "size": 48},
|
||||
"subtitle": {"enabled": True, "auto_generated": True},
|
||||
}
|
||||
|
||||
|
||||
mock_asr = MagicMock()
|
||||
service = self._make_service(tmp_path, plan_config, asr_service=mock_asr)
|
||||
|
||||
|
||||
# Mock ASR raises exception
|
||||
with patch.object(service, '_generate_asr_subtitles', side_effect=RuntimeError("ASR error")):
|
||||
with patch.object(service, "_generate_asr_subtitles", side_effect=RuntimeError("ASR error")):
|
||||
result = service._maybe_generate_ass(video_duration=10.0)
|
||||
|
||||
|
||||
assert result is not None, "ASR 失败但有标题时应生成 ASS 文件"
|
||||
content = result.read_text(encoding="utf-8")
|
||||
assert "降级标题" in content, "标题应出现在降级 ASS 文件中"
|
||||
|
||||
Reference in New Issue
Block a user