4 Commits

Author SHA1 Message Date
a830549069 Update src/app/page.tsx 2026-05-23 02:44:33 +00:00
13bea032e7 Merge version_3 into main
Merge version_3 into main
2026-05-23 02:42:13 +00:00
e9ae2d83ff Update src/app/page.tsx 2026-05-23 02:42:10 +00:00
4e66f324df Merge version_2 into main
Merge version_2 into main
2026-05-23 02:39:23 +00:00

View File

@@ -9,6 +9,35 @@ import { useState } from "react";
export default function ClipToolPage() { export default function ClipToolPage() {
const [videoUrl, setVideoUrl] = useState(""); const [videoUrl, setVideoUrl] = useState("");
const [captions, setCaptions] = useState(true);
const [layout, setLayout] = useState("vertical");
const [timeframe, setTimeframe] = useState("30s");
const [loading, setLoading] = useState(false);
const [error, setError] = useState("");
const [clips, setClips] = useState<string[]>([]);
const handleGenerate = async () => {
if (!videoUrl) {
setError("Please enter a valid YouTube URL.");
return;
}
setLoading(true);
setError("");
try {
const response = await fetch('/api/generate-clips', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ videoUrl, captions, layout, timeframe })
});
const data = await response.json();
if (data.error) throw new Error(data.error);
setClips(data.clips || []);
} catch (err: any) {
setError(err.message || "Something went wrong. Please try again.");
} finally {
setLoading(false);
}
};
return ( return (
<ThemeProvider <ThemeProvider
@@ -33,7 +62,7 @@ export default function ClipToolPage() {
<div id="tool-interface" data-section="tool-interface" className="py-20 flex flex-col items-center justify-center min-h-[80vh] px-4 text-center"> <div id="tool-interface" data-section="tool-interface" className="py-20 flex flex-col items-center justify-center min-h-[80vh] px-4 text-center">
<h1 className="text-4xl md:text-5xl font-bold mb-6">ClipGen AI Tool</h1> <h1 className="text-4xl md:text-5xl font-bold mb-6">ClipGen AI Tool</h1>
<p className="max-w-xl mb-10 opacity-80">Paste your YouTube video URL below to start generating high-impact clips with custom layout and caption settings.</p> <p className="max-w-xl mb-10 opacity-80">Input your YouTube URL and configure your clipping settings below.</p>
<div className="w-full max-w-lg space-y-6"> <div className="w-full max-w-lg space-y-6">
<Input <Input
@@ -43,26 +72,61 @@ export default function ClipToolPage() {
ariaLabel="YouTube Video URL" ariaLabel="YouTube Video URL"
/> />
<div className="grid grid-cols-1 md:grid-cols-2 gap-4 text-left"> <div className="grid grid-cols-1 md:grid-cols-3 gap-4 text-left">
<div className="p-4 rounded-xl border"> <div className="p-4 rounded-xl border">
<h3 className="font-semibold mb-2">Captions</h3> <h3 className="font-semibold mb-2">Captions</h3>
<p className="text-sm opacity-70">Enable AI-powered subtitles</p> <select
value={captions ? "on" : "off"}
onChange={(e) => setCaptions(e.target.value === "on")}
className="w-full bg-transparent border-none focus:ring-0"
>
<option value="on">Enabled</option>
<option value="off">Disabled</option>
</select>
</div> </div>
<div className="p-4 rounded-xl border"> <div className="p-4 rounded-xl border">
<h3 className="font-semibold mb-2">Layout</h3> <h3 className="font-semibold mb-2">Layout</h3>
<p className="text-sm opacity-70">Optimize for TikTok/Reels</p> <select
value={layout}
onChange={(e) => setLayout(e.target.value)}
className="w-full bg-transparent border-none focus:ring-0"
>
<option value="vertical">Vertical (9:16)</option>
<option value="square">Square (1:1)</option>
<option value="horizontal">Horizontal (16:9)</option>
</select>
</div> </div>
<div className="p-4 rounded-xl border"> <div className="p-4 rounded-xl border">
<h3 className="font-semibold mb-2">Timeframe</h3> <h3 className="font-semibold mb-2">Time</h3>
<p className="text-sm opacity-70">Select clip duration</p> <select
value={timeframe}
onChange={(e) => setTimeframe(e.target.value)}
className="w-full bg-transparent border-none focus:ring-0"
>
<option value="30s">30 Seconds</option>
<option value="60s">60 Seconds</option>
<option value="90s">90 Seconds</option>
</select>
</div> </div>
</div> </div>
<ButtonElasticEffect <ButtonElasticEffect
text="Generate Clips Now" text={loading ? "Processing..." : "Generate Clips Now"}
onClick={() => alert(`Generating clips for: ${videoUrl}`)} onClick={handleGenerate}
disabled={loading}
className="w-full" className="w-full"
/> />
{error && <p className="text-red-500 mt-4">{error}</p>}
{clips.length > 0 && (
<div className="mt-10 grid grid-cols-1 gap-6 w-full">
<h2 className="text-2xl font-semibold">Generated Clips</h2>
{clips.map((clip, i) => (
<video key={i} src={clip} controls className="w-full rounded-2xl shadow-lg" />
))}
</div>
)}
</div> </div>
</div> </div>
</ReactLenis> </ReactLenis>