음성 재생과 운영 배포 정리

This commit is contained in:
Yun Chan 2026-06-28 12:18:20 +09:00
parent 8ed185ce6c
commit ac7db95542
1020 changed files with 46863 additions and 2175 deletions

View file

@ -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()