Baseta's picture
Update app.py from anycoder
0eb4c39 verified
import gradio as gr
import time
import random
import numpy as np
from PIL import Image
import io
import base64
from typing import Tuple, Optional
def generate_video_from_text(
prompt: str,
duration: int = 5,
style: str = "realistic",
quality: str = "high",
motion_strength: float = 0.5,
seed: Optional[int] = None
) -> str:
"""
Generate a video from text prompt using simulated WAN model.
Args:
prompt: Text description of the video to generate
duration: Video duration in seconds
style: Video style (realistic, artistic, anime, cartoon)
quality: Video quality (low, medium, high)
motion_strength: Strength of motion in video (0.0 to 1.0)
seed: Random seed for reproducible generation
Returns:
Path to generated video file
"""
if not prompt.strip():
raise gr.Error("Please enter a text prompt to generate a video.")
# Simulate video generation process
progress_steps = [
"Analyzing prompt...",
"Generating keyframes...",
"Applying style transfer...",
"Creating motion vectors...",
"Rendering video...",
"Post-processing...",
"Finalizing video..."
]
for i, step in enumerate(progress_steps):
time.sleep(0.5) # Simulate processing time
if i == len(progress_steps) - 1:
yield f"βœ… {step}"
else:
yield f"⏳ {step}"
# Generate a placeholder video (in real implementation, this would call WAN API)
# For demo purposes, we'll create a simple animated frame sequence
frames = []
num_frames = duration * 10 # 10 fps
if seed is None:
seed = random.randint(0, 999999)
np.random.seed(seed)
# Create simple animated frames based on prompt
for i in range(num_frames):
# Generate a frame with some motion
width, height = 512, 512
frame = np.zeros((height, width, 3), dtype=np.uint8)
# Create gradient background
for y in range(height):
for x in range(width):
frame[y, x, 0] = int(255 * (x / width) * (1 + 0.3 * np.sin(i * 0.1)))
frame[y, x, 1] = int(255 * (y / height) * (1 + 0.3 * np.cos(i * 0.1)))
frame[y, x, 2] = int(128 + 127 * np.sin((x + y + i * 10) * 0.01))
# Add some moving elements based on prompt
center_x = width // 2 + int(100 * np.sin(i * 0.05) * motion_strength)
center_y = height // 2 + int(100 * np.cos(i * 0.05) * motion_strength)
cv2 = __import__('cv2')
cv2.circle(frame, (center_x, center_y), 50, (255, 255, 255), -1)
frames.append(Image.fromarray(frame))
# Save frames as a video (placeholder - in real implementation, return actual video)
# For demo, we'll return a sample video URL
sample_videos = {
"realistic": "https://sample-videos.com/zip/10/mp4/SampleVideo_1280x720_1mb.mp4",
"artistic": "https://sample-videos.com/zip/10/mp4/SampleVideo_1280x720_2mb.mp4",
"anime": "https://sample-videos.com/zip/10/mp4/SampleVideo_1280x720_5mb.mp4",
"cartoon": "https://sample-videos.com/zip/10/mp4/SampleVideo_1280x720_1mb.mp4"
}
return sample_videos.get(style, sample_videos["realistic"])
def generate_video_from_image(
image: np.ndarray,
prompt: str,
duration: int = 5,
motion_strength: float = 0.5,
seed: Optional[int] = None
) -> str:
"""
Generate a video from an image with text prompt for motion.
Args:
image: Input image as numpy array
prompt: Text description of desired motion/animation
duration: Video duration in seconds
motion_strength: Strength of motion in video (0.0 to 1.0)
seed: Random seed for reproducible generation
Returns:
Path to generated video file
"""
if image is None:
raise gr.Error("Please upload an image to generate a video.")
if not prompt.strip():
raise gr.Error("Please describe the motion you want to add to the image.")
# Simulate processing
progress_steps = [
"Analyzing image...",
"Extracting features...",
"Generating motion from prompt...",
"Creating video frames...",
"Applying motion blur...",
"Rendering final video..."
]
for step in progress_steps:
time.sleep(0.6)
# Return sample video for demo
return "https://sample-videos.com/zip/10/mp4/SampleVideo_1280x720_2mb.mp4"
def create_custom_css() -> str:
"""Create custom CSS for the application."""
return """
.gradio-container {
max-width: 1200px !important;
margin: auto !important;
}
.main-header {
text-align: center;
margin-bottom: 2rem;
padding: 1.5rem;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
border-radius: 15px;
color: white;
}
.generation-card {
border: 2px solid #e5e7eb;
border-radius: 15px;
padding: 1.5rem;
margin: 1rem 0;
background: white;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
}
.progress-container {
margin: 1rem 0;
padding: 1rem;
background: #f3f4f6;
border-radius: 10px;
font-family: monospace;
}
.example-prompt {
cursor: pointer;
padding: 0.5rem;
margin: 0.25rem;
background: #f9fafb;
border: 1px solid #e5e7eb;
border-radius: 8px;
transition: all 0.2s;
}
.example-prompt:hover {
background: #ede9fe;
border-color: #8b5cf6;
}
"""
# Create the custom theme
custom_theme = gr.themes.Soft(
primary_hue="purple",
secondary_hue="indigo",
neutral_hue="slate",
font=gr.themes.GoogleFont("Inter"),
text_size="lg",
spacing_size="lg",
radius_size="md"
).set(
button_primary_background_fill="*primary_600",
button_primary_background_fill_hover="*primary_700",
block_title_text_weight="600",
block_border_width="2px",
block_border_color="*neutral_200",
)
# Gradio 6: NO parameters in gr.Blocks() constructor!
with gr.Blocks() as demo:
# Header
gr.HTML("""
<div class="main-header">
<h1>🎬 WAN Video Generator</h1>
<p>Transform your ideas into stunning videos with advanced AI technology</p>
<p style="font-size: 0.9rem; margin-top: 0.5rem;">
Built with <a href="https://huggingface.co/spaces/akhaliq/anycoder" target="_blank" style="color: white; text-decoration: underline;">anycoder</a>
</p>
</div>
""")
with gr.Tabs() as tabs:
# Text to Video Tab
with gr.TabItem("πŸ“ Text to Video", elem_id="text-to-video"):
with gr.Row():
with gr.Column(scale=2):
gr.Markdown("### 🎯 Generate Video from Text")
prompt_input = gr.Textbox(
label="Video Description",
placeholder="Describe the video you want to generate... (e.g., 'A serene beach with waves gently lapping at sunset')",
lines=3,
max_lines=5
)
with gr.Row():
duration_slider = gr.Slider(
minimum=2,
maximum=30,
value=5,
step=1,
label="Duration (seconds)"
)
motion_slider = gr.Slider(
minimum=0.0,
maximum=1.0,
value=0.5,
step=0.1,
label="Motion Strength"
)
with gr.Row():
style_dropdown = gr.Dropdown(
choices=["realistic", "artistic", "anime", "cartoon"],
value="realistic",
label="Video Style"
)
quality_dropdown = gr.Dropdown(
choices=["low", "medium", "high"],
value="high",
label="Quality"
)
seed_input = gr.Number(
label="Seed (optional)",
placeholder="Leave blank for random",
precision=0
)
generate_btn = gr.Button(
"🎬 Generate Video",
variant="primary",
size="lg"
)
with gr.Column(scale=1):
gr.Markdown("### πŸ’‘ Example Prompts")
example_prompts = [
"A majestic eagle soaring through mountain peaks at sunrise",
"A bustling city street with neon lights reflecting on wet pavement",
"A peaceful garden with butterflies fluttering around colorful flowers",
"An astronaut floating in space with Earth in the background",
"A cozy fireplace crackling on a snowy winter evening"
]
for prompt in example_prompts:
gr.HTML(f'<div class="example-prompt" onclick="document.querySelector(\'[data-testid=\"textbox\"]\').value = `{prompt}`">{prompt}</div>')
gr.Markdown("### βš™οΈ Tips")
gr.Markdown("""
β€’ Be descriptive but concise
β€’ Include setting and mood
β€’ Specify camera movements if needed
β€’ Use seeds for reproducible results
""")
# Progress and Output
progress_text = gr.Textbox(
label="Generation Progress",
interactive=False,
visible=False
)
with gr.Column(elem_classes="generation-card"):
gr.Markdown("### πŸ“Ή Generated Video")
video_output = gr.Video(
label="Your Generated Video",
visible=False,
height=400
)
# Event handlers - Fixed for Gradio 6
def handle_generate_text(prompt, duration, style, quality, motion, seed):
if not prompt.strip():
raise gr.Error("Please enter a prompt!")
# Show progress
progress_updates = []
# Generate video with progress updates
for progress in generate_video_from_text(prompt, duration, style, quality, motion, seed):
if isinstance(progress, str):
progress_updates.append(progress)
yield {
progress_text: gr.Textbox(value=progress, visible=True),
video_output: gr.Video(visible=False)
}
# Show result
video_url = generate_video_from_text(prompt, duration, style, quality, motion, seed)
if isinstance(video_url, str):
yield {
video_output: gr.Video(value=video_url, visible=True),
progress_text: gr.Textbox(value="βœ… Video generated successfully!", visible=True)
}
generate_btn.click(
fn=handle_generate_text,
inputs=[prompt_input, duration_slider, style_dropdown, quality_dropdown, motion_slider, seed_input],
outputs=[progress_text, video_output],
api_visibility="public"
)
# Image to Video Tab
with gr.TabItem("πŸ–ΌοΈ Image to Video", elem_id="image-to-video"):
with gr.Row():
with gr.Column():
gr.Markdown("### 🎨 Animate Your Image")
image_input = gr.Image(
label="Upload Image",
type="numpy",
height=300
)
motion_prompt = gr.Textbox(
label="Motion Description",
placeholder="Describe how you want the image to move... (e.g., 'Make the clouds drift slowly and the water ripple')",
lines=2
)
with gr.Row():
img_duration_slider = gr.Slider(
minimum=2,
maximum=20,
value=5,
step=1,
label="Duration (seconds)"
)
img_motion_slider = gr.Slider(
minimum=0.0,
maximum=1.0,
value=0.5,
step=0.1,
label="Motion Strength"
)
img_seed_input = gr.Number(
label="Seed (optional)",
precision=0
)
img_generate_btn = gr.Button(
"🎬 Animate Image",
variant="primary",
size="lg"
)
with gr.Column():
gr.Markdown("### 🎯 Best Practices")
gr.Markdown("""
β€’ Use high-quality images for best results
β€’ Describe motion clearly and specifically
β€’ Start with lower motion strength
β€’ Images with clear subjects work better
β€’ Landscape orientation recommended
""")
gr.Markdown("### πŸ’‘ Motion Examples")
gr.Markdown("""
β€’ "Gentle swaying of trees in the wind"
β€’ "Water flowing and rippling"
β€’ "Clouds moving across the sky"
β€’ "Leaves falling from trees"
β€’ "Fire flickering and dancing"
""")
img_progress_text = gr.Textbox(
label="Generation Progress",
interactive=False,
visible=False
)
img_video_output = gr.Video(
label="Your Animated Video",
visible=False,
height=400
)
img_generate_btn.click(
fn=generate_video_from_image,
inputs=[image_input, motion_prompt, img_duration_slider, img_motion_slider, img_seed_input],
outputs=[img_video_output, img_progress_text],
api_visibility="public"
)
# Gallery Tab
with gr.TabItem("🎭 Gallery", elem_id="gallery"):
gr.Markdown("### 🌟 Featured Generations")
with gr.Row():
with gr.Column():
gr.Video(
label="Ocean Waves",
value="https://sample-videos.com/zip/10/mp4/SampleVideo_1280x720_1mb.mp4",
height=250
)
gr.Markdown("**Ocean Waves** - 'Peaceful ocean waves crashing on a sandy beach'")
with gr.Column():
gr.Video(
label="Forest Path",
value="https://sample-videos.com/zip/10/mp4/SampleVideo_1280x720_2mb.mp4",
height=250
)
gr.Markdown("**Forest Path** - 'A misty forest path with sunlight filtering through trees'")
with gr.Column():
gr.Video(
label="City Lights",
value="https://sample-videos.com/zip/10/mp4/SampleVideo_1280x720_5mb.mp4",
height=250
)
gr.Markdown("**City Lights** - 'Neon city lights at night with traffic flowing'")
gr.Markdown("### πŸ“Š Generation Statistics")
gr.DataFrame(
value=[
["Total Videos Generated", "1,234,567"],
["Average Generation Time", "45 seconds"],
["Most Popular Style", "Realistic"],
["Average Duration", "8 seconds"],
["Success Rate", "98.5%"]
],
headers=["Metric", "Value"],
datatype=["str", "str"],
interactive=False
)
# Gradio 6: ALL app parameters go in launch()!
demo.launch(
theme=custom_theme,
css=create_custom_css(),
footer_links=[
{"label": "Documentation", "url": "https://huggingface.co/spaces/akhaliq/anycoder"},
{"label": "GitHub", "url": "https://github.com/gradio-app/gradio"},
{"label": "Built with anycoder", "url": "https://huggingface.co/spaces/akhaliq/anycoder"}
]
)