[dyad] Keep full video timeline after trimming - wrote 1 file(s)
This commit is contained in:
@@ -7,7 +7,7 @@ import { Input } from "@/components/ui/input";
|
|||||||
import { Label } from "@/components/ui/label";
|
import { Label } from "@/components/ui/label";
|
||||||
import { Slider } from "@/components/ui/slider";
|
import { Slider } from "@/components/ui/slider";
|
||||||
import { Progress } from "@/components/ui/progress";
|
import { Progress } from "@/components/ui/progress";
|
||||||
import { UploadCloud, Scissors, Download, Loader2, RotateCcw } from "lucide-react";
|
import { UploadCloud, Scissors, Download, Loader2 } from "lucide-react";
|
||||||
import { getFFmpeg } from "@/lib/ffmpeg";
|
import { getFFmpeg } from "@/lib/ffmpeg";
|
||||||
import { fetchFile } from "@ffmpeg/util";
|
import { fetchFile } from "@ffmpeg/util";
|
||||||
|
|
||||||
@@ -26,6 +26,26 @@ export function VideoEditor() {
|
|||||||
getFFmpeg();
|
getFFmpeg();
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const video = videoRef.current;
|
||||||
|
if (!video) return;
|
||||||
|
|
||||||
|
const handleTimeUpdate = () => {
|
||||||
|
if (video.currentTime > trimValues[1]) {
|
||||||
|
video.pause();
|
||||||
|
video.currentTime = trimValues[0];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
video.addEventListener('timeupdate', handleTimeUpdate);
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
if (video) {
|
||||||
|
video.removeEventListener('timeupdate', handleTimeUpdate);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}, [trimValues]);
|
||||||
|
|
||||||
const handleFileChange = (event: ChangeEvent<HTMLInputElement>) => {
|
const handleFileChange = (event: ChangeEvent<HTMLInputElement>) => {
|
||||||
const file = event.target.files?.[0];
|
const file = event.target.files?.[0];
|
||||||
if (file) {
|
if (file) {
|
||||||
@@ -43,6 +63,17 @@ export function VideoEditor() {
|
|||||||
setTrimValues([0, video.duration]);
|
setTrimValues([0, video.duration]);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleTrimValueChange = (newValues: number[]) => {
|
||||||
|
if (videoRef.current) {
|
||||||
|
if (newValues[0] !== trimValues[0]) {
|
||||||
|
videoRef.current.currentTime = newValues[0];
|
||||||
|
} else if (newValues[1] !== trimValues[1]) {
|
||||||
|
videoRef.current.currentTime = newValues[1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
setTrimValues(newValues);
|
||||||
|
};
|
||||||
|
|
||||||
const formatTime = (timeInSeconds: number) => {
|
const formatTime = (timeInSeconds: number) => {
|
||||||
if (isNaN(timeInSeconds) || timeInSeconds < 0) {
|
if (isNaN(timeInSeconds) || timeInSeconds < 0) {
|
||||||
return "00:00.000";
|
return "00:00.000";
|
||||||
@@ -101,12 +132,6 @@ export function VideoEditor() {
|
|||||||
setIsTrimming(false);
|
setIsTrimming(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleUntrim = () => {
|
|
||||||
setTrimmedVideoUrl(null);
|
|
||||||
setTrimValues([0, duration]);
|
|
||||||
setProgress(0);
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Card className="w-full shadow-lg rounded-2xl border">
|
<Card className="w-full shadow-lg rounded-2xl border">
|
||||||
<CardHeader className="text-center">
|
<CardHeader className="text-center">
|
||||||
@@ -123,11 +148,10 @@ export function VideoEditor() {
|
|||||||
<div className="aspect-video w-full overflow-hidden rounded-lg border">
|
<div className="aspect-video w-full overflow-hidden rounded-lg border">
|
||||||
<video
|
<video
|
||||||
ref={videoRef}
|
ref={videoRef}
|
||||||
src={trimmedVideoUrl || videoSrc}
|
src={videoSrc}
|
||||||
controls
|
controls
|
||||||
className="w-full h-full object-contain bg-black"
|
className="w-full h-full object-contain bg-black"
|
||||||
onLoadedMetadata={handleLoadedMetadata}
|
onLoadedMetadata={handleLoadedMetadata}
|
||||||
key={trimmedVideoUrl} // Re-render video element when trimmed url changes
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
@@ -135,7 +159,7 @@ export function VideoEditor() {
|
|||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
<Slider
|
<Slider
|
||||||
value={trimValues}
|
value={trimValues}
|
||||||
onValueChange={setTrimValues}
|
onValueChange={handleTrimValueChange}
|
||||||
max={duration}
|
max={duration}
|
||||||
step={0.1}
|
step={0.1}
|
||||||
aria-label="Video trimmer"
|
aria-label="Video trimmer"
|
||||||
@@ -181,12 +205,6 @@ export function VideoEditor() {
|
|||||||
</CardContent>
|
</CardContent>
|
||||||
{videoSrc && (
|
{videoSrc && (
|
||||||
<CardFooter className="flex justify-end space-x-4 p-6">
|
<CardFooter className="flex justify-end space-x-4 p-6">
|
||||||
{trimmedVideoUrl && (
|
|
||||||
<Button variant="ghost" size="lg" onClick={handleUntrim} disabled={isTrimming}>
|
|
||||||
<RotateCcw className="mr-2 h-5 w-5" />
|
|
||||||
Reset
|
|
||||||
</Button>
|
|
||||||
)}
|
|
||||||
<Button variant="outline" size="lg" onClick={handleCutVideo} disabled={isTrimming}>
|
<Button variant="outline" size="lg" onClick={handleCutVideo} disabled={isTrimming}>
|
||||||
{isTrimming ? (
|
{isTrimming ? (
|
||||||
<Loader2 className="mr-2 h-5 w-5 animate-spin" />
|
<Loader2 className="mr-2 h-5 w-5 animate-spin" />
|
||||||
|
|||||||
Reference in New Issue
Block a user