mirror of
https://github.com/linyqh/NarratoAI.git
synced 2026-08-01 10:55:54 +00:00
新增完整的voxcpm系列本地语音合成功能,包括: - 新增配置常量、加载逻辑与示例配置项 - 集成webui界面:引擎选型、参数配置与语音预览 - 实现核心调用逻辑,包含API地址标准化、重试机制与文件处理 - 新增两套单元测试覆盖核心流程 - 在字幕转录设置页面补充转录工具包的下载提示文本
82 lines
3.7 KiB
Python
82 lines
3.7 KiB
Python
import tempfile
|
|
import unittest
|
|
from pathlib import Path
|
|
from unittest.mock import patch
|
|
|
|
from app.services import voice
|
|
|
|
|
|
class FakeResponse:
|
|
def __init__(self, *, status_code=200, content=b"", payload=None):
|
|
self.status_code = status_code
|
|
self.content = content
|
|
self._payload = payload or {}
|
|
self.text = "OK"
|
|
|
|
def json(self):
|
|
return self._payload
|
|
|
|
|
|
class VoxCPM2TtsTests(unittest.TestCase):
|
|
def setUp(self):
|
|
self.original_config = dict(voice.config.voxcpm_2b)
|
|
self.original_proxy = dict(voice.config.proxy)
|
|
|
|
def tearDown(self):
|
|
voice.config.voxcpm_2b.clear()
|
|
voice.config.voxcpm_2b.update(self.original_config)
|
|
voice.config.proxy.clear()
|
|
voice.config.proxy.update(self.original_proxy)
|
|
|
|
def test_voice_design_sends_control_and_downloads_wav(self):
|
|
voice.config.voxcpm_2b.clear()
|
|
voice.config.voxcpm_2b.update({
|
|
"api_url": "http://127.0.0.1:7863/v1/audio/speech",
|
|
"mode": "design", "control": "温暖自然的年轻女声",
|
|
"cfg_value": 2.0, "inference_timesteps": 10,
|
|
"normalize": True, "denoise": False, "output_48k": True,
|
|
"context_aware": True, "streaming": False,
|
|
})
|
|
voice.config.proxy.clear()
|
|
with tempfile.TemporaryDirectory() as temp_dir:
|
|
output = Path(temp_dir) / "output.wav"
|
|
with (
|
|
patch("app.services.voice.requests.post", return_value=FakeResponse(payload={"downloads": {"wav": "/download/result.wav"}})) as post,
|
|
patch("app.services.voice.requests.get", return_value=FakeResponse(content=b"wav-2b")) as get,
|
|
patch("app.services.voice.get_audio_duration_from_file", return_value=2.0),
|
|
):
|
|
result = voice.voxcpm2_tts(" 高质量旁白。 ", "voxcpm_2b:design", str(output))
|
|
self.assertIsNotNone(result)
|
|
self.assertEqual(output.read_bytes(), b"wav-2b")
|
|
self.assertEqual(post.call_args.args[0], "http://127.0.0.1:7863/tts")
|
|
self.assertIsNone(post.call_args.kwargs["files"])
|
|
self.assertEqual(post.call_args.kwargs["data"]["control"], "温暖自然的年轻女声")
|
|
self.assertEqual(post.call_args.kwargs["data"]["output_48k"], "true")
|
|
self.assertEqual(get.call_args.args[0], "http://127.0.0.1:7863/download/result.wav")
|
|
|
|
def test_clone_uploads_reference_audio(self):
|
|
voice.config.voxcpm_2b.clear()
|
|
voice.config.voxcpm_2b.update({
|
|
"api_url": "http://127.0.0.1:7863/tts/batch",
|
|
"mode": "clone", "prompt_text": "参考音频文本",
|
|
})
|
|
voice.config.proxy.clear()
|
|
with tempfile.TemporaryDirectory() as temp_dir:
|
|
reference = Path(temp_dir) / "reference.wav"
|
|
output = Path(temp_dir) / "output.wav"
|
|
reference.write_bytes(b"reference")
|
|
with (
|
|
patch("app.services.voice.requests.post", return_value=FakeResponse(payload={"downloads": {"wav": "/download/result.wav"}})) as post,
|
|
patch("app.services.voice.requests.get", return_value=FakeResponse(content=b"wav")),
|
|
patch("app.services.voice.get_audio_duration_from_file", return_value=1.0),
|
|
):
|
|
result = voice.voxcpm2_tts("克隆测试", f"voxcpm_2b:{reference}", str(output))
|
|
self.assertIsNotNone(result)
|
|
self.assertEqual(post.call_args.args[0], "http://127.0.0.1:7863/tts")
|
|
self.assertIn("reference_audio", post.call_args.kwargs["files"])
|
|
self.assertEqual(post.call_args.kwargs["data"]["prompt_text"], "参考音频文本")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|