From a68b9bf01f35319e98e65891228223af933fbafd Mon Sep 17 00:00:00 2001 From: memeflyfly <55984574+1624318455@users.noreply.github.com> Date: Mon, 11 May 2026 21:56:11 +0800 Subject: [PATCH] feat: add Edge TTS rate/pitch sliders to voice settings (#629) Add speed (rate) and pitch controls for Edge TTS provider: - Frontend: speedToEdgeRate()/hzToEdgePitch() helpers + UI sliders - Backend: rate/pitch passthrough in OpenaiTtsRequest and controller - i18n: add edgeRate/edgePitch keys across all 8 languages - Rate: 0.5x-2.0x slider, Pitch: -20Hz to +20Hz slider --- packages/client/src/api/hermes/tts.ts | 2 + .../components/hermes/chat/MessageItem.vue | 5 ++ .../hermes/settings/VoiceSettings.vue | 52 ++++++++++++++++++- packages/client/src/composables/useSpeech.ts | 5 ++ .../src/composables/useVoiceSettings.ts | 16 +++++- packages/client/src/i18n/locales/de.ts | 5 ++ packages/client/src/i18n/locales/en.ts | 5 ++ packages/client/src/i18n/locales/es.ts | 5 ++ packages/client/src/i18n/locales/fr.ts | 5 ++ packages/client/src/i18n/locales/ja.ts | 5 ++ packages/client/src/i18n/locales/ko.ts | 5 ++ packages/client/src/i18n/locales/pt.ts | 5 ++ packages/client/src/i18n/locales/zh.ts | 5 ++ packages/client/src/utils/ttsHelpers.ts | 16 ++++++ packages/server/src/controllers/hermes/tts.ts | 4 ++ packages/server/src/services/hermes/tts.ts | 6 ++- 16 files changed, 142 insertions(+), 4 deletions(-) create mode 100644 packages/client/src/utils/ttsHelpers.ts diff --git a/packages/client/src/api/hermes/tts.ts b/packages/client/src/api/hermes/tts.ts index c22d28d..581dabc 100644 --- a/packages/client/src/api/hermes/tts.ts +++ b/packages/client/src/api/hermes/tts.ts @@ -1,6 +1,8 @@ export interface TtsOptions { text: string lang?: string + rate?: string // Edge TTS rate format: "+NN%" or "-NN%" + pitch?: string // Edge TTS pitch format: "+NNHz" or "-NNHz" } export async function generateSpeech(opts: TtsOptions): Promise<{ audio: Blob; engine: string }> { diff --git a/packages/client/src/components/hermes/chat/MessageItem.vue b/packages/client/src/components/hermes/chat/MessageItem.vue index 502f703..111d525 100644 --- a/packages/client/src/components/hermes/chat/MessageItem.vue +++ b/packages/client/src/components/hermes/chat/MessageItem.vue @@ -17,6 +17,7 @@ import { } from "./highlight"; import { useGlobalSpeech } from "@/composables/useSpeech"; import { useVoiceSettings } from "@/composables/useVoiceSettings"; +import { speedToEdgeRate, hzToEdgePitch } from "@/utils/ttsHelpers"; const TOOL_PAYLOAD_DISPLAY_LIMIT = 2000; @@ -420,6 +421,8 @@ function handleSpeechToggle() { speech.openaiToggle(props.message.id, content, { baseUrl: apiUrl, voice: voiceSettings.edgeVoice.value, + rate: speedToEdgeRate(voiceSettings.edgeRate.value), + pitch: hzToEdgePitch(voiceSettings.edgePitchHz.value), }) return } @@ -466,6 +469,8 @@ onMounted(() => { speech.openaiPlay(props.message.id, content, { baseUrl: '/api/tts/proxy', voice: voiceSettings.edgeVoice.value, + rate: speedToEdgeRate(voiceSettings.edgeRate.value), + pitch: hzToEdgePitch(voiceSettings.edgePitchHz.value), }) } else if (voiceSettings.provider.value === 'webspeech') { const text = speech.extractReadableText(content) diff --git a/packages/client/src/components/hermes/settings/VoiceSettings.vue b/packages/client/src/components/hermes/settings/VoiceSettings.vue index 42d1686..5b406b4 100644 --- a/packages/client/src/components/hermes/settings/VoiceSettings.vue +++ b/packages/client/src/components/hermes/settings/VoiceSettings.vue @@ -1,9 +1,10 @@