From c6bc8170d1eec4afdb480dea409524c3d9c3838b Mon Sep 17 00:00:00 2001 From: CI Bot Date: Tue, 14 Jul 2026 09:35:53 +0800 Subject: [PATCH] =?UTF-8?q?chore:=20rebase=E5=88=B0develop=20+=20=E6=A0=BC?= =?UTF-8?q?=E5=BC=8F=E5=8C=96=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/api/app/api/routes/tts.py | 2 +- apps/worker/video_processing/tts_engine.py | 8 +--- .../unified_render_service.py | 5 +-- packages/adapters/tts/mock_tts_service.py | 4 +- packages/domain/voice_presets.py | 7 +--- tests/unit/test_tts_voiceover.py | 41 ++++++++----------- 6 files changed, 25 insertions(+), 42 deletions(-) diff --git a/apps/api/app/api/routes/tts.py b/apps/api/app/api/routes/tts.py index bb7f04d2b..2a01f06b2 100755 --- a/apps/api/app/api/routes/tts.py +++ b/apps/api/app/api/routes/tts.py @@ -46,8 +46,8 @@ from packages.application.voice_library.use_cases import ( CreateVoiceLibraryUseCase, QuotaExceededError, ) -from packages.ports.user_repository import UserRepository from packages.domain.voice_presets import list_voices +from packages.ports.user_repository import UserRepository logger = logging.getLogger(__name__) diff --git a/apps/worker/video_processing/tts_engine.py b/apps/worker/video_processing/tts_engine.py index 102e7c375..be1e1f7d7 100755 --- a/apps/worker/video_processing/tts_engine.py +++ b/apps/worker/video_processing/tts_engine.py @@ -244,9 +244,7 @@ class TtsEngine: # 音量调整 # 用 adelay 延迟到字幕开始时间 delay_ms = int(max(0, int(seg.start_time * 1000))) - filter_parts.append( - f"[{i}:a]adelay={delay_ms}:all=1,volume=0.8[{seg_label}]" - ) + filter_parts.append(f"[{i}:a]adelay={delay_ms}:all=1,volume=0.8[{seg_label}]") delay_labels.append(f"[{seg_label}]") if not delay_labels: @@ -262,9 +260,7 @@ class TtsEngine: filter_parts.append(f"{delay_labels[0]}[{tts_label}]") else: # 多个片段 amix 叠加 - filter_parts.append( - f"{mix_inputs}amix=inputs={n_inputs}:duration=longest[{tts_label}]" - ) + filter_parts.append(f"{mix_inputs}amix=inputs={n_inputs}:duration=longest[{tts_label}]") return ";".join(filter_parts), audio_files diff --git a/apps/worker/video_processing/unified_render_service.py b/apps/worker/video_processing/unified_render_service.py index 154394e83..379626b36 100755 --- a/apps/worker/video_processing/unified_render_service.py +++ b/apps/worker/video_processing/unified_render_service.py @@ -44,6 +44,7 @@ from video_processing.render_audio import RenderContext, merge_audio_video, mix_ from video_processing.render_subtitles import generate_ass_subtitles from video_processing.subtitle_generator import generate_ass_from_timeline from video_processing.tts_engine import TtsEngine + from packages.domain.tts_config import TtsConfig logger = logging.getLogger(__name__) @@ -534,9 +535,7 @@ class UnifiedRenderService: tts_engine = TtsEngine(tts_service, self.work_dir / "tts") # 整段配音模式 - result = tts_engine.generate_full_voiceover( - tts_config, total_duration=video_duration - ) + result = tts_engine.generate_full_voiceover(tts_config, total_duration=video_duration) if not result.success or not result.segments: logger.warning("TTS 配音生成失败,跳过: %s", result.error_message) diff --git a/packages/adapters/tts/mock_tts_service.py b/packages/adapters/tts/mock_tts_service.py index 40b9afeac..185c3344c 100755 --- a/packages/adapters/tts/mock_tts_service.py +++ b/packages/adapters/tts/mock_tts_service.py @@ -168,9 +168,7 @@ class MockTtsService(TtsService): filter_parts = [] # 主音 + 轻微频率调制 - filter_parts.append( - f"sine=frequency={base_freq}:duration={duration}:sample_rate={sample_rate}" - ) + filter_parts.append(f"sine=frequency={base_freq}:duration={duration}:sample_rate={sample_rate}") # 颤音效果 filter_parts.append(f"tremolo=f={tremolo_freq}:d={tremolo_depth}") diff --git a/packages/domain/voice_presets.py b/packages/domain/voice_presets.py index 6f16453af..857683625 100755 --- a/packages/domain/voice_presets.py +++ b/packages/domain/voice_presets.py @@ -212,12 +212,7 @@ def list_voices( if keyword: kw = keyword.lower() - result = [ - v for v in result - if kw in v.name.lower() - or kw in v.description.lower() - or kw in v.voice_id.lower() - ] + result = [v for v in result if kw in v.name.lower() or kw in v.description.lower() or kw in v.voice_id.lower()] return result diff --git a/tests/unit/test_tts_voiceover.py b/tests/unit/test_tts_voiceover.py index 091b0b3b4..3c6d265b3 100755 --- a/tests/unit/test_tts_voiceover.py +++ b/tests/unit/test_tts_voiceover.py @@ -4,6 +4,9 @@ from pathlib import Path import pytest +from apps.worker.video_processing.tts_engine import TtsEngine, VoiceoverResult, VoiceoverSegment +from packages.adapters.tts.mock_tts_service import MockTtsService +from packages.domain.tts_config import TtsConfig from packages.domain.voice_presets import ( VoiceGender, VoicePreset, @@ -12,11 +15,7 @@ from packages.domain.voice_presets import ( get_voice, list_voices, ) -from packages.domain.tts_config import TtsConfig from packages.ports.tts_service import TtsError, TtsService -from packages.adapters.tts.mock_tts_service import MockTtsService -from apps.worker.video_processing.tts_engine import TtsEngine, VoiceoverResult, VoiceoverSegment - # ─── TtsConfig 配置解析 ──────────────────────────────────── @@ -75,16 +74,18 @@ class TestTtsConfig: assert config.volume == 1.0 def test_parse_invalid_types(self): - config = TtsConfig.parse({ - "enabled": True, - "speed": "fast", - "pitch": "high", - "volume": "loud", - "voice_id": 123, - "text": 456, - "align_mode": "invalid", - "overlap_mode": "invalid", - }) + config = TtsConfig.parse( + { + "enabled": True, + "speed": "fast", + "pitch": "high", + "volume": "loud", + "voice_id": 123, + "text": 456, + "align_mode": "invalid", + "overlap_mode": "invalid", + } + ) assert config.speed == 1.0 assert config.pitch == 0.0 assert config.volume == 0.8 @@ -178,9 +179,7 @@ class TestMockTtsService: voices = ["female_warm", "male_stable", "child_cute"] for vid in voices: output = tmp_path / f"{vid}.wav" - result = self.service.synthesize( - "测试", voice_id=vid, output_path=output - ) + result = self.service.synthesize("测试", voice_id=vid, output_path=output) assert result.exists() def test_synthesize_speed_faster(self, tmp_path): @@ -199,9 +198,7 @@ class TestMockTtsService: def test_synthesize_pitch_changes(self, tmp_path): output = tmp_path / "high_pitch.wav" - result = self.service.synthesize( - "测试", voice_id="female_warm", pitch=6, output_path=output - ) + result = self.service.synthesize("测试", voice_id="female_warm", pitch=6, output_path=output) assert result.exists() def test_synthesize_empty_text_raises(self): @@ -229,9 +226,7 @@ class TestMockTtsService: def test_synthesize_unknown_voice_fallback(self, tmp_path): output = tmp_path / "fallback.wav" # 未知音色应该 fallback 到默认音色,不报错 - result = self.service.synthesize( - "测试", voice_id="unknown_voice", output_path=output - ) + result = self.service.synthesize("测试", voice_id="unknown_voice", output_path=output) assert result.exists()