feat(speech): switch mentor voice to anna and slow warm speed to 0.88

diana auditioned too bright for the mentor persona; anna measures
steadier (median F0 220Hz, lowest variance) in production auditions.
This commit is contained in:
2026-07-19 03:01:48 +08:00
parent 7c67a38508
commit 9210b7dde6
3 changed files with 5 additions and 5 deletions
@@ -36,7 +36,7 @@ public class AihrSpeechService {
private static final String DEFAULT_TTS_VOICE = "anna"; private static final String DEFAULT_TTS_VOICE = "anna";
private static final Pattern SAFE_VOICE = Pattern.compile("[A-Za-z0-9_./:-]{1,200}"); private static final Pattern SAFE_VOICE = Pattern.compile("[A-Za-z0-9_./:-]{1,200}");
private static final Map<String, String> ROLE_VOICES = Map.of( private static final Map<String, String> ROLE_VOICES = Map.of(
"mentor", "diana", "mentor", "anna",
"customer", "bella", "customer", "bella",
"interviewer", "alex" "interviewer", "alex"
); );
@@ -181,7 +181,7 @@ public class AihrSpeechService {
return switch (emotion) { return switch (emotion) {
case "intense" -> 1.12; case "intense" -> 1.12;
case "serious" -> 1.04; case "serious" -> 1.04;
case "warm" -> 0.92; case "warm" -> 0.88;
case "professional" -> 0.96; case "professional" -> 0.96;
default -> 0.98; default -> 0.98;
}; };
@@ -32,8 +32,8 @@ class AihrSpeechServiceTest {
var legacy = AihrSpeechService.buildRequestBody( var legacy = AihrSpeechService.buildRequestBody(
mapper, runtime, "普通播报", "alex", null); mapper, runtime, "普通播报", "alex", null);
assertEquals("FunAudioLLM/CosyVoice2-0.5B:diana", mentor.path("voice").asText()); assertEquals("FunAudioLLM/CosyVoice2-0.5B:anna", mentor.path("voice").asText());
assertEquals(0.92, mentor.path("speed").asDouble()); assertEquals(0.88, mentor.path("speed").asDouble());
assertTrue(mentor.path("input").asText().contains("师傅语气")); assertTrue(mentor.path("input").asText().contains("师傅语气"));
assertEquals("FunAudioLLM/CosyVoice2-0.5B:bella", customer.path("voice").asText()); assertEquals("FunAudioLLM/CosyVoice2-0.5B:bella", customer.path("voice").asText());
assertEquals(1.3, customer.path("speed").asDouble()); assertEquals(1.3, customer.path("speed").asDouble());
+1 -1
View File
@@ -3,7 +3,7 @@ import { apiRequest, apiUrl, authHeaders, readTextPayload } from './api';
const audioExtensions = ['.mp3', '.wav', '.m4a', '.webm', '.aac', '.ogg']; const audioExtensions = ['.mp3', '.wav', '.m4a', '.webm', '.aac', '.ogg'];
export const MENTOR_VOICE_PROFILE: SpeechVoiceProfile = { role: 'mentor', emotion: 'warm', speed: 0.92 }; export const MENTOR_VOICE_PROFILE: SpeechVoiceProfile = { role: 'mentor', emotion: 'warm', speed: 0.88 };
export const INTERVIEWER_VOICE_PROFILE: SpeechVoiceProfile = { role: 'interviewer', emotion: 'professional', speed: 0.96 }; export const INTERVIEWER_VOICE_PROFILE: SpeechVoiceProfile = { role: 'interviewer', emotion: 'professional', speed: 0.96 };
export const customerVoiceProfile = (emotion = 0): SpeechVoiceProfile => { export const customerVoiceProfile = (emotion = 0): SpeechVoiceProfile => {
if (emotion >= 80) return { role: 'customer', emotion: 'intense', speed: 1.12 }; if (emotion >= 80) return { role: 'customer', emotion: 'intense', speed: 1.12 };