chore: upload a ref audio
This commit is contained in:
@@ -47,7 +47,7 @@ const UploadAudio: React.FC<UploadAudioProps> = (props) => {
|
||||
return (
|
||||
<Tooltip
|
||||
styles={{
|
||||
body: {
|
||||
container: {
|
||||
maxWidth: 290,
|
||||
width: 'max-content'
|
||||
}
|
||||
|
||||
@@ -165,7 +165,9 @@ export default {
|
||||
'playground.params.duration': 'Duration (seconds)',
|
||||
'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'
|
||||
'playground.params.voiceStyle': 'Instructions',
|
||||
'playground.params.maxTokens': 'Max New Tokens',
|
||||
'playground.params.refAudio': 'Reference Audio',
|
||||
'playground.params.refAudio.tips':
|
||||
'Enter a reference audio URL, or upload an audio file.'
|
||||
};
|
||||
|
||||
@@ -168,9 +168,11 @@ export default {
|
||||
'playground.params.duration': 'Duration (seconds)',
|
||||
'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'
|
||||
'playground.params.voiceStyle': 'Instructions',
|
||||
'playground.params.maxTokens': 'Max New Tokens',
|
||||
'playground.params.refAudio': 'Reference Audio',
|
||||
'playground.params.refAudio.tips':
|
||||
'Enter a reference audio URL, or upload an audio file.'
|
||||
};
|
||||
|
||||
// ========== To-Do: Translate Keys (Remove After Translation) ==========
|
||||
|
||||
@@ -162,9 +162,11 @@ export default {
|
||||
'playground.params.duration': 'Duration (seconds)',
|
||||
'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'
|
||||
'playground.params.voiceStyle': 'Instructions',
|
||||
'playground.params.maxTokens': 'Max New Tokens',
|
||||
'playground.params.refAudio': 'Reference Audio',
|
||||
'playground.params.refAudio.tips':
|
||||
'Enter a reference audio URL, or upload an audio file.'
|
||||
};
|
||||
|
||||
// ========== To-Do: Translate Keys (Remove After Translation) ==========
|
||||
|
||||
@@ -158,7 +158,9 @@ export default {
|
||||
'playground.params.duration': '时长 (秒)',
|
||||
'playground.params.resolution': '分辨率',
|
||||
'playground.params.taskType': '任务类型',
|
||||
'playground.params.voiceStyle': '语音风格',
|
||||
'playground.params.maxTokens': '最大生成长度',
|
||||
'playground.params.refAudio': '参考音频 URL'
|
||||
'playground.params.voiceStyle': '情感',
|
||||
'playground.params.maxTokens': '最大生成 Token 数',
|
||||
'playground.params.refAudio': '参考音频',
|
||||
'playground.params.refAudio.tips':
|
||||
'输入一个参考音频的 URL,或上传一个音频文件。'
|
||||
};
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
import SealInput from '@/components/seal-form/seal-input';
|
||||
import UploadAudio from '@/components/upload-audio';
|
||||
import { convertFileToBase64 } from '@/utils/load-audio-file';
|
||||
import { CloseCircleFilled } from '@ant-design/icons';
|
||||
import { useIntl } from '@umijs/max';
|
||||
import { Form } from 'antd';
|
||||
import React from 'react';
|
||||
import styled from 'styled-components';
|
||||
import { useFormContext } from '../config/form-context';
|
||||
|
||||
const SuffixWrapper = styled.div`
|
||||
.icon {
|
||||
font-size: 12px;
|
||||
color: var(--ant-color-text-quaternary);
|
||||
cursor: pointer;
|
||||
&:hover {
|
||||
color: var(--ant-color-text-tertiary);
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
export const RefAudioFormItem: React.FC = () => {
|
||||
const { meta } = useFormContext();
|
||||
const form = Form.useFormInstance();
|
||||
const intl = useIntl();
|
||||
const [filleName, setFileName] = React.useState<string>('');
|
||||
|
||||
// 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 (
|
||||
<Form.Item
|
||||
name="ref_audio"
|
||||
getValueProps={(value) => ({ value: filleName ? filleName : value })}
|
||||
>
|
||||
<SealInput.Input
|
||||
allowClear
|
||||
readOnly={!!filleName}
|
||||
suffix={
|
||||
<SuffixWrapper>
|
||||
{filleName ? (
|
||||
<span onClick={handleClear}>
|
||||
<CloseCircleFilled className="icon" />
|
||||
</span>
|
||||
) : null}
|
||||
<UploadAudio
|
||||
size="small"
|
||||
type="text"
|
||||
accept={['.mp3', '.mp4', '.wav', '.m4a'].join(', ')}
|
||||
onChange={handleUploadChange}
|
||||
></UploadAudio>
|
||||
</SuffixWrapper>
|
||||
}
|
||||
description={intl.formatMessage({
|
||||
id: 'playground.params.refAudio.tips'
|
||||
})}
|
||||
label={intl.formatMessage({ id: 'playground.params.refAudio' })}
|
||||
></SealInput.Input>
|
||||
</Form.Item>
|
||||
);
|
||||
};
|
||||
@@ -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
|
||||
// }
|
||||
// ]
|
||||
// }
|
||||
];
|
||||
@@ -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<string, any>;
|
||||
};
|
||||
|
||||
const ParamsSettings: React.FC<ParamsSettingsProps> = forwardRef(
|
||||
@@ -36,7 +38,8 @@ const ParamsSettings: React.FC<ParamsSettingsProps> = forwardRef(
|
||||
paramsConfig,
|
||||
modelList,
|
||||
showModelSelector = true,
|
||||
extra
|
||||
extra,
|
||||
meta
|
||||
},
|
||||
ref
|
||||
) => {
|
||||
@@ -136,56 +139,60 @@ const ParamsSettings: React.FC<ParamsSettingsProps> = forwardRef(
|
||||
};
|
||||
|
||||
return (
|
||||
<Form
|
||||
name={formId}
|
||||
form={form}
|
||||
onValuesChange={handleValuesChange}
|
||||
onFinish={handleOnFinish}
|
||||
onFinishFailed={handleOnFinishFailed}
|
||||
initialValues={initialValues}
|
||||
>
|
||||
<div>
|
||||
{
|
||||
<>
|
||||
<h3 className="m-b-20 font-size-14 line-24 font-500">
|
||||
{parametersTitle || (
|
||||
<span>
|
||||
{intl.formatMessage({ id: 'playground.parameters' })}
|
||||
</span>
|
||||
<FormContext.Provider value={{ meta }}>
|
||||
<Form
|
||||
name={formId}
|
||||
form={form}
|
||||
onValuesChange={handleValuesChange}
|
||||
onFinish={handleOnFinish}
|
||||
onFinishFailed={handleOnFinishFailed}
|
||||
initialValues={initialValues}
|
||||
>
|
||||
<div>
|
||||
{
|
||||
<>
|
||||
<h3 className="m-b-20 font-size-14 line-24 font-500">
|
||||
{parametersTitle || (
|
||||
<span>
|
||||
{intl.formatMessage({ id: 'playground.parameters' })}
|
||||
</span>
|
||||
)}
|
||||
</h3>
|
||||
{showModelSelector && (
|
||||
<Form.Item
|
||||
name="model"
|
||||
rules={[
|
||||
{
|
||||
required: true,
|
||||
message: intl.formatMessage(
|
||||
{
|
||||
id: 'common.form.rule.select'
|
||||
},
|
||||
{
|
||||
name: intl.formatMessage({ id: 'playground.model' })
|
||||
}
|
||||
)
|
||||
}
|
||||
]}
|
||||
>
|
||||
<SealSelect
|
||||
description={intl.formatMessage({
|
||||
id: 'playground.model.noavailable.tips2'
|
||||
})}
|
||||
onChange={handleOnModelChange}
|
||||
showSearch={true}
|
||||
options={modelList}
|
||||
label={intl.formatMessage({ id: 'playground.model' })}
|
||||
></SealSelect>
|
||||
</Form.Item>
|
||||
)}
|
||||
</h3>
|
||||
{showModelSelector && (
|
||||
<Form.Item
|
||||
name="model"
|
||||
rules={[
|
||||
{
|
||||
required: true,
|
||||
message: intl.formatMessage(
|
||||
{
|
||||
id: 'common.form.rule.select'
|
||||
},
|
||||
{ name: intl.formatMessage({ id: 'playground.model' }) }
|
||||
)
|
||||
}
|
||||
]}
|
||||
>
|
||||
<SealSelect
|
||||
description={intl.formatMessage({
|
||||
id: 'playground.model.noavailable.tips2'
|
||||
})}
|
||||
onChange={handleOnModelChange}
|
||||
showSearch={true}
|
||||
options={modelList}
|
||||
label={intl.formatMessage({ id: 'playground.model' })}
|
||||
></SealSelect>
|
||||
</Form.Item>
|
||||
)}
|
||||
</>
|
||||
}
|
||||
{renderFields()}
|
||||
{extra}
|
||||
</div>
|
||||
</Form>
|
||||
</>
|
||||
}
|
||||
{renderFields()}
|
||||
{extra}
|
||||
</div>
|
||||
</Form>
|
||||
</FormContext.Provider>
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
@@ -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<MessageProps> = forwardRef((props, ref) => {
|
||||
key: 'advanced_config',
|
||||
label: intl.formatMessage({ id: 'resources.form.advanced' }),
|
||||
forceRender: true,
|
||||
children: formItems
|
||||
children: (
|
||||
<>
|
||||
{formItems}
|
||||
<RefAudioFormItem />
|
||||
</>
|
||||
)
|
||||
}
|
||||
]}
|
||||
></CollapsePanel>
|
||||
@@ -471,6 +477,7 @@ const GroundTTS: React.FC<MessageProps> = forwardRef((props, ref) => {
|
||||
<div className="box">
|
||||
<DynamicParams
|
||||
ref={formRef}
|
||||
meta={modelMeta}
|
||||
onValuesChange={handleOnValuesChange}
|
||||
initialValues={parameters}
|
||||
modelList={modelList}
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
import { createContext, useContext } from 'react';
|
||||
|
||||
export interface FormContextProps {
|
||||
meta?: Record<string, any>;
|
||||
}
|
||||
|
||||
/**
|
||||
* for dynamic form config useContext
|
||||
*/
|
||||
export const FormContext = createContext<FormContextProps>({});
|
||||
|
||||
export const useFormContext = () => {
|
||||
const context = useContext(FormContext);
|
||||
if (!context) {
|
||||
throw new Error('useFormContext must be used within a FormContextProvider');
|
||||
}
|
||||
return context;
|
||||
};
|
||||
@@ -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',
|
||||
|
||||
@@ -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<string, string> = {
|
||||
'audio/wav': 'wav',
|
||||
'audio/mp3': 'mp3',
|
||||
|
||||
Reference in New Issue
Block a user