video-flow-b/components/pages/script-to-video.tsx

168 lines
6.2 KiB
TypeScript

"use client";
import { useState } from 'react';
import { Button } from '@/components/ui/button';
import { Card } from '@/components/ui/card';
import { Textarea } from '@/components/ui/textarea';
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
import { ArrowLeft, Loader2 } from 'lucide-react';
import { useRouter } from 'next/navigation';
import { ModeEnum, ResolutionEnum } from "@/app/model/enums";
import { createScriptEpisode, CreateScriptEpisodeRequest, updateScriptEpisode, UpdateScriptEpisodeRequest } from "@/api/script_episode";
import { convertScriptToScene } from "@/api/video_flow";
export function ScriptToVideo() {
const router = useRouter();
const [script, setScript] = useState('');
const [selectedMode, setSelectedMode] = useState<ModeEnum>(ModeEnum.AUTOMATIC);
const [selectedResolution, setSelectedResolution] = useState<ResolutionEnum>(ResolutionEnum.HD_720P);
const [isCreating, setIsCreating] = useState(false);
const handleBack = () => {
router.push('/create');
};
const handleCreate = async () => {
if (!script.trim()) {
alert('请输入剧本内容');
return;
}
try {
setIsCreating(true);
// Create episode
const episodeData: CreateScriptEpisodeRequest = {
title: "Script Episode",
script_id: 0, // This should come from a project
status: 1,
summary: script
};
const episodeResponse = await createScriptEpisode(episodeData);
if (episodeResponse.code !== 0) {
alert(`创建剧集失败: ${episodeResponse.message}`);
return;
}
const episodeId = episodeResponse.data.id;
// Convert script to scenes
const convertResponse = await convertScriptToScene(script, episodeId, 0);
if (convertResponse.code === 0) {
// Update episode with generated data
const updateEpisodeData: UpdateScriptEpisodeRequest = {
id: episodeId,
atmosphere: convertResponse.data.atmosphere,
summary: convertResponse.data.summary,
scene: convertResponse.data.scene,
characters: convertResponse.data.characters,
};
await updateScriptEpisode(updateEpisodeData);
// Navigate to workflow
router.push(`/create/work-flow?episodeId=${episodeId}`);
} else {
alert(`转换失败: ${convertResponse.message}`);
}
} catch (error) {
console.error('创建过程出错:', error);
alert("创建项目时发生错误,请稍后重试");
} finally {
setIsCreating(false);
}
};
return (
<div className="min-h-screen bg-gradient-to-br from-slate-900 via-purple-900 to-slate-900 p-6">
<div className="max-w-4xl mx-auto">
{/* Header */}
<div className="flex items-center gap-4 mb-8">
<Button
variant="ghost"
size="sm"
onClick={handleBack}
className="text-white/70 hover:text-white"
>
<ArrowLeft className="h-4 w-4" />
</Button>
<h1 className="text-2xl font-bold text-white">Script to Video</h1>
</div>
{/* Main Content */}
<Card className="p-6 bg-white/5 border-white/10">
<div className="space-y-6">
{/* Script Input */}
<div>
<label className="block text-sm font-medium text-white/70 mb-2">
Script Content
</label>
<Textarea
value={script}
onChange={(e) => setScript(e.target.value)}
placeholder="Enter your script here..."
className="min-h-[200px] bg-white/5 border-white/20 text-white placeholder:text-white/50"
rows={10}
/>
</div>
{/* Settings */}
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
<div>
<label className="block text-sm font-medium text-white/70 mb-2">
Mode
</label>
<Select value={selectedMode.toString()} onValueChange={(value) => setSelectedMode(Number(value) as ModeEnum)}>
<SelectTrigger className="bg-white/5 border-white/20 text-white">
<SelectValue />
</SelectTrigger>
<SelectContent>
<SelectItem value={ModeEnum.AUTOMATIC.toString()}>Automatic</SelectItem>
<SelectItem value={ModeEnum.MANUAL.toString()}>Manual</SelectItem>
</SelectContent>
</Select>
</div>
<div>
<label className="block text-sm font-medium text-white/70 mb-2">
Resolution
</label>
<Select value={selectedResolution.toString()} onValueChange={(value) => setSelectedResolution(Number(value) as ResolutionEnum)}>
<SelectTrigger className="bg-white/5 border-white/20 text-white">
<SelectValue />
</SelectTrigger>
<SelectContent>
<SelectItem value={ResolutionEnum.HD_720P.toString()}>720P HD</SelectItem>
<SelectItem value={ResolutionEnum.FULL_HD_1080P.toString()}>1080P Full HD</SelectItem>
<SelectItem value={ResolutionEnum.UHD_2K.toString()}>2K UHD</SelectItem>
<SelectItem value={ResolutionEnum.UHD_4K.toString()}>4K UHD</SelectItem>
</SelectContent>
</Select>
</div>
</div>
{/* Create Button */}
<div className="flex justify-end">
<Button
onClick={handleCreate}
disabled={isCreating || !script.trim()}
className="bg-purple-600 hover:bg-purple-700"
>
{isCreating ? (
<>
<Loader2 className="h-4 w-4 mr-2 animate-spin" />
Creating...
</>
) : (
'Create Video'
)}
</Button>
</div>
</div>
</Card>
</div>
</div>
);
}