From 7a5c28228b5446ae2482775d42960e8cbdbed337 Mon Sep 17 00:00:00 2001 From: jialin Date: Sat, 31 Jan 2026 13:39:42 +0800 Subject: [PATCH] chore: upload a ref audio --- src/components/upload-audio/index.tsx | 2 +- src/locales/en-US/playground.ts | 8 +- src/locales/ja-JP/playground.ts | 8 +- src/locales/ru-RU/playground.ts | 8 +- src/locales/zh-CN/playground.ts | 8 +- src/pages/playground/audio/form.tsx | 77 ++++++++ src/pages/playground/audio/params-config.ts | 155 +++++++++++++++ .../playground/components/dynamic-params.tsx | 107 ++++++----- .../playground/components/ground-tts.tsx | 13 +- src/pages/playground/config/form-context.ts | 18 ++ src/pages/playground/config/params-config.ts | 179 ------------------ src/utils/load-audio-file.ts | 2 + 12 files changed, 340 insertions(+), 245 deletions(-) create mode 100644 src/pages/playground/audio/form.tsx create mode 100644 src/pages/playground/audio/params-config.ts create mode 100644 src/pages/playground/config/form-context.ts diff --git a/src/components/upload-audio/index.tsx b/src/components/upload-audio/index.tsx index 1a8e03d4..19d79599 100644 --- a/src/components/upload-audio/index.tsx +++ b/src/components/upload-audio/index.tsx @@ -47,7 +47,7 @@ const UploadAudio: React.FC = (props) => { return ( { + const { meta } = useFormContext(); + const form = Form.useFormInstance(); + const intl = useIntl(); + const [filleName, setFileName] = React.useState(''); + + // handle upload audio file, transfer to a base64 url + const handleUploadChange = async (data: { file: any; fileList: any }) => { + const { file } = data; + const base64 = await convertFileToBase64(file); + form.setFieldsValue({ + ref_audio: base64 + }); + setFileName(file.name); + + console.log('Uploaded file base64 url:', base64); + }; + + const handleClear = () => { + form.setFieldsValue({ + ref_audio: '' + }); + setFileName(''); + }; + + return ( + ({ value: filleName ? filleName : value })} + > + + {filleName ? ( + + + + ) : null} + + + } + description={intl.formatMessage({ + id: 'playground.params.refAudio.tips' + })} + label={intl.formatMessage({ id: 'playground.params.refAudio' })} + > + + ); +}; diff --git a/src/pages/playground/audio/params-config.ts b/src/pages/playground/audio/params-config.ts new file mode 100644 index 00000000..f011a772 --- /dev/null +++ b/src/pages/playground/audio/params-config.ts @@ -0,0 +1,155 @@ +import _ from 'lodash'; +import { ParamsSchema } from '../config/types'; + +export const TTSAdvancedParamsConfig: ParamsSchema[] = [ + { + type: 'Input', + name: 'task_type', + options: [], + attrs: { + allowClear: true + }, + label: { + text: 'playground.params.taskType', + isLocalized: true + }, + rules: [ + { + required: false + } + ] + }, + { + type: 'AutoComplete', + 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, + step: 1, + min: 0 + }, + formItemAttrs: { + getValueProps: (value: number) => { + return { + value: value || null + }; + } + }, + rules: [ + { + required: false + } + ] + } +]; + +export const TTSParamsConfig: ParamsSchema[] = [ + { + type: 'AutoComplete', + name: 'voice', + options: [], + label: { + text: 'playground.params.voice', + isLocalized: true + }, + rules: [ + { + required: false, + message: 'Voice is required' + } + ] + }, + { + type: 'Select', + name: 'response_format', + options: [ + { label: 'mp3', value: 'mp3' }, + // { label: 'opus', value: 'opus' }, + // { label: 'aac', value: 'aac' }, + // { label: 'flac', value: 'flac' }, + { label: 'wav', value: 'wav' } + // { label: 'pcm', value: 'pcm' } + ], + label: { + text: 'playground.params.format', + isLocalized: true + }, + rules: [ + { + required: false + } + ] + } + // { + // type: 'Select', + // name: 'speed', + // options: [ + // { label: '0.25x', value: 0.25 }, + // { label: '0.5x', value: 0.5 }, + // { label: '1x', value: 1 }, + // { label: '2x', value: 2 }, + // { label: '4x', value: 4 } + // ], + // label: { + // text: 'playground.params.speed', + // isLocalized: true + // }, + // rules: [ + // { + // required: false + // } + // ] + // } +]; diff --git a/src/pages/playground/components/dynamic-params.tsx b/src/pages/playground/components/dynamic-params.tsx index f6795c96..d76002cb 100644 --- a/src/pages/playground/components/dynamic-params.tsx +++ b/src/pages/playground/components/dynamic-params.tsx @@ -10,6 +10,7 @@ import React, { useId, useImperativeHandle } from 'react'; +import { FormContext } from '../config/form-context'; import { ParamsSchema } from '../config/types'; type ParamsSettingsProps = { @@ -24,6 +25,7 @@ type ParamsSettingsProps = { extra?: React.ReactNode; watchFields?: string[]; formFields?: string; + meta?: Record; }; const ParamsSettings: React.FC = forwardRef( @@ -36,7 +38,8 @@ const ParamsSettings: React.FC = forwardRef( paramsConfig, modelList, showModelSelector = true, - extra + extra, + meta }, ref ) => { @@ -136,56 +139,60 @@ const ParamsSettings: React.FC = forwardRef( }; return ( -
-
- { - <> -

- {parametersTitle || ( - - {intl.formatMessage({ id: 'playground.parameters' })} - + + +
+ { + <> +

+ {parametersTitle || ( + + {intl.formatMessage({ id: 'playground.parameters' })} + + )} +

+ {showModelSelector && ( + + + )} -

- {showModelSelector && ( - - - - )} - - } - {renderFields()} - {extra} -
-
+ + } + {renderFields()} + {extra} + + + ); } ); diff --git a/src/pages/playground/components/ground-tts.tsx b/src/pages/playground/components/ground-tts.tsx index 83623d6e..5801a790 100644 --- a/src/pages/playground/components/ground-tts.tsx +++ b/src/pages/playground/components/ground-tts.tsx @@ -23,11 +23,12 @@ import React, { useState } from 'react'; import { AUDIO_TEXT_TO_SPEECH_API, CHAT_API, textToSpeech } from '../apis'; -import { extractErrorMessage } from '../config'; +import { RefAudioFormItem } from '../audio/form'; import { TTSParamsConfig as paramsConfig, TTSAdvancedParamsConfig -} from '../config/params-config'; +} from '../audio/params-config'; +import { extractErrorMessage } from '../config'; import { MessageItem, ParamsSchema } from '../config/types'; import '../style/ground-llm.less'; import '../style/system-message-wrap.less'; @@ -342,7 +343,12 @@ const GroundTTS: React.FC = forwardRef((props, ref) => { key: 'advanced_config', label: intl.formatMessage({ id: 'resources.form.advanced' }), forceRender: true, - children: formItems + children: ( + <> + {formItems} + + + ) } ]} > @@ -471,6 +477,7 @@ const GroundTTS: React.FC = forwardRef((props, ref) => {
; +} + +/** + * for dynamic form config useContext + */ +export const FormContext = createContext({}); + +export const useFormContext = () => { + const context = useContext(FormContext); + if (!context) { + throw new Error('useFormContext must be used within a FormContextProvider'); + } + return context; +}; diff --git a/src/pages/playground/config/params-config.ts b/src/pages/playground/config/params-config.ts index dd46e1ae..c2a1c81a 100644 --- a/src/pages/playground/config/params-config.ts +++ b/src/pages/playground/config/params-config.ts @@ -1,4 +1,3 @@ -import _ from 'lodash'; import { ParamsSchema } from './types'; export interface SizeOption { @@ -31,184 +30,6 @@ export const imageSizeOptions: { { label: '1024x1024(1:1)', value: '1024x1024', width: 1024, height: 1024 } ]; -export const TTSParamsConfig: ParamsSchema[] = [ - { - type: 'AutoComplete', - name: 'voice', - options: [], - label: { - text: 'playground.params.voice', - isLocalized: true - }, - rules: [ - { - required: false, - message: 'Voice is required' - } - ] - }, - { - type: 'Select', - name: 'response_format', - options: [ - { label: 'mp3', value: 'mp3' }, - // { label: 'opus', value: 'opus' }, - // { label: 'aac', value: 'aac' }, - // { label: 'flac', value: 'flac' }, - { label: 'wav', value: 'wav' } - // { label: 'pcm', value: 'pcm' } - ], - label: { - text: 'playground.params.format', - isLocalized: true - }, - rules: [ - { - required: false - } - ] - } - // { - // type: 'Select', - // name: 'speed', - // options: [ - // { label: '0.25x', value: 0.25 }, - // { label: '0.5x', value: 0.5 }, - // { label: '1x', value: 1 }, - // { label: '2x', value: 2 }, - // { label: '4x', value: 4 } - // ], - // label: { - // text: 'playground.params.speed', - // isLocalized: true - // }, - // rules: [ - // { - // required: false - // } - // ] - // } -]; - -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: 'Slider', - name: 'max_new_tokens', - label: { - text: 'playground.params.maxTokens', - isLocalized: true - }, - attrs: { - allowClear: true, - inputnumber: true, - step: 1, - min: 0 - }, - formItemAttrs: { - 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', diff --git a/src/utils/load-audio-file.ts b/src/utils/load-audio-file.ts index 69596c36..f0030d86 100644 --- a/src/utils/load-audio-file.ts +++ b/src/utils/load-audio-file.ts @@ -1,6 +1,8 @@ import { message } from 'antd'; import { convertFileSize } from './index'; +// TODO: create a file.ts in utils folder to manage file related utils + export const audioTypeMap: Record = { 'audio/wav': 'wav', 'audio/mp3': 'mp3',