chore: black + isort 格式化
CI/CD Pipeline / Frontend Lint (pull_request) Successful in 1m10s
CI/CD Pipeline / Unit Tests (pull_request) Successful in 1m17s
CI/CD Pipeline / Validate Code Quality And Tests (pull_request) Successful in 3m16s
CI/CD Pipeline / Build & Push Staging (Watchtower auto-deploy) (pull_request) Has been skipped
CI/CD Pipeline / Build Production Runtime Images (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 / Deploy Production (pull_request) Has been skipped
CI/CD Pipeline / Production Browser E2E (pull_request) Has been skipped
CI/CD Pipeline / Integration Tests (pull_request) Failing after 1m36s

This commit is contained in:
xiaoxia-bot
2026-07-14 10:35:46 +08:00
parent 251201c2c8
commit 76d82322fe
5 changed files with 31 additions and 62 deletions
@@ -186,13 +186,7 @@ class ChromaKeyEngine:
# 同时稍微提升红和蓝来补偿色偏
r_gain = 1.0 + spill * 0.15
b_gain = 1.0 + spill * 0.15
parts.append(
f"colorchannelmixer="
f"rr={r_gain}:"
f"gg={g_gain}:"
f"bb={b_gain}:"
f"aa=1"
)
parts.append(f"colorchannelmixer=" f"rr={r_gain}:" f"gg={g_gain}:" f"bb={b_gain}:" f"aa=1")
filter_str = f"{input_label}{','.join(parts)}{output_label}"
return filter_str
@@ -217,11 +211,7 @@ class ChromaKeyEngine:
similarity = self.config.similarity
blend = self.config.blend
return (
f"{input_label}"
f"chromakey=color={color}:similarity={similarity}:blend={blend}"
f"{output_label}"
)
return f"{input_label}" f"chromakey=color={color}:similarity={similarity}:blend={blend}" f"{output_label}"
def apply_chroma_key_if_needed(
@@ -29,9 +29,9 @@ logger = logging.getLogger(__name__)
class NoiseReductionLevel(str, Enum):
"""降噪等级预设。"""
LOW = "low" # 轻度降噪,保留细节,适合轻微背景噪音
LOW = "low" # 轻度降噪,保留细节,适合轻微背景噪音
MEDIUM = "medium" # 中度降噪,平衡效果和音质
HIGH = "high" # 高度降噪,适合嘈杂环境,可能轻微影响音质
HIGH = "high" # 高度降噪,适合嘈杂环境,可能轻微影响音质
CUSTOM = "custom" # 自定义参数
@@ -39,9 +39,9 @@ class NoiseReductionLevel(str, Enum):
# 值越大(越接近 0),降噪越强;值越小(越负),降噪越弱
_LEVEL_PARAMS = {
NoiseReductionLevel.LOW: {
"nf": -35, # 噪音阈值(dB),越负越保守
"tn": -10, # 噪音频谱平滑度
"tr": 50, # 时间分辨率(ms
"nf": -35, # 噪音阈值(dB),越负越保守
"tn": -10, # 噪音频谱平滑度
"tr": 50, # 时间分辨率(ms
},
NoiseReductionLevel.MEDIUM: {
"nf": -25,
+1 -1
View File
@@ -152,7 +152,7 @@ def _apply_noise_reduction_if_needed(ctx: RenderContext, audio_path: Path) -> Pa
engine = NoiseReductionEngine(config)
filter_str = engine.build_filter("[0:a]", "[out]")
# 提取滤镜部分(不带标签)
filter_part = filter_str[len("[0:a]"):-len("[out]")]
filter_part = filter_str[len("[0:a]") : -len("[out]")]
nr_output_path = audio_path.with_name(f"{audio_path.stem}_nr.aac")
command = [
@@ -28,6 +28,7 @@ from dataclasses import dataclass, field
from pathlib import Path
from typing import Any
from video_processing.chroma_key_engine import apply_chroma_key_if_needed
from video_processing.color_grade_engine import ColorGradeConfig, ColorGradeEngine
from video_processing.ffmpeg_utils import (
DEFAULT_FPS,
@@ -47,7 +48,6 @@ from video_processing.subtitle_generator import generate_ass_from_timeline
from video_processing.tts_engine import TtsEngine
from packages.domain.tts_config import TtsConfig
from video_processing.chroma_key_engine import apply_chroma_key_if_needed
logger = logging.getLogger(__name__)
@@ -856,11 +856,12 @@ class UnifiedRenderService:
# chroma key 绿幕抠像
try:
from video_processing.chroma_key_engine import ChromaKeyConfig, ChromaKeyEngine
ck_config = ChromaKeyConfig.from_dict(clip.config.get("chroma_key"))
if ck_config.has_effect():
ck_engine = ChromaKeyEngine(ck_config)
ck_full = ck_engine.build_filter("[in]", "[out]")
ck_filter_part = ck_full[len("[in]"):-len("[out]")]
ck_filter_part = ck_full[len("[in]") : -len("[out]")]
filters.append(ck_filter_part)
except Exception as e:
logger.warning("[unified-render] chroma key 直通模式应用失败,跳过: %s", e)
@@ -908,12 +909,13 @@ class UnifiedRenderService:
af_parts: list[str] = []
try:
from video_processing.noise_reduction_engine import NoiseReductionConfig, NoiseReductionEngine
plan_config = getattr(self.plan, "config", {}) or {}
nr_config = NoiseReductionConfig.from_dict(plan_config.get("audio_noise_reduction"))
if nr_config.has_effect():
nr_engine = NoiseReductionEngine(nr_config)
nr_full = nr_engine.build_filter("[in]", "[out]")
nr_filter_part = nr_full[len("[in]"):-len("[out]")]
nr_filter_part = nr_full[len("[in]") : -len("[out]")]
af_parts.append(nr_filter_part)
except Exception as e:
logger.warning("[unified-render] 直通模式音频降噪应用失败,跳过: %s", e)
@@ -1104,12 +1106,13 @@ class UnifiedRenderService:
# chroma key 绿幕抠像(在 scale 之后,fps 之前)
try:
from video_processing.chroma_key_engine import ChromaKeyConfig, ChromaKeyEngine
ck_config = ChromaKeyConfig.from_dict(clip.config.get("chroma_key"))
if ck_config.has_effect():
ck_engine = ChromaKeyEngine(ck_config)
# 提取滤镜部分(不带输入输出标签)
ck_full = ck_engine.build_filter("[in]", "[out]")
ck_filter_part = ck_full[len("[in]"):-len("[out]")]
ck_filter_part = ck_full[len("[in]") : -len("[out]")]
filters.append(ck_filter_part)
except Exception as e:
logger.warning("[unified-render] chroma key 应用失败,跳过 clip=%s: %s", clip.clip_id, e)
@@ -3,7 +3,6 @@
from __future__ import annotations
import pytest
from video_processing.chroma_key_engine import (
CHROMA_KEY_PRESETS,
ChromaKeyConfig,
@@ -17,7 +16,6 @@ from video_processing.noise_reduction_engine import (
apply_noise_reduction_if_needed,
)
# ═══════════════════════════════════════════════════════════════
# ChromaKeyConfig 测试
# ═══════════════════════════════════════════════════════════════
@@ -156,9 +154,7 @@ class TestChromaKeyEngine:
def test_build_filter_with_spill_suppress(self):
"""溢色抑制时增加 colorchannelmixer."""
config = ChromaKeyConfig(
enabled=True, key_color="#00FF00", similarity=0.3, blend=0.1, spill_suppress=0.5
)
config = ChromaKeyConfig(enabled=True, key_color="#00FF00", similarity=0.3, blend=0.1, spill_suppress=0.5)
engine = ChromaKeyEngine(config)
result = engine.build_filter("[v0]", "[v1]")
assert "colorkey" in result
@@ -168,9 +164,7 @@ class TestChromaKeyEngine:
def test_build_filter_no_spill_suppress(self):
"""无溢色抑制时不含 colorchannelmixer."""
config = ChromaKeyConfig(
enabled=True, key_color="#00FF00", similarity=0.3, blend=0.1, spill_suppress=0.0
)
config = ChromaKeyConfig(enabled=True, key_color="#00FF00", similarity=0.3, blend=0.1, spill_suppress=0.0)
engine = ChromaKeyEngine(config)
result = engine.build_filter("[v0]", "[v1]")
assert "colorkey" in result
@@ -238,9 +232,7 @@ class TestApplyChromaKeyIfNeeded:
def test_disabled_chroma_key(self):
"""禁用的抠像配置返回 None."""
result = apply_chroma_key_if_needed(
{"chroma_key": {"enabled": False}}, "[in]", "[out]"
)
result = apply_chroma_key_if_needed({"chroma_key": {"enabled": False}}, "[in]", "[out]")
assert result is None
def test_enabled_chroma_key(self):
@@ -320,9 +312,7 @@ class TestNoiseReductionConfig:
def test_from_dict_custom_level(self):
"""自定义降噪等级."""
config = NoiseReductionConfig.from_dict(
{"enabled": True, "level": "custom", "noise_floor": -30.0}
)
config = NoiseReductionConfig.from_dict({"enabled": True, "level": "custom", "noise_floor": -30.0})
assert config.level == NoiseReductionLevel.CUSTOM
assert config.get_effective_noise_floor() == -30.0
@@ -334,14 +324,10 @@ class TestNoiseReductionConfig:
def test_noise_floor_clamp(self):
"""noise_floor 越界自动钳制."""
# 低于最小值
config = NoiseReductionConfig.from_dict(
{"enabled": True, "level": "custom", "noise_floor": -100}
)
config = NoiseReductionConfig.from_dict({"enabled": True, "level": "custom", "noise_floor": -100})
assert config.noise_floor == -60.0
# 高于最大值
config = NoiseReductionConfig.from_dict(
{"enabled": True, "level": "custom", "noise_floor": 0}
)
config = NoiseReductionConfig.from_dict({"enabled": True, "level": "custom", "noise_floor": 0})
assert config.noise_floor == -5.0
def test_voice_enhance(self):
@@ -392,9 +378,7 @@ class TestNoiseReductionEngine:
def test_custom_level(self):
"""自定义降噪等级."""
config = NoiseReductionConfig(
enabled=True, level=NoiseReductionLevel.CUSTOM, noise_floor=-40.0
)
config = NoiseReductionConfig(enabled=True, level=NoiseReductionLevel.CUSTOM, noise_floor=-40.0)
engine = NoiseReductionEngine(config)
result = engine.build_filter("[in]", "[out]")
assert "nf=-40" in result
@@ -452,9 +436,7 @@ class TestApplyNoiseReductionIfNeeded:
def test_enabled_config(self):
"""启用配置返回滤镜字符串."""
result = apply_noise_reduction_if_needed(
{"enabled": True, "level": "medium"}, "[a0]", "[nr0]"
)
result = apply_noise_reduction_if_needed({"enabled": True, "level": "medium"}, "[a0]", "[nr0]")
assert result is not None
assert "afftdn" in result
assert "[a0]" in result
@@ -462,9 +444,7 @@ class TestApplyNoiseReductionIfNeeded:
def test_invalid_config_degrades(self):
"""无效配置不崩溃."""
result = apply_noise_reduction_if_needed(
{"enabled": True, "level": 12345}, "[in]", "[out]"
)
result = apply_noise_reduction_if_needed({"enabled": True, "level": 12345}, "[in]", "[out]")
# 不抛异常,可能返回 None 或有效结果
assert result is None or isinstance(result, str)
@@ -517,18 +497,16 @@ class TestParameterBoundaries:
@pytest.mark.parametrize(
"similarity,expected",
[
(0.0, 0.01), # 低于最小值 → 钳制到 min
(0.01, 0.01), # 最小值
(0.5, 0.5), # 中间值
(1.0, 1.0), # 最大值
(2.0, 1.0), # 超过最大值 → 钳制到 max
(0.0, 0.01), # 低于最小值 → 钳制到 min
(0.01, 0.01), # 最小值
(0.5, 0.5), # 中间值
(1.0, 1.0), # 最大值
(2.0, 1.0), # 超过最大值 → 钳制到 max
],
)
def test_similarity_boundaries(self, similarity, expected):
"""similarity 边界值测试."""
config = ChromaKeyConfig.from_dict(
{"enabled": True, "similarity": similarity}
)
config = ChromaKeyConfig.from_dict({"enabled": True, "similarity": similarity})
assert abs(config.similarity - expected) < 0.001
@pytest.mark.parametrize(
@@ -558,7 +536,5 @@ class TestParameterBoundaries:
)
def test_noise_floor_boundaries(self, noise_floor, expected):
"""noise_floor 边界值测试."""
config = NoiseReductionConfig.from_dict(
{"enabled": True, "level": "custom", "noise_floor": noise_floor}
)
config = NoiseReductionConfig.from_dict({"enabled": True, "level": "custom", "noise_floor": noise_floor})
assert abs(config.noise_floor - expected) < 0.001