Seedance-Free / app.py
ginipick's picture
Update app.py
a5e046f verified
raw
history blame
10.5 kB
#!/usr/bin/env python3
"""
AI Video Generator with Gradio
Single file application - app.py
"""
import os
import gradio as gr
import replicate
import base64
from PIL import Image
import io
import requests
from datetime import datetime
import tempfile
# API token setup
api_token = os.getenv("RAPI_TOKEN")
if api_token:
os.environ["REPLICATE_API_TOKEN"] = api_token
# Aspect ratio options
ASPECT_RATIOS = {
"16:9": "16:9 (YouTube, Standard Video)",
"4:3": "4:3 (Traditional TV Format)",
"1:1": "1:1 (Instagram Feed)",
"3:4": "3:4 (Instagram Portrait)",
"9:16": "9:16 (Instagram Reels, TikTok)",
"21:9": "21:9 (Cinematic Wide)",
"9:21": "9:21 (Ultra Vertical)"
}
def update_prompt_placeholder(mode):
"""Update prompt placeholder based on mode"""
if mode == "Text to Video":
return gr.update(placeholder="Describe the video you want to create.\nExample: The sun rises slowly between tall buildings. [Ground-level follow shot] Bicycle tires roll over a dew-covered street at dawn.")
else:
return gr.update(placeholder="Describe how the image should move.\nExample: Camera slowly zooms in while clouds move across the sky. The subject's hair gently moves in the wind.")
def update_image_input(mode):
"""Show/hide image input based on mode"""
if mode == "Image to Video":
return gr.update(visible=True)
else:
return gr.update(visible=False)
def generate_video(mode, prompt, image, aspect_ratio, seed, api_key_input, progress=gr.Progress()):
"""Main video generation function"""
# API token check
token = api_key_input or api_token
if not token:
return None, "❌ API token required. Please set RAPI_TOKEN environment variable or enter your API key."
os.environ["REPLICATE_API_TOKEN"] = token
# Input validation
if not prompt:
return None, "❌ Please enter a prompt."
if mode == "Image to Video" and image is None:
return None, "❌ Please upload an image."
try:
progress(0, desc="Preparing video generation...")
# Input parameters setup
input_params = {
"prompt": prompt,
"duration": 5,
"resolution": "480p",
"aspect_ratio": aspect_ratio,
"seed": seed
}
# Image to video mode
if mode == "Image to Video" and image is not None:
progress(0.1, desc="Processing image...")
# Convert PIL Image to base64
if isinstance(image, str): # File path
with Image.open(image) as img:
buffered = io.BytesIO()
img.save(buffered, format="PNG")
image_base64 = base64.b64encode(buffered.getvalue()).decode()
else: # PIL Image object
buffered = io.BytesIO()
image.save(buffered, format="PNG")
image_base64 = base64.b64encode(buffered.getvalue()).decode()
input_params["image"] = f"data:image/png;base64,{image_base64}"
progress(0.3, desc="Calling Replicate API...")
# Run Replicate
output = replicate.run(
"bytedance/seedance-1-lite",
input=input_params
)
progress(0.7, desc="Downloading video...")
# Get video data
if hasattr(output, 'read'):
video_data = output.read()
else:
# Download from URL
response = requests.get(output)
video_data = response.content
# Save to temporary file
with tempfile.NamedTemporaryFile(delete=False, suffix='.mp4') as tmp_file:
tmp_file.write(video_data)
video_path = tmp_file.name
# Also save as output.mp4
with open("output.mp4", "wb") as file:
file.write(video_data)
progress(1.0, desc="Complete!")
# Generation info
info = f"""βœ… Video generated successfully!
πŸ“Š Generation Info:
- Mode: {mode}
- Aspect Ratio: {aspect_ratio}
- Seed: {seed}
- Duration: 5 seconds
- Resolution: 480p
- File: output.mp4"""
return video_path, info
except Exception as e:
error_msg = f"❌ Error occurred: {str(e)}"
return None, error_msg
# Gradio interface
with gr.Blocks(title="Bytedance Seedance Video Free", theme=gr.themes.Soft()) as app:
gr.Markdown("""
# 🎬 Bytedance Seedance Video' Free
Generate videos from text or images using **Replicate API**.
[![Powered by Ginigen](https://img.shields.io/badge/Powered%20by-Replicate-blue)](https://ginigen.com/)
""")
with gr.Row():
with gr.Column(scale=1):
# API Settings
with gr.Accordion("βš™οΈ API Settings", open=not bool(api_token)):
if api_token:
gr.Markdown("βœ… API token loaded from environment variable.")
api_key_input = gr.Textbox(
label="Replicate API Token (Optional)",
type="password",
placeholder="Enter to override environment variable",
value=""
)
else:
gr.Markdown("⚠️ RAPI_TOKEN environment variable not set.")
api_key_input = gr.Textbox(
label="Replicate API Token (Required)",
type="password",
placeholder="Enter your Replicate API token",
value=""
)
# Generation mode
mode = gr.Radio(
label="🎯 Generation Mode",
choices=["Text to Video", "Image to Video"],
value="Text to Video"
)
# Image upload
image_input = gr.Image(
label="πŸ“· Upload Image",
type="pil",
visible=False
)
# Aspect ratio
aspect_ratio = gr.Dropdown(
label="πŸ“ Aspect Ratio",
choices=list(ASPECT_RATIOS.keys()),
value="16:9",
info="Choose ratio optimized for social media platforms"
)
# Ratio description
ratio_info = gr.Markdown(value=f"Selected ratio: {ASPECT_RATIOS['16:9']}")
# Seed setting
seed = gr.Number(
label="🎲 Random Seed",
value=42,
precision=0,
info="Use same seed value to reproduce same results"
)
# Fixed settings display
gr.Markdown("""
### πŸ“‹ Fixed Settings
- **Duration**: 5 seconds
- **Resolution**: 480p
""")
with gr.Column(scale=2):
# Prompt input
prompt = gr.Textbox(
label="✍️ Prompt",
lines=5,
placeholder="Describe the video you want to create.\nExample: The sun rises slowly between tall buildings. [Ground-level follow shot] Bicycle tires roll over a dew-covered street at dawn."
)
# Generate button
generate_btn = gr.Button("🎬 Generate Video", variant="primary", size="lg")
# Results display
with gr.Column():
output_video = gr.Video(
label="πŸ“Ή Generated Video",
autoplay=True
)
output_info = gr.Textbox(
label="Information",
lines=8,
interactive=False
)
# Usage instructions
with gr.Accordion("πŸ“– How to Use", open=False):
gr.Markdown("""
### Installation
1. **Install required packages**:
```bash
pip install gradio replicate pillow requests
```
2. **Set environment variable** (optional):
```bash
export RAPI_TOKEN="your-replicate-api-token"
```
3. **Run**:
```bash
python app.py
```
### Features
- **Text to Video**: Generate video from text description only
- **Image to Video**: Transform uploaded image into animated video
- **Aspect Ratios**: Choose ratios optimized for various social media platforms
- **Seed Value**: Use same seed to reproduce identical results
### Prompt Writing Tips
- Use specific and detailed descriptions
- Specify camera movements (e.g., zoom in, pan left, tracking shot)
- Describe lighting and atmosphere (e.g., golden hour, dramatic lighting)
- Indicate movement speed (e.g., slowly, rapidly, gently)
""")
# Examples
gr.Examples(
examples=[
["Text to Video", "A serene lake at sunrise with mist rolling over the water. Camera slowly pans across the landscape as birds fly overhead.", None, "16:9", 42],
["Text to Video", "Urban street scene at night with neon lights reflecting on wet pavement. People walking with umbrellas, camera tracking forward.", None, "9:16", 123],
["Text to Video", "Close-up of a flower blooming in time-lapse, soft natural lighting, shallow depth of field.", None, "1:1", 789],
],
inputs=[mode, prompt, image_input, aspect_ratio, seed],
label="Example Prompts"
)
# Event handlers
mode.change(
fn=update_prompt_placeholder,
inputs=[mode],
outputs=[prompt]
)
mode.change(
fn=update_image_input,
inputs=[mode],
outputs=[image_input]
)
aspect_ratio.change(
fn=lambda x: f"Selected ratio: {ASPECT_RATIOS[x]}",
inputs=[aspect_ratio],
outputs=[ratio_info]
)
generate_btn.click(
fn=generate_video,
inputs=[mode, prompt, image_input, aspect_ratio, seed, api_key_input],
outputs=[output_video, output_info]
)
# Run app
if __name__ == "__main__":
app.launch(
server_name="0.0.0.0",
server_port=7860,
share=False,
inbrowser=True
)