[主说话人端点]:完成音色消失结束录音,包含临时音色画像、端点配置和回归测试

This commit is contained in:
mkbk
2026-06-17 21:33:33 +08:00
parent f9da304568
commit da91be6e5c
8 changed files with 372 additions and 12 deletions
+80
View File
@@ -26,6 +26,12 @@ class AppConfig:
wake_kws_score: float = 1.0
wake_ack_text: str = "我在"
post_playback_drain_ms: int = 50
pipeline_mode: str = "live_turn_based"
endpoint_mode: str = "primary_speaker"
speaker_profile_ms: int = 600
speaker_absent_ms: int = 300
speaker_similarity_threshold: float = 0.70
speaker_min_rms: float = 0.012
vad_provider: str = "hybrid"
vad_threshold: float = 0.5
vad_min_duration_ms: int = 250
@@ -37,6 +43,7 @@ class AppConfig:
tts_model: str = "mimo-v2.5-tts"
tts_voice: str = "mimo_default"
speech_models_dir: Path = Path("models")
context_mode: str = "session_memory"
context_max_messages: int = 12
context_max_chars: int = 12000
@@ -67,6 +74,14 @@ class AppConfig:
wake_kws_score=float(get("WAKE_KWS_SCORE", "1.0") or "1.0"),
wake_ack_text=get("WAKE_ACK_TEXT", "我在") or "我在",
post_playback_drain_ms=int(get("POST_PLAYBACK_DRAIN_MS", "50") or "50"),
pipeline_mode=(get("PIPELINE_MODE", "live_turn_based") or "live_turn_based").lower(),
endpoint_mode=(get("ENDPOINT_MODE", "primary_speaker") or "primary_speaker").lower(),
speaker_profile_ms=int(get("SPEAKER_PROFILE_MS", "600") or "600"),
speaker_absent_ms=int(get("SPEAKER_ABSENT_MS", "300") or "300"),
speaker_similarity_threshold=float(
get("SPEAKER_SIMILARITY_THRESHOLD", "0.70") or "0.70"
),
speaker_min_rms=float(get("SPEAKER_MIN_RMS", "0.012") or "0.012"),
vad_provider=(get("VAD_PROVIDER", "hybrid") or "hybrid").lower(),
vad_threshold=float(get("VAD_THRESHOLD", "0.5") or "0.5"),
vad_min_duration_ms=int(get("VAD_MIN_DURATION_MS", "250") or "250"),
@@ -78,6 +93,7 @@ class AppConfig:
tts_model=get("TTS_MODEL", "mimo-v2.5-tts") or "mimo-v2.5-tts",
tts_voice=get("TTS_VOICE", "mimo_default") or "mimo_default",
speech_models_dir=Path(get("SPEECH_MODELS_DIR", "models") or "models"),
context_mode=(get("CONTEXT_MODE", "session_memory") or "session_memory").lower(),
context_max_messages=int(get("CONTEXT_MAX_MESSAGES", "12") or "12"),
context_max_chars=int(get("CONTEXT_MAX_CHARS", "12000") or "12000"),
)
@@ -178,6 +194,60 @@ class AppConfig:
"startup",
)
)
if self.pipeline_mode not in {"live_turn_based"}:
errors.append(
ProviderError(
ErrorCode.CONFIG_MISSING_VALUE,
"OWNER_PIPELINE_MODE must be live_turn_based",
False,
"config",
"startup",
)
)
if self.endpoint_mode not in {"primary_speaker", "vad"}:
errors.append(
ProviderError(
ErrorCode.CONFIG_MISSING_VALUE,
"OWNER_ENDPOINT_MODE must be primary_speaker or vad",
False,
"config",
"startup",
)
)
for name, value in {
"OWNER_SPEAKER_PROFILE_MS": self.speaker_profile_ms,
"OWNER_SPEAKER_ABSENT_MS": self.speaker_absent_ms,
}.items():
if value <= 0:
errors.append(
ProviderError(
ErrorCode.CONFIG_MISSING_VALUE,
f"{name} must be positive",
False,
"config",
"startup",
)
)
if not 0 < self.speaker_similarity_threshold <= 1:
errors.append(
ProviderError(
ErrorCode.CONFIG_MISSING_VALUE,
"OWNER_SPEAKER_SIMILARITY_THRESHOLD must be in (0, 1]",
False,
"config",
"startup",
)
)
if self.speaker_min_rms <= 0:
errors.append(
ProviderError(
ErrorCode.CONFIG_MISSING_VALUE,
"OWNER_SPEAKER_MIN_RMS must be positive",
False,
"config",
"startup",
)
)
if self.vad_provider not in {"hybrid", "local", "energy"}:
errors.append(
ProviderError(
@@ -224,6 +294,16 @@ class AppConfig:
"startup",
)
)
if self.context_mode not in {"session_memory"}:
errors.append(
ProviderError(
ErrorCode.CONFIG_MISSING_VALUE,
"OWNER_CONTEXT_MODE must be session_memory",
False,
"config",
"startup",
)
)
return errors
def api_url(self, path: str) -> str: