From d4a1e9f5f67201f7a25960956ce97e20edfecdfa Mon Sep 17 00:00:00 2001 From: Neko Ayaka Date: Fri, 18 Apr 2025 23:45:02 +0800 Subject: [PATCH] feat(stage-web|stage-tamagotchi): supports Alibaba Cloud Model Studio & Volcano Engine --- apps/stage-tamagotchi/locales/en.yml | 11 ++ apps/stage-tamagotchi/locales/zh-CN.yml | 11 ++ .../providers/alibaba-cloud-model-studio.vue | 154 +++++++++++++++ .../pages/settings/providers/elevenlabs.vue | 153 ++++++++++++-- .../settings/providers/microsoft-speech.vue | 7 - .../pages/settings/providers/volcengine.vue | 144 ++++++++++++++ apps/stage-tamagotchi/src/styles/themes.css | 2 +- apps/stage-web/locales/en.yml | 11 ++ apps/stage-web/locales/zh-CN.yml | 11 ++ .../providers/alibaba-cloud-model-studio.vue | 154 +++++++++++++++ .../pages/settings/providers/elevenlabs.vue | 153 ++++++++++++-- .../settings/providers/microsoft-speech.vue | 7 - .../pages/settings/providers/volcengine.vue | 144 ++++++++++++++ apps/stage-web/src/styles/themes.css | 2 +- cspell.config.yaml | 7 + packages/stage-ui/package.json | 1 + .../components/Providers/SpeechPlayground.vue | 24 --- .../Providers/SpeechProviderSettings.vue | 5 +- .../Providers/SpeechVoiceSettings.vue | 102 ---------- .../src/components/Providers/index.ts | 2 - packages/stage-ui/src/constants/elevenlabs.ts | 48 ----- packages/stage-ui/src/constants/index.ts | 1 - .../stage-ui/src/stores/fix/elevenlabs.ts | 186 ------------------ .../stage-ui/src/stores/fix/list-voices.ts | 22 --- packages/stage-ui/src/stores/fix/microsoft.ts | 174 ---------------- packages/stage-ui/src/stores/fix/voice.ts | 41 ---- .../stage-ui/src/stores/modules/speech.ts | 27 +-- packages/stage-ui/src/stores/providers.ts | 126 +++++++++++- packages/stage-ui/src/stores/settings.ts | 2 +- .../stories/ThemeColorsHueControl.vue | 2 +- packages/stage-ui/stories/themes.css | 2 +- pnpm-lock.yaml | 11 ++ 32 files changed, 1057 insertions(+), 690 deletions(-) create mode 100644 apps/stage-tamagotchi/src/pages/settings/providers/alibaba-cloud-model-studio.vue create mode 100644 apps/stage-tamagotchi/src/pages/settings/providers/volcengine.vue create mode 100644 apps/stage-web/src/pages/settings/providers/alibaba-cloud-model-studio.vue create mode 100644 apps/stage-web/src/pages/settings/providers/volcengine.vue delete mode 100644 packages/stage-ui/src/components/Providers/SpeechVoiceSettings.vue delete mode 100644 packages/stage-ui/src/constants/elevenlabs.ts delete mode 100644 packages/stage-ui/src/stores/fix/elevenlabs.ts delete mode 100644 packages/stage-ui/src/stores/fix/list-voices.ts delete mode 100644 packages/stage-ui/src/stores/fix/microsoft.ts delete mode 100644 packages/stage-ui/src/stores/fix/voice.ts diff --git a/apps/stage-tamagotchi/locales/en.yml b/apps/stage-tamagotchi/locales/en.yml index 489378307..23f566340 100644 --- a/apps/stage-tamagotchi/locales/en.yml +++ b/apps/stage-tamagotchi/locales/en.yml @@ -218,6 +218,9 @@ settings: title: Voice Settings description: LLMs, speech providers, etc. provider: + alibaba-cloud-model-studio: + description: bailian.console.aliyun.com + title: Alibaba Cloud Model Studio anthropic: description: anthropic.com title: Anthropic | Claude @@ -326,6 +329,14 @@ settings: vllm: description: vllm.ai title: vLLM + volcengine: + description: volcengine.com + fields: + field: + appId: + description: App ID of the project where you can obtain in Console + label: App ID + title: Volcano Engine xai: description: x.ai title: xAI diff --git a/apps/stage-tamagotchi/locales/zh-CN.yml b/apps/stage-tamagotchi/locales/zh-CN.yml index 5039e739c..afe10c3e1 100644 --- a/apps/stage-tamagotchi/locales/zh-CN.yml +++ b/apps/stage-tamagotchi/locales/zh-CN.yml @@ -207,6 +207,9 @@ settings: title: 声音配置 description: LLM,语音合成,语音识别提供商等 provider: + alibaba-cloud-model-studio: + description: bailian.console.aliyun.com + title: 阿里百炼 anthropic: description: anthropic.com title: Anthropic | Claude @@ -313,6 +316,14 @@ settings: vllm: description: vllm.ai title: vLLM + volcengine: + description: volcengine.com + fields: + field: + appId: + description: 可在控制台获取的 App ID + label: App ID + title: 火山引擎 xai: description: X.AI title: xAI diff --git a/apps/stage-tamagotchi/src/pages/settings/providers/alibaba-cloud-model-studio.vue b/apps/stage-tamagotchi/src/pages/settings/providers/alibaba-cloud-model-studio.vue new file mode 100644 index 000000000..55d0faac3 --- /dev/null +++ b/apps/stage-tamagotchi/src/pages/settings/providers/alibaba-cloud-model-studio.vue @@ -0,0 +1,154 @@ + + + diff --git a/apps/stage-tamagotchi/src/pages/settings/providers/elevenlabs.vue b/apps/stage-tamagotchi/src/pages/settings/providers/elevenlabs.vue index b991e51c9..e66eed0ba 100644 --- a/apps/stage-tamagotchi/src/pages/settings/providers/elevenlabs.vue +++ b/apps/stage-tamagotchi/src/pages/settings/providers/elevenlabs.vue @@ -3,13 +3,15 @@ import type { UnElevenLabsOptions } from '@xsai-ext/providers-local' import type { SpeechProviderWithExtraOptions } from '@xsai-ext/shared-providers' import { + FieldCheckbox, + FieldRange, SpeechPlayground, SpeechProviderSettings, - SpeechVoiceSettings, } from '@proj-airi/stage-ui/components' import { useProvidersStore, useSpeechStore } from '@proj-airi/stage-ui/stores' import { storeToRefs } from 'pinia' -import { computed } from 'vue' +import { computed, onMounted, ref, watch } from 'vue' +import { useI18n } from 'vue-i18n' const providerId = 'elevenlabs' const defaultModel = 'eleven_multilingual_v2' @@ -23,9 +25,18 @@ const defaultVoiceSettings = { useSpeakerBoost: true, } +const pitch = ref(0) +const speed = ref(1.0) +const volume = ref(0) +const style = ref(0) +const stability = ref(0.5) +const similarityBoost = ref(0.75) +const useSpeakerBoost = ref(false) + const speechStore = useSpeechStore() const providersStore = useProvidersStore() const { providers } = storeToRefs(providersStore) +const { t } = useI18n() // Check if API key is configured const apiKeyConfigured = computed(() => !!providers.value[providerId]?.apiKey) @@ -35,11 +46,6 @@ const availableVoices = computed(() => { return speechStore.availableVoices[providerId] || [] }) -// Get available languages -const availableLanguages = computed(() => { - return speechStore.availableLanguages -}) - // Generate speech with ElevenLabs-specific parameters async function handleGenerateSpeech(input: string, voiceId: string, _useSSML: boolean) { const provider = providersStore.getProviderInstance(providerId) as SpeechProviderWithExtraOptions @@ -65,6 +71,65 @@ async function handleGenerateSpeech(input: string, voiceId: string, _useSSML: bo }, ) } + +onMounted(async () => { + const providerConfig = providersStore.getProviderConfig(providerId) + const providerMetadata = providersStore.getProviderMetadata(providerId) + if (await providerMetadata.validators.validateProviderConfig(providerConfig)) { + await speechStore.loadVoicesForProvider(providerId) + } + else { + console.error('Failed to validate provider config', providerConfig) + } +}) + +watch(pitch, async () => { + const providerConfig = providersStore.getProviderConfig(providerId) + providerConfig.pitch = pitch.value +}) + +watch(speed, async () => { + const providerConfig = providersStore.getProviderConfig(providerId) + providerConfig.speed = speed.value +}) + +watch(volume, async () => { + const providerConfig = providersStore.getProviderConfig(providerId) + providerConfig.volume = volume.value +}) + +watch(style, async () => { + const providerConfig = providersStore.getProviderConfig(providerId) + providerConfig.style = style.value +}) + +watch(stability, async () => { + const providerConfig = providersStore.getProviderConfig(providerId) + providerConfig.stability = stability.value +}) + +watch(similarityBoost, async () => { + const providerConfig = providersStore.getProviderConfig(providerId) + providerConfig.similarityBoost = similarityBoost.value +}) + +watch(useSpeakerBoost, async () => { + const providerConfig = providersStore.getProviderConfig(providerId) + providerConfig.useSpeakerBoost = useSpeakerBoost.value +}) + +watch(providers, async () => { + const providerConfig = providersStore.getProviderConfig(providerId) + const providerMetadata = providersStore.getProviderMetadata(providerId) + if (await providerMetadata.validators.validateProviderConfig(providerConfig)) { + await speechStore.loadVoicesForProvider(providerId) + } + else { + console.error('Failed to validate provider config', providerConfig) + } +}, { + immediate: true, +})