| import gradio as gr |
| import requests |
| import os |
| import time |
| import logging |
| from PIL import Image |
| import io |
|
|
| |
| logging.basicConfig(level=logging.INFO) |
| logger = logging.getLogger(__name__) |
|
|
| |
| API_KEY = os.environ.get("key", os.environ.get("Key", "")) |
| if not API_KEY: |
| logger.error("❌ No API key found") |
|
|
| def upload_to_temp_url(image): |
| """Upload image to temporary hosting and return URL""" |
| |
| |
| |
| |
| |
| |
| |
| return None |
|
|
| def generate_video(image, prompt_text, model_id, progress=gr.Progress()): |
| """Generate video using image upload and prompt""" |
| |
| if not API_KEY: |
| yield "❌ API key not configured", None |
| return |
| |
| try: |
| progress(0, desc="Preparing request...") |
| |
| |
| |
| |
| if image is None: |
| yield "⚠️ Please upload an image", None |
| return |
| |
| |
| |
| yield "⏳ Image uploaded. For now, please also provide a public URL (hosting service needed)", None |
| return |
| |
| |
| |
| except Exception as e: |
| logger.error(f"❌ Error: {str(e)}") |
| yield f"❌ Error: {str(e)}", None |
|
|
| |
| with gr.Blocks(title="BytePlus Video Generator", theme=gr.themes.Soft()) as demo: |
| |
| gr.Markdown(""" |
| # 🎥 BytePlus Video Generator |
| Upload an image and describe the video you want to generate |
| """) |
| |
| with gr.Row(): |
| with gr.Column(): |
| |
| image_input = gr.Image( |
| label="📤 Upload Starting Image", |
| type="pil", |
| height=300 |
| ) |
| |
| |
| prompt = gr.Textbox( |
| label="📝 Video Description", |
| placeholder="Describe what you want to see...", |
| lines=3, |
| value="At breakneck speed, drones thread through intricate obstacles --duration 5 --camerafixed false" |
| ) |
| |
| |
| model_id = gr.Textbox( |
| label="Model ID", |
| value="seedance-1-5-pro-251215", |
| visible=False |
| ) |
| |
| |
| generate_btn = gr.Button("🚀 Generate Video", variant="primary", size="lg") |
| |
| with gr.Column(): |
| |
| status = gr.Textbox( |
| label="Status", |
| lines=2, |
| interactive=False |
| ) |
| |
| |
| video_output = gr.Video( |
| label="🎬 Generated Video", |
| interactive=False, |
| show_download_button=True, |
| height=300 |
| ) |
| |
| |
| gr.Markdown("---") |
| gr.Markdown("### Example Prompts") |
| with gr.Row(): |
| gr.Button("Nature Drone").click( |
| fn=lambda: "Aerial drone shot over mountains at sunrise, cinematic --duration 5 --camerafixed false", |
| outputs=prompt |
| ) |
| gr.Button("City Race").click( |
| fn=lambda: "Fast drone racing through futuristic city streets --duration 5 --camerafixed false", |
| outputs=prompt |
| ) |
| gr.Button("Ocean Waves").click( |
| fn=lambda: "Drone following waves at golden hour --duration 5 --camerafixed false", |
| outputs=prompt |
| ) |
| |
| |
| gr.Markdown(""" |
| --- |
| ⚠️ **Note:** Currently requires publicly accessible image URLs. |
| Working on direct image upload support! |
| """) |
| |
| |
| def placeholder_gen(image, prompt, model): |
| if image is None: |
| return "Please upload an image first", None |
| return "Image uploaded! (URL hosting coming soon)", None |
| |
| |
| generate_btn.click( |
| fn=placeholder_gen, |
| inputs=[image_input, prompt, model_id], |
| outputs=[status, video_output] |
| ) |
|
|
| if __name__ == "__main__": |
| demo.launch(server_name="0.0.0.0") |