From 2cafaa94774ada1435c644ea98e6dd87b4374bb9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=94=A8=E6=88=B7CI=20Test?= Date: Sat, 11 Jul 2026 01:04:10 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20CosyVoice=20=E9=9F=B3=E8=89=B2=E5=90=8D?= =?UTF-8?q?=20v3=20=E5=90=8E=E7=BC=80=E4=BF=AE=E5=A4=8D=EF=BC=88418?= =?UTF-8?q?=E9=94=99=E8=AF=AF=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 根因:cosyvoice-v3.5-plus 模型要求系统音色使用 _v3 后缀命名 (如 longxiaochun_v3),旧名 longxiaochun 导致引擎返回 418 音色不支持。 修复: - config.py: 默认音色 longxiaochun → longxiaochun_v3 - preset_voices.py: 8个预置音色全部加 _v3 后缀 - cosyvoice_service.py: docstring 示例更新 - 相关测试文件 voice_id 全部同步更新 - 188个单元测试全绿 --- packages/application/cosyvoice_service.py | 2 +- packages/domain/preset_voices.py | 18 +++++++------- packages/shared/config.py | 2 +- tests/unit/test_cosyvoice_service.py | 4 +-- tests/unit/test_preset_voices.py | 30 +++++++++++------------ tests/unit/test_tts_job.py | 8 +++--- tests/unit/test_tts_segment_synthesis.py | 0 tests/unit/test_voice_clone_workflow.py | 0 8 files changed, 32 insertions(+), 32 deletions(-) mode change 100644 => 100755 packages/domain/preset_voices.py mode change 100644 => 100755 packages/shared/config.py mode change 100755 => 100644 tests/unit/test_cosyvoice_service.py mode change 100755 => 100644 tests/unit/test_tts_segment_synthesis.py mode change 100755 => 100644 tests/unit/test_voice_clone_workflow.py diff --git a/packages/application/cosyvoice_service.py b/packages/application/cosyvoice_service.py index f42784eaa..de1b4cef0 100755 --- a/packages/application/cosyvoice_service.py +++ b/packages/application/cosyvoice_service.py @@ -84,7 +84,7 @@ class CosyVoiceService: result = service.clone_voice(audio_url="https://example.com/audio.mp3") # 语音合成 - result = service.synthesize_speech(text="你好世界", voice_id="longxiaochun") + result = service.synthesize_speech(text="你好世界", voice_id="longxiaochun_v3") """ # 音色状态轮询配置 diff --git a/packages/domain/preset_voices.py b/packages/domain/preset_voices.py old mode 100644 new mode 100755 index 8b534f561..42e9c53d1 --- a/packages/domain/preset_voices.py +++ b/packages/domain/preset_voices.py @@ -16,7 +16,7 @@ class PresetVoice: """预置音色定义。 Attributes: - voice_id: CosyVoice 模型音色名(如 longxiaochun) + voice_id: CosyVoice 模型音色名(如 longxiaochun_v3) name: 中文展示名 description: 音色描述 gender: 性别(male/female) @@ -49,7 +49,7 @@ class PresetVoice: # 预置音色列表(阿里云 CosyVoice 真实可用音色) PRESET_VOICES: list[PresetVoice] = [ PresetVoice( - voice_id="longxiaochun", + voice_id="longxiaochun_v3", name="龙小淳", description="温柔女声,适合情感类内容", gender="female", @@ -57,7 +57,7 @@ PRESET_VOICES: list[PresetVoice] = [ tags=["温柔", "女声", "情感"], ), PresetVoice( - voice_id="longxiaoxia", + voice_id="longxiaoxia_v3", name="龙小夏", description="知性女声,适合新闻播报", gender="female", @@ -65,7 +65,7 @@ PRESET_VOICES: list[PresetVoice] = [ tags=["知性", "女声", "播报"], ), PresetVoice( - voice_id="longxiaochen", + voice_id="longxiaochen_v3", name="龙小晨", description="磁性男声,适合有声书", gender="male", @@ -73,7 +73,7 @@ PRESET_VOICES: list[PresetVoice] = [ tags=["磁性", "男声", "有声书"], ), PresetVoice( - voice_id="longyue", + voice_id="longyue_v3", name="龙悦", description="甜美女声,适合广告配音", gender="female", @@ -81,7 +81,7 @@ PRESET_VOICES: list[PresetVoice] = [ tags=["甜美", "女声", "广告"], ), PresetVoice( - voice_id="longshu", + voice_id="longshu_v3", name="龙书", description="沉稳男声,适合教育讲解", gender="male", @@ -89,7 +89,7 @@ PRESET_VOICES: list[PresetVoice] = [ tags=["沉稳", "男声", "教育"], ), PresetVoice( - voice_id="longjing", + voice_id="longjing_v3", name="龙静", description="优雅女声,适合纪录片解说", gender="female", @@ -97,7 +97,7 @@ PRESET_VOICES: list[PresetVoice] = [ tags=["优雅", "女声", "纪录片"], ), PresetVoice( - voice_id="longbo", + voice_id="longbo_v3", name="龙博", description="浑厚男声,适合科技类内容", gender="male", @@ -105,7 +105,7 @@ PRESET_VOICES: list[PresetVoice] = [ tags=["浑厚", "男声", "科技"], ), PresetVoice( - voice_id="longtian", + voice_id="longtian_v3", name="龙甜", description="活泼女声,适合短视频配音", gender="female", diff --git a/packages/shared/config.py b/packages/shared/config.py old mode 100644 new mode 100755 index 1fa28ecde..e6a7d748f --- a/packages/shared/config.py +++ b/packages/shared/config.py @@ -33,7 +33,7 @@ class SharedSettings(BaseSettings): cosyvoice_api_key: str = "" cosyvoice_base_url: str = "https://dashscope.aliyuncs.com/api/v1" cosyvoice_model: str = "cosyvoice-v3.5-plus" - cosyvoice_voice: str = "longxiaochun" # 默认音色 + cosyvoice_voice: str = "longxiaochun_v3" # 默认音色 cosyvoice_sample_rate: int = 22050 cosyvoice_format: str = "mp3" # 输出格式:mp3/wav/pcm # 音色克隆模型名(固定为 voice-enrollment) diff --git a/tests/unit/test_cosyvoice_service.py b/tests/unit/test_cosyvoice_service.py old mode 100755 new mode 100644 index c2e48da69..42c0f79e9 --- a/tests/unit/test_cosyvoice_service.py +++ b/tests/unit/test_cosyvoice_service.py @@ -397,7 +397,7 @@ class TestSynthesizeSpeech: service = _make_service(http_client=mock_client) result = service.synthesize_speech( - text="你好世界", voice_id="longxiaochun" + text="你好世界", voice_id="longxiaochun_v3" ) assert isinstance(result, SynthesizeResult) @@ -411,7 +411,7 @@ class TestSynthesizeSpeech: payload = call_args.kwargs["json"] assert payload["model"] == "cosyvoice-v3.5-plus" assert payload["input"]["text"] == "你好世界" - assert payload["input"]["voice"] == "longxiaochun" + assert payload["input"]["voice"] == "longxiaochun_v3" assert payload["input"]["format"] == "mp3" assert payload["input"]["sample_rate"] == 22050 assert payload["input"]["rate"] == 1.0 diff --git a/tests/unit/test_preset_voices.py b/tests/unit/test_preset_voices.py index d938f6ed0..07cb500ea 100644 --- a/tests/unit/test_preset_voices.py +++ b/tests/unit/test_preset_voices.py @@ -64,7 +64,7 @@ class TestPresetVoice: def test_preset_voice_to_dict(self) -> None: """序列化。""" voice = PresetVoice( - voice_id="longxiaochun", + voice_id="longxiaochun_v3", name="龙小淳", description="温柔女声", gender="female", @@ -73,7 +73,7 @@ class TestPresetVoice: result = voice.to_dict() - assert result["voice_id"] == "longxiaochun" + assert result["voice_id"] == "longxiaochun_v3" assert result["name"] == "龙小淳" assert result["description"] == "温柔女声" assert result["gender"] == "female" @@ -127,14 +127,14 @@ class TestPresetVoicesConfig: def test_cosyvoice_voice_ids(self) -> None: """音色 ID 应为 CosyVoice 真实可用的音色名。""" expected_ids = { - "longxiaochun", - "longxiaoxia", - "longxiaochen", - "longyue", - "longshu", - "longjing", - "longbo", - "longtian", + "longxiaochun_v3", + "longxiaoxia_v3", + "longxiaochen_v3", + "longyue_v3", + "longshu_v3", + "longjing_v3", + "longbo_v3", + "longtian_v3", } actual_ids = {v.voice_id for v in PRESET_VOICES} assert actual_ids == expected_ids @@ -164,10 +164,10 @@ class TestPresetVoiceHelpers: def test_get_preset_voice_by_id_found(self) -> None: """按 ID 查找存在的音色。""" - voice = get_preset_voice_by_id("longxiaochun") + voice = get_preset_voice_by_id("longxiaochun_v3") assert voice is not None assert voice.name == "龙小淳" - assert voice.voice_id == "longxiaochun" + assert voice.voice_id == "longxiaochun_v3" def test_get_preset_voice_by_id_not_found(self) -> None: """按 ID 查找不存在的音色。""" @@ -176,9 +176,9 @@ class TestPresetVoiceHelpers: def test_is_preset_voice_true(self) -> None: """判断预置音色返回 True。""" - assert is_preset_voice("longxiaochun") is True - assert is_preset_voice("longxiaoxia") is True - assert is_preset_voice("longbo") is True + assert is_preset_voice("longxiaochun_v3") is True + assert is_preset_voice("longxiaoxia_v3") is True + assert is_preset_voice("longbo_v3") is True def test_is_preset_voice_false(self) -> None: """判断非预置音色返回 False。""" diff --git a/tests/unit/test_tts_job.py b/tests/unit/test_tts_job.py index f00294adc..9d23eefc8 100644 --- a/tests/unit/test_tts_job.py +++ b/tests/unit/test_tts_job.py @@ -15,7 +15,7 @@ class TestTTSJobCreate: job = TTSJob.create( user_id="user_001", input_text="这是一段测试文本", - voice_id="longxiaochun", + voice_id="longxiaochun_v3", voice_model="cosyvoice-v1", project_id="project_001", voice_clone_profile_id="profile_001", @@ -26,7 +26,7 @@ class TestTTSJobCreate: assert job.id assert job.user_id == "user_001" assert job.input_text == "这是一段测试文本" - assert job.voice_id == "longxiaochun" + assert job.voice_id == "longxiaochun_v3" assert job.voice_model == "cosyvoice-v1" assert job.project_id == "project_001" assert job.voice_clone_profile_id == "profile_001" @@ -291,7 +291,7 @@ class TestTTSJobToDict: job = TTSJob.create( user_id="user_001", input_text="测试文本", - voice_id="longxiaochun", + voice_id="longxiaochun_v3", voice_model="cosyvoice-v1", project_id="project_001", voice_clone_profile_id="profile_001", @@ -306,7 +306,7 @@ class TestTTSJobToDict: assert result["id"] == job.id assert result["user_id"] == "user_001" assert result["input_text"] == "测试文本" - assert result["voice_id"] == "longxiaochun" + assert result["voice_id"] == "longxiaochun_v3" assert result["voice_model"] == "cosyvoice-v1" assert result["project_id"] == "project_001" assert result["voice_clone_profile_id"] == "profile_001" diff --git a/tests/unit/test_tts_segment_synthesis.py b/tests/unit/test_tts_segment_synthesis.py old mode 100755 new mode 100644 diff --git a/tests/unit/test_voice_clone_workflow.py b/tests/unit/test_voice_clone_workflow.py old mode 100755 new mode 100644 -- 2.54.0