942910d99e
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 29s
CI/CD Pipeline / Validate - Type Check (mypy) (pull_request) Successful in 1m10s
CI/CD Pipeline / Validate - Migration (alembic) (pull_request) Successful in 1m17s
CI/CD Pipeline / Validate - Code Quality (pull_request) Failing after 1m51s
CI/CD Pipeline / Frontend Lint (pull_request) Successful in 40s
CI/CD Pipeline / PR Build Web Image (pull_request) Successful in 37s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 35s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 58s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Successful in 1m9s
AI Code Review / AI Code Review (pull_request) Successful in 2m8s
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 4m4s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m40s
CI/CD Pipeline / Integration Tests (pull_request) Successful in 3m3s
CI/CD Pipeline / Unit Tests (pull_request) Successful in 4m9s
CI/CD Pipeline / Canary Release to Production (pull_request) Has been cancelled
ACR Cleanup / ACR Image Cleanup (pull_request_target) Has been cancelled
Preview Cleanup / Cleanup Preview Environment (pull_request) Successful in 28s
CI/CD Pipeline / Production Browser E2E (pull_request) Failing after 1230h39m13s
CI/CD Pipeline / ACR Image Cleanup (pull_request) Failing after 1230h55m18s
CI/CD Pipeline / Staging E2E Tests (pull_request) Failing after 1230h55m22s
CI/CD Pipeline / Deploy Production (pull_request) Failing after 1230h55m24s
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Failing after 1231h14m2s
CI/CD Pipeline / Build Production Web Image (pull_request) Failing after 1231h14m40s
CI/CD Pipeline / Build Production API Image (pull_request) Failing after 1231h14m42s
CI/CD Pipeline / Frontend Unit Tests (pull_request) Failing after 1231h14m44s
CI/CD Pipeline / Build Staging Worker Image (pull_request) Failing after 1231h45m4s
CI/CD Pipeline / Build Staging API Image (pull_request) Failing after 1231h45m8s
CI/CD Pipeline / Staging API Integration Tests (pull_request) Failing after 1231h28m4s
CI/CD Pipeline / Build Production Worker Image (pull_request) Failing after 1231h47m21s
CI/CD Pipeline / Build Staging Web Image (pull_request) Failing after 1232h17m49s
- 抽离TrimConfig/TrimSegment数据类、三选二推导、边界钳制、多段裁剪、滤镜构建到packages/domain/trim_config.py - trim_engine.py: 339→67行 (-80%),保留TrimEngine薄包装类+模块级向后兼容导入 - 64个纯逻辑单测全绿,原有34个测试无回归 - 合计98 passed
68 lines
2.1 KiB
Python
Executable File
68 lines
2.1 KiB
Python
Executable File
"""裁剪引擎 — 基于 FFmpeg trim/atrim 的精确帧级裁剪.
|
||
|
||
支持:
|
||
- 入点出点裁剪(start_time / end_time / duration 三选二)
|
||
- 边界自动钳制(超出素材时长自动修正,不阻断渲染)
|
||
- 多段裁剪(一个素材裁剪出多段)
|
||
- 音画同步(视频 + 音频同步裁剪)
|
||
|
||
注:核心领域模型已抽离到 packages/domain/trim_config.py,
|
||
本模块保留薄包装层,确保向后兼容。
|
||
"""
|
||
|
||
from __future__ import annotations
|
||
|
||
import logging
|
||
from typing import Any
|
||
|
||
from packages.domain.trim_config import ( # noqa: F401 — 向后兼容
|
||
MIN_TRIM_DURATION,
|
||
TrimConfig,
|
||
TrimSegment,
|
||
build_audio_trim_filter as _build_audio_trim_filter,
|
||
build_video_trim_filter as _build_video_trim_filter,
|
||
extract_trim_from_clip_config,
|
||
parse_segments_from_config as _parse_segments_from_config,
|
||
resolve_segments as _resolve_segments,
|
||
)
|
||
|
||
logger = logging.getLogger(__name__)
|
||
|
||
|
||
class TrimEngine:
|
||
"""裁剪引擎 — 生成 FFmpeg trim / atrim 滤镜.
|
||
|
||
薄包装层,实际逻辑委托给 packages.domain.trim_config。
|
||
"""
|
||
|
||
@staticmethod
|
||
def build_video_trim_filter(
|
||
input_label: str,
|
||
trim: TrimConfig,
|
||
output_label: str,
|
||
) -> str:
|
||
"""构建视频裁剪滤镜链."""
|
||
return _build_video_trim_filter(input_label, trim, output_label)
|
||
|
||
@staticmethod
|
||
def build_audio_trim_filter(
|
||
input_label: str,
|
||
trim: TrimConfig,
|
||
output_label: str,
|
||
) -> str:
|
||
"""构建音频裁剪滤镜链."""
|
||
return _build_audio_trim_filter(input_label, trim, output_label)
|
||
|
||
@staticmethod
|
||
def resolve_segments(
|
||
segments: list[TrimSegment],
|
||
asset_duration: float,
|
||
) -> list[TrimSegment]:
|
||
"""解析并钳制多段裁剪配置,过滤无效段."""
|
||
return _resolve_segments(segments, asset_duration)
|
||
|
||
@staticmethod
|
||
def parse_segments_from_config(config: dict[str, Any] | None) -> list[TrimSegment]:
|
||
"""从 clip config 中解析多段裁剪配置."""
|
||
return _parse_segments_from_config(config)
|