feat: add tts params

This commit is contained in:
jialin
2026-01-30 22:58:11 +08:00
parent f0cdefad90
commit b3e186fea4
8 changed files with 259 additions and 40 deletions
+1 -1
View File
@@ -2,7 +2,7 @@ import { createFromIconfontCN } from '@ant-design/icons';
// import './iconfont/iconfont.js';
const IconFont = createFromIconfontCN({
scriptUrl: '//at.alicdn.com/t/c/font_3892962_hd8klbsk0yg.js'
scriptUrl: '//at.alicdn.com/t/c/font_4613488_mis8x88kojd.js'
});
export default IconFont;
+5 -1
View File
@@ -163,5 +163,9 @@ export default {
'playground.uploadImage.url.holder': 'Enter an image URL',
'playground.uploadImage.url.button': 'Add Image from URL',
'playground.params.duration': 'Duration (seconds)',
'playground.params.resolution': 'Resolution'
'playground.params.resolution': 'Resolution',
'playground.params.taskType': 'Task Type',
'playground.params.voiceStyle': 'Voice Style',
'playground.params.maxTokens': 'Maximum Generate Length',
'playground.params.refAudio': 'Reference Audio URL'
};
+5 -1
View File
@@ -166,7 +166,11 @@ export default {
'playground.uploadImage.url.holder': 'Enter an image URL',
'playground.uploadImage.url.button': 'Add Image from URL',
'playground.params.duration': 'Duration (seconds)',
'playground.params.resolution': 'Resolution'
'playground.params.resolution': 'Resolution',
'playground.params.taskType': 'Task Type',
'playground.params.voiceStyle': 'Voice Style',
'playground.params.maxTokens': 'Maximum Generate Length',
'playground.params.refAudio': 'Reference Audio URL'
};
// ========== To-Do: Translate Keys (Remove After Translation) ==========
+5 -1
View File
@@ -160,7 +160,11 @@ export default {
'playground.uploadImage.url.holder': 'Enter an image URL',
'playground.uploadImage.url.button': 'Add Image from URL',
'playground.params.duration': 'Duration (seconds)',
'playground.params.resolution': 'Resolution'
'playground.params.resolution': 'Resolution',
'playground.params.taskType': 'Task Type',
'playground.params.voiceStyle': 'Voice Style',
'playground.params.maxTokens': 'Maximum Generate Length',
'playground.params.refAudio': 'Reference Audio URL'
};
// ========== To-Do: Translate Keys (Remove After Translation) ==========
+5 -1
View File
@@ -156,5 +156,9 @@ export default {
'playground.uploadImage.url.holder': '请输入图片链接',
'playground.uploadImage.url.button': '从链接添加图片',
'playground.params.duration': '时长 (秒)',
'playground.params.resolution': '分辨率'
'playground.params.resolution': '分辨率',
'playground.params.taskType': '任务类型',
'playground.params.voiceStyle': '语音风格',
'playground.params.maxTokens': '最大生成长度',
'playground.params.refAudio': '参考音频 URL'
};
+118 -35
View File
@@ -2,10 +2,12 @@ import { setRouteCache } from '@/atoms/route-cache';
import AlertInfo from '@/components/alert-info';
import IconFont from '@/components/icon-font';
import AutoComplete from '@/components/seal-form/auto-complete';
import FieldComponent from '@/components/seal-form/field-component';
import SealSelect from '@/components/seal-form/seal-select';
import SpeechContent from '@/components/speech-content';
import routeCachekey from '@/config/route-cachekey';
import useOverlayScroller from '@/hooks/use-overlay-scroller';
import CollapsePanel from '@/pages/_components/collapse-panel';
import { getLocale, useIntl, useSearchParams } from '@umijs/max';
import { Form, Spin } from 'antd';
import classNames from 'classnames';
@@ -22,7 +24,10 @@ import React, {
} from 'react';
import { AUDIO_TEXT_TO_SPEECH_API, CHAT_API, textToSpeech } from '../apis';
import { extractErrorMessage } from '../config';
import { TTSParamsConfig as paramsConfig } from '../config/params-config';
import {
TTSParamsConfig as paramsConfig,
TTSAdvancedParamsConfig
} from '../config/params-config';
import { MessageItem, ParamsSchema } from '../config/types';
import '../style/ground-llm.less';
import '../style/system-message-wrap.less';
@@ -31,6 +36,14 @@ import DynamicParams from './dynamic-params';
import MessageInput from './message-input';
import ViewCommonCode from './view-common-code';
const MetaFields = [
'task_type',
'language',
'instructions',
'max_new_tokens',
'ref_audio'
];
interface MessageProps {
modelList: Global.BaseOption<string>[];
loaded?: boolean;
@@ -75,10 +88,14 @@ const GroundTTS: React.FC<MessageProps> = forwardRef((props, ref) => {
const [voiceDataList, setVoiceList] = useState<Global.BaseOption<string>[]>(
[]
);
const [modelMeta, setModelMeta] = useState<any>({});
const formRef = useRef<any>(null);
const { initialize } = useOverlayScroller();
const { initialize: innitializeParams } = useOverlayScroller();
const [activeKey, setActiveKey] = useState<string | string[]>(
'advanced_config'
);
useImperativeHandle(ref, () => {
return {
@@ -226,31 +243,32 @@ const GroundTTS: React.FC<MessageProps> = forwardRef((props, ref) => {
setShow(false);
};
const handleSelectModel = useCallback(
async (value: string) => {
if (!value) {
return;
}
const model = modelList.find((item) => item.value === value);
const list = _.map(model?.meta?.voices || [], (item: any) => {
return {
label: item,
value: item
};
});
const handleSelectModel = async (value: string) => {
if (!value) {
return;
}
const model = modelList.find((item) => item.value === value);
const list = _.map(model?.meta?.voices || [], (item: any) => {
return {
label: item,
value: item
};
});
const newList = sortVoiceList(locale, list);
setVoiceList(newList);
setParams((pre: any) => {
return {
...pre,
model: value,
voice: newList[0]?.value
};
});
},
[modelList]
);
const newList = sortVoiceList(locale, list);
setVoiceList(newList);
setModelMeta(model?.meta || {});
setParams((pre: any) => {
return {
...pre,
..._.pick(model?.meta || {}, MetaFields),
task_type: model?.meta?.default_task_type,
max_new_tokens: model?.meta?.max_model_len || null,
model: value,
voice: newList[0]?.value
};
});
};
const handleOnValuesChange = useCallback(
(changeValues: Record<string, any>, allValues: Record<string, any>) => {
@@ -273,7 +291,65 @@ const GroundTTS: React.FC<MessageProps> = forwardRef((props, ref) => {
checkvalueRef.current = e.target.checked;
};
const renderExtra = useMemo(() => {
const handleOnCollapse = (keys: string | string[]) => {
setActiveKey(keys);
};
const renderAdvancedFields = () => {
const formItems = TTSAdvancedParamsConfig.map((item: ParamsSchema) => {
const comProps = {
...item.attrs,
label: item.label.isLocalized
? intl.formatMessage({ id: item.label.text })
: item.label.text
};
return (
<>
<Form.Item
name={item.name}
rules={item.rules}
key={item.name}
{...item.formItemAttrs}
>
<FieldComponent
{...comProps}
description={
item.description?.isLocalized
? intl.formatMessage({ id: item.description.text })
: item.description?.text
}
onChange={null}
{..._.omit(item, [
'name',
'rules',
'disabledConfig',
'description'
])}
{...item.initAttrs?.(modelMeta)}
></FieldComponent>
</Form.Item>
</>
);
});
return (
<CollapsePanel
activeKey={activeKey}
onChange={handleOnCollapse}
accordion={false}
items={[
{
key: 'advanced_config',
label: intl.formatMessage({ id: 'resources.form.advanced' }),
forceRender: true,
children: formItems
}
]}
></CollapsePanel>
);
};
const renderExtra = () => {
return paramsConfig.map((item: ParamsSchema) => {
const comProps = {
...item.attrs,
@@ -283,16 +359,18 @@ const GroundTTS: React.FC<MessageProps> = forwardRef((props, ref) => {
: item.label.text
};
return (
<Form.Item name={item.name} rules={item.rules} key={item.name}>
{item.type === 'AutoComplete' ? (
<AutoComplete {...comProps} />
) : (
<SealSelect {...comProps}></SealSelect>
)}
</Form.Item>
<>
<Form.Item name={item.name} rules={item.rules} key={item.name}>
{item.type === 'AutoComplete' ? (
<AutoComplete {...comProps} />
) : (
<SealSelect {...comProps}></SealSelect>
)}
</Form.Item>
</>
);
});
}, [paramsConfig, intl, voiceList]);
};
useEffect(() => {
if (defaultModel && modelList.length) {
@@ -396,7 +474,12 @@ const GroundTTS: React.FC<MessageProps> = forwardRef((props, ref) => {
onValuesChange={handleOnValuesChange}
initialValues={parameters}
modelList={modelList}
extra={[renderExtra]}
extra={[
<>
{renderExtra()}
{renderAdvancedFields()}
</>
]}
/>
</div>
</div>
@@ -1,3 +1,4 @@
import _ from 'lodash';
import { ParamsSchema } from './types';
export interface SizeOption {
@@ -89,6 +90,124 @@ export const TTSParamsConfig: ParamsSchema[] = [
// }
];
export const TTSAdvancedParamsConfig: ParamsSchema[] = [
{
type: 'Select',
name: 'task_type',
options: [],
attrs: {
allowClear: true
},
label: {
text: 'playground.params.taskType',
isLocalized: true
},
initAttrs: (meta: any) => {
return {
options: _.map(meta?.task_types || [], (item: string) => ({
label: item,
value: item
}))
};
},
rules: [
{
required: false
}
]
},
{
type: 'Select',
name: 'language',
options: [],
initAttrs: (meta: any) => {
return {
options: _.map(meta?.languages || [], (item: string) => ({
label: item,
value: item
}))
};
},
attrs: {
allowClear: true
},
label: {
text: 'playground.params.language',
isLocalized: true
},
rules: [
{
required: false
}
]
},
{
type: 'Select',
name: 'instructions',
label: {
text: 'playground.params.voiceStyle',
isLocalized: true
},
attrs: {
allowClear: true
},
initAttrs: (meta: any) => {
return {
options: _.map(meta?.voices || [], (item: string) => ({
label: item,
value: item
}))
};
},
rules: [
{
required: false
}
]
},
{
type: 'InputNumber',
name: 'max_new_tokens',
label: {
text: 'playground.params.maxTokens',
isLocalized: true
},
attrs: {
allowClear: true,
min: 0
},
formItemAttrs: {
hidden: true,
getValueProps: (value: number) => {
return {
value: value || null
};
}
},
rules: [
{
required: false
}
]
},
{
type: 'Input',
name: 'ref_audio',
label: {
text: 'playground.params.refAudio',
isLocalized: true
},
attrs: {
allowClear: true
},
rules: [
{
required: false
}
]
}
];
export const RealtimeParamsConfig: ParamsSchema[] = [
{
type: 'Select',
+1
View File
@@ -53,6 +53,7 @@ export interface ParamsSchema {
text: string;
isLocalized?: boolean;
};
initAttrs?: (meta: any) => Record<string, any>;
dependencies?: string[];
style?: React.CSSProperties;
options?: Global.BaseOption<string | number | null>[];