Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .env
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
NEXT_PUBLIC_DOMAIN=https://easyvideotrans.com
NEXT_PUBLIC_DOMAIN=https://easyvideotrans.com
BACKEND_URL=http://localhost:8080
10 changes: 8 additions & 2 deletions app/(default)/playground/pageContent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
} from '@/app/utils/mitter';
import React, { useEffect } from 'react';
import ChineseAudio from '@/app/(default)/playground/widgets/chineseAudio';
import VerifySubtitles from '@/app/(default)/playground/widgets/verifySubtitles';
import ConnectAudio from '@/app/(default)/playground/widgets/connectAudio';
import dynamic from 'next/dynamic';

Expand Down Expand Up @@ -65,16 +66,21 @@ const PageContent = () => {
},
{
key: '3',
label: '校验字幕',
children: <VerifySubtitles onFinish={onNextStep} videoId={state.videoId} />,
},
{
key: '4',
label: '中文字幕配音',
children: <ChineseAudio onFinish={onNextStep} videoId={state.videoId} />,
},
{
key: '4',
key: '5',
label: '语音连接',
children: <ConnectAudio onFinish={onNextStep} videoId={state.videoId} />,
},
{
key: '5',
key: '6',
label: '渲染预览视频',
children: <RenderVideo videoId={state.videoId} />,
},
Expand Down
111 changes: 97 additions & 14 deletions app/(default)/playground/widgets/chineseAudio.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,26 @@ import { generateTTS } from '@/app/request/playground';
import { IGenerateTTSProp } from '@/app/type';
import { addLogEvent } from '@/app/utils/mitter';
import { TRANSLATE_OPTIONS } from '@/app/const/translate_option';
import { OPENAI_VOICE_OPTIONS, OPENAI_MODEL_OPTIONS } from '@/app/const/openai_voices';

interface Props {
onFinish: () => void;
videoId: string;
}

// Extended form type to include OpenAI-specific fields
interface FormValues extends IGenerateTTSProp {
openai_voice?: string;
openai_model?: string;
openai_instructions?: string;
}

const ChineseAudio: React.FC<Props> = ({ onFinish, videoId }) => {
const [form] = Form.useForm<IGenerateTTSProp>();
const [form] = Form.useForm<FormValues>();

const state = useReactive({
translateSrtOk: false,
selectedVendor: 'openai', // Default to OpenAI TTS
});

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

const handleGenerateTTS = async () => {
const { tts_vendor, tts_key, tts_character } = form.getFieldsValue();
const formValues = form.getFieldsValue() as any; // Type assertion to handle form values
const { tts_vendor, tts_key, tts_character, openai_voice, openai_model, openai_instructions } = formValues;

const data: IGenerateTTSProp = {
video_id: videoId,
tts_vendor,
tts_key,
tts_character,
tts_key: tts_key || '', // Only used for Edge TTS if needed
tts_character: tts_character || '',
};

// Add OpenAI-specific parameters if OpenAI vendor is selected
if (tts_vendor === 'openai') {
data.tts_params = {
voice: openai_voice || 'alloy',
model: openai_model || 'tts-1',
instructions: openai_instructions || undefined,
};
}

generateTTSRun(data);
};

const handleVendorChange = (vendor: string) => {
state.selectedVendor = vendor;
// Clear form fields when changing vendor
if (vendor === 'openai') {
form.setFieldsValue({
tts_character: '', // Clear Edge TTS character when switching to OpenAI
openai_voice: 'alloy', // Set default OpenAI voice
openai_model: 'tts-1', // Set default OpenAI model
});
} else {
form.setFieldsValue({
tts_character: 'zh-CN-XiaoyiNeural', // Set default Edge TTS character
});
}
};

useEffect(() => {
form.setFieldValue('videoId', videoId);
// Initialize vendor state from form initial values
state.selectedVendor = 'openai';
}, [videoId]);

return (
Expand All @@ -60,34 +99,78 @@ const ChineseAudio: React.FC<Props> = ({ onFinish, videoId }) => {
layout="horizontal"
initialValues={{
videoId,
tts_vendor: 'edge',
tts_vendor: 'openai', // Default to OpenAI
tts_key: '',
tts_character: 'zh-CN-XiaoyiNeural',
openai_voice: 'alloy',
openai_model: 'tts-1',
openai_instructions: '',
}}
onSubmitCapture={onFinish}
>
<Form.Item label="视频ID" name={'videoId'}>
<Input disabled value={videoId} />
</Form.Item>
<Form.Item label={'TTS vendor'}>
<Form.Item label={'TTS Vendor'}>
<Form.Item
name="tts_vendor"
style={{ display: 'inline-block', width: '200px' }}
>
<Select
placeholder="选择TTS vendor"
options={[{ value: 'edge', label: 'edge' }]}
onChange={handleVendorChange}
options={[
{ value: 'openai', label: 'OpenAI TTS (推荐)' },
{ value: 'edge', label: 'Microsoft Edge TTS (已弃用)' }
]}
/>
</Form.Item>
</Form.Item>
<Form.Item label={'TTS Character'}>
<Form.Item name="tts_character">
<Select placeholder="选择TTS Character" options={TRANSLATE_OPTIONS} />

{/* Edge TTS Configuration */}
{state.selectedVendor === 'edge' && (
<>
<Form.Item label={'注意'}>
<div style={{ color: '#ff4d4f', marginBottom: '10px' }}>
⚠️ Edge TTS 已弃用,建议使用 OpenAI TTS 获得更好的语音质量
</div>
</Form.Item>
<Form.Item label={'Edge Character'}>
<Form.Item name="tts_character">
<Select placeholder="选择Edge TTS角色" options={TRANSLATE_OPTIONS} />
</Form.Item>
</Form.Item>
</>
)}

{/* OpenAI TTS Configuration */}
{state.selectedVendor === 'openai' && (
<>
<Form.Item label={'OpenAI Voice'}>
<Form.Item name="openai_voice">
<Select placeholder="选择OpenAI语音" options={OPENAI_VOICE_OPTIONS} />
</Form.Item>
</Form.Item>
<Form.Item label={'OpenAI Model'}>
<Form.Item name="openai_model">
<Select placeholder="选择OpenAI模型" options={OPENAI_MODEL_OPTIONS} />
</Form.Item>
</Form.Item>
<Form.Item label={'Voice Instructions'} name="openai_instructions">
<Input.TextArea
placeholder="可选:语音指令,如'Speak in a cheerful and positive tone'"
rows={2}
/>
</Form.Item>
</>
)}

{/* Only show API key field for Edge TTS */}
{state.selectedVendor === 'edge' && (
<Form.Item label="Key" name={'tts_key'}>
<Input placeholder="密钥(Edge TTS可选)" />
</Form.Item>
</Form.Item>
<Form.Item label="key" name={'tts_key'}>
<Input />
</Form.Item>
)}
<Form.Item label={'生成TTS'}>
<Button
type="primary"
Expand Down
Loading
Loading