Skip to content

Commit 010a34a

Browse files
committed
feat: open-ai tts support
1 parent 247e761 commit 010a34a

File tree

7 files changed

+431
-19
lines changed

7 files changed

+431
-19
lines changed

.env

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
1-
NEXT_PUBLIC_DOMAIN=https://easyvideotrans.com
1+
NEXT_PUBLIC_DOMAIN=https://easyvideotrans.com
2+
BACKEND_URL=http://localhost:8080

app/(default)/playground/pageContent.tsx

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import {
1212
} from '@/app/utils/mitter';
1313
import React, { useEffect } from 'react';
1414
import ChineseAudio from '@/app/(default)/playground/widgets/chineseAudio';
15+
import VerifySubtitles from '@/app/(default)/playground/widgets/verifySubtitles';
1516
import ConnectAudio from '@/app/(default)/playground/widgets/connectAudio';
1617
import dynamic from 'next/dynamic';
1718

@@ -65,16 +66,21 @@ const PageContent = () => {
6566
},
6667
{
6768
key: '3',
69+
label: '校验字幕',
70+
children: <VerifySubtitles onFinish={onNextStep} videoId={state.videoId} />,
71+
},
72+
{
73+
key: '4',
6874
label: '中文字幕配音',
6975
children: <ChineseAudio onFinish={onNextStep} videoId={state.videoId} />,
7076
},
7177
{
72-
key: '4',
78+
key: '5',
7379
label: '语音连接',
7480
children: <ConnectAudio onFinish={onNextStep} videoId={state.videoId} />,
7581
},
7682
{
77-
key: '5',
83+
key: '6',
7884
label: '渲染预览视频',
7985
children: <RenderVideo videoId={state.videoId} />,
8086
},

app/(default)/playground/widgets/chineseAudio.tsx

Lines changed: 97 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,26 @@ import { generateTTS } from '@/app/request/playground';
55
import { IGenerateTTSProp } from '@/app/type';
66
import { addLogEvent } from '@/app/utils/mitter';
77
import { TRANSLATE_OPTIONS } from '@/app/const/translate_option';
8+
import { OPENAI_VOICE_OPTIONS, OPENAI_MODEL_OPTIONS } from '@/app/const/openai_voices';
89

910
interface Props {
1011
onFinish: () => void;
1112
videoId: string;
1213
}
1314

