diff --git a/src/components/VideoStudio.js b/src/components/VideoStudio.js
new file mode 100644
index 0000000..e49b537
--- /dev/null
+++ b/src/components/VideoStudio.js
@@ -0,0 +1,554 @@
+import { muapi } from '../lib/muapi.js';
+import { t2vModels, getAspectRatiosForVideoModel, getDurationsForModel, getResolutionsForVideoModel } from '../lib/models.js';
+import { AuthModal } from './AuthModal.js';
+
+export function VideoStudio() {
+ const container = document.createElement('div');
+ container.className = 'w-full h-full flex flex-col items-center justify-center bg-app-bg relative p-4 md:p-6 overflow-y-auto custom-scrollbar overflow-x-hidden';
+
+ // --- State ---
+ const defaultModel = t2vModels[0];
+ let selectedModel = defaultModel.id;
+ let selectedModelName = defaultModel.name;
+ let selectedAr = defaultModel.inputs?.aspect_ratio?.default || '16:9';
+ let selectedDuration = defaultModel.inputs?.duration?.default || 5;
+ let selectedResolution = defaultModel.inputs?.resolution?.default || '';
+ let dropdownOpen = null;
+
+ // ==========================================
+ // 1. HERO SECTION
+ // ==========================================
+ const hero = document.createElement('div');
+ hero.className = 'flex flex-col items-center mb-10 md:mb-20 animate-fade-in-up transition-all duration-700';
+ hero.innerHTML = `
+
+ Video Studio
+ Create stunning AI videos from text in seconds
+ `;
+ container.appendChild(hero);
+
+ // ==========================================
+ // 2. PROMPT BAR
+ // ==========================================
+ const promptWrapper = document.createElement('div');
+ promptWrapper.className = 'w-full max-w-4xl relative z-40 animate-fade-in-up';
+ promptWrapper.style.animationDelay = '0.2s';
+
+ const bar = document.createElement('div');
+ bar.className = 'w-full bg-[#111]/90 backdrop-blur-xl border border-white/10 rounded-[1.5rem] md:rounded-[2.5rem] p-3 md:p-5 flex flex-col gap-3 md:gap-5 shadow-3xl';
+
+ const topRow = document.createElement('div');
+ topRow.className = 'flex items-start gap-5 px-2';
+
+ const textarea = document.createElement('textarea');
+ textarea.placeholder = 'Describe the video you imagine';
+ textarea.className = 'flex-1 bg-transparent border-none text-white text-base md:text-xl placeholder:text-muted focus:outline-none resize-none pt-2.5 leading-relaxed min-h-[40px] max-h-[150px] md:max-h-[250px] overflow-y-auto custom-scrollbar';
+ textarea.rows = 1;
+ textarea.oninput = () => {
+ textarea.style.height = 'auto';
+ const maxHeight = window.innerWidth < 768 ? 150 : 250;
+ textarea.style.height = Math.min(textarea.scrollHeight, maxHeight) + 'px';
+ };
+
+ topRow.appendChild(textarea);
+ bar.appendChild(topRow);
+
+ // Bottom Row: Controls
+ const bottomRow = document.createElement('div');
+ bottomRow.className = 'flex flex-col sm:flex-row items-stretch sm:items-center justify-between gap-4 px-2 pt-4 border-t border-white/5';
+
+ const controlsLeft = document.createElement('div');
+ controlsLeft.className = 'flex items-center gap-1.5 md:gap-2.5 relative overflow-x-auto no-scrollbar pb-1 md:pb-0';
+
+ const createControlBtn = (icon, label, id) => {
+ const btn = document.createElement('button');
+ btn.id = id;
+ btn.className = 'flex items-center gap-1.5 md:gap-2.5 px-3 md:px-4 py-2 md:py-2.5 bg-white/5 hover:bg-white/10 rounded-xl md:rounded-2xl transition-all border border-white/5 group whitespace-nowrap';
+ btn.innerHTML = `
+ ${icon}
+ ${label}
+
+ `;
+ return btn;
+ };
+
+ const modelBtn = createControlBtn(`
+
+ V
+
+ `, selectedModelName, 'v-model-btn');
+
+ const arBtn = createControlBtn(`
+
+ `, selectedAr, 'v-ar-btn');
+
+ const durationBtn = createControlBtn(`
+
+ `, `${selectedDuration}s`, 'v-duration-btn');
+
+ const resolutionBtn = createControlBtn(`
+
+ `, selectedResolution || '720p', 'v-resolution-btn');
+
+ controlsLeft.appendChild(modelBtn);
+ controlsLeft.appendChild(arBtn);
+ controlsLeft.appendChild(durationBtn);
+ controlsLeft.appendChild(resolutionBtn);
+
+ // Initial visibility
+ const initDurations = getDurationsForModel(defaultModel.id);
+ durationBtn.style.display = initDurations.length > 0 ? 'flex' : 'none';
+ const initResolutions = getResolutionsForVideoModel(defaultModel.id);
+ resolutionBtn.style.display = initResolutions.length > 0 ? 'flex' : 'none';
+
+ const generateBtn = document.createElement('button');
+ generateBtn.className = 'bg-primary text-black px-6 md:px-8 py-3 md:py-3.5 rounded-xl md:rounded-[1.5rem] font-black text-sm md:text-base hover:shadow-glow hover:scale-105 active:scale-95 transition-all flex items-center justify-center gap-2.5 w-full sm:w-auto shadow-lg';
+ generateBtn.innerHTML = `Generate ✨`;
+
+ bottomRow.appendChild(controlsLeft);
+ bottomRow.appendChild(generateBtn);
+ bar.appendChild(bottomRow);
+ promptWrapper.appendChild(bar);
+ container.appendChild(promptWrapper);
+
+ // ==========================================
+ // 3. DROPDOWNS
+ // ==========================================
+ const dropdown = document.createElement('div');
+ dropdown.className = 'absolute bottom-[102%] left-2 z-50 transition-all opacity-0 pointer-events-none scale-95 origin-bottom-left glass rounded-3xl p-3 translate-y-2 w-[calc(100vw-3rem)] max-w-xs shadow-4xl border border-white/10 flex flex-col';
+
+ const updateControlsForModel = (modelId) => {
+ const availableArs = getAspectRatiosForVideoModel(modelId);
+ selectedAr = availableArs[0];
+ document.getElementById('v-ar-btn-label').textContent = selectedAr;
+
+ const durations = getDurationsForModel(modelId);
+ if (durations.length > 0) {
+ selectedDuration = durations[0];
+ document.getElementById('v-duration-btn-label').textContent = `${selectedDuration}s`;
+ durationBtn.style.display = 'flex';
+ } else {
+ durationBtn.style.display = 'none';
+ }
+
+ const resolutions = getResolutionsForVideoModel(modelId);
+ if (resolutions.length > 0) {
+ selectedResolution = resolutions[0];
+ document.getElementById('v-resolution-btn-label').textContent = selectedResolution;
+ resolutionBtn.style.display = 'flex';
+ } else {
+ resolutionBtn.style.display = 'none';
+ }
+ };
+
+ const showDropdown = (type, anchorBtn) => {
+ dropdown.innerHTML = '';
+ dropdown.classList.remove('opacity-0', 'pointer-events-none');
+ dropdown.classList.add('opacity-100', 'pointer-events-auto');
+
+ if (type === 'model') {
+ dropdown.classList.add('w-[calc(100vw-3rem)]', 'max-w-xs');
+ dropdown.classList.remove('max-w-[240px]', 'max-w-[200px]');
+ dropdown.innerHTML = `
+
+ `;
+ const list = dropdown.querySelector('#v-model-list-container');
+
+ const renderModels = (filter = '') => {
+ list.innerHTML = '';
+ const filtered = t2vModels.filter(m => m.name.toLowerCase().includes(filter.toLowerCase()) || m.id.toLowerCase().includes(filter.toLowerCase()));
+ filtered.forEach(m => {
+ const item = document.createElement('div');
+ item.className = `flex items-center justify-between p-3.5 hover:bg-white/5 rounded-2xl cursor-pointer transition-all border border-transparent hover:border-white/5 ${selectedModel === m.id ? 'bg-white/5 border-white/5' : ''}`;
+ item.innerHTML = `
+
+
${m.name.charAt(0)}
+
+ ${m.name}
+
+
+ ${selectedModel === m.id ? '' : ''}
+ `;
+ item.onclick = (e) => {
+ e.stopPropagation();
+ selectedModel = m.id;
+ selectedModelName = m.name;
+ document.getElementById('v-model-btn-label').textContent = selectedModelName;
+ updateControlsForModel(selectedModel);
+ closeDropdown();
+ };
+ list.appendChild(item);
+ });
+ };
+
+ renderModels();
+ const searchInput = dropdown.querySelector('#v-model-search');
+ searchInput.onclick = (e) => e.stopPropagation();
+ searchInput.oninput = (e) => renderModels(e.target.value);
+
+ } else if (type === 'ar') {
+ dropdown.classList.add('max-w-[240px]');
+ dropdown.innerHTML = `Aspect Ratio
`;
+ const list = document.createElement('div');
+ list.className = 'flex flex-col gap-1';
+ const availableArs = getAspectRatiosForVideoModel(selectedModel);
+ availableArs.forEach(r => {
+ const item = document.createElement('div');
+ item.className = 'flex items-center justify-between p-3.5 hover:bg-white/5 rounded-2xl cursor-pointer transition-all group';
+ item.innerHTML = `
+
+ ${selectedAr === r ? '' : ''}
+ `;
+ item.onclick = (e) => {
+ e.stopPropagation();
+ selectedAr = r;
+ document.getElementById('v-ar-btn-label').textContent = r;
+ closeDropdown();
+ };
+ list.appendChild(item);
+ });
+ dropdown.appendChild(list);
+
+ } else if (type === 'duration') {
+ dropdown.classList.add('max-w-[200px]');
+ dropdown.innerHTML = `Duration
`;
+ const list = document.createElement('div');
+ list.className = 'flex flex-col gap-1';
+ const durations = getDurationsForModel(selectedModel);
+ durations.forEach(d => {
+ const item = document.createElement('div');
+ item.className = 'flex items-center justify-between p-3.5 hover:bg-white/5 rounded-2xl cursor-pointer transition-all group';
+ item.innerHTML = `
+ ${d}s
+ ${selectedDuration === d ? '' : ''}
+ `;
+ item.onclick = (e) => {
+ e.stopPropagation();
+ selectedDuration = d;
+ document.getElementById('v-duration-btn-label').textContent = `${d}s`;
+ closeDropdown();
+ };
+ list.appendChild(item);
+ });
+ dropdown.appendChild(list);
+
+ } else if (type === 'resolution') {
+ dropdown.classList.add('max-w-[200px]');
+ dropdown.innerHTML = `Resolution
`;
+ const list = document.createElement('div');
+ list.className = 'flex flex-col gap-1';
+ const resolutions = getResolutionsForVideoModel(selectedModel);
+ resolutions.forEach(r => {
+ const item = document.createElement('div');
+ item.className = 'flex items-center justify-between p-3.5 hover:bg-white/5 rounded-2xl cursor-pointer transition-all group';
+ item.innerHTML = `
+ ${r}
+ ${selectedResolution === r ? '' : ''}
+ `;
+ item.onclick = (e) => {
+ e.stopPropagation();
+ selectedResolution = r;
+ document.getElementById('v-resolution-btn-label').textContent = r;
+ closeDropdown();
+ };
+ list.appendChild(item);
+ });
+ dropdown.appendChild(list);
+ }
+
+ // Position dropdown
+ const btnRect = anchorBtn.getBoundingClientRect();
+ const containerRect = container.getBoundingClientRect();
+ if (window.innerWidth < 768) {
+ dropdown.style.left = '50%';
+ dropdown.style.transform = 'translateX(-50%) translate(0, 8px)';
+ } else {
+ dropdown.style.left = `${btnRect.left - containerRect.left}px`;
+ dropdown.style.transform = 'translate(0, 8px)';
+ }
+ dropdown.style.bottom = `${containerRect.bottom - btnRect.top + 8}px`;
+ };
+
+ const closeDropdown = () => {
+ dropdown.classList.add('opacity-0', 'pointer-events-none');
+ dropdown.classList.remove('opacity-100', 'pointer-events-auto');
+ dropdownOpen = null;
+ };
+
+ const toggleDropdown = (type, btn) => (e) => {
+ e.stopPropagation();
+ if (dropdownOpen === type) closeDropdown();
+ else { dropdownOpen = type; showDropdown(type, btn); }
+ };
+
+ modelBtn.onclick = toggleDropdown('model', modelBtn);
+ arBtn.onclick = toggleDropdown('ar', arBtn);
+ durationBtn.onclick = toggleDropdown('duration', durationBtn);
+ resolutionBtn.onclick = toggleDropdown('resolution', resolutionBtn);
+
+ window.addEventListener('click', closeDropdown);
+ container.appendChild(dropdown);
+
+ // ==========================================
+ // 4. CANVAS AREA + HISTORY
+ // ==========================================
+ const generationHistory = [];
+
+ const historySidebar = document.createElement('div');
+ historySidebar.className = 'fixed right-0 top-0 h-full w-20 md:w-24 bg-black/60 backdrop-blur-xl border-l border-white/5 z-50 flex flex-col items-center py-4 gap-3 overflow-y-auto transition-all duration-500 translate-x-full opacity-0';
+ historySidebar.id = 'video-history-sidebar';
+
+ const historyLabel = document.createElement('div');
+ historyLabel.className = 'text-[9px] font-bold text-muted uppercase tracking-widest mb-2';
+ historyLabel.textContent = 'History';
+ historySidebar.appendChild(historyLabel);
+
+ const historyList = document.createElement('div');
+ historyList.className = 'flex flex-col gap-2 w-full px-2';
+ historySidebar.appendChild(historyList);
+ container.appendChild(historySidebar);
+
+ // Main canvas
+ const canvas = document.createElement('div');
+ canvas.className = 'absolute inset-0 flex flex-col items-center justify-center p-4 min-[800px]:p-16 z-10 opacity-0 pointer-events-none transition-all duration-1000 translate-y-10 scale-95';
+
+ const videoContainer = document.createElement('div');
+ videoContainer.className = 'relative group';
+
+ const resultVideo = document.createElement('video');
+ resultVideo.className = 'max-h-[60vh] max-w-[80vw] rounded-3xl shadow-3xl border border-white/10 interactive-glow object-contain';
+ resultVideo.controls = true;
+ resultVideo.loop = true;
+ resultVideo.autoplay = true;
+ resultVideo.muted = true;
+ resultVideo.playsInline = true;
+ videoContainer.appendChild(resultVideo);
+
+ // Canvas Controls
+ const canvasControls = document.createElement('div');
+ canvasControls.className = 'mt-6 flex gap-3 opacity-0 transition-opacity delay-500 duration-500 justify-center';
+
+ const regenerateBtn = document.createElement('button');
+ regenerateBtn.className = 'bg-white/10 hover:bg-white/20 px-6 py-2.5 rounded-2xl text-xs font-bold transition-all border border-white/5 backdrop-blur-lg text-white';
+ regenerateBtn.textContent = '↻ Regenerate';
+
+ const downloadBtn = document.createElement('button');
+ downloadBtn.className = 'bg-primary text-black px-6 py-2.5 rounded-2xl text-xs font-bold transition-all shadow-glow active:scale-95';
+ downloadBtn.textContent = '↓ Download';
+
+ const newPromptBtn = document.createElement('button');
+ newPromptBtn.className = 'bg-white/10 hover:bg-white/20 px-6 py-2.5 rounded-2xl text-xs font-bold transition-all border border-white/5 backdrop-blur-lg text-white';
+ newPromptBtn.textContent = '+ New';
+
+ canvasControls.appendChild(regenerateBtn);
+ canvasControls.appendChild(downloadBtn);
+ canvasControls.appendChild(newPromptBtn);
+
+ canvas.appendChild(videoContainer);
+ canvas.appendChild(canvasControls);
+ container.appendChild(canvas);
+
+ // --- Helper: Show video in canvas ---
+ const showVideoInCanvas = (videoUrl) => {
+ hero.classList.add('hidden');
+ promptWrapper.classList.add('hidden');
+
+ resultVideo.src = videoUrl;
+ resultVideo.onloadeddata = () => {
+ canvas.classList.remove('opacity-0', 'pointer-events-none', 'translate-y-10', 'scale-95');
+ canvas.classList.add('opacity-100', 'translate-y-0', 'scale-100');
+ canvasControls.classList.remove('opacity-0');
+ canvasControls.classList.add('opacity-100');
+ };
+ };
+
+ // --- Helper: Add to history ---
+ const addToHistory = (entry) => {
+ generationHistory.unshift(entry);
+ localStorage.setItem('video_history', JSON.stringify(generationHistory.slice(0, 30)));
+ historySidebar.classList.remove('translate-x-full', 'opacity-0');
+ historySidebar.classList.add('translate-x-0', 'opacity-100');
+ renderHistory();
+ };
+
+ const renderHistory = () => {
+ historyList.innerHTML = '';
+ generationHistory.forEach((entry, idx) => {
+ const thumb = document.createElement('div');
+ thumb.className = `relative group/thumb cursor-pointer rounded-xl overflow-hidden border-2 transition-all duration-300 ${idx === 0 ? 'border-primary shadow-glow' : 'border-white/10 hover:border-white/30'}`;
+
+ thumb.innerHTML = `
+
+
+ `;
+
+ thumb.onclick = (e) => {
+ if (e.target.closest('.hist-download')) {
+ downloadFile(entry.url, `video-${entry.id || idx}.mp4`);
+ return;
+ }
+ showVideoInCanvas(entry.url);
+ historyList.querySelectorAll('div').forEach(t => {
+ t.classList.remove('border-primary', 'shadow-glow');
+ t.classList.add('border-white/10');
+ });
+ thumb.classList.remove('border-white/10');
+ thumb.classList.add('border-primary', 'shadow-glow');
+ };
+
+ historyList.appendChild(thumb);
+ });
+ };
+
+ // --- Helper: Download file ---
+ const downloadFile = async (url, filename) => {
+ try {
+ const response = await fetch(url);
+ const blob = await response.blob();
+ const blobUrl = URL.createObjectURL(blob);
+ const a = document.createElement('a');
+ a.href = blobUrl;
+ a.download = filename;
+ document.body.appendChild(a);
+ a.click();
+ document.body.removeChild(a);
+ URL.revokeObjectURL(blobUrl);
+ } catch (err) {
+ window.open(url, '_blank');
+ }
+ };
+
+ // --- Load history from localStorage ---
+ try {
+ const saved = JSON.parse(localStorage.getItem('video_history') || '[]');
+ if (saved.length > 0) {
+ saved.forEach(e => generationHistory.push(e));
+ historySidebar.classList.remove('translate-x-full', 'opacity-0');
+ historySidebar.classList.add('translate-x-0', 'opacity-100');
+ renderHistory();
+ }
+ } catch (e) { /* ignore */ }
+
+ // --- Button Handlers ---
+ downloadBtn.onclick = () => {
+ const current = resultVideo.src;
+ if (current) {
+ const entry = generationHistory.find(e => e.url === current);
+ downloadFile(current, `video-${entry?.id || 'clip'}.mp4`);
+ }
+ };
+
+ regenerateBtn.onclick = () => generateBtn.click();
+
+ newPromptBtn.onclick = () => {
+ canvas.classList.add('opacity-0', 'pointer-events-none', 'translate-y-10', 'scale-95');
+ canvas.classList.remove('opacity-100', 'translate-y-0', 'scale-100');
+ canvasControls.classList.add('opacity-0');
+ canvasControls.classList.remove('opacity-100');
+ hero.classList.remove('hidden', 'opacity-0', 'scale-95', '-translate-y-10', 'pointer-events-none');
+ promptWrapper.classList.remove('hidden', 'opacity-40');
+ textarea.value = '';
+ textarea.focus();
+ };
+
+ // ==========================================
+ // 5. GENERATION LOGIC
+ // ==========================================
+ generateBtn.onclick = async () => {
+ const prompt = textarea.value.trim();
+ if (!prompt) return;
+
+ const apiKey = localStorage.getItem('muapi_key');
+ if (!apiKey) {
+ AuthModal(() => generateBtn.click());
+ return;
+ }
+
+ hero.classList.add('opacity-0', 'scale-95', '-translate-y-10', 'pointer-events-none');
+
+ generateBtn.disabled = true;
+ generateBtn.innerHTML = `◌ Generating...`;
+
+ try {
+ const params = {
+ prompt,
+ model: selectedModel,
+ aspect_ratio: selectedAr,
+ };
+
+ const durations = getDurationsForModel(selectedModel);
+ if (durations.length > 0) params.duration = selectedDuration;
+
+ const resolutions = getResolutionsForVideoModel(selectedModel);
+ if (resolutions.length > 0) params.resolution = selectedResolution;
+
+ const model = t2vModels.find(m => m.id === selectedModel);
+ if (model?.inputs?.quality) params.quality = model.inputs.quality.default;
+
+ const res = await muapi.generateVideo(params);
+
+ console.log('[VideoStudio] Full response:', res);
+
+ if (res && res.url) {
+ addToHistory({
+ id: res.id || Date.now().toString(),
+ url: res.url,
+ prompt,
+ model: selectedModel,
+ aspect_ratio: selectedAr,
+ duration: selectedDuration,
+ timestamp: new Date().toISOString()
+ });
+ showVideoInCanvas(res.url);
+ } else {
+ console.error('[VideoStudio] No video URL in response:', res);
+ throw new Error('No video URL returned by API');
+ }
+ } catch (e) {
+ console.error(e);
+ generateBtn.innerHTML = `Error: ${e.message.slice(0, 40)}`;
+ setTimeout(() => {
+ generateBtn.innerHTML = `Generate ✨`;
+ generateBtn.disabled = false;
+ }, 3000);
+ } finally {
+ generateBtn.disabled = false;
+ generateBtn.innerHTML = `Generate ✨`;
+ }
+ };
+
+ return container;
+}
diff --git a/src/lib/models.js b/src/lib/models.js
index 5994678..2d86987 100644
--- a/src/lib/models.js
+++ b/src/lib/models.js
@@ -2021,3 +2021,408 @@ export const getAspectRatiosForModel = (modelId) => {
return ['1:1', '16:9', '9:16', '4:3', '3:2', '21:9'];
};
+
+// ==========================================
+// Text-to-Video Models
+// ==========================================
+export const t2vModels = [
+ {
+ "id": "seedance-lite-t2v",
+ "name": "Seedance Lite",
+ "inputs": {
+ "prompt": { "type": "string", "title": "Prompt", "name": "prompt", "description": "The prompt to generate the video" },
+ "aspect_ratio": { "enum": ["16:9", "9:16", "1:1", "4:3", "3:4", "21:9", "9:21"], "title": "Aspect Ratio", "name": "aspect_ratio", "type": "string", "description": "Aspect ratio of the output video.", "default": "16:9" },
+ "duration": { "title": "Duration", "name": "duration", "type": "int", "description": "The duration of the generated video in seconds", "default": 5 },
+ "resolution": { "enum": ["480p", "720p", "1080p"], "title": "Resolution", "name": "resolution", "type": "string", "description": "The resolution of the generated video.", "default": "480p" }
+ }
+ },
+ {
+ "id": "seedance-pro-t2v",
+ "name": "Seedance Pro",
+ "inputs": {
+ "prompt": { "type": "string", "title": "Prompt", "name": "prompt", "description": "The prompt to generate the video" },
+ "aspect_ratio": { "enum": ["16:9", "9:16", "1:1", "4:3", "3:4", "21:9", "9:21"], "title": "Aspect Ratio", "name": "aspect_ratio", "type": "string", "description": "Aspect ratio of the output video.", "default": "16:9" },
+ "duration": { "title": "Duration", "name": "duration", "type": "int", "description": "The duration of the generated video in seconds", "default": 5 },
+ "resolution": { "enum": ["480p", "720p", "1080p"], "title": "Resolution", "name": "resolution", "type": "string", "description": "The resolution of the generated video.", "default": "480p" }
+ }
+ },
+ {
+ "id": "seedance-pro-t2v-fast",
+ "name": "Seedance Pro Fast",
+ "inputs": {
+ "prompt": { "type": "string", "title": "Prompt", "name": "prompt", "description": "The prompt to generate the video" },
+ "aspect_ratio": { "enum": ["16:9", "9:16", "1:1", "4:3", "3:4", "21:9"], "title": "Aspect Ratio", "name": "aspect_ratio", "type": "string", "description": "Aspect ratio of the output video.", "default": "16:9" },
+ "duration": { "title": "Duration", "name": "duration", "type": "int", "description": "The duration of the generated video in seconds", "default": 5 },
+ "resolution": { "enum": ["480p", "720p", "1080p"], "title": "Resolution", "name": "resolution", "type": "string", "description": "The resolution of the generated video.", "default": "480p" }
+ }
+ },
+ {
+ "id": "seedance-v1.5-pro-t2v",
+ "name": "Seedance v1.5 Pro",
+ "inputs": {
+ "prompt": { "type": "string", "title": "Prompt", "name": "prompt", "description": "Text prompt describing the video." },
+ "aspect_ratio": { "enum": ["16:9", "9:16", "1:1", "3:4", "4:3", "21:9"], "title": "Aspect Ratio", "name": "aspect_ratio", "type": "string", "description": "Aspect ratio of the output video.", "default": "16:9" },
+ "duration": { "title": "Duration", "name": "duration", "type": "int", "description": "The duration of the generated video in seconds", "default": 5 },
+ "resolution": { "enum": ["480p", "720p", "1080p"], "title": "Resolution", "name": "resolution", "type": "string", "description": "The resolution of the generated video.", "default": "720p" }
+ }
+ },
+ {
+ "id": "seedance-v1.5-pro-t2v-fast",
+ "name": "Seedance v1.5 Pro Fast",
+ "inputs": {
+ "prompt": { "type": "string", "title": "Prompt", "name": "prompt", "description": "Text prompt describing the video." },
+ "aspect_ratio": { "enum": ["16:9", "9:16", "1:1", "3:4", "4:3", "21:9"], "title": "Aspect Ratio", "name": "aspect_ratio", "type": "string", "description": "Aspect ratio of the output video.", "default": "16:9" },
+ "duration": { "title": "Duration", "name": "duration", "type": "int", "description": "The duration of the generated video in seconds", "default": 5 },
+ "resolution": { "enum": ["720p", "1080p"], "title": "Resolution", "name": "resolution", "type": "string", "description": "The resolution of the generated video.", "default": "720p" }
+ }
+ },
+ {
+ "id": "kling-v2.1-master-t2v",
+ "name": "Kling v2.1 Master",
+ "inputs": {
+ "prompt": { "type": "string", "title": "Prompt", "name": "prompt", "description": "Text prompt describing the video." },
+ "aspect_ratio": { "enum": ["16:9", "9:16", "1:1"], "title": "Aspect Ratio", "name": "aspect_ratio", "type": "string", "description": "Aspect ratio of the output video.", "default": "16:9" },
+ "duration": { "title": "Duration", "name": "duration", "type": "int", "description": "The duration of the generated video in seconds", "default": 5 }
+ }
+ },
+ {
+ "id": "kling-v2.5-turbo-pro-t2v",
+ "name": "Kling v2.5 Turbo Pro",
+ "inputs": {
+ "prompt": { "type": "string", "title": "Prompt", "name": "prompt", "description": "Text prompt describing the video." },
+ "aspect_ratio": { "enum": ["16:9", "9:16", "1:1"], "title": "Aspect Ratio", "name": "aspect_ratio", "type": "string", "description": "Aspect ratio of the output video.", "default": "9:16" },
+ "duration": { "title": "Duration", "name": "duration", "type": "int", "description": "The duration of the generated video in seconds", "default": 5 }
+ }
+ },
+ {
+ "id": "kling-v2.6-pro-t2v",
+ "name": "Kling v2.6 Pro",
+ "inputs": {
+ "prompt": { "type": "string", "title": "Prompt", "name": "prompt", "description": "The prompt to generate the video" },
+ "aspect_ratio": { "enum": ["16:9", "9:16", "1:1"], "title": "Aspect Ratio", "name": "aspect_ratio", "type": "string", "description": "Aspect ratio of the output video.", "default": "16:9" },
+ "duration": { "enum": [5, 10], "title": "Duration", "name": "duration", "type": "int", "description": "The duration of the generated video in seconds.", "default": 5 }
+ }
+ },
+ {
+ "id": "kling-o1-text-to-video",
+ "name": "Kling O1 Pro",
+ "inputs": {
+ "prompt": { "type": "string", "title": "Prompt", "name": "prompt", "description": "Text prompt describing the video." },
+ "aspect_ratio": { "enum": ["16:9", "9:16", "1:1"], "title": "Aspect Ratio", "name": "aspect_ratio", "type": "string", "description": "Aspect ratio of the output video.", "default": "16:9" },
+ "duration": { "enum": [5, 10], "title": "Duration", "name": "duration", "type": "int", "description": "The duration of the generated video in seconds", "default": 5 }
+ }
+ },
+ {
+ "id": "kling-v3.0-pro-text-to-video",
+ "name": "Kling v3.0 Pro",
+ "inputs": {
+ "prompt": { "type": "string", "title": "Prompt", "name": "prompt", "description": "Text prompt describing the video." },
+ "aspect_ratio": { "enum": ["16:9", "9:16", "1:1"], "title": "Aspect Ratio", "name": "aspect_ratio", "type": "string", "description": "The aspect ratio of the generated video", "default": "16:9" },
+ "duration": { "title": "Duration", "name": "duration", "type": "int", "description": "The duration of the generated video in seconds", "default": 5 }
+ }
+ },
+ {
+ "id": "kling-v3.0-standard-text-to-video",
+ "name": "Kling v3.0 Standard",
+ "inputs": {
+ "prompt": { "type": "string", "title": "Prompt", "name": "prompt", "description": "Text prompt describing the video." },
+ "aspect_ratio": { "enum": ["16:9", "9:16", "1:1"], "title": "Aspect Ratio", "name": "aspect_ratio", "type": "string", "description": "The aspect ratio of the generated video", "default": "16:9" },
+ "duration": { "title": "Duration", "name": "duration", "type": "int", "description": "The duration of the generated video in seconds", "default": 5 }
+ }
+ },
+ {
+ "id": "veo3-text-to-video",
+ "name": "Veo 3",
+ "inputs": {
+ "prompt": { "type": "string", "title": "Prompt", "name": "prompt", "description": "Text prompt describing the desired video content." },
+ "aspect_ratio": { "enum": ["16:9", "9:16"], "title": "Aspect Ratio", "name": "aspect_ratio", "type": "string", "description": "Aspect ratio of the output video.", "default": "16:9" }
+ }
+ },
+ {
+ "id": "veo3-fast-text-to-video",
+ "name": "Veo 3 Fast",
+ "inputs": {
+ "prompt": { "type": "string", "title": "Prompt", "name": "prompt", "description": "Text prompt describing the desired video content." },
+ "aspect_ratio": { "enum": ["16:9", "9:16"], "title": "Aspect Ratio", "name": "aspect_ratio", "type": "string", "description": "Aspect ratio of the output video.", "default": "16:9" }
+ }
+ },
+ {
+ "id": "veo3.1-text-to-video",
+ "name": "Veo 3.1",
+ "inputs": {
+ "prompt": { "type": "string", "title": "Prompt", "name": "prompt", "description": "Text prompt describing the video." },
+ "aspect_ratio": { "enum": ["16:9", "9:16"], "title": "Aspect Ratio", "name": "aspect_ratio", "type": "string", "description": "Aspect ratio of the output video.", "default": "16:9" },
+ "duration": { "enum": [8], "title": "Duration", "name": "duration", "type": "int", "description": "The duration of the generated video in seconds", "default": 8 },
+ "resolution": { "enum": ["1080p"], "title": "Resolution", "name": "resolution", "type": "string", "description": "The resolution of the generated video.", "default": "1080p" }
+ }
+ },
+ {
+ "id": "veo3.1-fast-text-to-video",
+ "name": "Veo 3.1 Fast",
+ "inputs": {
+ "prompt": { "type": "string", "title": "Prompt", "name": "prompt", "description": "Text prompt describing the video." },
+ "aspect_ratio": { "enum": ["16:9", "9:16"], "title": "Aspect Ratio", "name": "aspect_ratio", "type": "string", "description": "Aspect ratio of the output video.", "default": "16:9" },
+ "duration": { "enum": [8], "title": "Duration", "name": "duration", "type": "int", "description": "The duration of the generated video in seconds", "default": 8 },
+ "resolution": { "enum": ["1080p"], "title": "Resolution", "name": "resolution", "type": "string", "description": "The resolution of the generated video.", "default": "1080p" }
+ }
+ },
+ {
+ "id": "runway-text-to-video",
+ "name": "Runway Gen-3",
+ "inputs": {
+ "prompt": { "type": "string", "title": "Prompt", "name": "prompt", "description": "The prompt to be used to generate a video" },
+ "aspect_ratio": { "enum": ["16:9", "9:16", "1:1", "4:3", "3:4"], "title": "Aspect Ratio", "name": "aspect_ratio", "type": "string", "description": "Aspect ratio of the output video.", "default": "16:9" },
+ "duration": { "enum": [5, 8], "title": "Duration", "name": "duration", "type": "int", "description": "The duration in seconds. If 8-second video is selected, 1080p resolution cannot be used.", "default": 5 },
+ "resolution": { "enum": ["720p", "1080p"], "title": "Resolution", "name": "resolution", "type": "string", "description": "The resolution of the generated video. If 1080p is selected, 8-second video cannot be generated.", "default": "720p" }
+ }
+ },
+ {
+ "id": "wan2.1-text-to-video",
+ "name": "Wan 2.1",
+ "inputs": {
+ "prompt": { "type": "string", "title": "Prompt", "name": "prompt", "description": "The prompt to generate the video" },
+ "aspect_ratio": { "enum": ["16:9", "9:16"], "title": "Aspect Ratio", "name": "aspect_ratio", "type": "string", "description": "Aspect ratio of the output video.", "default": "16:9" },
+ "duration": { "title": "Duration", "name": "duration", "type": "int", "description": "The duration of the generated video in seconds", "default": 5 },
+ "resolution": { "enum": ["480p", "720p"], "title": "Resolution", "name": "resolution", "type": "string", "description": "The resolution of the generated video.", "default": "480p" },
+ "quality": { "enum": ["medium", "high"], "title": "Quality", "name": "quality", "type": "string", "description": "The quality of the generated video.", "default": "medium" }
+ }
+ },
+ {
+ "id": "wan2.2-text-to-video",
+ "name": "Wan 2.2",
+ "inputs": {
+ "prompt": { "type": "string", "title": "Prompt", "name": "prompt", "description": "The prompt to generate the video" },
+ "aspect_ratio": { "enum": ["16:9", "9:16"], "title": "Aspect Ratio", "name": "aspect_ratio", "type": "string", "description": "Aspect ratio of the output video.", "default": "16:9" },
+ "duration": { "title": "Duration", "name": "duration", "type": "int", "description": "The duration of the generated video in seconds.", "default": 5 },
+ "resolution": { "enum": ["480p", "720p"], "title": "Resolution", "name": "resolution", "type": "string", "description": "The resolution of the generated video.", "default": "480p" },
+ "quality": { "enum": ["medium", "high"], "title": "Quality", "name": "quality", "type": "string", "description": "The quality of the generated video.", "default": "medium" }
+ }
+ },
+ {
+ "id": "wan2.2-5b-fast-t2v",
+ "name": "Wan 2.2 Fast",
+ "inputs": {
+ "prompt": { "type": "string", "title": "Prompt", "name": "prompt", "description": "Text prompt describing the video." },
+ "aspect_ratio": { "enum": ["16:9", "9:16", "1:1"], "title": "Aspect Ratio", "name": "aspect_ratio", "type": "string", "description": "Aspect ratio of the output video.", "default": "16:9" },
+ "resolution": { "enum": ["480p", "580p", "720p"], "title": "Resolution", "name": "resolution", "type": "string", "description": "The resolution of the generated video.", "default": "480p" }
+ }
+ },
+ {
+ "id": "wan2.5-text-to-video",
+ "name": "Wan 2.5",
+ "inputs": {
+ "prompt": { "type": "string", "title": "Prompt", "name": "prompt", "description": "The prompt to generate the video" },
+ "aspect_ratio": { "enum": ["16:9", "9:16"], "title": "Aspect Ratio", "name": "aspect_ratio", "type": "string", "description": "Aspect ratio of the output video.", "default": "16:9" },
+ "duration": { "title": "Duration", "name": "duration", "type": "int", "description": "The duration of the generated video in seconds", "default": 5 },
+ "resolution": { "enum": ["480p", "720p", "1080p"], "title": "Resolution", "name": "resolution", "type": "string", "description": "The resolution of the generated video.", "default": "480p" }
+ }
+ },
+ {
+ "id": "wan2.5-text-to-video-fast",
+ "name": "Wan 2.5 Fast",
+ "inputs": {
+ "prompt": { "type": "string", "title": "Prompt", "name": "prompt", "description": "The prompt to generate the video" },
+ "aspect_ratio": { "enum": ["16:9", "9:16"], "title": "Aspect Ratio", "name": "aspect_ratio", "type": "string", "description": "Aspect ratio of the output video.", "default": "16:9" },
+ "duration": { "title": "Duration", "name": "duration", "type": "int", "description": "The duration of the generated video in seconds", "default": 5 },
+ "resolution": { "enum": ["720p", "1080p"], "title": "Resolution", "name": "resolution", "type": "string", "description": "The resolution of the generated video.", "default": "720p" }
+ }
+ },
+ {
+ "id": "wan2.6-text-to-video",
+ "name": "Wan 2.6",
+ "inputs": {
+ "prompt": { "type": "string", "title": "Prompt", "name": "prompt", "description": "The prompt to generate the video" },
+ "aspect_ratio": { "enum": ["16:9", "9:16"], "title": "Aspect Ratio", "name": "aspect_ratio", "type": "string", "description": "Aspect ratio of the output video.", "default": "16:9" },
+ "duration": { "enum": [5, 10, 15], "title": "Duration", "name": "duration", "type": "int", "description": "The duration of the generated video in seconds", "default": 5 },
+ "resolution": { "enum": ["720p", "1080p"], "title": "Resolution", "name": "resolution", "type": "string", "description": "The resolution of the generated video.", "default": "720p" }
+ }
+ },
+ {
+ "id": "hunyuan-text-to-video",
+ "name": "Hunyuan",
+ "inputs": {
+ "prompt": { "type": "string", "title": "Prompt", "name": "prompt", "description": "Text prompt describing the video." },
+ "aspect_ratio": { "enum": ["16:9", "9:16", "1:1"], "title": "Aspect Ratio", "name": "aspect_ratio", "type": "string", "description": "Aspect ratio of the output video.", "default": "16:9" }
+ }
+ },
+ {
+ "id": "hunyuan-fast-text-to-video",
+ "name": "Hunyuan Fast",
+ "inputs": {
+ "prompt": { "type": "string", "title": "Prompt", "name": "prompt", "description": "Text prompt describing the video." },
+ "aspect_ratio": { "enum": ["16:9", "9:16", "1:1"], "title": "Aspect Ratio", "name": "aspect_ratio", "type": "string", "description": "Aspect ratio of the output video.", "default": "16:9" }
+ }
+ },
+ {
+ "id": "pixverse-v4.5-t2v",
+ "name": "Pixverse v4.5",
+ "inputs": {
+ "prompt": { "type": "string", "title": "Prompt", "name": "prompt", "description": "The prompt to generate the video" },
+ "aspect_ratio": { "enum": ["16:9", "9:16", "1:1", "4:3", "3:4"], "title": "Aspect Ratio", "name": "aspect_ratio", "type": "string", "description": "Aspect ratio of the output video.", "default": "16:9" },
+ "duration": { "title": "Duration", "name": "duration", "type": "int", "description": "The duration of the generated video in seconds. 8s not supported for 1080p resolution.", "default": 5 },
+ "resolution": { "enum": ["360p", "540p", "720p", "1080p"], "title": "Resolution", "name": "resolution", "type": "string", "description": "The resolution of the generated video.", "default": "720p" }
+ }
+ },
+ {
+ "id": "pixverse-v5-t2v",
+ "name": "Pixverse v5",
+ "inputs": {
+ "prompt": { "type": "string", "title": "Prompt", "name": "prompt", "description": "The prompt to generate the video" },
+ "aspect_ratio": { "enum": ["16:9", "9:16", "1:1", "4:3", "3:4"], "title": "Aspect Ratio", "name": "aspect_ratio", "type": "string", "description": "Aspect ratio of the output video.", "default": "16:9" },
+ "duration": { "title": "Duration", "name": "duration", "type": "int", "description": "The duration of the generated video in seconds", "default": 5 },
+ "resolution": { "enum": ["360p", "540p", "720p", "1080p"], "title": "Resolution", "name": "resolution", "type": "string", "description": "The resolution of the generated video.", "default": "720p" }
+ }
+ },
+ {
+ "id": "pixverse-v5.5-t2v",
+ "name": "Pixverse v5.5",
+ "inputs": {
+ "prompt": { "type": "string", "title": "Prompt", "name": "prompt", "description": "The prompt to generate the video" },
+ "aspect_ratio": { "enum": ["16:9", "9:16", "1:1", "4:3", "3:4"], "title": "Aspect Ratio", "name": "aspect_ratio", "type": "string", "description": "Aspect ratio of the output video.", "default": "16:9" },
+ "duration": { "enum": [5, 8, 10], "title": "Duration", "name": "duration", "type": "int", "description": "The duration of the generated video in seconds.", "default": 5 },
+ "resolution": { "enum": ["360p", "540p", "720p", "1080p"], "title": "Resolution", "name": "resolution", "type": "string", "description": "The resolution of the generated video.", "default": "360p" }
+ }
+ },
+ {
+ "id": "minimax-hailuo-02-standard-t2v",
+ "name": "Hailuo 02 Standard",
+ "inputs": {
+ "prompt": { "type": "string", "title": "Prompt", "name": "prompt", "description": "Text prompt describing the video." },
+ "duration": { "enum": [6, 10], "title": "Duration", "name": "duration", "type": "int", "description": "The duration of the generated video in seconds", "default": 6 },
+ "resolution": { "enum": ["768P"], "title": "Resolution", "name": "resolution", "type": "string", "description": "The resolution of the generated video.", "default": "768P" }
+ }
+ },
+ {
+ "id": "minimax-hailuo-02-pro-t2v",
+ "name": "Hailuo 02 Pro",
+ "inputs": {
+ "prompt": { "type": "string", "title": "Prompt", "name": "prompt", "description": "Text prompt describing the video." },
+ "duration": { "enum": [6], "title": "Duration", "name": "duration", "type": "int", "description": "The duration of the generated video in seconds", "default": 6 },
+ "resolution": { "enum": ["1080P"], "title": "Resolution", "name": "resolution", "type": "string", "description": "The resolution of the generated video.", "default": "1080P" }
+ }
+ },
+ {
+ "id": "minimax-hailuo-2.3-pro-t2v",
+ "name": "Hailuo 2.3 Pro",
+ "inputs": {
+ "prompt": { "type": "string", "title": "Prompt", "name": "prompt", "description": "Text prompt describing the video." },
+ "resolution": { "enum": ["1080p"], "title": "Resolution", "name": "resolution", "type": "string", "description": "The resolution of the generated video.", "default": "1080p" }
+ }
+ },
+ {
+ "id": "minimax-hailuo-2.3-standard-t2v",
+ "name": "Hailuo 2.3 Standard",
+ "inputs": {
+ "prompt": { "type": "string", "title": "Prompt", "name": "prompt", "description": "Text prompt describing the video." },
+ "duration": { "enum": [6, 10], "title": "Duration", "name": "duration", "type": "int", "description": "The duration of the generated video in seconds", "default": 6 }
+ }
+ },
+ {
+ "id": "openai-sora",
+ "name": "Sora",
+ "inputs": {
+ "prompt": { "type": "string", "title": "Prompt", "name": "prompt", "description": "Text prompt describing the video." },
+ "aspect_ratio": { "enum": ["16:9", "9:16", "1:1"], "title": "Aspect Ratio", "name": "aspect_ratio", "type": "string", "description": "Aspect ratio of the output video.", "default": "16:9" },
+ "resolution": { "enum": ["480p", "720p", "1080p"], "title": "Resolution", "name": "resolution", "type": "string", "description": "The resolution of the generated video.", "default": "480p" }
+ }
+ },
+ {
+ "id": "openai-sora-2-text-to-video",
+ "name": "Sora 2",
+ "inputs": {
+ "prompt": { "type": "string", "title": "Prompt", "name": "prompt", "description": "The prompt to generate the video" },
+ "aspect_ratio": { "enum": ["16:9", "9:16"], "title": "Aspect Ratio", "name": "aspect_ratio", "type": "string", "description": "Aspect ratio of the output video.", "default": "16:9" },
+ "duration": { "enum": [10, 15], "title": "Duration", "name": "duration", "type": "int", "description": "The duration of the generated video in seconds", "default": 10 }
+ }
+ },
+ {
+ "id": "openai-sora-2-pro-text-to-video",
+ "name": "Sora 2 Pro",
+ "inputs": {
+ "prompt": { "type": "string", "title": "Prompt", "name": "prompt", "description": "The prompt to generate the video" },
+ "aspect_ratio": { "enum": ["16:9", "9:16"], "title": "Aspect Ratio", "name": "aspect_ratio", "type": "string", "description": "Aspect ratio of the output video.", "default": "16:9" },
+ "duration": { "enum": [10, 15, 25], "title": "Duration", "name": "duration", "type": "int", "description": "The duration of the generated video in seconds. Currently 25 seconds supports 720p only.", "default": 10 },
+ "resolution": { "enum": ["720p", "1080p"], "title": "Resolution", "name": "resolution", "type": "string", "description": "The resolution of the generated video.", "default": "720p" }
+ }
+ },
+ {
+ "id": "vidu-v2.0-t2v",
+ "name": "Vidu v2.0",
+ "inputs": {
+ "prompt": { "type": "string", "title": "Prompt", "name": "prompt", "description": "The prompt to generate the video" },
+ "aspect_ratio": { "enum": ["9:16"], "title": "Aspect Ratio", "name": "aspect_ratio", "type": "string", "description": "Aspect ratio of the output video.", "default": "9:16" },
+ "duration": { "enum": [4], "title": "Duration", "name": "duration", "type": "int", "description": "The duration of the generated video in seconds.", "default": 4 },
+ "resolution": { "enum": ["1080p"], "title": "Resolution", "name": "resolution", "type": "string", "description": "The resolution of the generated video.", "default": "1080p" }
+ }
+ },
+ {
+ "id": "ovi-text-to-video",
+ "name": "OVI",
+ "inputs": {
+ "prompt": { "type": "string", "title": "Prompt", "name": "prompt", "description": "Text prompt describing the video." },
+ "aspect_ratio": { "enum": ["16:9", "9:16"], "title": "Aspect Ratio", "name": "aspect_ratio", "type": "string", "description": "Aspect ratio of the output video.", "default": "16:9" }
+ }
+ },
+ {
+ "id": "grok-imagine-text-to-video",
+ "name": "Grok Imagine",
+ "inputs": {
+ "prompt": { "type": "string", "title": "Prompt", "name": "prompt", "description": "Text prompt describing the video." },
+ "aspect_ratio": { "enum": ["9:16", "16:9", "2:3", "3:2", "1:1"], "title": "Aspect Ratio", "name": "aspect_ratio", "type": "string", "description": "Aspect ratio of the output video.", "default": "1:1" },
+ "duration": { "enum": [6, 10], "title": "Duration", "name": "duration", "type": "int", "description": "The duration of the generated video in seconds.", "default": 6 }
+ }
+ },
+ {
+ "id": "ltx-2-pro-text-to-video",
+ "name": "LTX 2 Pro",
+ "inputs": {
+ "prompt": { "type": "string", "title": "Prompt", "name": "prompt", "description": "Text prompt describing the video." },
+ "duration": { "enum": [6, 8, 10], "title": "Duration", "name": "duration", "type": "int", "description": "The duration of the generated video in seconds", "default": 6 }
+ }
+ },
+ {
+ "id": "ltx-2-fast-text-to-video",
+ "name": "LTX 2 Fast",
+ "inputs": {
+ "prompt": { "type": "string", "title": "Prompt", "name": "prompt", "description": "Text prompt describing the video." },
+ "duration": { "enum": [6, 8, 10, 12, 14, 16, 18, 20], "title": "Duration", "name": "duration", "type": "int", "description": "The duration of the generated video in seconds", "default": 6 }
+ }
+ },
+ {
+ "id": "ltx-2-19b-text-to-video",
+ "name": "LTX 2 19B",
+ "inputs": {
+ "prompt": { "type": "string", "title": "Prompt", "name": "prompt", "description": "Text prompt describing the video." },
+ "aspect_ratio": { "enum": ["16:9", "9:16"], "title": "Aspect Ratio", "name": "aspect_ratio", "type": "string", "description": "The aspect ratio of the generated video", "default": "16:9" },
+ "duration": { "title": "Duration", "name": "duration", "type": "int", "description": "The duration of the generated video in seconds", "default": 5 },
+ "resolution": { "enum": ["480p", "720p", "1080p"], "title": "Resolution", "name": "resolution", "type": "string", "description": "The resolution of the generated video.", "default": "720p" }
+ }
+ }
+];
+
+export const getVideoModelById = (id) => t2vModels.find(m => m.id === id);
+
+export const getAspectRatiosForVideoModel = (modelId) => {
+ const model = getVideoModelById(modelId);
+ if (!model) return ['16:9'];
+ const arInput = model.inputs?.aspect_ratio;
+ if (arInput && arInput.enum) return arInput.enum;
+ return ['16:9', '9:16', '1:1'];
+};
+
+export const getDurationsForModel = (modelId) => {
+ const model = getVideoModelById(modelId);
+ if (!model) return [5];
+ const durInput = model.inputs?.duration;
+ if (durInput && durInput.enum) return durInput.enum;
+ if (durInput) return [durInput.default || 5];
+ return [];
+};
+
+export const getResolutionsForVideoModel = (modelId) => {
+ const model = getVideoModelById(modelId);
+ if (!model) return [];
+ const resInput = model.inputs?.resolution;
+ if (resInput && resInput.enum) return resInput.enum;
+ return [];
+};
diff --git a/src/lib/muapi.js b/src/lib/muapi.js
index d66c28a..f709557 100644
--- a/src/lib/muapi.js
+++ b/src/lib/muapi.js
@@ -1,4 +1,4 @@
-import { getModelById } from './models.js';
+import { getModelById, getVideoModelById } from './models.js';
export class MuapiClient {
constructor() {
@@ -160,6 +160,58 @@ export class MuapiClient {
throw new Error('Generation timed out after polling.');
}
+ async generateVideo(params) {
+ const key = this.getKey();
+
+ const modelInfo = getVideoModelById(params.model);
+ const endpoint = modelInfo?.endpoint || params.model;
+ const url = `${this.baseUrl}/api/v1/${endpoint}`;
+
+ const finalPayload = { prompt: params.prompt };
+
+ if (params.aspect_ratio) finalPayload.aspect_ratio = params.aspect_ratio;
+ if (params.duration) finalPayload.duration = params.duration;
+ if (params.resolution) finalPayload.resolution = params.resolution;
+ if (params.quality) finalPayload.quality = params.quality;
+
+ console.log('[Muapi] Video Request:', url);
+ console.log('[Muapi] Video Payload:', finalPayload);
+
+ try {
+ const response = await fetch(url, {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json',
+ 'x-api-key': key
+ },
+ body: JSON.stringify(finalPayload)
+ });
+
+ if (!response.ok) {
+ const errText = await response.text();
+ console.error('[Muapi] API Error Body:', errText);
+ throw new Error(`API Request Failed: ${response.status} ${response.statusText} - ${errText.slice(0, 100)}`);
+ }
+
+ const submitData = await response.json();
+ console.log('[Muapi] Video Submit Response:', submitData);
+
+ const requestId = submitData.request_id || submitData.id;
+ if (!requestId) return submitData;
+
+ console.log('[Muapi] Polling for video results, request_id:', requestId);
+ const result = await this.pollForResult(requestId, key, 120, 2000);
+
+ const videoUrl = result.outputs?.[0] || result.url || result.output?.url;
+ console.log('[Muapi] Video URL:', videoUrl);
+ return { ...result, url: videoUrl };
+
+ } catch (error) {
+ console.error("Muapi Video Client Error:", error);
+ throw error;
+ }
+ }
+
getDimensionsFromAR(ar) {
// Base unit 1024 (Flux standard)
switch (ar) {
diff --git a/src/main.js b/src/main.js
index 6ff8dde..c1e287e 100644
--- a/src/main.js
+++ b/src/main.js
@@ -13,7 +13,9 @@ function navigate(page) {
if (page === 'image') {
contentArea.appendChild(ImageStudio());
} else if (page === 'video') {
- contentArea.innerHTML = 'Video Studio Coming Soon 🎬
';
+ import('./components/VideoStudio.js').then(({ VideoStudio }) => {
+ contentArea.appendChild(VideoStudio());
+ });
} else if (page === 'cinema') {
import('./components/CinemaStudio.js').then(({ CinemaStudio }) => {
contentArea.appendChild(CinemaStudio());