forked from innovacion/playground
119 lines
3.8 KiB
TypeScript
119 lines
3.8 KiB
TypeScript
'use client';
|
|
|
|
import { aspectRatioSizes, videoDurations } from '@/lib/google-ai';
|
|
|
|
interface VideoConfigProps {
|
|
model: string;
|
|
aspectRatio: string;
|
|
onAspectRatioChange: (ratio: string) => void;
|
|
duration: number;
|
|
onDurationChange: (duration: number) => void;
|
|
negativePrompt: string;
|
|
onNegativePromptChange: (prompt: string) => void;
|
|
safetyLevel: 'block_none' | 'block_some' | 'block_most';
|
|
onSafetyLevelChange: (level: 'block_none' | 'block_some' | 'block_most') => void;
|
|
}
|
|
|
|
export function VideoConfig({
|
|
aspectRatio,
|
|
onAspectRatioChange,
|
|
duration,
|
|
onDurationChange,
|
|
negativePrompt,
|
|
onNegativePromptChange,
|
|
safetyLevel,
|
|
onSafetyLevelChange,
|
|
}: VideoConfigProps) {
|
|
const availableRatios = Object.keys(aspectRatioSizes);
|
|
const size = aspectRatioSizes[aspectRatio];
|
|
|
|
return (
|
|
<div className="space-y-4">
|
|
<h3 className="text-sm font-medium text-foreground">Configuración de Video</h3>
|
|
|
|
{/* Aspect Ratio */}
|
|
<div className="space-y-2">
|
|
<label className="text-xs font-medium text-muted-foreground">
|
|
Aspect Ratio
|
|
</label>
|
|
<div className="grid grid-cols-5 gap-2">
|
|
{availableRatios.map((ratio) => (
|
|
<button
|
|
key={ratio}
|
|
onClick={() => onAspectRatioChange(ratio)}
|
|
className={`
|
|
px-3 py-2 text-xs rounded-lg font-medium transition-all
|
|
${aspectRatio === ratio
|
|
? 'bg-primary text-primary-foreground'
|
|
: 'bg-secondary hover:bg-accent'
|
|
}
|
|
`}
|
|
>
|
|
{ratio}
|
|
</button>
|
|
))}
|
|
</div>
|
|
{size && (
|
|
<p className="text-xs text-muted-foreground">
|
|
Dimensiones: {size.width}x{size.height}px
|
|
</p>
|
|
)}
|
|
</div>
|
|
|
|
{/* Duración */}
|
|
<div className="space-y-2">
|
|
<label className="text-xs font-medium text-muted-foreground">
|
|
Duración: {duration} segundos
|
|
</label>
|
|
<div className="flex gap-2">
|
|
{videoDurations.map((dur) => (
|
|
<button
|
|
key={dur.value}
|
|
onClick={() => onDurationChange(dur.value)}
|
|
className={`
|
|
flex-1 px-3 py-2 text-xs rounded-lg font-medium transition-all
|
|
${duration === dur.value
|
|
? 'bg-primary text-primary-foreground'
|
|
: 'bg-secondary hover:bg-accent'
|
|
}
|
|
`}
|
|
>
|
|
{dur.label}
|
|
</button>
|
|
))}
|
|
</div>
|
|
</div>
|
|
|
|
{/* Negative Prompt */}
|
|
<div className="space-y-2">
|
|
<label className="text-xs font-medium text-muted-foreground">
|
|
Negative Prompt (opcional)
|
|
</label>
|
|
<textarea
|
|
value={negativePrompt}
|
|
onChange={(e) => onNegativePromptChange(e.target.value)}
|
|
placeholder="Elementos que NO quieres en el video..."
|
|
className="w-full px-3 py-2 bg-secondary border border-border rounded-lg text-sm focus:outline-none focus:ring-2 focus:ring-primary resize-none"
|
|
rows={2}
|
|
/>
|
|
</div>
|
|
|
|
{/* Safety Level */}
|
|
<div className="space-y-2">
|
|
<label className="text-xs font-medium text-muted-foreground">
|
|
Nivel de Seguridad
|
|
</label>
|
|
<select
|
|
value={safetyLevel}
|
|
onChange={(e) => onSafetyLevelChange(e.target.value as any)}
|
|
className="w-full px-3 py-2 bg-secondary border border-border rounded-lg text-sm focus:outline-none focus:ring-2 focus:ring-primary"
|
|
>
|
|
<option value="block_none">Sin bloqueo</option>
|
|
<option value="block_some">Bloqueo moderado</option>
|
|
<option value="block_most">Bloqueo alto</option>
|
|
</select>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|