Spaces:
Runtime error
Runtime error
| import gradio as gr | |
| import torch | |
| from diffusers import StableDiffusionPipeline | |
| import os | |
| import uuid | |
| import animation_logic as anim | |
| import video_utils as vid | |
| # --- Model Config (SDXS Optimized) --- | |
| device = "cpu" | |
| model_id = "IDKiro/sdxs-512-dreamshaper" | |
| pipe = StableDiffusionPipeline.from_pretrained(model_id, torch_dtype=torch.float32) | |
| pipe.to(device) | |
| def run_deforum( | |
| prompt_list_str, neg_prompt, max_frames, | |
| zoom_str, angle_str, tx_str, ty_str, | |
| cadence, fps | |
| ): | |
| # Setup | |
| width, height = 256, 256 | |
| try: | |
| prompts = eval(prompt_list_str) | |
| except: | |
| return None, None, "Error: Prompt dictionary format invalid." | |
| # Parse Schedules | |
| zoom_s = anim.parse_keyframe_string(zoom_str, max_frames) | |
| angle_s = anim.parse_keyframe_string(angle_str, max_frames) | |
| tx_s = anim.parse_keyframe_string(tx_str, max_frames) | |
| ty_s = anim.parse_keyframe_string(ty_str, max_frames) | |
| all_frames = [] | |
| prev_gen_frame = None | |
| # Generation Loop | |
| for f in range(max_frames): | |
| if f % cadence == 0: | |
| # Determine prompt | |
| current_prompt = prompts[max(k for k in prompts.keys() if k <= f)] | |
| # Warp previous frame if it exists | |
| if prev_gen_frame is not None: | |
| # We warp the frame based on the cumulative motion across the cadence gap | |
| init_image = anim.anim_frame_warp(prev_gen_frame, angle_s[f], zoom_s[f], tx_s[f], ty_s[f]) | |
| # SDXS Inference (1-step, 0 guidance) | |
| new_frame = pipe( | |
| current_prompt, | |
| image=init_image, # This mimics the 'strength' logic | |
| negative_prompt=neg_prompt, | |
| num_inference_steps=1, | |
| guidance_scale=0.0, | |
| width=width, height=height | |
| ).images[0] | |
| else: | |
| # First frame | |
| new_frame = pipe( | |
| current_prompt, | |
| negative_prompt=neg_prompt, | |
| num_inference_steps=1, | |
| guidance_scale=0.0, | |
| width=width, height=height | |
| ).images[0] | |
| # Handle Cadence Interpolation for the gap behind us | |
| if cadence > 1 and prev_gen_frame is not None: | |
| start_gap = f - cadence | |
| for i in range(1, cadence): | |
| alpha = i / cadence | |
| interp_frame = anim.lerp_frames(prev_gen_frame, new_frame, alpha) | |
| all_frames.append(interp_frame) | |
| all_frames.append(new_frame) | |
| prev_gen_frame = new_frame | |
| yield new_frame, None, None | |
| # Finalize Video and Zip | |
| video_file = vid.frames_to_video(all_frames, f"output_{uuid.uuid4().hex[:6]}.mp4", fps) | |
| zip_file = vid.export_to_zip(all_frames, f"frames_{uuid.uuid4().hex[:6]}.zip") | |
| yield all_frames[-1], video_file, zip_file | |
| # --- Gradio Interface --- | |
| with gr.Blocks(theme=gr.themes.Glass()) as demo: | |
| gr.Markdown("# 🎨 Deforum Soonr Variant 2") | |
| with gr.Row(): | |
| with gr.Column(scale=1): | |
| prompts = gr.Textbox(label="Prompts (Frame: Prompt Dict)", | |
| value='{0: "a snowy mountain", 15: "a fiery volcano"}', lines=3) | |
| neg_p = gr.Textbox(label="Negative Prompt", value="blur, lowres, text") | |
| with gr.Row(): | |
| frames_n = gr.Number(label="Max Frames", value=20) | |
| cadence_n = gr.Slider(1, 4, value=2, step=1, label="Cadence (Skip Steps)") | |
| fps_n = gr.Number(label="FPS", value=10) | |
| with gr.Accordion("Motion Parameters", open=False): | |
| zoom = gr.Textbox(label="Zoom", value="0:(1.04)") | |
| angle = gr.Textbox(label="Angle", value="0:(2*sin(t/5))") | |
| tx = gr.Textbox(label="Translation X", value="0:(0)") | |
| ty = gr.Textbox(label="Translation Y", value="0:(0)") | |
| btn = gr.Button("Generate", variant="primary") | |
| with gr.Column(scale=1): | |
| preview = gr.Image(label="Live Frame Preview") | |
| video_out = gr.Video(label="Rendered Animation") | |
| file_out = gr.File(label="Download Batch (ZIP)") | |
| btn.click( | |
| fn=run_deforum, | |
| inputs=[prompts, neg_p, frames_n, zoom, angle, tx, ty, cadence_n, fps_n], | |
| outputs=[preview, video_out, file_out] | |
| ) | |
| demo.launch() |