import React, { useState, useEffect, FormEvent, ChangeEvent } from 'react'; interface InputData { prompt: string; negativePrompt: string; // New field base_model: string; steps: number; guidance_scale: number; frames: number; width: number; height: number; seed: number; zoom_in_motion_strength: number; zoom_out_motion_strength: number; pan_left_motion_strength: number; pan_right_motion_strength: number; pan_up_motion_strength: number; pan_down_motion_strength: number; rolling_clockwise_motion_strength: number; rolling_anticlockwise_motion_strength: number; output_format: string; } interface OutputData { prediction: any; timestamp: string; prompt: string; } const TruncatedText = ({ text }: { text: string }) => { const [isTruncated, setIsTruncated] = useState(true); const toggleTruncated = () => { setIsTruncated(!isTruncated); }; if (text.length < 34) { return {text}; } return ( {isTruncated ? `${text.substring(0, 24)}...` : text} ); }; const IndexPage = () => { const [inputData, setInputData] = useState({ prompt: '', negativePrompt: '', base_model: 'realisticVisionV20_v20', steps: 25, guidance_scale: 7.5, frames: 16, width: 768, height: 512, seed: -1, zoom_in_motion_strength: 0, zoom_out_motion_strength: 0, pan_left_motion_strength: 0, pan_right_motion_strength: 0.75, pan_up_motion_strength: 0, pan_down_motion_strength: 0, rolling_clockwise_motion_strength: 0, rolling_anticlockwise_motion_strength: 0, output_format: 'mp4' }); const [output, setOutput] = useState([]); const [isLoading, setIsLoading] = useState(false); useEffect(() => { const savedOutput = localStorage.getItem('output'); if (savedOutput) { setOutput(JSON.parse(savedOutput)); } }, []); useEffect(() => { output.forEach(video => { console.log('Video URL:', video.prediction.output); }); }, [output]); const handleChange = (e: ChangeEvent) => { const { name, value } = e.target; setInputData((prevData) => ({ ...prevData, [name]: value })); }; const handleSubmit = async (e: FormEvent) => { e.preventDefault(); setIsLoading(true); // Automatically convert string numbers to actual numbers const payload = Object.fromEntries( Object.entries(inputData).map(([key, value]) => { return [key, isNaN(Number(value)) ? value : Number(value)]; }) ); try { const response = await fetch('/api/animatediff', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify(payload), // use payload here instead of inputData }); const result = await response.json(); if (response.ok) { const timestamp = new Date().toISOString(); const newOutput = { prediction: result.prediction, timestamp, prompt: inputData.prompt, }; const updatedOutput = [...output, newOutput]; setOutput(updatedOutput); localStorage.setItem('output', JSON.stringify(updatedOutput)); setInputData({ prompt: '', negativePrompt: '', base_model: 'realisticVisionV20_v20', steps: 25, guidance_scale: 7.5, frames: 16, width: 768, height: 512, seed: -1, zoom_in_motion_strength: 0, zoom_out_motion_strength: 0, pan_left_motion_strength: 0, pan_right_motion_strength: 0.75, pan_up_motion_strength: 0, pan_down_motion_strength: 0, rolling_clockwise_motion_strength: 0, rolling_anticlockwise_motion_strength: 0, output_format: 'mp4' }); } } catch (error) { console.error("An error occurred:", error); } finally { setIsLoading(false); } }; return (

AnimateDiff Generation

{/* Video Settings */}

Video Settings

{/* Added flex container */}
{/* Dimensions */}
{/* Numeric Inputs */} {['steps', 'guidance_scale', 'frames', 'width', 'height', 'seed'].map((key) => (
))}
{/* Motion Settings */}

Motion Settings

{/* Output Settings */}

Output Settings

{/* Submit Button */}
{output.map((video, index) => (

Generated Video {index + 1}:

{/* Download Button */}

Date: {new Date(video.timestamp).toLocaleDateString()} Time: {new Date(video.timestamp).toLocaleTimeString()}

))}
); }; export default IndexPage;