00Boobs00 commited on
Commit
aab6df4
Β·
verified Β·
1 Parent(s): 6bc490c

Upload folder using huggingface_hub

Browse files
Files changed (2) hide show
  1. app.py +331 -0
  2. requirements.txt +4 -0
app.py ADDED
@@ -0,0 +1,331 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ from typing import Optional, List, Dict, Any
3
+ import numpy as np
4
+ import time
5
+ from utils import WANVideoGenerator, LoRAManager, NSFWChecker
6
+ from config import MODEL_CONFIGS, AVAILABLE_LORAS, NSFW_CONFIG
7
+
8
+ # Initialize core components
9
+ generator = WANVideoGenerator()
10
+ lora_manager = LoRAManager()
11
+ nsfw_checker = NSFWChecker()
12
+
13
+ def generate_video(
14
+ image: np.ndarray,
15
+ prompt: str,
16
+ selected_model: str,
17
+ enabled_loras: List[str],
18
+ enable_nsfw: bool,
19
+ video_length: int,
20
+ resolution: str,
21
+ progress=gr.Progress()
22
+ ) -> tuple[str, str, Dict[str, Any]]:
23
+ """
24
+ Main video generation function with WAN-scale processing
25
+
26
+ Args:
27
+ image: Input image as numpy array
28
+ prompt: Optional text prompt for video generation
29
+ selected_model: Selected WAN model variant
30
+ enabled_loras: List of active LoRA adapters
31
+ enable_nsfw: Whether to allow NSFW content generation
32
+ video_length: Target video length in frames
33
+ resolution: Output resolution preset
34
+ progress: Gradio progress tracker
35
+
36
+ Returns:
37
+ Tuple of (video_path, status_message, generation_metadata)
38
+ """
39
+ try:
40
+ # Step 1: Validate inputs
41
+ progress(0.1, desc="πŸ” Validating inputs...")
42
+ if image is None:
43
+ raise gr.Error("No image provided. Please upload an image to generate video.")
44
+
45
+ # Step 2: NSFW check if enabled
46
+ if enable_nsfw and NSFW_CONFIG["require_confirmation"]:
47
+ progress(0.15, desc="⚠️ NSFW mode active - bypassing standard filters")
48
+ elif not enable_nsfw:
49
+ progress(0.15, desc="πŸ›‘οΈ Running safety checks...")
50
+ if nsfw_checker.check_image(image):
51
+ raise gr.Error("Input image flagged by safety filter. Enable NSFW mode to bypass.")
52
+
53
+ # Step 3: Load selected model and LoRAs
54
+ progress(0.2, desc=f"πŸ“¦ Loading {selected_model} model...")
55
+ generator.load_model(selected_model)
56
+
57
+ progress(0.3, desc=f"πŸ”Œ Activating {len(enabled_loras)} LoRA adapters...")
58
+ active_loras = lora_manager.load_loras(enabled_loras)
59
+
60
+ # Step 4: Generate video frames
61
+ progress(0.4, desc="🎬 Generating video frames...")
62
+ frames = []
63
+ for i in range(video_length):
64
+ progress(0.4 + (i / video_length) * 0.5,
65
+ desc=f"Rendering frame {i+1}/{video_length}...")
66
+ frame = generator.generate_frame(
67
+ image=image,
68
+ prompt=prompt,
69
+ frame_index=i,
70
+ total_frames=video_length,
71
+ active_loras=active_loras
72
+ )
73
+ frames.append(frame)
74
+ time.sleep(0.1) # Simulate processing time
75
+
76
+ # Step 5: Compile video
77
+ progress(0.95, desc="πŸŽ₯ Compiling final video...")
78
+ output_path = generator.compile_video(
79
+ frames=frames,
80
+ resolution=resolution,
81
+ fps=30
82
+ )
83
+
84
+ # Step 6: Prepare metadata
85
+ metadata = {
86
+ "model": selected_model,
87
+ "loras": enabled_loras,
88
+ "nsfw_mode": enable_nsfw,
89
+ "resolution": resolution,
90
+ "frames": video_length,
91
+ "prompt": prompt or "No prompt provided",
92
+ "status": "βœ… Generation complete"
93
+ }
94
+
95
+ progress(1.0, desc="βœ… Done!")
96
+ return output_path, "Video generated successfully!", metadata
97
+
98
+ except Exception as e:
99
+ raise gr.Error(f"Generation failed: {str(e)}")
100
+
101
+ def update_lora_visibility(enable_nsfw: bool) -> Dict[str, Any]:
102
+ """Update LoRA options based on NSFW mode"""
103
+ if enable_nsfw:
104
+ return gr.Dropdown(
105
+ choices=list(AVAILABLE_LORAS.keys()),
106
+ value=[],
107
+ multiselect=True,
108
+ label="🎨 Active LoRA Adapters (NSFW options unlocked)"
109
+ )
110
+ else:
111
+ safe_loras = {k: v for k, v in AVAILABLE_LORAS.items() if not v.get("nsfw", False)}
112
+ return gr.Dropdown(
113
+ choices=list(safe_loras.keys()),
114
+ value=[],
115
+ multiselect=True,
116
+ label="🎨 Active LoRA Adapters (Safe mode)"
117
+ )
118
+
119
+ def create_interface():
120
+ """Create the main Gradio interface"""
121
+
122
+ with gr.Blocks() as demo:
123
+ gr.HTML("""
124
+ <div style='text-align: center; padding: 20px;'>
125
+ <h1>πŸ₯Š WAN-Scale Image-to-Video Architecture πŸ₯Š</h1>
126
+ <p>Built with anycoder - <a href='https://huggingface.co/spaces/akhaliq/anycoder' target='_blank'>View on Hugging Face</a></p>
127
+ <p style='font-size: 1.2em; color: #666;'>Turn static images into dynamic videos with WAN foundation models</p>
128
+ </div>
129
+ """)
130
+
131
+ # Global state
132
+ generation_state = gr.State({"session_id": None})
133
+
134
+ with gr.Row():
135
+ # Sidebar for controls
136
+ with gr.Sidebar(position="left", width=320):
137
+ gr.Markdown("### βš™οΈ Generation Settings")
138
+
139
+ model_selector = gr.Dropdown(
140
+ choices=list(MODEL_CONFIGS.keys()),
141
+ value="wan-2.1-14b",
142
+ label="πŸ€– WAN Model",
143
+ info="Select foundation model variant"
144
+ )
145
+
146
+ nsfw_toggle = gr.Checkbox(
147
+ value=False,
148
+ label="πŸ”ž Enable NSFW Content",
149
+ info="Bypass safety filters (requires confirmation)"
150
+ )
151
+
152
+ lora_selector = gr.Dropdown(
153
+ choices=[k for k, v in AVAILABLE_LORAS.items() if not v.get("nsfw", False)],
154
+ value=[],
155
+ multiselect=True,
156
+ label="🎨 Active LoRA Adapters",
157
+ info="Select style and domain adapters"
158
+ )
159
+
160
+ with gr.Accordion("πŸ“ Video Settings", open=False):
161
+ video_length = gr.Slider(
162
+ minimum=16,
163
+ maximum=128,
164
+ value=32,
165
+ step=8,
166
+ label="Video Length (frames)"
167
+ )
168
+
169
+ resolution = gr.Radio(
170
+ choices=["512x512", "768x768", "1024x576", "1920x1080"],
171
+ value="768x768",
172
+ label="Resolution"
173
+ )
174
+
175
+ with gr.Accordion("πŸš€ Advanced Options", open=False):
176
+ inference_steps = gr.Slider(
177
+ minimum=10,
178
+ maximum=100,
179
+ value=50,
180
+ label="Inference Steps"
181
+ )
182
+
183
+ cfg_scale = gr.Slider(
184
+ minimum=1.0,
185
+ maximum=20.0,
186
+ value=7.5,
187
+ step=0.5,
188
+ label="CFG Scale"
189
+ )
190
+
191
+ # Status indicators
192
+ model_status = gr.Label(
193
+ value={"Status": "Ready", "VRAM": "24GB Available"},
194
+ label="System Status"
195
+ )
196
+
197
+ # Main content area
198
+ with gr.Column():
199
+ gr.Markdown("### πŸ“€ Input Image")
200
+ input_image = gr.Image(
201
+ label="Upload Starting Frame",
202
+ type="numpy",
203
+ height=400,
204
+ sources=["upload", "webcam", "clipboard"]
205
+ )
206
+
207
+ gr.Markdown("### πŸ“ Optional Text Prompt")
208
+ prompt_box = gr.Textbox(
209
+ placeholder="Describe the motion, style, or scene...",
210
+ label="Prompt (optional)",
211
+ lines=2,
212
+ max_lines=4
213
+ )
214
+
215
+ with gr.Row():
216
+ generate_btn = gr.Button(
217
+ "🎬 Generate Video",
218
+ variant="primary",
219
+ scale=2
220
+ )
221
+ clear_btn = gr.ClearButton(
222
+ components=[input_image, prompt_box],
223
+ value="πŸ—‘οΈ Clear"
224
+ )
225
+
226
+ # Progress tracking
227
+ progress_bar = gr.Progress()
228
+ status_text = gr.Textbox(
229
+ label="Status",
230
+ interactive=False,
231
+ show_copy_button=True
232
+ )
233
+
234
+ gr.Markdown("### πŸ“Ό Output Video")
235
+ output_video = gr.Video(
236
+ label="Generated Video",
237
+ height=400,
238
+ autoplay=True,
239
+ show_download_button=True
240
+ )
241
+
242
+ # Generation metadata
243
+ with gr.Accordion("πŸ“Š Generation Details", open=False):
244
+ metadata_json = gr.JSON(
245
+ label="Metadata",
246
+ open=False
247
+ )
248
+
249
+ # Event handlers
250
+ nsfw_toggle.change(
251
+ fn=update_lora_visibility,
252
+ inputs=nsfw_toggle,
253
+ outputs=lora_selector,
254
+ api_visibility="private"
255
+ )
256
+
257
+ generate_btn.click(
258
+ fn=generate_video,
259
+ inputs=[
260
+ input_image,
261
+ prompt_box,
262
+ model_selector,
263
+ lora_selector,
264
+ nsfw_toggle,
265
+ video_length,
266
+ resolution
267
+ ],
268
+ outputs=[
269
+ output_video,
270
+ status_text,
271
+ metadata_json
272
+ ],
273
+ api_visibility="public",
274
+ concurrency_limit=2 # Limit concurrent generations
275
+ )
276
+
277
+ # Update model status on selection
278
+ model_selector.change(
279
+ fn=lambda x: {"Status": f"Loaded {x}", "VRAM": "24GB Used"},
280
+ inputs=model_selector,
281
+ outputs=model_status,
282
+ api_visibility="private"
283
+ )
284
+
285
+ # Demo load event
286
+ demo.load(
287
+ fn=lambda: "System initialized and ready",
288
+ outputs=status_text,
289
+ api_visibility="private"
290
+ )
291
+
292
+ return demo
293
+
294
+ # Create and launch the application
295
+ if __name__ == "__main__":
296
+ demo = create_interface()
297
+
298
+ demo.launch(
299
+ server_name="0.0.0.0",
300
+ server_port=7860,
301
+ share=False,
302
+ debug=False,
303
+ show_error=True,
304
+ max_threads=4,
305
+ theme=gr.themes.Soft(
306
+ primary_hue="purple",
307
+ secondary_hue="indigo",
308
+ neutral_hue="slate",
309
+ font=gr.themes.GoogleFont("Inter"),
310
+ text_size="lg",
311
+ spacing_size="lg",
312
+ radius_size="md"
313
+ ).set(
314
+ button_primary_background_fill="*primary_600",
315
+ button_primary_background_fill_hover="*primary_700",
316
+ block_title_text_weight="600",
317
+ block_background_fill="*neutral_50"
318
+ ),
319
+ footer_links=[
320
+ {"label": "Built with anycoder", "url": "https://huggingface.co/spaces/akhaliq/anycoder"},
321
+ {"label": "Model Docs", "url": "https://huggingface.co/docs"},
322
+ {"label": "API Reference", "url": "/docs"}
323
+ ],
324
+ css="""
325
+ .gradio-container { max-width: 1400px; margin: auto; }
326
+ .contain { display: flex; flex-direction: column; height: 100vh; }
327
+ #component-0 { height: 100%; }
328
+ .gr-button { font-weight: 600; }
329
+ .gr-markdown { text-align: center; }
330
+ """
331
+ )
requirements.txt ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ config
2
+ gradio
3
+ numpy
4
+ utils