Files
xiaoxia-saas/apps/worker/video_processing/speed_engine.py
T
AI Bot 5162ffa29c
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 14s
CI/CD Pipeline / Frontend Lint (pull_request) Successful in 35s
CI/CD Pipeline / Validate - Type Check (mypy) (pull_request) Successful in 1m15s
CI/CD Pipeline / Validate - Migration (alembic) (pull_request) Successful in 1m14s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 35s
CI/CD Pipeline / Validate - Code Quality (pull_request) Failing after 2m55s
CI/CD Pipeline / PR Build Web Image (pull_request) Successful in 1m59s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Successful in 39s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 52s
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 4m20s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m5s
AI Code Review / AI Code Review (pull_request) Successful in 5m54s
CI/CD Pipeline / CI Gate (pull_request) 失败: CI/CD Pipeline / Validate - Code Quality (pull_request) [backend-only]
CI/CD Pipeline / Integration Tests (pull_request) Successful in 3m38s
CI/CD Pipeline / Unit Tests (pull_request) Successful in 5m20s
CI/CD Pipeline / Staging E2E Tests (pull_request) Has been cancelled
CI/CD Pipeline / Staging API Integration Tests (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 / ACR Image Cleanup (pull_request) Has been cancelled
CI/CD Pipeline / Canary Release to Production (pull_request) Has been cancelled
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Failing after 1221h30m54s
CI/CD Pipeline / Build Production Web Image (pull_request) Failing after 1221h30m56s
CI/CD Pipeline / Build Production API Image (pull_request) Failing after 1221h30m57s
CI/CD Pipeline / Frontend Unit Tests (pull_request) Failing after 1221h30m58s
CI/CD Pipeline / Build Staging Worker Image (pull_request) Failing after 1223h43m12s
CI/CD Pipeline / Build Staging API Image (pull_request) Failing after 1223h43m16s
CI/CD Pipeline / Build Production Worker Image (pull_request) Failing after 1222h3m41s
CI/CD Pipeline / Build Staging Web Image (pull_request) Failing after 1224h16m0s
test(wave117): 抽离speed_config领域模型 + 57单测
2026-07-27 12:41:44 +08:00

75 lines
2.4 KiB
Python
Executable File
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""视频调速引擎 — 基于 FFmpeg setpts + atempo 的速度调整能力.
支持:
- 0.25x ~ 4x 变速范围
- 视频调速(setpts)
- 音频调速(atempo,多级串联处理超范围值)
- 音调修正(pitch_correct,默认开启)
- 边界自动钳制,不阻断渲染
注:核心领域模型已抽离到 packages/domain/speed_config.py,
本模块保留薄包装层,确保向后兼容。
"""
from __future__ import annotations
from typing import Optional
from packages.domain.speed_config import ( # noqa: F401 — 向后兼容
DEFAULT_SPEED,
MAX_SPEED,
MIN_SPEED,
SpeedConfig,
_split_atempo_stages,
adjust_duration as _adjust_duration_base,
build_audio_filter as _build_audio_filter_base,
build_video_filter as _build_video_filter_base,
resolve_clip_speed as _resolve_clip_speed_base,
)
class SpeedEngine:
"""调速引擎 — 生成 FFmpeg 调速滤镜链.
薄包装层,实际逻辑委托给 packages.domain.speed_config。
"""
def build_video_filter(self, config: SpeedConfig) -> str:
"""生成视频调速滤镜字符串."""
return _build_video_filter_base(config)
def build_audio_filter(self, config: SpeedConfig) -> str:
"""生成音频调速滤镜字符串."""
return _build_audio_filter_base(config)
@staticmethod
def _split_atempo_stages(speed: float) -> list[float]:
"""将速度拆分为多级 atempo 串联(内部方法,向后兼容)."""
return _split_atempo_stages(speed)
def adjust_duration(self, original_duration: float, config: SpeedConfig) -> float:
"""计算调速后的时长."""
return _adjust_duration_base(original_duration, config)
def build_clip_speed_filter(
self,
speed: float,
pitch_correct: bool = True,
) -> tuple[str, str, SpeedConfig]:
"""便捷方法:从单一 speed 值生成视频+音频滤镜."""
config = SpeedConfig(speed=speed, pitch_correct=pitch_correct)
config.clamp()
return (
self.build_video_filter(config),
self.build_audio_filter(config),
config,
)
@staticmethod
def resolve_clip_speed(
clip_config: dict,
global_speed: float = DEFAULT_SPEED,
) -> float:
"""从 clip config 中解析 playback_speed,0 或缺失则使用全局速度."""
return _resolve_clip_speed_base(clip_config, global_speed)