feat: 转场特效引擎 — TransitionEngine + 14种转场预设 + 时长边界校验 + 降级策略

核心能力:
- TransitionEngine 抽象层:TransitionType枚举 + TransitionConfig配置 + 引擎类
- 14种转场预设:fade/dissolve/zoom/circlecrop/rectcrop + slide*4 + wipe*4
- 转场时长边界校验:0.3s~2s范围,超出自动钳制
- 降级策略:不支持的转场自动fallback到硬切(cut),不阻断渲染
- 别名支持:slide_left/slide-left/crossfade/wipe/zoomin等多种写法

系统集成:
- UnifiedRenderService 接入 TransitionEngine,替换直接xfade调用
- EditPlanClip 领域模型新增 transition_duration 字段
- SQLAlchemy model + repository 同步新增列
- API层 Schema + Service 同步支持 transition_duration
- 向前兼容:transition_duration=0 表示使用全局默认值

测试:
- 54个新增单测:枚举/配置解析/边界校验/降级策略/滤镜链构建/集成验证
- 84个渲染测试 + 16个适配器测试全绿,无回归
This commit is contained in:
CI Bot
2026-07-14 00:08:16 +08:00
parent 17fbae13a8
commit 5c002de181
10 changed files with 921 additions and 6 deletions
+3
View File
@@ -54,6 +54,7 @@ class SQLAlchemyEditPlanClipRepository:
start_time=clip.start_time,
duration=clip.duration,
transition_effect=clip.transition_effect,
transition_duration=clip.transition_duration,
status=clip.status,
config=clip.config,
)
@@ -76,6 +77,7 @@ class SQLAlchemyEditPlanClipRepository:
model.start_time = clip.start_time
model.duration = clip.duration
model.transition_effect = clip.transition_effect
model.transition_duration = clip.transition_duration
model.status = clip.status
model.config = clip.config
model.updated_at = clip.updated_at
@@ -120,6 +122,7 @@ class SQLAlchemyEditPlanClipRepository:
start_time=model.start_time or 0.0,
duration=model.duration or 0.0,
transition_effect=model.transition_effect or "cut",
transition_duration=getattr(model, "transition_duration", 0.0) or 0.0,
status=EditPlanClipStatus(model.status) if model.status else EditPlanClipStatus.PENDING,
config=model.config or {},
created_at=model.created_at,
@@ -196,6 +196,7 @@ class EditPlanClipModel(Base):
start_time = Column(Float, nullable=False, default=0.0)
duration = Column(Float, nullable=False, default=0.0)
transition_effect = Column(String(20), nullable=False, default="cut")
transition_duration = Column(Float, nullable=False, default=0.0)
status = Column(String(20), nullable=False, default="pending", index=True)
config = Column(JSON, nullable=False, default=dict)
created_at = Column(DateTime, nullable=False, default=lambda: datetime.now(timezone.utc))