feat: 绿幕抠像 + 音频降噪引擎(Chroma Key + Noise Reduction) (#303)
CI/CD Pipeline / Validate Code Quality And Tests (push) Successful in 39s
CI/CD Pipeline / Unit Tests (push) Successful in 1m22s
CI/CD Pipeline / Frontend Lint (push) Successful in 1m22s
CI/CD Pipeline / Build Production Runtime Images (push) Has been skipped
CI/CD Pipeline / Deploy Production (push) Has been skipped
CI/CD Pipeline / Production Browser E2E (push) Has been skipped
CI/CD Pipeline / Integration Tests (push) Failing after 1m13s
CI/CD Pipeline / Build & Push Staging (Watchtower auto-deploy) (push) Has been cancelled
CI/CD Pipeline / Staging E2E Tests (push) Has been cancelled
CI/CD Pipeline / Staging API Integration Tests (push) Has been cancelled
CI/CD Pipeline / Validate Code Quality And Tests (push) Successful in 39s
CI/CD Pipeline / Unit Tests (push) Successful in 1m22s
CI/CD Pipeline / Frontend Lint (push) Successful in 1m22s
CI/CD Pipeline / Build Production Runtime Images (push) Has been skipped
CI/CD Pipeline / Deploy Production (push) Has been skipped
CI/CD Pipeline / Production Browser E2E (push) Has been skipped
CI/CD Pipeline / Integration Tests (push) Failing after 1m13s
CI/CD Pipeline / Build & Push Staging (Watchtower auto-deploy) (push) Has been cancelled
CI/CD Pipeline / Staging E2E Tests (push) Has been cancelled
CI/CD Pipeline / Staging API Integration Tests (push) Has been cancelled
This commit was merged in pull request #303.
This commit is contained in:
@@ -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,
|
||||
@@ -333,9 +334,14 @@ class UnifiedRenderService:
|
||||
"[unified-render] pass-through BGM mix failed, skipping: plan_id=%s", self.plan.id
|
||||
)
|
||||
else:
|
||||
ctx = RenderContext(work_dir=self.work_dir, plan_id=self.plan.id)
|
||||
config = self.plan.config or {}
|
||||
bgm_config = config.get("bgm", {}) or {}
|
||||
noise_reduction_config = config.get("audio_noise_reduction")
|
||||
ctx = RenderContext(
|
||||
work_dir=self.work_dir,
|
||||
plan_id=self.plan.id,
|
||||
noise_reduction_config=noise_reduction_config,
|
||||
)
|
||||
audio_path = mix_audio(
|
||||
ctx,
|
||||
layers,
|
||||
@@ -975,6 +981,18 @@ class UnifiedRenderService:
|
||||
grade_filter = ColorGradeEngine.build_filter(color_grade)
|
||||
if grade_filter:
|
||||
filters.append(grade_filter)
|
||||
# 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]")]
|
||||
filters.append(ck_filter_part)
|
||||
except Exception as e:
|
||||
logger.warning("[unified-render] chroma key 直通模式应用失败,跳过: %s", e)
|
||||
|
||||
filters.append("setpts=PTS-STARTPTS")
|
||||
filters.append(f"fps={self.output_fps}")
|
||||
@@ -1015,6 +1033,24 @@ class UnifiedRenderService:
|
||||
# background 以外的视频素材,默认带音频
|
||||
has_audio = role != "background"
|
||||
if has_audio:
|
||||
# 检查是否需要音频降噪
|
||||
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]")]
|
||||
af_parts.append(nr_filter_part)
|
||||
except Exception as e:
|
||||
logger.warning("[unified-render] 直通模式音频降噪应用失败,跳过: %s", e)
|
||||
|
||||
if af_parts:
|
||||
command.extend(["-af", ",".join(af_parts)])
|
||||
|
||||
command.extend(["-c:a", "aac", "-b:a", "128k"])
|
||||
|
||||
# 统一截断时长(同时作用于视频和音频)
|
||||
@@ -1258,6 +1294,19 @@ class UnifiedRenderService:
|
||||
grade_filter = ColorGradeEngine.build_filter(color_grade)
|
||||
if grade_filter:
|
||||
filters.append(grade_filter)
|
||||
# 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]")]
|
||||
filters.append(ck_filter_part)
|
||||
except Exception as e:
|
||||
logger.warning("[unified-render] chroma key 应用失败,跳过 clip=%s: %s", clip.clip_id, e)
|
||||
|
||||
filters.append("setpts=PTS-STARTPTS")
|
||||
filters.append(f"fps={self.output_fps}")
|
||||
|
||||
Reference in New Issue
Block a user