Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 57d45c3219 | |||
| fbf3c5288e | |||
| c8163cbadc |
@@ -12,7 +12,6 @@
|
|||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import json
|
|
||||||
import logging
|
import logging
|
||||||
from typing import Any, Dict, List, Optional
|
from typing import Any, Dict, List, Optional
|
||||||
|
|
||||||
|
|||||||
@@ -9,12 +9,11 @@
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
from typing import Optional
|
|
||||||
|
|
||||||
|
from packages.domain.chroma_key_config import CHROMA_KEY_PRESETS # noqa: F401
|
||||||
|
from packages.domain.chroma_key_config import apply_chroma_key_if_needed # noqa: F401
|
||||||
from packages.domain.chroma_key_config import (
|
from packages.domain.chroma_key_config import (
|
||||||
CHROMA_KEY_PRESETS,
|
|
||||||
ChromaKeyConfig,
|
ChromaKeyConfig,
|
||||||
apply_chroma_key_if_needed,
|
|
||||||
)
|
)
|
||||||
from packages.domain.chroma_key_config import ( # noqa: F401 — 向后兼容
|
from packages.domain.chroma_key_config import ( # noqa: F401 — 向后兼容
|
||||||
build_chromakey_filter as _build_chromakey_filter_base,
|
build_chromakey_filter as _build_chromakey_filter_base,
|
||||||
|
|||||||
@@ -195,17 +195,3 @@ class ColorGradeEngine:
|
|||||||
|
|
||||||
|
|
||||||
# ── 便捷函数 ──────────────────────────────────────────────────────────────────
|
# ── 便捷函数 ──────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
|
||||||
def get_preset_names() -> list[tuple[str, str]]:
|
|
||||||
"""获取所有预设名称列表.
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
[(preset_key, display_name), ...]
|
|
||||||
"""
|
|
||||||
return [(key, PRESET_DISPLAY_NAMES.get(key, key)) for key in PRESET_PARAMS.keys()]
|
|
||||||
|
|
||||||
|
|
||||||
def get_preset_params(preset: str) -> dict[str, float] | None:
|
|
||||||
"""获取指定预设的参数."""
|
|
||||||
return PRESET_PARAMS.get(preset)
|
|
||||||
|
|||||||
@@ -22,11 +22,9 @@ from shared.ffmpeg_utils import ( # noqa: F401
|
|||||||
|
|
||||||
# xfade 转场纯逻辑已抽离到 domain 层,这里 re-export 保持向后兼容
|
# xfade 转场纯逻辑已抽离到 domain 层,这里 re-export 保持向后兼容
|
||||||
from packages.domain.xfade_builder import DEFAULT_TRANSITION_DURATION as _default_transition_duration_base # noqa: F401
|
from packages.domain.xfade_builder import DEFAULT_TRANSITION_DURATION as _default_transition_duration_base # noqa: F401
|
||||||
from packages.domain.xfade_builder import (
|
from packages.domain.xfade_builder import SUPPORTED_TRANSITIONS # noqa: F401
|
||||||
SUPPORTED_TRANSITIONS,
|
from packages.domain.xfade_builder import XFADE_TRANSITION_MAP # noqa: F401
|
||||||
XFADE_TRANSITION_MAP,
|
from packages.domain.xfade_builder import XFade_TRANSITION_NAMES # noqa: F401
|
||||||
XFade_TRANSITION_NAMES,
|
|
||||||
)
|
|
||||||
from packages.domain.xfade_builder import build_xfade_filter_chain as _build_xfade_filter_chain_base
|
from packages.domain.xfade_builder import build_xfade_filter_chain as _build_xfade_filter_chain_base
|
||||||
from packages.domain.xfade_builder import chain_filters as _chain_filters_base
|
from packages.domain.xfade_builder import chain_filters as _chain_filters_base
|
||||||
from packages.domain.xfade_builder import resolve_xfade_transition as _resolve_xfade_transition_base
|
from packages.domain.xfade_builder import resolve_xfade_transition as _resolve_xfade_transition_base
|
||||||
|
|||||||
@@ -9,16 +9,21 @@ from __future__ import annotations
|
|||||||
|
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
|
# isort: off
|
||||||
from packages.domain.noise_reduction_config import (
|
from packages.domain.noise_reduction_config import (
|
||||||
NoiseReductionConfig,
|
NoiseReductionConfig,
|
||||||
NoiseReductionLevel,
|
NoiseReductionLevel, # noqa: F401
|
||||||
)
|
)
|
||||||
from packages.domain.noise_reduction_config import (
|
from packages.domain.noise_reduction_config import (
|
||||||
apply_noise_reduction_if_needed as _apply_noise_reduction_if_needed_base,
|
apply_noise_reduction_if_needed as _apply_noise_reduction_if_needed_base,
|
||||||
)
|
)
|
||||||
from packages.domain.noise_reduction_config import build_afftdn_filter as _build_afftdn_filter_base # noqa: F401 — 向后兼容
|
from packages.domain.noise_reduction_config import (
|
||||||
|
build_afftdn_filter as _build_afftdn_filter_base,
|
||||||
|
) # noqa: F401 — 向后兼容
|
||||||
from packages.domain.noise_reduction_config import build_arnndn_filter as _build_arnndn_filter_base
|
from packages.domain.noise_reduction_config import build_arnndn_filter as _build_arnndn_filter_base
|
||||||
|
|
||||||
|
# isort: on
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -18,22 +18,13 @@ from pathlib import Path
|
|||||||
|
|
||||||
# 向后兼容:POSITION_BOTTOM_CENTER 也从 pip_config 再导出
|
# 向后兼容:POSITION_BOTTOM_CENTER 也从 pip_config 再导出
|
||||||
from packages.domain.pip_config import POSITION_BOTTOM_CENTER # noqa: E402, F401
|
from packages.domain.pip_config import POSITION_BOTTOM_CENTER # noqa: E402, F401
|
||||||
|
from packages.domain.pip_config import PiPConfig # noqa: F401
|
||||||
from packages.domain.pip_config import (
|
from packages.domain.pip_config import (
|
||||||
ANIMATION_FADE,
|
ANIMATION_FADE,
|
||||||
ANIMATION_SCALE,
|
|
||||||
ANIMATION_SLIDE_BOTTOM,
|
ANIMATION_SLIDE_BOTTOM,
|
||||||
ANIMATION_SLIDE_LEFT,
|
ANIMATION_SLIDE_LEFT,
|
||||||
ANIMATION_SLIDE_RIGHT,
|
ANIMATION_SLIDE_RIGHT,
|
||||||
ANIMATION_SLIDE_TOP,
|
ANIMATION_SLIDE_TOP,
|
||||||
POSITION_BOTTOM_LEFT,
|
|
||||||
POSITION_BOTTOM_RIGHT,
|
|
||||||
POSITION_CENTER,
|
|
||||||
POSITION_CENTER_LEFT,
|
|
||||||
POSITION_CENTER_RIGHT,
|
|
||||||
POSITION_TOP_CENTER,
|
|
||||||
POSITION_TOP_LEFT,
|
|
||||||
POSITION_TOP_RIGHT,
|
|
||||||
PiPConfig,
|
|
||||||
PiPLayerConfig,
|
PiPLayerConfig,
|
||||||
)
|
)
|
||||||
from packages.domain.pip_config import ( # noqa: F401 — 向后兼容:保留模块级导出
|
from packages.domain.pip_config import ( # noqa: F401 — 向后兼容:保留模块级导出
|
||||||
|
|||||||
@@ -13,9 +13,6 @@ from pathlib import Path
|
|||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
from packages.domain.ass_subtitle_builder import (
|
from packages.domain.ass_subtitle_builder import (
|
||||||
TITLE_MARGIN_BOTTOM,
|
|
||||||
TITLE_MARGIN_SIDE,
|
|
||||||
TITLE_MARGIN_TOP,
|
|
||||||
build_ass_content,
|
build_ass_content,
|
||||||
)
|
)
|
||||||
from packages.domain.ass_subtitle_builder import build_ass_style as _build_ass_style_base # noqa: F401 — 向后兼容
|
from packages.domain.ass_subtitle_builder import build_ass_style as _build_ass_style_base # noqa: F401 — 向后兼容
|
||||||
|
|||||||
@@ -14,16 +14,20 @@ import logging
|
|||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
|
# isort: off
|
||||||
from packages.domain.sticker_config import (
|
from packages.domain.sticker_config import (
|
||||||
POSITION_PRESETS,
|
POSITION_PRESETS, # noqa: F401
|
||||||
STICKER_CATEGORIES,
|
STICKER_CATEGORIES, # noqa: F401
|
||||||
ImageStickerConfig,
|
ImageStickerConfig,
|
||||||
StickerOverlayResult,
|
StickerOverlayResult,
|
||||||
TextStickerConfig,
|
TextStickerConfig,
|
||||||
)
|
)
|
||||||
from packages.domain.sticker_config import get_sticker_categories as _get_sticker_categories_base # noqa: F401 向后兼容导出
|
from packages.domain.sticker_config import (
|
||||||
|
get_sticker_categories as _get_sticker_categories_base,
|
||||||
|
) # noqa: F401 向后兼容导出
|
||||||
from packages.domain.sticker_config import parse_stickers_from_config as _parse_stickers_base
|
from packages.domain.sticker_config import parse_stickers_from_config as _parse_stickers_base
|
||||||
from packages.domain.sticker_config import (
|
from packages.domain.sticker_config import (
|
||||||
|
# isort: on
|
||||||
resolve_sticker_position,
|
resolve_sticker_position,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -25,28 +25,22 @@ from __future__ import annotations
|
|||||||
|
|
||||||
import logging
|
import logging
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
from video_processing.path_security import PathSecurityError, is_in_allowed_dirs, safe_resolve_path
|
from video_processing.path_security import PathSecurityError, is_in_allowed_dirs, safe_resolve_path
|
||||||
|
|
||||||
from packages.domain.subtitle_style import (
|
from packages.domain.subtitle_style import (
|
||||||
ALLOWED_SUBTITLE_EXTENSIONS,
|
ALLOWED_SUBTITLE_EXTENSIONS,
|
||||||
DEFAULT_COLOR,
|
|
||||||
DEFAULT_FONT,
|
|
||||||
DEFAULT_FONT_SIZE,
|
DEFAULT_FONT_SIZE,
|
||||||
DEFAULT_MAX_CHARS_PER_LINE,
|
|
||||||
DEFAULT_POSITION,
|
DEFAULT_POSITION,
|
||||||
DEFAULT_STROKE_COLOR,
|
|
||||||
DEFAULT_STROKE_WIDTH,
|
|
||||||
POSITION_ALIASES,
|
|
||||||
POSITION_ALIGNMENT,
|
|
||||||
SubtitleSegment,
|
SubtitleSegment,
|
||||||
SubtitleStyle,
|
SubtitleStyle,
|
||||||
)
|
)
|
||||||
from packages.domain.subtitle_style import escape_ass_text as _escape_ass_text # noqa: F401 向后兼容导出
|
from packages.domain.subtitle_style import escape_ass_text as _escape_ass_text # noqa: F401 向后兼容导出
|
||||||
from packages.domain.subtitle_style import format_ass_time as _format_ass_time
|
from packages.domain.subtitle_style import format_ass_time as _format_ass_time
|
||||||
from packages.domain.subtitle_style import hex_to_ass_bgr as _hex_to_ass_bgr
|
from packages.domain.subtitle_style import hex_to_ass_bgr as _hex_to_ass_bgr # noqa: F401
|
||||||
from packages.domain.subtitle_style import hex_to_ass_color as _hex_to_ass_color
|
from packages.domain.subtitle_style import hex_to_ass_color as _hex_to_ass_color # noqa: F401
|
||||||
from packages.domain.subtitle_style import opacity_to_ass_alpha as _opacity_to_ass_alpha
|
from packages.domain.subtitle_style import opacity_to_ass_alpha as _opacity_to_ass_alpha # noqa: F401
|
||||||
from packages.domain.subtitle_style import wrap_text as _wrap_text
|
from packages.domain.subtitle_style import wrap_text as _wrap_text
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|||||||
@@ -15,16 +15,14 @@ from __future__ import annotations
|
|||||||
import logging
|
import logging
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
|
from packages.domain.trim_config import MIN_TRIM_DURATION # noqa: F401
|
||||||
|
from packages.domain.trim_config import extract_trim_from_clip_config # noqa: F401
|
||||||
from packages.domain.trim_config import (
|
from packages.domain.trim_config import (
|
||||||
MIN_TRIM_DURATION,
|
|
||||||
TrimConfig,
|
TrimConfig,
|
||||||
TrimSegment,
|
TrimSegment,
|
||||||
)
|
)
|
||||||
from packages.domain.trim_config import build_audio_trim_filter as _build_audio_trim_filter # noqa: F401 — 向后兼容
|
from packages.domain.trim_config import build_audio_trim_filter as _build_audio_trim_filter # noqa: F401 — 向后兼容
|
||||||
from packages.domain.trim_config import build_video_trim_filter as _build_video_trim_filter
|
from packages.domain.trim_config import build_video_trim_filter as _build_video_trim_filter
|
||||||
from packages.domain.trim_config import (
|
|
||||||
extract_trim_from_clip_config,
|
|
||||||
)
|
|
||||||
from packages.domain.trim_config import parse_segments_from_config as _parse_segments_from_config
|
from packages.domain.trim_config import parse_segments_from_config as _parse_segments_from_config
|
||||||
from packages.domain.trim_config import resolve_segments as _resolve_segments
|
from packages.domain.trim_config import resolve_segments as _resolve_segments
|
||||||
|
|
||||||
|
|||||||
@@ -53,7 +53,6 @@ from video_processing.tts_engine import TtsEngine
|
|||||||
from video_processing.watermark_engine import WatermarkConfig, WatermarkEngine
|
from video_processing.watermark_engine import WatermarkConfig, WatermarkEngine
|
||||||
|
|
||||||
from packages.domain.render_layer_utils import LAYER_Z_INDEX as _IMPORTED_LAYER_Z_INDEX
|
from packages.domain.render_layer_utils import LAYER_Z_INDEX as _IMPORTED_LAYER_Z_INDEX
|
||||||
from packages.domain.render_layer_utils import can_pass_through as _can_pass_through_pure
|
|
||||||
from packages.domain.render_layer_utils import clip_adjusted_duration as _clip_adjusted_duration_pure
|
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
|
from packages.domain.render_layer_utils import clip_effective_duration as _clip_effective_duration_pure
|
||||||
from packages.domain.render_layer_utils import clip_playback_speed as _clip_playback_speed_pure
|
from packages.domain.render_layer_utils import clip_playback_speed as _clip_playback_speed_pure
|
||||||
|
|||||||
@@ -14,10 +14,9 @@
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
from typing import Any
|
|
||||||
|
|
||||||
|
from packages.domain.watermark_config import WATERMARK_POSITIONS # noqa: F401
|
||||||
from packages.domain.watermark_config import (
|
from packages.domain.watermark_config import (
|
||||||
WATERMARK_POSITIONS,
|
|
||||||
WatermarkConfig,
|
WatermarkConfig,
|
||||||
)
|
)
|
||||||
from packages.domain.watermark_config import ( # noqa: F401 — 向后兼容
|
from packages.domain.watermark_config import ( # noqa: F401 — 向后兼容
|
||||||
|
|||||||
@@ -186,7 +186,7 @@ class PiPConfig:
|
|||||||
"""最大 z_index."""
|
"""最大 z_index."""
|
||||||
if not self.layers:
|
if not self.layers:
|
||||||
return 0
|
return 0
|
||||||
return max(l.z_index for l in self.layers)
|
return max(layer.z_index for layer in self.layers)
|
||||||
|
|
||||||
|
|
||||||
# ── 纯逻辑工具函数 ───────────────────────────────────────────────────────────
|
# ── 纯逻辑工具函数 ───────────────────────────────────────────────────────────
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from dataclasses import dataclass, field
|
from dataclasses import dataclass
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
# ── 常量 ──────────────────────────────────────────────────────────────────────
|
# ── 常量 ──────────────────────────────────────────────────────────────────────
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
from dataclasses import dataclass, field
|
from dataclasses import dataclass
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
from dataclasses import dataclass, field
|
from dataclasses import dataclass
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ class TestConstants:
|
|||||||
|
|
||||||
def test_preset_params_complete(self):
|
def test_preset_params_complete(self):
|
||||||
assert set(PRESET_PARAMS.keys()) == VALID_PRESETS
|
assert set(PRESET_PARAMS.keys()) == VALID_PRESETS
|
||||||
for preset, params in PRESET_PARAMS.items():
|
for _preset, params in PRESET_PARAMS.items():
|
||||||
assert set(params.keys()) == set(ALL_PARAM_KEYS)
|
assert set(params.keys()) == set(ALL_PARAM_KEYS)
|
||||||
|
|
||||||
def test_default_params_keys(self):
|
def test_default_params_keys(self):
|
||||||
@@ -54,7 +54,7 @@ class TestConstants:
|
|||||||
assert min_val <= DEFAULT_PARAMS[key] <= max_val
|
assert min_val <= DEFAULT_PARAMS[key] <= max_val
|
||||||
|
|
||||||
def test_all_presets_within_ranges(self):
|
def test_all_presets_within_ranges(self):
|
||||||
for preset, params in PRESET_PARAMS.items():
|
for _preset, params in PRESET_PARAMS.items():
|
||||||
for key in ALL_PARAM_KEYS:
|
for key in ALL_PARAM_KEYS:
|
||||||
min_val, max_val = PARAM_RANGES[key]
|
min_val, max_val = PARAM_RANGES[key]
|
||||||
assert min_val <= params[key] <= max_val, f"{preset}.{key}={params[key]} out of range"
|
assert min_val <= params[key] <= max_val, f"{preset}.{key}={params[key]} out of range"
|
||||||
|
|||||||
@@ -208,7 +208,7 @@ class TestPiPConfigFromDict:
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
assert cfg.layer_count == 3
|
assert cfg.layer_count == 3
|
||||||
assert [l.source for l in cfg.layers] == ["bottom", "mid", "top"]
|
assert [layer.source for layer in cfg.layers] == ["bottom", "mid", "top"]
|
||||||
|
|
||||||
def test_invalid_layer_skipped(self):
|
def test_invalid_layer_skipped(self):
|
||||||
cfg = PiPConfig.from_dict(
|
cfg = PiPConfig.from_dict(
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ class TestConstants:
|
|||||||
assert len(POSITION_PRESETS) == 9
|
assert len(POSITION_PRESETS) == 9
|
||||||
|
|
||||||
def test_position_presets_normalized(self):
|
def test_position_presets_normalized(self):
|
||||||
for name, (x, y) in POSITION_PRESETS.items():
|
for _name, (x, y) in POSITION_PRESETS.items():
|
||||||
assert 0.0 <= x <= 1.0
|
assert 0.0 <= x <= 1.0
|
||||||
assert 0.0 <= y <= 1.0
|
assert 0.0 <= y <= 1.0
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user