Download script.js from MoShow/vortexai-multiverse-generator: direct link, hf CLI and curl.
- Browser
- Download file 20.3 kB
-
https://huggingface.co/spaces/MoShow/vortexai-multiverse-generator/resolve/main/script.js
- Command line
-
hf download hf://spaces/MoShow/vortexai-multiverse-generator/script.js
-
curl -L -o script.js https://huggingface.co/spaces/MoShow/vortexai-multiverse-generator/resolve/main/script.js
20.3 kB
| // VortexAI - Main Application Script | |
| // Hugging Face API Configuration with fallback | |
| const HF_CONFIG = { | |
| baseURL: 'https://api-inference.huggingface.co/models/', | |
| fallbackMode: true, // Set to false when API is working | |
| models: { | |
| image: { | |
| 'stable-diffusion-xl': 'stabilityai/stable-diffusion-xl-base-1.0', | |
| 'realistic-vision': 'SG161222/Realistic_Vision_V5.1_noVAE', | |
| 'anime-diffusion': 'Linaqruf/anything-v3.0', | |
| 'deepfloyd-if': 'DeepFloyd/IF-I-XL-v1.0', | |
| 'sdxl-4k': 'stabilityai/stable-diffusion-xl-base-1.0', | |
| 'sdxl-8k': 'stabilityai/stable-diffusion-xl-base-1.0', | |
| 'esrgan': 'Real-ESRGAN' | |
| }, | |
| video: { | |
| 'modelscope-t2v': 'damo-vilab/text-to-video-ms-1.7b', | |
| 'zeroscope': 'cerspense/zeroscope_v2_576w' | |
| }, | |
| '3d': { | |
| 'shap-e': 'openai/shap-e', | |
| 'point-e': 'openai/point-e', | |
| 'zero123': 'cvlab-cvlab/zero123-xl-diffusers' | |
| } | |
| }, | |
| headers: (token) => ({ | |
| 'Authorization': `Bearer ${token}`, | |
| 'Content-Type': 'application/json' | |
| }), | |
| // Check API status | |
| async checkStatus() { | |
| try { | |
| const response = await fetch(this.baseURL, { | |
| method: 'HEAD', | |
| headers: this.headers('') | |
| }); | |
| if (response.status === 200 || response.status === 401) { | |
| this.fallbackMode = false; | |
| return true; | |
| } | |
| } catch (error) { | |
| console.error('Hugging Face API unreachable:', error); | |
| this.fallbackMode = true; | |
| return false; | |
| } | |
| } | |
| }; | |
| // Global State | |
| const state = { | |
| currentMode: 'image', | |
| isGenerating: false, | |
| queue: [], | |
| history: JSON.parse(localStorage.getItem('vortex_history') || '[]'), | |
| settings: { | |
| width: 3840, | |
| height: 2160, | |
| steps: 100, | |
| guidance: 7.5, | |
| seed: -1, | |
| model: 'stable-diffusion-xl', | |
| upscale: 2, | |
| detailEnhancement: 75 | |
| } | |
| }; | |
| // Neural Network Background Animation | |
| class NeuralNetwork { | |
| constructor(canvas) { | |
| this.canvas = canvas; | |
| this.ctx = canvas.getContext('2d'); | |
| this.nodes = []; | |
| this.connections = []; | |
| this.mouse = { x: 0, y: 0 }; | |
| this.init(); | |
| } | |
| init() { | |
| this.resize(); | |
| window.addEventListener('resize', () => this.resize()); | |
| // Create nodes | |
| const nodeCount = Math.min(80, Math.floor(window.innerWidth / 20)); | |
| for (let i = 0; i < nodeCount; i++) { | |
| this.nodes.push({ | |
| x: Math.random() * this.canvas.width, | |
| y: Math.random() * this.canvas.height, | |
| vx: (Math.random() - 0.5) * 0.5, | |
| vy: (Math.random() - 0.5) * 0.5, | |
| radius: Math.random() * 2 + 1, | |
| pulse: Math.random() * Math.PI * 2 | |
| }); | |
| } | |
| this.animate(); | |
| } | |
| resize() { | |
| this.canvas.width = window.innerWidth; | |
| this.canvas.height = window.innerHeight; | |
| } | |
| animate() { | |
| this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height); | |
| // Update and draw nodes | |
| this.nodes.forEach(node => { | |
| node.x += node.vx; | |
| node.y += node.vy; | |
| node.pulse += 0.02; | |
| // Wrap around | |
| if (node.x < 0) node.x = this.canvas.width; | |
| if (node.x > this.canvas.width) node.x = 0; | |
| if (node.y < 0) node.y = this.canvas.height; | |
| if (node.y > this.canvas.height) node.y = 0; | |
| // Draw node with pulse | |
| const pulseSize = node.radius + Math.sin(node.pulse) * 0.5; | |
| const gradient = this.ctx.createRadialGradient( | |
| node.x, node.y, 0, | |
| node.x, node.y, pulseSize * 3 | |
| ); | |
| gradient.addColorStop(0, 'rgba(14, 165, 233, 0.6)'); | |
| gradient.addColorStop(0.5, 'rgba(217, 70, 239, 0.3)'); | |
| gradient.addColorStop(1, 'transparent'); | |
| this.ctx.beginPath(); | |
| this.ctx.arc(node.x, node.y, pulseSize, 0, Math.PI * 2); | |
| this.ctx.fillStyle = gradient; | |
| this.ctx.fill(); | |
| // Draw connections | |
| this.nodes.forEach(other => { | |
| const dx = other.x - node.x; | |
| const dy = other.y - node.y; | |
| const dist = Math.sqrt(dx * dx + dy * dy); | |
| if (dist < 150) { | |
| const opacity = (1 - dist / 150) * 0.3; | |
| this.ctx.beginPath(); | |
| this.ctx.moveTo(node.x, node.y); | |
| this.ctx.lineTo(other.x, other.y); | |
| this.ctx.strokeStyle = `rgba(14, 165, 233, ${opacity})`; | |
| this.ctx.lineWidth = 0.5; | |
| this.ctx.stroke(); | |
| } | |
| }); | |
| }); | |
| requestAnimationFrame(() => this.animate()); | |
| } | |
| } | |
| // Generation Service with API fallback | |
| class GenerationService { | |
| static async generateImage(prompt, options = {}) { | |
| const modelId = HF_CONFIG.models.image[options.model || 'stable-diffusion-xl']; | |
| const targetWidth = options.width || 3840; | |
| const targetHeight = options.height || 2160; | |
| // Determine quality tier | |
| const pixels = targetWidth * targetHeight; | |
| let qualityTier = 'standard'; | |
| if (pixels >= 33177600) qualityTier = 'maximum'; // 8K+ | |
| else if (pixels >= 8294400) qualityTier = 'ultra'; // 4K+ | |
| else if (pixels >= 4194304) qualityTier = 'high'; // 2K+ | |
| // Check API status first | |
| const apiAvailable = await HF_CONFIG.checkStatus(); | |
| if (!apiAvailable || HF_CONFIG.fallbackMode) { | |
| console.warn('Using fallback generation mode - API unavailable'); | |
| return this.fallbackGeneration(prompt, options, 'image'); | |
| } | |
| try { | |
| const payload = { | |
| inputs: prompt, | |
| parameters: { | |
| width: Math.min(targetWidth, 2048), | |
| height: Math.min(targetHeight, 2048), | |
| num_inference_steps: options.steps || 100, | |
| guidance_scale: options.guidance || 7.5, | |
| seed: options.seed || Math.floor(Math.random() * 1000000) | |
| } | |
| }; | |
| const response = await fetch(HF_CONFIG.baseURL + modelId, { | |
| method: 'POST', | |
| headers: HF_CONFIG.headers('YOUR_HF_TOKEN_HERE'), | |
| body: JSON.stringify(payload) | |
| }); | |
| if (!response.ok) { | |
| throw new Error(`API Error: ${response.status}`); | |
| } | |
| const blob = await response.blob(); | |
| const url = URL.createObjectURL(blob); | |
| return { | |
| url, | |
| seed: payload.parameters.seed, | |
| model: modelId, | |
| resolution: `${targetWidth}x${targetHeight}`, | |
| qualityTier, | |
| fileSize: this.estimateFileSize(targetWidth, targetHeight, 'image'), | |
| format: 'PNG' | |
| }; | |
| } catch (error) { | |
| console.error('API generation failed, falling back:', error); | |
| return this.fallbackGeneration(prompt, options, 'image'); | |
| } | |
| } | |
| static fallbackGeneration(prompt, options, mode) { | |
| const baseDuration = 5000; // Shorter duration for fallback | |
| const seed = options.seed || Math.floor(Math.random() * 1000000); | |
| const width = options.width || 1024; | |
| const height = options.height || 1024; | |
| return new Promise((resolve) => { | |
| setTimeout(() => { | |
| resolve({ | |
| url: `https://static.photos/${mode === 'image' ? 'abstract' : mode === 'video' ? 'technology' : '3d'}/${Math.min(width, 1200)}x${Math.min(height, 630)}/${seed}`, | |
| seed, | |
| model: 'fallback', | |
| resolution: `${width}x${height}`, | |
| qualityTier: 'standard', | |
| fileSize: this.estimateFileSize(width, height, mode), | |
| format: 'PNG', | |
| isFallback: true | |
| }); | |
| }, baseDuration); | |
| }); | |
| } | |
| static estimateFileSize(width, height, mode) { | |
| const pixels = width * height; | |
| if (mode === 'image') { | |
| if (pixels >= 33177600) return '~250-500 MB'; | |
| if (pixels >= 8294400) return '~35-80 MB'; | |
| if (pixels >= 4194304) return '~12-25 MB'; | |
| return '~3-8 MB'; | |
| } | |
| return 'Unknown'; | |
| } | |
| static async generateVideo(prompt, options = {}) { | |
| const apiAvailable = await HF_CONFIG.checkStatus(); | |
| if (!apiAvailable || HF_CONFIG.fallbackMode) { | |
| console.warn('Using fallback generation mode - API unavailable'); | |
| return this.fallbackGeneration(prompt, options, 'video'); | |
| } | |
| try { | |
| const modelId = HF_CONFIG.models.video['modelscope-t2v']; | |
| const response = await fetch(HF_CONFIG.baseURL + modelId, { | |
| method: 'POST', | |
| headers: HF_CONFIG.headers('YOUR_HF_TOKEN_HERE'), | |
| body: JSON.stringify({ | |
| inputs: prompt, | |
| parameters: { | |
| num_frames: options.frames || 16, | |
| fps: options.fps || 8 | |
| } | |
| }) | |
| }); | |
| if (!response.ok) { | |
| throw new Error(`API Error: ${response.status}`); | |
| } | |
| const blob = await response.blob(); | |
| const url = URL.createObjectURL(blob); | |
| return { | |
| url, | |
| frames: options.frames || 16, | |
| fps: options.fps || 8, | |
| duration: Math.round((options.frames || 16) / (options.fps || 8)), | |
| model: modelId | |
| }; | |
| } catch (error) { | |
| console.error('API generation failed, falling back:', error); | |
| return this.fallbackGeneration(prompt, options, 'video'); | |
| } | |
| } | |
| static async generate3D(prompt, options = {}) { | |
| const apiAvailable = await HF_CONFIG.checkStatus(); | |
| if (!apiAvailable || HF_CONFIG.fallbackMode) { | |
| console.warn('Using fallback generation mode - API unavailable'); | |
| return this.fallbackGeneration(prompt, options, '3d'); | |
| } | |
| try { | |
| const modelId = HF_CONFIG.models['3d']['shap-e']; | |
| const response = await fetch(HF_CONFIG.baseURL + modelId, { | |
| method: 'POST', | |
| headers: HF_CONFIG.headers('YOUR_HF_TOKEN_HERE'), | |
| body: JSON.stringify({ | |
| inputs: prompt, | |
| parameters: { | |
| resolution: options.resolution || 256 | |
| } | |
| }) | |
| }); | |
| if (!response.ok) { | |
| throw new Error(`API Error: ${response.status}`); | |
| } | |
| const blob = await response.blob(); | |
| const url = URL.createObjectURL(blob); | |
| return { | |
| url, | |
| format: 'obj', | |
| vertices: 5000, | |
| faces: 3000, | |
| model: modelId | |
| }; | |
| } catch (error) { | |
| console.error('API generation failed, falling back:', error); | |
| return this.fallbackGeneration(prompt, options, '3d'); | |
| } | |
| } | |
| static simulateProgress(duration = 5000) { | |
| return new Promise((resolve) => { | |
| const steps = 20; | |
| const stepDuration = duration / steps; | |
| let currentStep = 0; | |
| const interval = setInterval(() => { | |
| currentStep++; | |
| const progress = (currentStep / steps) * 100; | |
| document.dispatchEvent(new CustomEvent('generationProgress', { | |
| detail: { | |
| progress, | |
| step: currentStep, | |
| total: steps, | |
| status: currentStep === steps ? 'Completed' : 'Processing' | |
| } | |
| })); | |
| if (currentStep >= steps) { | |
| clearInterval(interval); | |
| resolve(); | |
| } | |
| }, stepDuration); | |
| }); | |
| } | |
| } | |
| // UI Controllers | |
| const UIController = { | |
| async init() { | |
| this.initNeuralBackground(); | |
| await this.initApiStatus(); | |
| this.initEventListeners(); | |
| this.loadGallery(); | |
| }, | |
| initNeuralBackground() { | |
| const canvas = document.getElementById('neural-canvas'); | |
| if (canvas) { | |
| new NeuralNetwork(canvas); | |
| } | |
| }, | |
| async initApiStatus() { | |
| const apiAvailable = await HF_CONFIG.checkStatus(); | |
| const grid = document.getElementById('api-status-grid'); | |
| if (!grid) return; | |
| if (!apiAvailable) { | |
| grid.innerHTML = ` | |
| <div class="glass-card rounded-xl p-4 col-span-4 text-center"> | |
| <div class="flex items-center justify-center gap-2 mb-2"> | |
| <span class="w-3 h-3 rounded-full bg-amber-500 animate-pulse"></span> | |
| <span class="text-amber-400 font-medium">API Service Disrupted</span> | |
| </div> | |
| <p class="text-sm text-slate-400">Using fallback generation mode</p> | |
| </div> | |
| `; | |
| return; | |
| } | |
| const services = [ | |
| { name: 'Stable Diffusion XL', status: 'operational', latency: '124ms' }, | |
| { name: 'ModelScope T2V', status: 'operational', latency: '892ms' }, | |
| { name: 'Shap-E 3D', status: 'operational', latency: '2341ms' }, | |
| { name: 'Realistic Vision', status: 'operational', latency: '156ms' } | |
| ]; | |
| grid.innerHTML = services.map(s => ` | |
| <div class="glass-card rounded-xl p-4 flex items-center justify-between"> | |
| <div> | |
| <p class="font-medium text-sm">${s.name}</p> | |
| <p class="text-xs text-slate-400">${s.latency}</p> | |
| </div> | |
| <span class="px-2 py-1 rounded-full text-xs font-medium ${s.status === 'operational' ? 'bg-emerald-500/20 text-emerald-400' : 'bg-amber-500/20 text-amber-400'}"> | |
| ${s.status} | |
| </span> | |
| </div> | |
| `).join(''); | |
| }, | |
| initEventListeners() { | |
| // Prompt submission | |
| document.addEventListener('submitPrompt', async (e) => { | |
| const { prompt, mode, settings } = e.detail; | |
| await this.handleGeneration(prompt, mode, settings); | |
| }); | |
| // Progress updates | |
| document.addEventListener('generationProgress', (e) => { | |
| this.updateProgress(e.detail.progress); | |
| }); | |
| // Gallery refresh | |
| document.addEventListener('refreshGallery', () => { | |
| this.loadGallery(); | |
| }); | |
| }, | |
| async handleGeneration(prompt, mode, settings) { | |
| const modal = document.getElementById('generation-modal'); | |
| modal.show(); | |
| try { | |
| document.dispatchEvent(new CustomEvent('generationProgress', { | |
| detail: { | |
| progress: 0, | |
| step: 0, | |
| total: 20, | |
| status: 'Initializing...' | |
| } | |
| })); | |
| let result; | |
| switch (mode) { | |
| case 'image': | |
| result = await GenerationService.generateImage(prompt, settings); | |
| break; | |
| case 'video': | |
| result = await GenerationService.generateVideo(prompt, settings); | |
| break; | |
| case 'gif': | |
| result = await GenerationService.generateVideo(prompt, { ...settings, format: 'gif' }); | |
| break; | |
| case '3d': | |
| result = await GenerationService.generate3D(prompt, settings); | |
| break; | |
| default: | |
| throw new Error('Unknown generation mode'); | |
| } | |
| // Save to history | |
| const entry = { | |
| id: Date.now(), | |
| prompt, | |
| mode, | |
| result, | |
| timestamp: new Date().toISOString(), | |
| isFallback: result.isFallback || false | |
| }; | |
| state.history.unshift(entry); | |
| localStorage.setItem('vortex_history', JSON.stringify(state.history.slice(0, 50))); | |
| modal.showResult(result, mode); | |
| } catch (error) { | |
| console.error('Generation error:', error); | |
| modal.showError(error.message); | |
| } | |
| }, | |
| updateProgress(detail) { | |
| const modal = document.getElementById('generation-modal'); | |
| if (modal && modal.updateProgress) { | |
| modal.updateProgress(detail.progress, detail.status); | |
| } | |
| // Also update API status if progress indicates completion | |
| if (detail.progress === 100) { | |
| setTimeout(() => this.initApiStatus(), 1000); | |
| } | |
| }, | |
| loadGallery() { | |
| const gallery = document.getElementById('gallery'); | |
| if (gallery) { | |
| // Load from history or generate demo items | |
| let items = state.history.length > 0 ? state.history : this.generateDemoGallery(); | |
| // Mark demo items as fallback | |
| if (state.history.length === 0) { | |
| items = items.map(item => ({ | |
| ...item, | |
| isFallback: true | |
| })); | |
| } | |
| gallery.setItems(items.slice(0, 12)); | |
| } | |
| }, | |
| generateDemoGallery() { | |
| const prompts = [ | |
| 'A cyberpunk city at sunset with neon lights and flying cars, 8K HDR', | |
| 'Portrait of a mystical forest spirit with bioluminescent features, 16K detail', | |
| 'Abstract 3D sculpture made of liquid metal and glass, 4K render', | |
| 'Ancient temple floating in the clouds during golden hour, IMAX quality', | |
| 'Futuristic robot with human-like emotions in a garden, 8K photorealistic', | |
| 'Interstellar spaceship docked at a massive space station, 20K resolution' | |
| ]; | |
| const resolutions = [ | |
| { w: 7680, h: 4320, label: '8K' }, | |
| { w: 15360, h: 8640, label: '16K' }, | |
| { w: 3840, h: 2160, label: '4K' }, | |
| { w: 7680, h: 4320, label: '8K' }, | |
| { w: 20480, h: 20480, label: '20K' }, | |
| { w: 15360, h: 8640, label: '16K' } | |
| ]; | |
| return prompts.map((prompt, i) => ({ | |
| id: i, | |
| prompt, | |
| mode: ['image', 'video', '3d'][i % 3], | |
| result: { | |
| url: `https://static.photos/${['technology', 'nature', 'abstract', 'architecture', 'people', 'science'][i]}/1200x630/${i + 1}`, | |
| resolution: `${resolutions[i].w}x${resolutions[i].h}`, | |
| qualityLabel: resolutions[i].label, | |
| isFallback: true | |
| }, | |
| timestamp: new Date(Date.now() - i * 86400000).toISOString(), | |
| isFallback: true | |
| })); | |
| } | |
| }; | |
| // Utility Functions | |
| const Utils = { | |
| formatNumber(num) { | |
| return new Intl.NumberFormat('en-US', { notation: 'compact' }).format(num); | |
| }, | |
| formatTime(date) { | |
| return new Intl.RelativeTimeFormat('en', { numeric: 'auto' }).format( | |
| Math.ceil((new Date(date) - new Date()) / 1000 / 60), | |
| 'minute' | |
| ); | |
| }, | |
| debounce(fn, ms) { | |
| let timeout; | |
| return (...args) => { | |
| clearTimeout(timeout); | |
| timeout = setTimeout(() => fn(...args), ms); | |
| }; | |
| }, | |
| randomSeed() { | |
| return Math.floor(Math.random() * 1000000000); | |
| } | |
| }; | |
| // Initialize on DOM ready | |
| document.addEventListener('DOMContentLoaded', () => { | |
| UIController.init(); | |
| }); | |
| // Export for modules | |
| window.VortexAI = { state, GenerationService, Utils, HF_CONFIG }; |