15+
// Extended form type to include OpenAI-specific fields
16+
interface FormValues extends IGenerateTTSProp {
17+
openai_voice?: string;
18+
openai_model?: string;
19+
openai_instructions?: string;
20+
}
21+
1422
const ChineseAudio: React.FC<Props> = ({ onFinish, videoId }) => {
15-
const [form] = Form.useForm<IGenerateTTSProp>();
23+
const [form] = Form.useForm<FormValues>();
1624

1725
const state = useReactive({
1826
translateSrtOk: false,
27+
selectedVendor: 'openai', // Default to OpenAI TTS
1928
});
2029

2130
const { run: generateTTSRun, loading: generateTTSLoading } = useRequest(
@@ -38,18 +47,48 @@ const ChineseAudio: React.FC<Props> = ({ onFinish, videoId }) => {
3847
);
3948

4049
const handleGenerateTTS = async () => {
41-
const { tts_vendor, tts_key, tts_character } = form.getFieldsValue();
50+
const formValues = form.getFieldsValue() as any; // Type assertion to handle form values
51+
const { tts_vendor, tts_key, tts_character, openai_voice, openai_model, openai_instructions } = formValues;
52+
4253
const data: IGenerateTTSProp = {
4354
video_id: videoId,
4455
tts_vendor,
45-
tts_key,
46-
tts_character,
56+
tts_key: tts_key || '', // Only used for Edge TTS if needed
57+
tts_character: tts_character || '',
4758
};
59+
60+
// Add OpenAI-specific parameters if OpenAI vendor is selected
61+
if (tts_vendor === 'openai') {
62+
data.tts_params = {
63+
voice: openai_voice || 'alloy',
64+
model: openai_model || 'tts-1',
65+
instructions: openai_instructions || undefined,
66+
};
67+
}
68+
4869
generateTTSRun(data);
4970
};
5071

72+
const handleVendorChange = (vendor: string) => {
73+
state.selectedVendor = vendor;
74+
// Clear form fields when changing vendor
75+
if (vendor === 'openai') {
76+
form.setFieldsValue({
77+
tts_character: '', // Clear Edge TTS character when switching to OpenAI
78+
openai_voice: 'alloy', // Set default OpenAI voice
79+
openai_model: 'tts-1', // Set default OpenAI model
80+
});
81+
} else {
82+
form.setFieldsValue({
83+
tts_character: 'zh-CN-XiaoyiNeural', // Set default Edge TTS character
84+
});
85+
}
86+
};
87+
5188
useEffect(() => {
5289
form.setFieldValue('videoId', videoId);
90+
// Initialize vendor state from form initial values
91+
state.selectedVendor = 'openai';
5392
}, [videoId]);
5493

5594
return (
@@ -60,34 +99,78 @@ const ChineseAudio: React.FC<Props> = ({ onFinish, videoId }) => {
6099
layout="horizontal"
61100
initialValues={{
62101
videoId,
63-
tts_vendor: 'edge',
102+
tts_vendor: 'openai', // Default to OpenAI
64103
tts_key: '',
65104
tts_character: 'zh-CN-XiaoyiNeural',
105+
openai_voice: 'alloy',
106+
openai_model: 'tts-1',
107+
openai_instructions: '',
66108
}}
67109
onSubmitCapture={onFinish}
68110
>
69111
<Form.Item label="视频ID" name={'videoId'}>
70112
<Input disabled value={videoId} />
71113
</Form.Item>
72-
<Form.Item label={'TTS vendor'}>
114+
<Form.Item label={'TTS Vendor'}>
73115
<Form.Item
74116
name="tts_vendor"
75117
style={{ display: 'inline-block', width: '200px' }}
76118
>
77119
<Select
78120
placeholder="选择TTS vendor"
79-
options={[{ value: 'edge', label: 'edge' }]}
121+
onChange={handleVendorChange}
122+
options={[
123+
{ value: 'openai', label: 'OpenAI TTS (推荐)' },
124+
{ value: 'edge', label: 'Microsoft Edge TTS (已弃用)' }
125+
]}
80126
/>
81127
</Form.Item>
82128
</Form.Item>
83-
<Form.Item label={'TTS Character'}>
84-
<Form.Item name="tts_character">
85-
<Select placeholder="选择TTS Character" options={TRANSLATE_OPTIONS} />
129+
130+
{/* Edge TTS Configuration */}
131+
{state.selectedVendor === 'edge' && (
132+
<>
133+
<Form.Item label={'注意'}>
134+
<div style={{ color: '#ff4d4f', marginBottom: '10px' }}>
135+
⚠️ Edge TTS 已弃用,建议使用 OpenAI TTS 获得更好的语音质量
136+
</div>
137+
</Form.Item>
138+
<Form.Item label={'Edge Character'}>
139+
<Form.Item name="tts_character">
140+
<Select placeholder="选择Edge TTS角色" options={TRANSLATE_OPTIONS} />
141+
</Form.Item>
142+
</Form.Item>
143+
</>
144+
)}
145+
146+
{/* OpenAI TTS Configuration */}
147+
{state.selectedVendor === 'openai' && (
148+
<>
149+
<Form.Item label={'OpenAI Voice'}>
150+
<Form.Item name="openai_voice">
151+
<Select placeholder="选择OpenAI语音" options={OPENAI_VOICE_OPTIONS} />
152+
</Form.Item>
153+
</Form.Item>
154+
<Form.Item label={'OpenAI Model'}>
155+
<Form.Item name="openai_model">
156+
<Select placeholder="选择OpenAI模型" options={OPENAI_MODEL_OPTIONS} />
157+
</Form.Item>
158+
</Form.Item>
159+
<Form.Item label={'Voice Instructions'} name="openai_instructions">
160+
<Input.TextArea
161+
placeholder="可选:语音指令,如'Speak in a cheerful and positive tone'"
162+
rows={2}
163+
/>
164+
</Form.Item>
165+
</>
166+
)}
167+
168+
{/* Only show API key field for Edge TTS */}
169+
{state.selectedVendor === 'edge' && (
170+
<Form.Item label="Key" name={'tts_key'}>
171+
<Input placeholder="密钥(Edge TTS可选)" />
86172
</Form.Item>
87-
</Form.Item>
88-
<Form.Item label="key" name={'tts_key'}>
89-
<Input />
90-
</Form.Item>
173+
)}
91174
<Form.Item label={'生成TTS'}>
92175
<Button
93176
type="primary"

0 commit comments

Comments
 (0)