fix: 清理删除旧路径后的 unused imports/variables 和孤儿测试
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 E2E Tests (pull_request) Has been skipped
CI/CD Pipeline / Staging API Integration 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 33s
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 / PR Build Worker Image (pull_request) Successful in 44s
CI/CD Pipeline / Validate - Migration (alembic) (pull_request) Successful in 1m58s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Successful in 2m7s
CI/CD Pipeline / Validate - Type Check (mypy) (pull_request) Successful in 2m9s
AI Code Review / AI Code Review (pull_request) Successful in 2m18s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 2m36s
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 2m6s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m51s
CI/CD Pipeline / Validate - Code Quality (pull_request) Failing after 4m24s
CI/CD Pipeline / Unit Tests (pull_request) Has been cancelled
CI/CD Pipeline / Integration Tests (pull_request) Has been cancelled
CI/CD Pipeline / Build Production API Image (pull_request) Has been cancelled
CI/CD Pipeline / Build Production Web Image (pull_request) Has been cancelled
CI/CD Pipeline / Build Production Worker Image (pull_request) Has been cancelled
CI/CD Pipeline / Deploy Production (pull_request) Has been cancelled
CI/CD Pipeline / Production Browser E2E (pull_request) Has been cancelled
CI/CD Pipeline / Canary Release to Production (pull_request) Has been cancelled
CI/CD Pipeline / CI Gate (pull_request) Has been cancelled
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 E2E Tests (pull_request) Has been skipped
CI/CD Pipeline / Staging API Integration 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 33s
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 / PR Build Worker Image (pull_request) Successful in 44s
CI/CD Pipeline / Validate - Migration (alembic) (pull_request) Successful in 1m58s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Successful in 2m7s
CI/CD Pipeline / Validate - Type Check (mypy) (pull_request) Successful in 2m9s
AI Code Review / AI Code Review (pull_request) Successful in 2m18s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 2m36s
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 2m6s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m51s
CI/CD Pipeline / Validate - Code Quality (pull_request) Failing after 4m24s
CI/CD Pipeline / Unit Tests (pull_request) Has been cancelled
CI/CD Pipeline / Integration Tests (pull_request) Has been cancelled
CI/CD Pipeline / Build Production API Image (pull_request) Has been cancelled
CI/CD Pipeline / Build Production Web Image (pull_request) Has been cancelled
CI/CD Pipeline / Build Production Worker Image (pull_request) Has been cancelled
CI/CD Pipeline / Deploy Production (pull_request) Has been cancelled
CI/CD Pipeline / Production Browser E2E (pull_request) Has been cancelled
CI/CD Pipeline / Canary Release to Production (pull_request) Has been cancelled
CI/CD Pipeline / CI Gate (pull_request) Has been cancelled
- generation.py: 移除 9 个 unused import (json, tempfile, Any, VirtualClip 等) - generation.py: 注释 3 个 unused variable (asset_library_id, voice_library_id, output_name) - generation_preview.py: 移除 unused import json - test_oneclick_gen_p0_fixes.py: 删除 TestTemplateClipEffectMapping (10个测试) 测试的 _apply_template_clip_effects/_extract_intro_outro_from_clip_configs 已随旧路径删除 单测 13637 passed, 0 failed
This commit is contained in:
@@ -5,7 +5,6 @@
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import logging
|
||||
|
||||
from app.auth import AuthenticatedUser, get_current_user
|
||||
|
||||
@@ -13,25 +13,15 @@
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import logging
|
||||
import tempfile
|
||||
import time
|
||||
from pathlib import Path
|
||||
from typing import Any
|
||||
|
||||
from video_processing.ffmpeg_utils import probe_duration
|
||||
from worker_app.celery_app import celery_app
|
||||
from worker_app.db import SessionLocal
|
||||
from worker_app.tasks.generation_plan_builder import VirtualClip as _VirtualClip
|
||||
from worker_app.tasks.generation_plan_builder import VirtualPlan as _VirtualPlan
|
||||
from worker_app.tasks.generation_plan_builder import apply_template_clip_effects as _apply_template_clip_effects
|
||||
from worker_app.tasks.generation_plan_builder import build_error_info as _build_error_info
|
||||
from worker_app.tasks.generation_plan_builder import (
|
||||
extract_intro_outro_from_clip_configs as _extract_intro_outro_from_clip_configs,
|
||||
)
|
||||
|
||||
from packages.domain.bgm_utils import merge_bgm_config
|
||||
|
||||
OUTPUT_WIDTH = 1280
|
||||
OUTPUT_HEIGHT = 720
|
||||
@@ -644,8 +634,8 @@ def generate_video(self, task_id: str) -> dict:
|
||||
return {"status": "failed", "error": f"generation task {task_id} not found"}
|
||||
|
||||
project_id = task_info["project_id"]
|
||||
asset_library_id = task_info["asset_library_id"]
|
||||
voice_library_id = task_info["voice_library_id"]
|
||||
# asset_library_id, voice_library_id 已在 _render_from_edit_plan 内部重新获取
|
||||
# (不再需要在 generate_video 顶层解包)
|
||||
template_id = task_info["template_id"]
|
||||
task_asset_ids = task_info["task_asset_ids"]
|
||||
batch_id = task_info["batch_id"]
|
||||
@@ -679,7 +669,7 @@ def generate_video(self, task_id: str) -> dict:
|
||||
except ValueError:
|
||||
editing_mode = EditingMode.ONE_TAKE
|
||||
|
||||
output_name = f"generated-{task_id}.mp4"
|
||||
# output_name 不再使用,渲染路径内部自行处理文件名
|
||||
|
||||
try:
|
||||
if template_id:
|
||||
|
||||
@@ -167,192 +167,3 @@ class TestP1Validations:
|
||||
# ── P1: 一键生成 clip 级效果层映射 ───────────────────────────────────────────
|
||||
|
||||
|
||||
class TestTemplateClipEffectMapping:
|
||||
"""P1: 模板 clip 级效果层映射到一键生成素材 clips."""
|
||||
|
||||
def _make_virtual_clip(self, idx: int, clip_type: str = "main", config: dict | None = None):
|
||||
from dataclasses import dataclass, field
|
||||
|
||||
_clip_type_val = clip_type
|
||||
|
||||
@dataclass
|
||||
class FakeClip:
|
||||
id: str = f"vc_{idx:03d}"
|
||||
plan_id: str = "task_001"
|
||||
clip_type: str = _clip_type_val
|
||||
order: int = idx
|
||||
asset_id: str = f"asset_{idx}"
|
||||
duration: float = 5.0
|
||||
transition_effect: str = "cut"
|
||||
transition_duration: float = 0.0
|
||||
playback_speed: float = 1.0
|
||||
config: dict = field(default_factory=dict)
|
||||
|
||||
return FakeClip(config=config or {})
|
||||
|
||||
def _make_template_clip_config(self, clip_type: str = "main", transition: str = "cut", config: dict | None = None):
|
||||
mock = MagicMock()
|
||||
mock.clip_type = clip_type
|
||||
mock.transition_effect = transition
|
||||
mock.config = config or {}
|
||||
mock.default_duration = 3.0
|
||||
mock.text_template = ""
|
||||
return mock
|
||||
|
||||
def test_transition_effect_mapped(self):
|
||||
"""转场效果正确映射到素材 clips."""
|
||||
from worker_app.tasks.generation import _apply_template_clip_effects
|
||||
|
||||
clips = [self._make_virtual_clip(i) for i in range(3)]
|
||||
clip_configs = [
|
||||
self._make_template_clip_config("main", transition="fade"),
|
||||
self._make_template_clip_config("main", transition="dissolve"),
|
||||
]
|
||||
|
||||
_apply_template_clip_effects(clips, clip_configs, "one_take")
|
||||
|
||||
# 前两个按顺序映射,第三个用最后一个模板配置
|
||||
assert clips[0].transition_effect == "fade"
|
||||
assert clips[1].transition_effect == "dissolve"
|
||||
assert clips[2].transition_effect == "dissolve" # 复用最后一个
|
||||
|
||||
def test_color_grade_mapped(self):
|
||||
"""滤镜配置正确映射到 clip.config.color_grade."""
|
||||
from worker_app.tasks.generation import _apply_template_clip_effects
|
||||
|
||||
clips = [self._make_virtual_clip(i) for i in range(2)]
|
||||
clip_configs = [
|
||||
self._make_template_clip_config(
|
||||
"main", config={"color_grade": {"enabled": True, "filter": "vintage", "brightness": 0.1}}
|
||||
),
|
||||
]
|
||||
|
||||
_apply_template_clip_effects(clips, clip_configs, "one_take")
|
||||
|
||||
assert clips[0].config["color_grade"]["filter"] == "vintage"
|
||||
assert clips[0].config["color_grade"]["brightness"] == 0.1
|
||||
# 第二个素材复用第一个模板配置
|
||||
assert clips[1].config["color_grade"]["filter"] == "vintage"
|
||||
|
||||
def test_existing_config_preserved(self):
|
||||
"""已有 clip.config 内容(如 role)被保留."""
|
||||
from worker_app.tasks.generation import _apply_template_clip_effects
|
||||
|
||||
clips = [self._make_virtual_clip(0, config={"role": "b_roll"})]
|
||||
clip_configs = [
|
||||
self._make_template_clip_config("main", config={"color_grade": {"enabled": True, "filter": "warm"}}),
|
||||
]
|
||||
|
||||
_apply_template_clip_effects(clips, clip_configs, "voice_over")
|
||||
|
||||
assert clips[0].config["role"] == "b_roll" # 保留原有配置
|
||||
assert clips[0].config["color_grade"]["filter"] == "warm" # 新增滤镜配置
|
||||
|
||||
def test_empty_clip_configs_no_change(self):
|
||||
"""空模板配置时 clips 保持不变."""
|
||||
from worker_app.tasks.generation import _apply_template_clip_effects
|
||||
|
||||
clips = [self._make_virtual_clip(i) for i in range(2)]
|
||||
_apply_template_clip_effects(clips, [], "one_take")
|
||||
|
||||
assert clips[0].transition_effect == "cut"
|
||||
assert clips[1].transition_effect == "cut"
|
||||
|
||||
def test_cut_transition_not_overwritten(self):
|
||||
"""模板转场为 cut 时不覆盖(保持默认)."""
|
||||
from worker_app.tasks.generation import _apply_template_clip_effects
|
||||
|
||||
clips = [self._make_virtual_clip(0)]
|
||||
clips[0].transition_effect = "fade" # 已有非默认值
|
||||
clip_configs = [
|
||||
self._make_template_clip_config("main", transition="cut"),
|
||||
]
|
||||
|
||||
_apply_template_clip_effects(clips, clip_configs, "one_take")
|
||||
|
||||
# 模板是 cut 时,保留原有值(避免无意义覆盖)
|
||||
assert clips[0].transition_effect == "fade"
|
||||
|
||||
def test_transition_duration_mapped(self):
|
||||
"""转场时长(transition_duration)从模板 config 正确映射到 clip."""
|
||||
from worker_app.tasks.generation import _apply_template_clip_effects
|
||||
|
||||
clips = [self._make_virtual_clip(i) for i in range(3)]
|
||||
clip_configs = [
|
||||
self._make_template_clip_config("main", transition="fade", config={"transition_duration": 0.8}),
|
||||
self._make_template_clip_config("main", transition="dissolve", config={"transition_duration": 1.2}),
|
||||
]
|
||||
|
||||
_apply_template_clip_effects(clips, clip_configs, "one_take")
|
||||
|
||||
# 前两个按顺序映射,第三个复用最后一个
|
||||
assert clips[0].transition_effect == "fade"
|
||||
assert clips[0].transition_duration == 0.8
|
||||
assert clips[1].transition_effect == "dissolve"
|
||||
assert clips[1].transition_duration == 1.2
|
||||
assert clips[2].transition_effect == "dissolve"
|
||||
assert clips[2].transition_duration == 1.2
|
||||
|
||||
def test_transition_duration_ignored_for_cut(self):
|
||||
"""模板转场为 cut 时,transition_duration 不生效(保持默认0)."""
|
||||
from worker_app.tasks.generation import _apply_template_clip_effects
|
||||
|
||||
clips = [self._make_virtual_clip(0)]
|
||||
clip_configs = [
|
||||
self._make_template_clip_config("main", transition="cut", config={"transition_duration": 0.5}),
|
||||
]
|
||||
|
||||
_apply_template_clip_effects(clips, clip_configs, "one_take")
|
||||
|
||||
# cut 转场不映射,transition_duration 也不应用
|
||||
assert clips[0].transition_duration == 0.0
|
||||
|
||||
def test_transition_duration_invalid_value_skipped(self):
|
||||
"""transition_duration 为无效值时安全跳过."""
|
||||
from worker_app.tasks.generation import _apply_template_clip_effects
|
||||
|
||||
clips = [self._make_virtual_clip(0)]
|
||||
clip_configs = [
|
||||
self._make_template_clip_config("main", transition="fade", config={"transition_duration": "abc"}),
|
||||
]
|
||||
|
||||
_apply_template_clip_effects(clips, clip_configs, "one_take")
|
||||
|
||||
assert clips[0].transition_effect == "fade"
|
||||
assert clips[0].transition_duration == 0.0 # 无效值保持默认
|
||||
|
||||
def test_intro_outro_extracted(self):
|
||||
"""intro/outro 类型 clip_config 正确提取为 plan 级 intro_outro 配置."""
|
||||
from worker_app.tasks.generation import _extract_intro_outro_from_clip_configs
|
||||
|
||||
clip_configs = [
|
||||
self._make_template_clip_config("intro", config={"intro_type": "text", "intro_text_color": "#ffffff"}),
|
||||
self._make_template_clip_config("main"),
|
||||
self._make_template_clip_config("outro", config={"outro_type": "follow", "outro_follow_text": "关注我们"}),
|
||||
]
|
||||
# 设置 intro/outro 的 text_template
|
||||
clip_configs[0].text_template = "精彩视频"
|
||||
clip_configs[0].default_duration = 2.5
|
||||
|
||||
result = _extract_intro_outro_from_clip_configs(clip_configs)
|
||||
|
||||
assert result["has_intro"] is True
|
||||
assert result["intro_type"] == "text"
|
||||
assert result["intro_text"] == "精彩视频"
|
||||
assert result["intro_duration"] == 2.5
|
||||
assert result["intro_text_color"] == "#ffffff"
|
||||
assert result["has_outro"] is True
|
||||
assert result["outro_type"] == "follow"
|
||||
assert result["outro_follow_text"] == "关注我们"
|
||||
|
||||
def test_intro_outro_empty_when_none(self):
|
||||
"""没有 intro/outro 时返回空 dict."""
|
||||
from worker_app.tasks.generation import _extract_intro_outro_from_clip_configs
|
||||
|
||||
clip_configs = [
|
||||
self._make_template_clip_config("main"),
|
||||
self._make_template_clip_config("main"),
|
||||
]
|
||||
|
||||
result = _extract_intro_outro_from_clip_configs(clip_configs)
|
||||
assert result == {}
|
||||
|
||||
Reference in New Issue
Block a user