anycoder-b6aa5638 / index.html
Mudrock10's picture
Upload folder using huggingface_hub
1a7f757 verified
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>VideoCoF - Unified Video Editing</title>
<script src="https://cdn.jsdelivr.net/npm/react@18.0.0/umd/react.development.js"></script>
<script src="https://cdn.jsdelivr.net/npm/react-dom@18.0.0/umd/react-dom.development.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@babel/standalone/babel.js"></script>
<script src="https://cdn.tailwindcss.com"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.3/css/all.min.css">
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap" rel="stylesheet">
<style>
body {
font-family: 'Inter', sans-serif;
}
.gradient-bg {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
}
.timeline-track {
background: linear-gradient(90deg, #e0e7ff 0%, #c7d2fe 50%, #a5b4fc 100%);
height: 4px;
border-radius: 2px;
}
.timeline-marker {
width: 12px;
height: 12px;
background: #4f46e5;
border-radius: 50%;
position: absolute;
top: -4px;
transform: translateX(-50%);
}
.video-timeline {
background: #f3f4f6;
border-radius: 8px;
padding: 1rem;
}
.tab-active {
background-color: #667eea;
color: white;
}
.tab-inactive {
background-color: #e5e7eb;
color: #374151;
}
.slider-thumb::-webkit-slider-thumb {
appearance: none;
width: 20px;
height: 20px;
background: #667eea;
border-radius: 50%;
cursor: pointer;
}
.slider-thumb::-moz-range-thumb {
width: 20px;
height: 20px;
background: #667eea;
border-radius: 50%;
cursor: pointer;
border: none;
}
</style>
</head>
<body>
<div id="root"></div>
<script type="text/babel">
const { useState, useEffect, useRef } = React;
function VideoCoF() {
const [videoFile, setVideoFile] = useState(null);
const [videoInfo, setVideoInfo] = useState(null);
const [timelineData, setTimelineData] = useState(null);
const [isProcessing, setIsProcessing] = useState(false);
const [activeTab, setActiveTab] = useState(0);
const [startTrim, setStartTrim] = useState(0);
const [endTrim, setEndTrim] = useState(100);
const [selectedEffects, setSelectedEffects] = useState([]);
const [selectedFilter, setSelectedFilter] = useState('None');
const [playbackSpeed, setPlaybackSpeed] = useState(1.0);
const [editedVideo, setEditedVideo] = useState(null);
const [videoDuration, setVideoDuration] = useState(0);
const [videoResolution, setVideoResolution] = useState({ width: 0, height: 0 });
const [videoFps, setVideoFps] = useState(0);
const [showSuccess, setShowSuccess] = useState(false);
const videoRef = useRef(null);
const fileInputRef = useRef(null);
const extractVideoInfo = (file) => {
// Simulate video info extraction
return {
duration: 120.5,
width: 1920,
height: 1080,
fps: 30,
frame_count: 3615
};
};
const createTimelineFigure = (videoInfo) => {
// Simulate timeline data
const timePoints = Array.from({ length: 100 }, (_, i) => i * videoInfo.duration / 100);
const intensity = timePoints.map(t => Math.sin(t * 0.1) * 0.5 + 0.5);
return { timePoints, intensity };
};
const handleFileUpload = (e) => {
const file = e.target.files[0];
if (file && file.type.startsWith('video/')) {
setVideoFile(file);
setIsProcessing(true);
setTimeout(() => {
const info = extractVideoInfo(file);
setVideoInfo(info);
setTimelineData(createTimelineFigure(info));
setVideoDuration(info.duration);
setVideoResolution({ width: info.width, height: info.height });
setVideoFps(info.fps);
setIsProcessing(false);
}, 1000);
}
};
const handleLoadVideo = () => {
if (fileInputRef.current) {
fileInputRef.current.click();
}
};
const handleApplyEdits = () => {
setIsProcessing(true);
setTimeout(() => {
setEditedVideo('edited_video.mp4');
setIsProcessing(false);
setShowSuccess(true);
setTimeout(() => setShowSuccess(false), 3000);
}, 2000);
};
const handleEffectToggle = (effect) => {
if (selectedEffects.includes(effect)) {
setSelectedEffects(selectedEffects.filter(e => e !== effect));
} else {
setSelectedEffects([...selectedEffects, effect]);
}
};
const handleDownload = () => {
const link = document.createElement('a');
link.href = editedVideo;
link.download = 'edited_video.mp4';
link.click();
};
return (
<div className="min-h-screen bg-gray-50">
{/* Header */}
<div className="gradient-bg text-white p-6 rounded-b-lg">
<div className="max-w-7xl mx-auto">
<h1 className="text-3xl font-bold mb-2">🎥 VideoCoF</h1>
<p className="text-lg mb-4">Unified Video Editing with Temporal Reasoner</p>
<a
href="https://huggingface.co/spaces/akhaliq/anycoder"
target="_blank"
className="text-white hover:underline"
>
Built with anycoder
</a>
</div>
</div>
<div className="max-w-7xl mx-auto p-6">
{/* Sidebar */}
<div className="bg-white rounded-lg shadow-md p-6 mb-6">
<h2 className="text-xl font-semibold mb-4">🎛️ Controls</h2>
<div className="mb-6">
<h3 className="text-lg font-medium mb-3">Upload Video</h3>
<input
ref={fileInputRef}
type="file"
accept="video/*"
onChange={handleFileUpload}
className="hidden"
/>
<button
onClick={handleLoadVideo}
className="w-full bg-blue-600 text-white py-3 px-4 rounded-lg hover:bg-blue-700 transition-colors"
>
Choose Video File
</button>
<p className="text-sm text-gray-500 mt-2">Supported formats: MP4, AVI, MOV, MKV</p>
</div>
{isProcessing && (
<div className="flex items-center justify-center py-4">
<div className="animate-spin rounded-full h-8 w-8 border-b-2 border-blue-600"></div>
<span className="ml-2">Processing video...</span>
</div>
)}
</div>
{/* Main Content */}
{videoFile ? (
<div className="space-y-6">
{/* Video Player */}
<div className="bg-white rounded-lg shadow-md p-6">
<h2 className="text-xl font-semibold mb-4">🎬 Video Player</h2>
<div className="grid grid-cols-1 lg:grid-cols-4 gap-4">
<div className="lg:col-span-3">
<div className="relative bg-black rounded-lg overflow-hidden aspect-video">
<video
ref={videoRef}
className="w-full h-full object-contain"
controls
>
<source src={URL.createObjectURL(videoFile)} type={videoFile.type} />
</video>
</div>
</div>
<div className="space-y-4">
<div>
<p className="text-sm text-gray-500">Duration</p>
<p className="font-semibold">{videoDuration.toFixed(2)}s</p>
</div>
<div>
<p className="text-sm text-gray-500">Resolution</p>
<p className="font-semibold">{videoResolution.width}×{videoResolution.height}</p>
</div>
<div>
<p className="text-sm text-gray-500">FPS</p>
<p className="font-semibold">{videoFps}</p>
</div>
</div>
</div>
</div>
{/* Timeline Editor */}
<div className="bg-white rounded-lg shadow-md p-6">
<h2 className="text-xl font-semibold mb-4">⏱️ Timeline Editor</h2>
<div className="video-timeline">
<div className="relative h-12">
<div className="timeline-track w-full"></div>
<div className="timeline-marker" style={{ left: `${startTrim}%` }}></div>
<div className="timeline-marker" style={{ left: `${endTrim}%` }}></div>
</div>
</div>
</div>
{/* Editing Tools */}
<div className="bg-white rounded-lg shadow-md p-6">
<h2 className="text-xl font-semibold mb-4">✂️ Editing Tools</h2>
<div className="flex space-x-2 mb-6">
{['Trim', 'Effects', 'Filters', 'Speed'].map((tab, index) => (
<button
key={tab}
onClick={() => setActiveTab(index)}
className={`px-4 py-2 rounded-lg font-medium transition-colors ${
activeTab === index ? 'tab-active' : 'tab-inactive'
}`}
>
{tab}
</button>
))}
</div>
<div className="space-y-6">
{activeTab === 0 && (
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
<div>
<label className="block text-sm font-medium text-gray-700 mb-2">
Start Time
</label>
<input
type="range"
min="0"
max={videoDuration}
step="0.1"
value={startTrim}
onChange={(e) => setStartTrim(parseFloat(e.target.value))}
className="w-full slider-thumb"
/>
<span className="text-sm text-gray-500">
{startTrim.toFixed(1)}s
</span>
</div>
<div>
<label className="block text-sm font-medium text-gray-700 mb-2">
End Time
</label>
<input
type="range"
min="0"
max={videoDuration}
step="0.1"
value={endTrim}
onChange={(e) => setEndTrim(parseFloat(e.target.value))}
className="w-full slider-thumb"
/>
<span className="text-sm text-gray-500">
{endTrim.toFixed(1)}s
</span>
</div>
</div>
)}
{activeTab === 1 && (
<div>
<label className="block text-sm font-medium text-gray-700 mb-2">
Apply Effects
</label>
<div className="grid grid-cols-2 md:grid-cols-3 gap-3">
{['Fade In', 'Fade Out', 'Crossfade', 'Blur', 'Sharpen'].map(effect => (
<button
key={effect}
onClick={() => handleEffectToggle(effect)}
className={`px-3 py-2 rounded-lg text-sm font-medium transition-colors ${
selectedEffects.includes(effect)
? 'bg-blue-600 text-white'
: 'bg-gray-200 text-gray-700 hover:bg-gray-300'
}`}
>
{effect}
</button>
))}
</div>
</div>
)}
{activeTab === 2 && (
<div>
<label className="block text-sm font-medium text-gray-700 mb-2">
Video Filter
</label>
<select
value={selectedFilter}
onChange={(e) => setSelectedFilter(e.target.value)}
className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500"
>
<option value="None">None</option>
<option value="Grayscale">Grayscale</option>
<option value="Sepia">Sepia</option>
<option value="Vintage">Vintage</option>
<option value="Cool">Cool</option>
<option value="Warm">Warm</option>
</select>
</div>
)}
{activeTab === 3 && (
<div>
<label className="block text-sm font-medium text-gray-700 mb-2">
Playback Speed
</label>
<input
type="range"
min="0.25"
max="2.0"
step="0.25"
value={playbackSpeed}
onChange={(e) => setPlaybackSpeed(parseFloat(e.target.value))}
className="w-full slider-thumb"
/>
<span className="text-sm text-gray-500">
{playbackSpeed}x
</span>
</div>
)}
</div>
</div>
{/* Apply Edits Button */}
<div className="text-center">
<button
onClick={handleApplyEdits}
disabled={isProcessing}
className="bg-blue-600 text-white px-8 py-3 rounded-lg font-medium hover:bg-blue-700 transition-colors disabled:bg-gray-400"
>
{isProcessing ? 'Applying Edits...' : 'Apply Edits'}
</button>
{showSuccess && (
<div className="mt-4 p-4 bg-green-100 border border-green-400 text-green-700 rounded-lg">
Edits applied successfully!
</div>
)}
</div>
{/* Export Options */}
{editedVideo && (
<div className="bg-white rounded-lg shadow-md p-6">
<h2 className="text-xl font-semibold mb-4">💾 Export Options</h2>
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
<div>
<label className="block text-sm font-medium text-gray-700 mb-2">
Export Format
</label>
<select className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500">
<option value="MP4">MP4</option>
<option value="AVI">AVI</option>
<option value="MOV">MOV</option>
</select>
</div>
<div className="flex items-end space-x-4">
<button
onClick={handleDownload}
className="bg-green-600 text-white px-6 py-2 rounded-lg font-medium hover:bg-green-700 transition-colors"
>
Download Edited Video
</button>
<button className="bg-gray-600 text-white px-6 py-2 rounded-lg font-medium hover:bg-gray-700 transition-colors">
Export to Cloud
</button>
</div>
</div>
</div>
)}
</div>
) : (
<div className="bg-white rounded-lg shadow-md p-12 text-center">
<div className="text-gray-400 mb-4">
<i className="fas fa-video text-6xl"></i>
</div>
<p className="text-lg text-gray-600">📁 Please upload a video file to get started with VideoCoF!</p>
</div>
)}
</div>
</div>
);
}
ReactDOM.render(<VideoCoF />, document.getElementById('root'));
</script>
</body>
</html>