AlekseyCalvin commited on
Commit
3548722
·
verified ·
1 Parent(s): 434512f

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +120 -0
app.py ADDED
@@ -0,0 +1,120 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import torch
3
+ from diffusers import StableDiffusionPipeline
4
+ import os
5
+ import uuid
6
+ import animation_logic as anim
7
+ import video_utils as vid
8
+
9
+ # --- Model Config (SDXS Optimized) ---
10
+ device = "cpu"
11
+ model_id = "IDKiro/sdxs-512-dreamshaper"
12
+ # Using float32 for CPU stability
13
+ pipe = StableDiffusionPipeline.from_pretrained(model_id, torch_dtype=torch.float32)
14
+ pipe.to(device)
15
+
16
+ def run_deforum(
17
+ prompt_list_str, neg_prompt, max_frames,
18
+ zoom_str, angle_str, tx_str, ty_str,
19
+ cadence, fps, color_match
20
+ ):
21
+ width, height = 256, 256
22
+ try:
23
+ # Expected format: {0: "prompt", 10: "prompt"}
24
+ prompts = eval(prompt_list_str)
25
+ except Exception as e:
26
+ return None, None, f"Error parsing prompts: {str(e)}"
27
+
28
+ # Parse Schedules
29
+ zoom_s = anim.parse_keyframe_string(zoom_str, int(max_frames))
30
+ angle_s = anim.parse_keyframe_string(angle_str, int(max_frames))
31
+ tx_s = anim.parse_keyframe_string(tx_str, int(max_frames))
32
+ ty_s = anim.parse_keyframe_string(ty_str, int(max_frames))
33
+
34
+ all_frames = []
35
+ prev_gen_frame = None
36
+ first_frame = None
37
+
38
+ for f in range(int(max_frames)):
39
+ if f % cadence == 0:
40
+ current_prompt = prompts[max(k for k in prompts.keys() if k <= f)]
41
+
42
+ if prev_gen_frame is not None:
43
+ # Warp
44
+ init_image = anim.anim_frame_warp(prev_gen_frame, angle_s[f], zoom_s[f], tx_s[f], ty_s[f])
45
+ # SDXS 1-step Inference
46
+ new_frame = pipe(
47
+ current_prompt,
48
+ image=init_image,
49
+ negative_prompt=neg_prompt,
50
+ num_inference_steps=1,
51
+ guidance_scale=0.0,
52
+ width=width, height=height
53
+ ).images[0]
54
+
55
+ if color_match and first_frame is not None:
56
+ new_frame = anim.maintain_colors(first_frame, new_frame)
57
+ else:
58
+ # First frame base generation
59
+ new_frame = pipe(
60
+ current_prompt,
61
+ negative_prompt=neg_prompt,
62
+ num_inference_steps=1,
63
+ guidance_scale=0.0,
64
+ width=width, height=height
65
+ ).images[0]
66
+ first_frame = new_frame
67
+
68
+ # Cadence Interpolation
69
+ if cadence > 1 and prev_gen_frame is not None:
70
+ for i in range(1, cadence):
71
+ alpha = i / cadence
72
+ interp_frame = anim.lerp_frames(prev_gen_frame, new_frame, alpha)
73
+ all_frames.append(interp_frame)
74
+
75
+ all_frames.append(new_frame)
76
+ prev_gen_frame = new_frame
77
+ yield new_frame, None, None
78
+
79
+ # Post-Processing
80
+ unique_id = uuid.uuid4().hex[:6]
81
+ video_file = vid.frames_to_video(all_frames, f"deforum_{unique_id}.mp4", fps)
82
+ zip_file = vid.export_to_zip(all_frames, f"frames_{unique_id}.zip")
83
+
84
+ yield all_frames[-1], video_file, zip_file
85
+
86
+ # --- UI Setup ---
87
+ with gr.Blocks() as demo:
88
+ gr.Markdown("# 🚀 Deforum SDXS CPU\nModular & Optimized for Free Tiers.")
89
+
90
+ with gr.Row():
91
+ with gr.Column():
92
+ p_input = gr.Textbox(label="Prompt Map", value='{0: "hyperrealistic forest", 10: "burning forest"}')
93
+ n_input = gr.Textbox(label="Negative Prompt", value="blurry, text, watermark")
94
+
95
+ with gr.Row():
96
+ f_count = gr.Slider(5, 100, value=20, step=1, label="Frames")
97
+ c_val = gr.Slider(1, 5, value=1, step=1, label="Cadence")
98
+ fps_val = gr.Number(label="FPS", value=10)
99
+ color_check = gr.Checkbox(label="Color Match", value=True)
100
+
101
+ with gr.Accordion("2D Motion (Keyframes)", open=False):
102
+ z_in = gr.Textbox(label="Zoom", value="0:(1.03)")
103
+ a_in = gr.Textbox(label="Angle", value="0:(0)")
104
+ tx_in = gr.Textbox(label="TX", value="0:(0)")
105
+ ty_in = gr.Textbox(label="TY", value="0:(0)")
106
+
107
+ run_btn = gr.Button("Generate", variant="primary")
108
+
109
+ with gr.Column():
110
+ preview = gr.Image(label="Live Stream")
111
+ video_out = gr.Video(label="Final Render")
112
+ file_out = gr.File(label="Batch PNGs")
113
+
114
+ run_btn.click(
115
+ fn=run_deforum,
116
+ inputs=[p_input, n_input, f_count, z_in, a_in, tx_in, ty_in, c_val, fps_val, color_check],
117
+ outputs=[preview, video_out, file_out]
118
+ )
119
+
120
+ demo.launch()