testing-cog / index.html
suppressor14's picture
This isnt working, the drag and drop video here function doesnt work, please rectify this - Follow Up Deployment
4c7d7af verified
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Video Story Generator</title>
<script src="https://cdn.tailwindcss.com"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<style>
.video-container {
position: relative;
padding-bottom: 56.25%; /* 16:9 aspect ratio */
height: 0;
overflow: hidden;
}
.video-container video {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
object-fit: cover;
}
.dropzone {
border: 2px dashed #ccc;
transition: all 0.3s ease;
min-height: 200px;
display: flex;
align-items: center;
justify-content: center;
}
.dropzone.active {
border-color: #4f46e5;
background-color: #eef2ff;
transform: scale(0.98);
}
.story-card {
background: linear-gradient(135deg, #f5f7fa 0%, #e4e8f0 100%);
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
}
.loading-dots:after {
content: '.';
animation: dots 1.5s steps(5, end) infinite;
}
@keyframes dots {
0%, 20% {
color: rgba(0,0,0,0);
text-shadow: .25em 0 0 rgba(0,0,0,0), .5em 0 0 rgba(0,0,0,0);
}
40% {
color: currentColor;
text-shadow: .25em 0 0 rgba(0,0,0,0), .5em 0 0 rgba(0,0,0,0);
}
60% {
text-shadow: .25em 0 0 currentColor, .5em 0 0 rgba(0,0,0,0);
}
80%, 100% {
text-shadow: .25em 0 0 currentColor, .5em 0 0 currentColor;
}
}
</style>
</head>
<body class="bg-gray-50 min-h-screen">
<div class="container mx-auto px-4 py-8 max-w-6xl">
<header class="text-center mb-12">
<h1 class="text-4xl md:text-5xl font-bold text-indigo-800 mb-4">Video Story Generator</h1>
<p class="text-lg text-gray-600 max-w-2xl mx-auto">
Upload your video and let our AI craft a unique story based on what it observes.
Perfect for content creators, storytellers, and anyone who loves creative narratives.
</p>
</header>
<div class="grid grid-cols-1 lg:grid-cols-2 gap-8 mb-12">
<div class="bg-white rounded-xl shadow-lg overflow-hidden">
<div class="p-6">
<h2 class="text-2xl font-semibold text-gray-800 mb-4">Upload Your Video</h2>
<div id="dropzone" class="dropzone rounded-lg p-8 text-center cursor-pointer mb-6">
<div id="upload-content" class="space-y-3">
<div class="flex justify-center">
<i class="fas fa-cloud-upload-alt text-5xl text-indigo-500"></i>
</div>
<h3 class="text-lg font-medium text-gray-700">Drag & drop your video here</h3>
<p class="text-sm text-gray-500">or click to browse files</p>
<p class="text-xs text-gray-400 mt-2">Supports MP4, MOV, AVI (Max 100MB)</p>
</div>
<input type="file" id="video-upload" class="hidden" accept="video/mp4,video/quicktime,video/x-msvideo">
</div>
<div id="video-preview-container" class="hidden mb-6">
<div class="video-container rounded-lg overflow-hidden shadow">
<video id="video-preview" controls></video>
</div>
<div class="mt-3 flex justify-between items-center">
<span id="video-name" class="text-sm font-medium text-gray-700 truncate"></span>
<button id="remove-video" class="text-red-500 hover:text-red-700 text-sm">
<i class="fas fa-times mr-1"></i> Remove
</button>
</div>
</div>
<div class="space-y-4">
<div>
<label for="story-style" class="block text-sm font-medium text-gray-700 mb-1">Story Style</label>
<select id="story-style" class="w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-indigo-500 focus:border-indigo-500">
<option value="fantasy">Fantasy Adventure</option>
<option value="scifi">Sci-Fi Mystery</option>
<option value="romance">Romantic Drama</option>
<option value="comedy">Humorous Tale</option>
<option value="horror">Spooky Horror</option>
<option value="realistic">Realistic Fiction</option>
</select>
</div>
<div>
<label for="character-name" class="block text-sm font-medium text-gray-700 mb-1">Main Character Name (optional)</label>
<input type="text" id="character-name" class="w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-indigo-500 focus:border-indigo-500" placeholder="e.g. Alex, Luna, Captain Nova">
</div>
<button id="generate-btn" class="w-full bg-indigo-600 hover:bg-indigo-700 text-white font-medium py-3 px-4 rounded-md transition duration-300 flex items-center justify-center disabled:opacity-50 disabled:cursor-not-allowed" disabled>
<i class="fas fa-magic mr-2"></i> Generate Story
</button>
</div>
</div>
</div>
<div class="bg-white rounded-xl shadow-lg overflow-hidden">
<div class="p-6 h-full flex flex-col">
<h2 class="text-2xl font-semibold text-gray-800 mb-4">Your Generated Story</h2>
<div id="story-placeholder" class="flex-1 flex items-center justify-center text-center p-8 bg-gray-50 rounded-lg">
<div>
<i class="fas fa-book-open text-4xl text-gray-300 mb-4"></i>
<p class="text-gray-500">Your story will appear here after you upload a video and click "Generate Story".</p>
</div>
</div>
<div id="loading-indicator" class="hidden flex-1 items-center justify-center p-8">
<div class="text-center">
<div class="inline-block animate-spin rounded-full h-12 w-12 border-t-2 border-b-2 border-indigo-500 mb-4"></div>
<p class="text-gray-700 loading-dots">Analyzing video and crafting your story</p>
</div>
</div>
<div id="story-container" class="hidden flex-1 story-card rounded-lg p-6 overflow-y-auto">
<h3 id="story-title" class="text-xl font-bold text-gray-800 mb-3"></h3>
<div id="story-content" class="text-gray-700 leading-relaxed"></div>
</div>
<div id="story-actions" class="hidden mt-6 flex justify-between">
<button id="copy-story" class="px-4 py-2 bg-gray-200 hover:bg-gray-300 rounded-md text-gray-700 transition duration-300">
<i class="fas fa-copy mr-2"></i> Copy Story
</button>
<button id="download-story" class="px-4 py-2 bg-indigo-600 hover:bg-indigo-700 rounded-md text-white transition duration-300">
<i class="fas fa-download mr-2"></i> Download as TXT
</button>
</div>
</div>
</div>
</div>
<div class="bg-indigo-50 rounded-xl p-6 mb-8">
<h3 class="text-xl font-semibold text-indigo-800 mb-3">How It Works</h3>
<div class="grid grid-cols-1 md:grid-cols-3 gap-4">
<div class="bg-white p-4 rounded-lg shadow">
<div class="text-indigo-600 mb-2">
<i class="fas fa-upload text-2xl"></i>
</div>
<h4 class="font-medium text-gray-800 mb-1">1. Upload Your Video</h4>
<p class="text-sm text-gray-600">Select any video from your device. Our system will analyze the visuals and motion.</p>
</div>
<div class="bg-white p-4 rounded-lg shadow">
<div class="text-indigo-600 mb-2">
<i class="fas fa-brain text-2xl"></i>
</div>
<h4 class="font-medium text-gray-800 mb-1">2. AI Analysis</h4>
<p class="text-sm text-gray-600">Our AI detects scenes, objects, colors, and movements to understand your video's content.</p>
</div>
<div class="bg-white p-4 rounded-lg shadow">
<div class="text-indigo-600 mb-2">
<i class="fas fa-book text-2xl"></i>
</div>
<h4 class="font-medium text-gray-800 mb-1">3. Story Generation</h4>
<p class="text-sm text-gray-600">A unique story is crafted based on the analysis, tailored to your selected style.</p>
</div>
</div>
</div>
<footer class="text-center text-gray-500 text-sm mt-12">
<p>Video Story Generator &copy; 2023 | All uploaded videos are processed locally in your browser</p>
</footer>
</div>
<script>
document.addEventListener('DOMContentLoaded', function() {
// DOM elements
const dropzone = document.getElementById('dropzone');
const videoUpload = document.getElementById('video-upload');
const videoPreview = document.getElementById('video-preview');
const videoPreviewContainer = document.getElementById('video-preview-container');
const videoName = document.getElementById('video-name');
const removeVideoBtn = document.getElementById('remove-video');
const uploadContent = document.getElementById('upload-content');
const generateBtn = document.getElementById('generate-btn');
const storyPlaceholder = document.getElementById('story-placeholder');
const loadingIndicator = document.getElementById('loading-indicator');
const storyContainer = document.getElementById('story-container');
const storyTitle = document.getElementById('story-title');
const storyContent = document.getElementById('story-content');
const storyActions = document.getElementById('story-actions');
const copyStoryBtn = document.getElementById('copy-story');
const downloadStoryBtn = document.getElementById('download-story');
const storyStyleSelect = document.getElementById('story-style');
const characterNameInput = document.getElementById('character-name');
// Drag and drop events
['dragenter', 'dragover', 'dragleave', 'drop'].forEach(eventName => {
dropzone.addEventListener(eventName, preventDefaults, false);
});
function preventDefaults(e) {
e.preventDefault();
e.stopPropagation();
}
['dragenter', 'dragover'].forEach(eventName => {
dropzone.addEventListener(eventName, highlight, false);
});
['dragleave', 'drop'].forEach(eventName => {
dropzone.addEventListener(eventName, unhighlight, false);
});
function highlight(e) {
e.preventDefault();
dropzone.classList.add('active');
}
function unhighlight() {
dropzone.classList.remove('active');
}
dropzone.addEventListener('drop', handleDrop, false);
dropzone.addEventListener('click', () => videoUpload.click());
function handleDrop(e) {
const dt = e.dataTransfer;
const files = dt.files;
// Reset dropzone appearance
dropzone.classList.remove('active');
// Process files if any
if (files.length > 0) {
handleFiles(files);
}
}
videoUpload.addEventListener('change', function() {
if (this.files.length) {
handleFiles(this.files);
}
});
function handleFiles(files) {
const file = files[0];
if (!file) return;
// Check if file is a video
const validTypes = ['video/mp4', 'video/quicktime', 'video/x-msvideo'];
if (!validTypes.includes(file.type)) {
alert('Please upload a video file (MP4, MOV, AVI)');
return;
}
// Check file size (100MB max)
if (file.size > 100 * 1024 * 1024) {
alert('File is too large. Maximum size is 100MB.');
return;
}
// Display video preview
const videoURL = URL.createObjectURL(file);
videoPreview.src = videoURL;
videoPreview.load();
videoName.textContent = file.name;
videoPreviewContainer.classList.remove('hidden');
uploadContent.classList.add('hidden');
generateBtn.disabled = false;
// Load metadata
videoPreview.onloadedmetadata = function() {
console.log(`Video loaded: ${file.name} (${Math.round(file.size/(1024*1024))}MB)`);
};
videoPreview.onerror = function() {
alert('Error loading video file');
resetVideoUpload();
};
}
removeVideoBtn.addEventListener('click', resetVideoUpload);
generateBtn.addEventListener('click', function() {
if (!videoPreview.src) return;
// Show loading state
storyPlaceholder.classList.add('hidden');
loadingIndicator.classList.remove('hidden');
storyContainer.classList.add('hidden');
storyActions.classList.add('hidden');
generateBtn.disabled = true;
generateBtn.innerHTML = '<i class="fas fa-cog fa-spin mr-2"></i> Generating...';
// Simulate analysis and story generation (in a real app, this would be an API call)
setTimeout(() => {
generateStory();
}, 3000);
});
function generateStory() {
// Get user inputs
const storyStyle = storyStyleSelect.value;
const characterName = characterNameInput.value.trim() || getRandomName();
// Simulate video analysis (in a real app, this would analyze actual video content)
const simulatedAnalysis = simulateVideoAnalysis();
// Generate story based on style and analysis
const story = createStory(simulatedAnalysis, storyStyle, characterName);
// Display the story
storyTitle.textContent = story.title;
storyContent.innerHTML = story.content.split('\n').map(para => `<p class="mb-4">${para}</p>`).join('');
// Update UI
loadingIndicator.classList.add('hidden');
storyContainer.classList.remove('hidden');
storyActions.classList.remove('hidden');
generateBtn.disabled = false;
generateBtn.innerHTML = '<i class="fas fa-magic mr-2"></i> Generate Story';
}
function simulateVideoAnalysis() {
// This would normally analyze the video content
// For demo purposes, we return simulated data
const colorPalette = ['#3b82f6', '#10b981', '#f59e0b', '#ef4444'];
const dominantColors = [...colorPalette].sort(() => 0.5 - Math.random()).slice(0, 3);
const possibleScenes = [
'a person walking through a forest',
'a city skyline at sunset',
'waves crashing on a beach',
'a busy street with cars and pedestrians',
'a close-up of a face with emotional expression',
'a group of animals interacting',
'a slow panning shot of mountains',
'raindrops falling on a window'
];
const possibleMoods = [
'peaceful and serene',
'tense and dramatic',
'joyful and energetic',
'mysterious and suspenseful',
'melancholic and reflective'
];
return {
dominantColors,
primaryScene: possibleScenes[Math.floor(Math.random() * possibleScenes.length)],
secondaryScene: possibleScenes[Math.floor(Math.random() * possibleScenes.length)],
mood: possibleMoods[Math.floor(Math.random() * possibleMoods.length)],
movementLevel: Math.random() > 0.5 ? 'high' : 'low',
containsFaces: Math.random() > 0.5,
containsNature: Math.random() > 0.7,
containsUrban: Math.random() > 0.7
};
}
function createStory(analysis, style, characterName) {
const styles = {
fantasy: {
title: `The ${characterName}'s Enchanted Journey`,
templates: [
`In a realm where the ${analysis.dominantColors[0].slice(1)} mists swirled endlessly, ${characterName} found themselves standing before ${analysis.containsNature ? 'an ancient oak with bark like wrinkled parchment' : 'a towering obsidian monolith'}. The air was thick with ${analysis.mood.includes('serene') ? 'the scent of magic' : 'unspoken dread'}.`,
`As ${characterName} ventured ${analysis.movementLevel === 'high' ? 'swiftly' : 'cautiously'} through the ${analysis.containsNature ? 'enchanted glade' : 'forbidden ruins'}, they noticed ${analysis.secondaryScene.includes('face') ? 'a pair of glowing eyes watching from the shadows' : 'strange symbols pulsating with an eerie light'}.`,
`Suddenly, ${analysis.mood.includes('joyful') ? 'a chorus of celestial voices filled the air' : 'the ground trembled violently'}. ${characterName} realized this was no ordinary ${analysis.containsUrban ? 'city' : 'forest'}—it was ${analysis.mood.includes('mysterious') ? 'a gateway to another dimension' : 'the battleground of forgotten gods'}.`
]
},
scifi: {
title: `${characterName} and the ${analysis.dominantColors[1].slice(1)} Signal`,
templates: [
`The ${analysis.dominantColors[0].slice(1)} alert flashed across the viewscreen as ${characterName} adjusted the quantum scanners. "${analysis.primaryScene.includes('city') ? 'Metropolis Sector' : 'Outer Rim Quadrant'} is showing anomalous readings," they muttered, fingers dancing over the holographic controls.`,
`Descending through ${analysis.mood.includes('tense') ? 'the ion storm' : 'the nebula'}, ${characterName}'s ship detected ${analysis.secondaryScene.includes('face') ? 'a humanoid lifeform' : 'an artificial structure'} where none should exist. The ${analysis.movementLevel === 'high' ? 'rapidly oscillating' : 'steady'} energy signature matched no known technology.`,
`"Computer, analyze ${analysis.dominantColors[1].slice(1)} spectrum," ${characterName} ordered. What they discovered would ${analysis.mood.includes('dramatic') ? 'change the course of galactic history' : 'challenge everything science understood about reality'}.`
]
},
romance: {
title: `${characterName}'s ${analysis.dominantColors[2].slice(1)} Heart`,
templates: [
`The ${analysis.primaryScene.includes('sunset') ? 'golden hues of sunset' : 'soft glow of streetlights'} painted ${characterName}'s face as they stood ${analysis.containsUrban ? 'on the bustling city bridge' : 'at the quiet beach shore'}. Their heart beat ${analysis.movementLevel === 'high' ? 'wildly' : 'a steady rhythm'}—they were waiting for someone.`,
`Memories flooded back: ${analysis.secondaryScene.includes('forest') ? 'that first meeting under the ancient trees' : 'the accidental coffee spill that started it all'}. The ${analysis.mood.includes('joyful') ? 'laughter they shared' : 'silent understanding between them'} had grown into something ${characterName} couldn't ignore.`,
`Then, ${analysis.mood.includes('serene') ? 'as gentle as the morning mist' : 'with dramatic flair'}, ${analysis.containsFaces ? 'the familiar face appeared' : 'a letter arrived'}. The ${analysis.dominantColors[2].slice(1)} ${analysis.containsNature ? 'rose' : 'envelope'} held the answer ${characterName} had been ${analysis.movementLevel === 'high' ? 'desperately' : 'patiently'} waiting for.`
]
},
comedy: {
title: `The ${analysis.dominantColors[0].slice(1)} Fiasco of ${characterName}`,
templates: [
`It all started when ${characterName} decided to ${analysis.primaryScene.includes('walking') ? 'take what they thought would be a simple walk' : 'film what they assumed would be an ordinary video'}. Little did they know, ${analysis.mood.includes('dramatic') ? 'fate had other, much sillier plans' : 'the universe was about to play the ultimate prank'}.`,
`First, there was the incident with the ${analysis.containsNature ? 'squirrel that turned out to be an undercover agent' : 'traffic cone that somehow became sentient'}. Then ${characterName} ${analysis.movementLevel === 'high' ? 'ran headfirst into' : 'slowly backed into'} ${analysis.secondaryScene.includes('face') ? 'their own reflection' : 'a situation no sane person would believe'}.`,
`By the time the ${analysis.dominantColors[1].slice(1)} ${analysis.containsUrban ? 'taxi' : 'tractor'} arrived, ${characterName} had ${analysis.mood.includes('joyful') ? 'somehow become mayor of a small town' : 'accidentally started a cult dedicated to breakfast foods'}. And the weirdest part? ${analysis.movementLevel === 'high' ? 'It only took seven minutes' : 'This was just Tuesday'}.`
]
},
horror: {
title: `The ${analysis.dominantColors[0].slice(1)} Whisper`,
templates: [
`${characterName} shouldn't have ${analysis.primaryScene.includes('forest') ? 'ventured into those woods after dark' : 'watched that unmarked video tape'}. Now, the ${analysis.mood.includes('serene') ? 'deceptively calm' : 'oppressively heavy'} silence was broken only by ${analysis.movementLevel === 'high' ? 'frantic scratching sounds' : 'slow, deliberate footsteps'}.`,
`The ${analysis.secondaryScene.includes('face') ? 'face in the window wasn't there when they looked directly at it' : 'shadows moved when nothing cast them'}. ${characterName}'s ${analysis.dominantColors[1].slice(1)} sweater offered no protection against the creeping dread that ${analysis.containsUrban ? 'even the city lights couldn't dispel' : 'the countryside emptiness amplified'}.`,
`Then came the ${analysis.mood.includes('mysterious') ? 'whispers in a language that shouldn't exist' : 'screams that might have been their own'}. The ${analysis.containsFaces ? 'mirrors reflected something... else' : 'lights began to fail one by one'}. ${characterName} realized too late: ${analysis.movementLevel === 'high' ? 'it was already inside' : 'they were never alone'}.`
]
},
realistic: {
title: `${characterName}'s ${analysis.primaryScene.includes('city') ? 'Urban' : 'Personal'} Journey`,
templates: [
`The ${analysis.primaryScene.includes('beach') ? 'rhythm of the waves' : 'hustle of the city'} formed a backdrop to ${characterName}'s ${analysis.mood.includes('joyful') ? 'day of discovery' : 'period of reflection'}. Life had been ${analysis.movementLevel === 'high' ? 'a whirlwind lately' : 'strangely still'}, and ${analysis.containsFaces ? 'the faces around them told stories of their own' : 'the environment mirrored their inner state'}.`,
`${analysis.secondaryScene.includes('walking') ? 'With each step' : 'As time passed'}, ${characterName} noticed ${analysis.dominantColors[0].slice(1)} ${analysis.containsNature ? 'flowers pushing through cracks in the pavement' : 'graffiti that seemed to speak directly to them'}. It was a reminder that ${analysis.mood.includes('serene') ? 'beauty persists' : 'change is inevitable'}.`,
`By ${analysis.containsUrban ? 'the time the streetlights flickered on' : 'sunset'}, ${characterName} had reached ${analysis.movementLevel === 'high' ? 'an unexpected conclusion' : 'a quiet acceptance'}. The ${analysis.dominantColors[1].slice(1)} ${analysis.containsFaces ? 'smile of a stranger' : 'quality of the light'} marked this as a day they would ${analysis.mood.includes('dramatic') ? 'never forget' : 'look back on with quiet gratitude'}.`
]
}
};
const selectedStyle = styles[style] || styles.fantasy;
return {
title: selectedStyle.title,
content: selectedStyle.templates.join('\n\n')
};
}
function getRandomName() {
const names = ['Alex', 'Morgan', 'Jordan', 'Taylor', 'Casey', 'Riley', 'Jamie', 'Quinn', 'Dakota', 'Skyler'];
return names[Math.floor(Math.random() * names.length)];
}
function resetVideoUpload() {
if (videoPreview.src) {
URL.revokeObjectURL(videoPreview.src);
}
videoPreview.src = '';
videoPreviewContainer.classList.add('hidden');
uploadContent.classList.remove('hidden');
generateBtn.disabled = true;
videoUpload.value = '';
resetStoryOutput();
}
function resetStoryOutput() {
storyPlaceholder.classList.remove('hidden');
loadingIndicator.classList.add('hidden');
storyContainer.classList.add('hidden');
storyActions.classList.add('hidden');
storyTitle.textContent = '';
storyContent.textContent = '';
generateBtn.disabled = !videoPreview.src;
generateBtn.innerHTML = '<i class="fas fa-magic mr-2"></i> Generate Story';
}
// Copy story to clipboard
copyStoryBtn.addEventListener('click', function() {
const storyText = `${storyTitle.textContent}\n\n${storyContent.textContent}`;
navigator.clipboard.writeText(storyText).then(() => {
const originalText = copyStoryBtn.innerHTML;
copyStoryBtn.innerHTML = '<i class="fas fa-check mr-2"></i> Copied!';
setTimeout(() => {
copyStoryBtn.innerHTML = originalText;
}, 2000);
});
});
// Download story as text file
downloadStoryBtn.addEventListener('click', function() {
const storyText = `${storyTitle.textContent}\n\n${storyContent.textContent}`;
const blob = new Blob([storyText], { type: 'text/plain' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = `${storyTitle.textContent.replace(/\s+/g, '_')}.txt`;
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
URL.revokeObjectURL(url);
});
});
</script>
<p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=suppressor14/testing-cog" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
</html>