음성 재생과 운영 배포 정리
This commit is contained in:
parent
8ed185ce6c
commit
ac7db95542
1020 changed files with 46863 additions and 2175 deletions
|
|
@ -4,9 +4,11 @@ from __future__ import annotations
|
|||
|
||||
import json
|
||||
import unittest
|
||||
from types import SimpleNamespace
|
||||
from unittest.mock import AsyncMock, patch
|
||||
|
||||
from .deps import Principal, Role
|
||||
from .persona_repository import PersonaVoiceMap
|
||||
from .routes import voice as voice_routes
|
||||
from .services.voice import VoicePreset
|
||||
|
||||
|
|
@ -289,6 +291,95 @@ class VoiceWebSocketContractTest(unittest.IsolatedAsyncioTestCase):
|
|||
bind_session.assert_not_awaited()
|
||||
is_available.assert_not_called()
|
||||
|
||||
async def test_bind_session_uses_db_voice_map_for_existing_session(self) -> None:
|
||||
websocket = FakeWebSocket()
|
||||
websocket.query_params = {"session_id": SESSION_ID}
|
||||
sess = SimpleNamespace(persona=SimpleNamespace(code="P2"))
|
||||
voice_map = PersonaVoiceMap(
|
||||
provider="openai",
|
||||
voice_id="voice-p2-custom",
|
||||
base_params={
|
||||
"preset": "calm-adult-male",
|
||||
"openai_voice": "onyx",
|
||||
"rate": 1.08,
|
||||
"instructions": "Low, guarded delivery.",
|
||||
},
|
||||
)
|
||||
get_voice_map = AsyncMock(return_value=voice_map)
|
||||
|
||||
with patch.object(
|
||||
voice_routes,
|
||||
"_load_voice_session",
|
||||
AsyncMock(return_value=(sess, None)),
|
||||
), patch.object(
|
||||
voice_routes,
|
||||
"get_session_voice_map",
|
||||
get_voice_map,
|
||||
):
|
||||
session_id, voice, err, meta = await voice_routes._bind_session(
|
||||
websocket, _principal()
|
||||
)
|
||||
|
||||
self.assertEqual(session_id, SESSION_ID)
|
||||
self.assertIsNone(err)
|
||||
self.assertEqual(meta["persona_catalog_source"], "session")
|
||||
self.assertEqual(voice, VoicePreset(
|
||||
preset="calm-adult-male",
|
||||
openai_voice="onyx",
|
||||
rate=1.08,
|
||||
instructions="Low, guarded delivery.",
|
||||
))
|
||||
get_voice_map.assert_awaited_once_with(SESSION_ID)
|
||||
|
||||
async def test_bind_session_explicit_preset_overrides_db_voice_map(self) -> None:
|
||||
websocket = FakeWebSocket()
|
||||
websocket.query_params = {"session_id": SESSION_ID, "preset": "soft-young-fem"}
|
||||
sess = SimpleNamespace(persona=SimpleNamespace(code="P2"))
|
||||
get_voice_map = AsyncMock()
|
||||
|
||||
with patch.object(
|
||||
voice_routes,
|
||||
"_load_voice_session",
|
||||
AsyncMock(return_value=(sess, None)),
|
||||
), patch.object(
|
||||
voice_routes,
|
||||
"get_session_voice_map",
|
||||
get_voice_map,
|
||||
):
|
||||
session_id, voice, err, _ = await voice_routes._bind_session(
|
||||
websocket, _principal()
|
||||
)
|
||||
|
||||
self.assertEqual(session_id, SESSION_ID)
|
||||
self.assertIsNone(err)
|
||||
self.assertEqual(voice.preset, "soft-young-fem")
|
||||
self.assertEqual(voice.openai_voice, "coral")
|
||||
get_voice_map.assert_not_awaited()
|
||||
|
||||
async def test_catalog_voice_map_is_used_for_dev_persona_binding_helper(self) -> None:
|
||||
voice_map = PersonaVoiceMap(
|
||||
provider="openai",
|
||||
voice_id="verse",
|
||||
base_params={"preset": "soft-young-fem", "rate": 0.9},
|
||||
)
|
||||
get_voice_map = AsyncMock(return_value=voice_map)
|
||||
|
||||
with patch.object(voice_routes, "get_persona_voice_map", get_voice_map):
|
||||
voice = await voice_routes._resolve_catalog_voice(
|
||||
persona_id="00000000-0000-0000-0000-000000000301",
|
||||
version=7,
|
||||
persona_code="P1",
|
||||
explicit_preset=None,
|
||||
)
|
||||
|
||||
self.assertEqual(voice.preset, "soft-young-fem")
|
||||
self.assertEqual(voice.openai_voice, "verse")
|
||||
self.assertAlmostEqual(voice.rate, 0.9)
|
||||
get_voice_map.assert_awaited_once_with(
|
||||
persona_id="00000000-0000-0000-0000-000000000301",
|
||||
version=7,
|
||||
)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue