fix(stage-web|stage-tamagotchi): speech
This commit is contained in:
@@ -47,18 +47,22 @@ settings:
|
||||
chinese: 简体中文
|
||||
english: English
|
||||
title: Language
|
||||
live2d:
|
||||
change-model:
|
||||
from-file: Load from File
|
||||
from-file-select: Select
|
||||
from-url: Load from URL
|
||||
from-url-confirm: Load
|
||||
from-url-placeholder: Enter Live2D model URL
|
||||
title: Change Model
|
||||
edit-motion-map:
|
||||
title: Edit motion map
|
||||
map-motions:
|
||||
play: Play Motion
|
||||
title: Map Motions
|
||||
title: Live2D Settings
|
||||
microphone: Microphone
|
||||
models: Model
|
||||
quit: Quit
|
||||
viewer: Viewer
|
||||
shortcuts:
|
||||
title: Shortcuts
|
||||
window:
|
||||
move: Move the window
|
||||
resize: Resize the window
|
||||
debug: Toggle developer tools
|
||||
press_keys: Press keys...
|
||||
other: Other
|
||||
pages:
|
||||
models:
|
||||
description: Live2D, VRM, etc.
|
||||
@@ -69,10 +73,9 @@ settings:
|
||||
sections:
|
||||
section:
|
||||
provider-model-selection:
|
||||
title: Model
|
||||
description: Select the suitable LLM provider for consciousness
|
||||
collapse: Collapse
|
||||
custom_model_placeholder: Enter custom model name...
|
||||
description: Select the suitable LLM provider for consciousness
|
||||
error: Error loading models
|
||||
expand: Expand
|
||||
loading: Loading available models...
|
||||
@@ -89,6 +92,7 @@ settings:
|
||||
show_less: Show less
|
||||
show_more: Show more
|
||||
subtitle: Select a model from the provider
|
||||
title: Model
|
||||
title: Consciousness
|
||||
description: Thinking, vision, speech synthesis, gaming, etc.
|
||||
gaming-factorio:
|
||||
@@ -111,13 +115,49 @@ settings:
|
||||
title: Discord
|
||||
speech:
|
||||
description: Speech synthesis
|
||||
sections:
|
||||
section:
|
||||
playground:
|
||||
buttons:
|
||||
stop:
|
||||
label: Stop
|
||||
select-voice:
|
||||
required: Please select a voice
|
||||
provider-voice-selection:
|
||||
custom_model_placeholder: Enter custom model name...
|
||||
custom_voice_placeholder: Enter custom voice ID...
|
||||
description: Select the suitable speech provider
|
||||
no_models: No models available
|
||||
no_models_description: No models were found for this provider
|
||||
no_voices: No voices available
|
||||
no_voices_description: No voices were found for this provider
|
||||
search_models_placeholder: Search models...
|
||||
search_models_results: Found {count} of {total} models
|
||||
search_voices_placeholder: Search voices...
|
||||
search_voices_results: Found {count} of {total} voices
|
||||
show_less: Show less
|
||||
show_more: Show more
|
||||
title: Provider
|
||||
voice-settings:
|
||||
input-ssml:
|
||||
placeholder: Enter SSML text...
|
||||
use-ssml:
|
||||
description: Enable to input raw SSML instead of plain text
|
||||
label: Use Custom SSML
|
||||
title: Speech
|
||||
title: Modules
|
||||
vision:
|
||||
description: Vision
|
||||
title: Vision
|
||||
x:
|
||||
description: X / Twitter browsing and usage
|
||||
title: X / Twitter
|
||||
providers:
|
||||
common:
|
||||
fields:
|
||||
field:
|
||||
api-key:
|
||||
label: API Key Input
|
||||
section:
|
||||
advanced:
|
||||
fields:
|
||||
@@ -148,6 +188,20 @@ settings:
|
||||
api-key:
|
||||
placeholder: Input Cloudflare Account ID
|
||||
title: Cloudflare Workers AI
|
||||
common:
|
||||
fields:
|
||||
field:
|
||||
pitch:
|
||||
description: >-
|
||||
Tune the pitch of synthesized speech (e.g., sharper or
|
||||
coarser)
|
||||
label: Pitch
|
||||
speed:
|
||||
description: Adjust the speed of speech
|
||||
label: Speed
|
||||
volume:
|
||||
description: Adjust the volume of speech
|
||||
label: Volume
|
||||
deepseek:
|
||||
description: deepseek.com
|
||||
title: DeepSeek
|
||||
@@ -193,6 +247,12 @@ settings:
|
||||
fireworks:
|
||||
description: fireworks.ai
|
||||
title: Fireworks.ai
|
||||
microsoft-speech:
|
||||
fields:
|
||||
field:
|
||||
region:
|
||||
description: Speech Service region
|
||||
label: Region
|
||||
mistral:
|
||||
description: mistral.ai
|
||||
title: Mistral
|
||||
@@ -246,10 +306,10 @@ settings:
|
||||
description: Traditional Japanese color palette
|
||||
title: Japanese Colors
|
||||
monet:
|
||||
description: Impressionist palette inspired by Claude Monet\'s works
|
||||
description: Impressionist palette inspired by Claude Monet's works
|
||||
title: Monet Colors
|
||||
morandi:
|
||||
description: Soft, muted tones inspired by Giorgio Morandi\'s paintings
|
||||
description: Soft, muted tones inspired by Giorgio Morandi's paintings
|
||||
title: Morandi Colors
|
||||
nordic:
|
||||
description: Scandinavian minimalist color scheme
|
||||
|
||||
@@ -35,17 +35,20 @@ settings:
|
||||
chinese: 简体中文
|
||||
english: English
|
||||
title: 语言
|
||||
live2d:
|
||||
change-model:
|
||||
from-file: 从文件加载
|
||||
from-file-select: 选择
|
||||
from-url: 从 URL 加载
|
||||
from-url-confirm: 加载
|
||||
from-url-placeholder: 输入 Live2D 模型 URL
|
||||
title: 更换模型
|
||||
map-motions:
|
||||
play: 播放动作
|
||||
title: 映射动作
|
||||
title: Live2D 设置
|
||||
microphone: 麦克风
|
||||
models: 模型
|
||||
quit: 退出
|
||||
viewer: 查看器
|
||||
shortcuts:
|
||||
title: 快捷键
|
||||
window:
|
||||
move: 移动窗口
|
||||
resize: 调整窗口大小
|
||||
debug: 切换开发者模式
|
||||
press_keys: 按下快捷键...
|
||||
other: 其他
|
||||
pages:
|
||||
models:
|
||||
description: 切换角色的 Live2D,VRM 模型
|
||||
@@ -53,14 +56,12 @@ settings:
|
||||
modules:
|
||||
consciousness:
|
||||
description: 人格设定、使用的模型等配置
|
||||
title: 意识
|
||||
sections:
|
||||
section:
|
||||
provider-model-selection:
|
||||
title: 模型
|
||||
description: 为意识选择合适的 LLM 提供商
|
||||
collapse: 折叠
|
||||
custom_model_placeholder: 输入自订模型名字
|
||||
description: 为意识选择合适的 LLM 提供商
|
||||
error: 获取出错啦
|
||||
expand: 展开
|
||||
loading: 获取模型中...
|
||||
@@ -77,6 +78,8 @@ settings:
|
||||
show_less: 显示更多
|
||||
show_more: 收起
|
||||
subtitle: 选择一个模型
|
||||
title: 模型
|
||||
title: 意识
|
||||
description: 思维,视觉,言语综合,游戏等
|
||||
gaming-factorio:
|
||||
description: 一起玩 Factorio!
|
||||
@@ -98,19 +101,57 @@ settings:
|
||||
title: Discord
|
||||
speech:
|
||||
description: 语音合成
|
||||
sections:
|
||||
section:
|
||||
playground:
|
||||
buttons:
|
||||
stop:
|
||||
label: 停止
|
||||
select-voice:
|
||||
required: 请选择声线
|
||||
provider-voice-selection:
|
||||
custom_model_placeholder: 输入指定模型名字...
|
||||
custom_voice_placeholder: 输入指定声线 ID...
|
||||
description: 选择合适的语音提供商
|
||||
no_models: 没有任何可用的模型
|
||||
no_models_description: 该提供商的模型列表没有返回任何的数据
|
||||
no_voices: 没有任何可用的声线
|
||||
no_voices_description: 该提供商的声线列表没有返回任何的数据
|
||||
pause: Pause
|
||||
play_sample: Play
|
||||
search_models_placeholder: 搜索模型...
|
||||
search_models_results: 找到 {count} / {total} 个模型
|
||||
search_voices_placeholder: 搜索声线...
|
||||
search_voices_results: 找到 {count} / {total} 个声线
|
||||
show_less: 显示更少
|
||||
show_more: 显示更多
|
||||
title: 选择语音合成提供商
|
||||
voice-settings:
|
||||
input-ssml:
|
||||
placeholder: 请输入 SSML 文本
|
||||
use-ssml:
|
||||
description: 启用后可以输入原始 SSML 而不是纯文本
|
||||
label: 选用自定义 SSML
|
||||
title: 发声
|
||||
title: 机体模块
|
||||
vision:
|
||||
description: 视觉
|
||||
title: 视觉
|
||||
x:
|
||||
description: X / Twitter 的浏览和使用
|
||||
title: X / Twitter
|
||||
providers:
|
||||
common:
|
||||
fields:
|
||||
field:
|
||||
api-key:
|
||||
label: API 密钥
|
||||
section:
|
||||
advanced:
|
||||
fields:
|
||||
field:
|
||||
headers:
|
||||
description: 添加自定义HTTP标头
|
||||
description: 添加自定义 HTTP 标头
|
||||
key:
|
||||
placeholder: 请求头名字
|
||||
label: HTTP 请求头
|
||||
@@ -129,12 +170,24 @@ settings:
|
||||
fields:
|
||||
field:
|
||||
account-id:
|
||||
description: Cloudflare帐户ID
|
||||
description: Cloudflare 帐户 ID
|
||||
label: Cloudflare Account ID
|
||||
placeholder: 请输入 Cloudflare Account ID
|
||||
api-key:
|
||||
placeholder: 请输入 Cloudflare Workers AI 的 API Key
|
||||
title: Workers AI
|
||||
common:
|
||||
fields:
|
||||
field:
|
||||
pitch:
|
||||
description: 调节合成语音的音高(比如更尖锐或更粗旷)
|
||||
label: 音高
|
||||
speed:
|
||||
description: 调节说话的语速
|
||||
label: 语速
|
||||
volume:
|
||||
description: 调节语音的响度
|
||||
label: 响度
|
||||
deepseek:
|
||||
description: DeepSeek.com
|
||||
title: 深度求索 DeepSeek
|
||||
@@ -180,6 +233,12 @@ settings:
|
||||
fireworks:
|
||||
description: Fireworks.ai
|
||||
title: Fireworks.ai
|
||||
microsoft-speech:
|
||||
fields:
|
||||
field:
|
||||
region:
|
||||
description: 服务 Endpoint 地区(比如亚太 eastasia 区域)
|
||||
label: Endpoint 地区
|
||||
mistral:
|
||||
description: mistral.ai
|
||||
title: Mistral
|
||||
@@ -231,7 +290,7 @@ settings:
|
||||
monet:
|
||||
title: 莫奈颜色
|
||||
morandi:
|
||||
title: Morandi颜色
|
||||
title: Morandi 颜色
|
||||
nordic:
|
||||
title: 北欧颜色
|
||||
title: 主题预设
|
||||
|
||||
@@ -29,6 +29,7 @@ const {
|
||||
activeSpeechProvider,
|
||||
activeSpeechModel,
|
||||
activeSpeechVoice,
|
||||
activeSpeechVoiceId,
|
||||
pitch,
|
||||
isLoadingSpeechProviderVoices,
|
||||
supportsModelListing,
|
||||
@@ -43,7 +44,6 @@ const {
|
||||
|
||||
const router = useRouter()
|
||||
|
||||
const voiceId = ref('')
|
||||
const voiceSearchQuery = ref('')
|
||||
const useSSML = ref(false)
|
||||
const testText = ref('Hello, my name is AI Assistant')
|
||||
@@ -100,7 +100,7 @@ async function generateTestSpeech() {
|
||||
|
||||
const input = useSSML.value
|
||||
? ssmlText.value
|
||||
: speechStore.generateSSML(testText.value, activeSpeechVoice.value)
|
||||
: speechStore.generateSSML(testText.value, activeSpeechVoice.value, { ...providerConfig, pitch: pitch.value })
|
||||
|
||||
const response = await generateSpeech({
|
||||
...provider.speech(activeSpeechModel.value, providerConfig),
|
||||
@@ -148,10 +148,6 @@ onUnmounted(() => {
|
||||
}
|
||||
})
|
||||
|
||||
function handleVoiceSelection(value: string) {
|
||||
activeSpeechVoice.value = availableVoices.value[activeSpeechProvider.value].find(voice => voice.id === value)
|
||||
}
|
||||
|
||||
function updateCustomVoiceName(value: string) {
|
||||
activeSpeechVoice.value = {
|
||||
id: value,
|
||||
@@ -167,16 +163,6 @@ function updateCustomVoiceName(value: string) {
|
||||
function updateCustomModelName(value: string) {
|
||||
activeSpeechModel.value = value
|
||||
}
|
||||
|
||||
watch(voiceId, (newVoice) => {
|
||||
const foundVoice = availableVoices.value[activeSpeechProvider.value].find(voice => voice.id === newVoice)
|
||||
if (foundVoice) {
|
||||
activeSpeechVoice.value = foundVoice
|
||||
}
|
||||
else {
|
||||
updateCustomVoiceName(newVoice)
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -353,6 +339,7 @@ watch(voiceId, (newVoice) => {
|
||||
>
|
||||
<VoiceCardManySelect
|
||||
v-model:search-query="voiceSearchQuery"
|
||||
v-model:voice-id="activeSpeechVoiceId"
|
||||
:voices="availableVoices[activeSpeechProvider]?.map(voice => ({
|
||||
id: voice.id,
|
||||
name: voice.name,
|
||||
@@ -360,7 +347,6 @@ watch(voiceId, (newVoice) => {
|
||||
previewURL: voice.previewURL,
|
||||
customizable: false,
|
||||
}))"
|
||||
:selected-voice-id="activeSpeechVoice?.id"
|
||||
:searchable="true"
|
||||
:search-placeholder="t('settings.pages.modules.speech.sections.section.provider-voice-selection.search_voices_placeholder')"
|
||||
:search-no-results-title="t('settings.pages.modules.speech.sections.section.provider-voice-selection.no_voices')"
|
||||
@@ -371,7 +357,6 @@ watch(voiceId, (newVoice) => {
|
||||
:collapse-button-text="t('settings.pages.modules.speech.sections.section.provider-voice-selection.show_less')"
|
||||
:play-button-text="t('settings.pages.modules.speech.sections.section.provider-voice-selection.play_sample')"
|
||||
:pause-button-text="t('settings.pages.modules.speech.sections.section.provider-voice-selection.pause')"
|
||||
@update:selected-voice-id="handleVoiceSelection"
|
||||
@update:custom-value="updateCustomVoiceName"
|
||||
/>
|
||||
</div>
|
||||
@@ -423,7 +408,7 @@ watch(voiceId, (newVoice) => {
|
||||
class="mt-2 space-y-6"
|
||||
>
|
||||
<FieldInput
|
||||
v-model="voiceId"
|
||||
v-model="activeSpeechVoiceId"
|
||||
type="text"
|
||||
label="Voice ID"
|
||||
description="Enter the voice ID for your custom voice"
|
||||
|
||||
+9
-1
@@ -10,7 +10,7 @@ import {
|
||||
} 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, ref } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
|
||||
const { t } = useI18n()
|
||||
@@ -29,6 +29,10 @@ const speechStore = useSpeechStore()
|
||||
const providersStore = useProvidersStore()
|
||||
const { providers } = storeToRefs(providersStore)
|
||||
|
||||
const pitch = ref(0)
|
||||
const speed = ref(1.0)
|
||||
const volume = ref(0)
|
||||
|
||||
// Additional settings specific to Microsoft Speech (region)
|
||||
const region = computed({
|
||||
get: () => providers.value[providerId]?.region as string | undefined || 'eastasia',
|
||||
@@ -80,6 +84,7 @@ async function handleGenerateSpeech(input: string, voiceId: string, useSSML: boo
|
||||
const ssml = speechStore.generateSSML(
|
||||
input,
|
||||
voice,
|
||||
{ ...providerConfig, pitch: pitch.value },
|
||||
)
|
||||
return await speechStore.speech(
|
||||
provider,
|
||||
@@ -123,6 +128,9 @@ async function handleGenerateSpeech(input: string, voiceId: string, useSSML: boo
|
||||
<!-- Voice settings specific to Microsoft Speech -->
|
||||
<template #voice-settings="{ voiceSettings, updateVoiceSettings }">
|
||||
<SpeechVoiceSettings
|
||||
v-model:pitch="pitch"
|
||||
v-model:speed="speed"
|
||||
v-model:volume="volume"
|
||||
:settings="voiceSettings"
|
||||
:show-pitch="true"
|
||||
:show-speed="true"
|
||||
|
||||
Reference in New Issue
Block a user