File size: 3,608 Bytes
c3502b3
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
a222ca5
c3502b3
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
973b510
c3502b3
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
import gradio as gr
import json
from deforum_engine import DeforumRunner

# Initialize Engine
runner = DeforumRunner(device="cpu")

def process(
    prompts_json, neg_prompt, max_frames, 
    width, height,
    zoom, angle, tx, ty,
    strength, noise,
    fps, steps
):
    # Validate JSON
    try:
        # Convert single quotes to double if user messed up
        prompts_json = prompts_json.replace("'", '"')
        # Ensure keys are integers
        prompts_dict = json.loads(prompts_json)
        prompts_fixed = {int(k): v for k, v in prompts_dict.items()}
    except:
        # Fallback manual parse
        try:
            prompts_fixed = eval(prompts_json)
        except:
            return None, None, None, "Error parsing prompts JSON"

    yield from runner.render(
        prompts_fixed, neg_prompt, int(max_frames),
        int(width), int(height),
        zoom, angle, tx, ty,
        strength, noise,
        int(fps), int(steps)
    )

css = """
#col-container {max_width: 900px; margin-left: auto; margin-right: auto;}
"""

with gr.Blocks() as demo:
    gr.Markdown("# 🌀 Authentic Deforum (CPU/SDXS)")
    gr.Markdown("""
    **Core Config:**
    * **Model:** SDXS-512-0.9 (Fast 1-step capable).
    * **Authenticity:** Full 2D Warping, Noise Schedules, and Img2Img Loopback.
    * **Tip:** Keep `Steps` around 3-4. If you use 1 step, 'Strength' (fade) will not work and frames will look disjointed.
    """)
    
    with gr.Row():
        with gr.Column():
            # Prompts
            prompts_input = gr.Code(
                label="Prompts (JSON format)", 
                value='{\n "0": "tiny cute swamp bunny, highly detailed, intricate, 8k",\n "30": "anthro swamp bunny, cyberpunk city background, neon lights"\n}',
                language="json"
            )
            neg_prompt = gr.Textbox(label="Negative Prompt", value="watermark, text, blurry")
            
            with gr.Row():
                max_frames = gr.Number(label="Max Frames", value=120, precision=0)
                fps = gr.Number(label="FPS", value=12, precision=0)
                steps = gr.Slider(1, 10, value=3, step=1, label="Steps (Rec: 3+)")
            
            with gr.Accordion("Motion Settings", open=True):
                gr.Markdown("Supports Math: `sin(t/10)`, `t*0.5`, etc. `t` = frame index.")
                angle = gr.Textbox(label="Angle (deg)", value="0:(0)")
                zoom = gr.Textbox(label="Zoom (1.0 = static)", value="0:(1.0 + 0.01*sin(t/20))")
                tx = gr.Textbox(label="Translation X", value="0:(2*sin(t/10))")
                ty = gr.Textbox(label="Translation Y", value="0:(0)")

            with gr.Accordion("Coherence (The 'Glue')", open=True):
                strength = gr.Textbox(label="Strength Schedule (0.0-1.0)", value="0:(0.65)")
                noise = gr.Textbox(label="Noise Schedule (0.0-1.0)", value="0:(0.04)")
                
            run_btn = gr.Button("Generate Animation", variant="primary")

        with gr.Column():
            out_image = gr.Image(label="Last Frame", type="pil")
            out_video = gr.Video(label="Video Output")
            out_zip = gr.File(label="Download Frames")
    
    run_btn.click(
        fn=process,
        inputs=[
            prompts_input, neg_prompt, max_frames,
            gr.State(256), gr.State(256), # Fixed resolution for CPU speed
            zoom, angle, tx, ty,
            strength, noise,
            fps, steps
        ],
        outputs=[out_image, out_video, out_zip]
    )

if __name__ == "__main__":
    demo.launch(css=css, theme=gr.themes.Glass())