| | 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") |