| | import gradio as gr |
| | import os |
| | import time |
| | from byteplussdkarkruntime import Ark |
| | import tempfile |
| | import requests |
| | from PIL import Image |
| | from io import BytesIO |
| |
|
| | |
| | client = None |
| |
|
| | def initialize_client(api_key): |
| | """Initialize the Ark client with the provided API key""" |
| | global client |
| | try: |
| | client = Ark( |
| | base_url="https://ark.ap-southeast.bytepluses.com/api/v3", |
| | api_key=api_key, |
| | ) |
| | return "✅ Client initialized successfully!" |
| | except Exception as e: |
| | return f"❌ Error initializing client: {str(e)}" |
| |
|
| | def generate_video(api_key, prompt_text, image_url, model_id="seedance-1-5-pro-251215"): |
| | """Generate video using the Ark API""" |
| | global client |
| | |
| | |
| | if client is None: |
| | init_result = initialize_client(api_key) |
| | if "❌" in init_result: |
| | return init_result, None |
| | else: |
| | |
| | try: |
| | client = Ark(base_url="https://ark.ap-southeast.bytepluses.com/api/v3", api_key=api_key) |
| | except: |
| | pass |
| | |
| | try: |
| | print("🚀 Creating video generation request...") |
| | |
| | |
| | content = [ |
| | { |
| | "type": "text", |
| | "text": prompt_text if prompt_text else "At breakneck speed, drones thread through intricate obstacles --duration 5 --camerafixed false" |
| | }, |
| | { |
| | "type": "image_url", |
| | "image_url": { |
| | "url": image_url if image_url else "https://ark-doc.tos-ap-southeast-1.bytepluses.com/seepro_i2v%20.png" |
| | } |
| | } |
| | ] |
| | |
| | |
| | create_result = client.content_generation.tasks.create( |
| | model=model_id, |
| | content=content |
| | ) |
| | |
| | task_id = create_result.id |
| | print(f"📋 Task ID: {task_id}") |
| | |
| | |
| | yield f"⏳ Task created with ID: {task_id}. Waiting for completion...", None |
| | |
| | max_attempts = 60 |
| | attempts = 0 |
| | |
| | while attempts < max_attempts: |
| | get_result = client.content_generation.tasks.get(task_id=task_id) |
| | status = get_result.status |
| | |
| | if status == "succeeded": |
| | print("✅ Task succeeded!") |
| | |
| | |
| | video_url = None |
| | if hasattr(get_result, 'output') and get_result.output: |
| | if isinstance(get_result.output, list) and len(get_result.output) > 0: |
| | video_url = get_result.output[0].get('video_url') |
| | |
| | if video_url: |
| | yield f"✅ Video generated successfully!", video_url |
| | else: |
| | yield f"✅ Task completed, but no video URL found in response. Full response: {get_result}", None |
| | break |
| | |
| | elif status == "failed": |
| | error_msg = get_result.error if hasattr(get_result, 'error') else "Unknown error" |
| | yield f"❌ Task failed: {error_msg}", None |
| | break |
| | else: |
| | progress_msg = f"⏳ Current status: {status}, waiting... (attempt {attempts + 1}/{max_attempts})" |
| | print(progress_msg) |
| | yield progress_msg, None |
| | time.sleep(1) |
| | attempts += 1 |
| | |
| | if attempts >= max_attempts: |
| | yield "⏰ Timeout: Task took too long to complete. Please try again.", None |
| | |
| | except Exception as e: |
| | yield f"❌ Error: {str(e)}", None |
| |
|
| | def upload_image(image_file): |
| | """Handle image upload and return URL""" |
| | if image_file is None: |
| | return "https://ark-doc.tos-ap-southeast-1.bytepluses.com/seepro_i2v%20.png" |
| | |
| | |
| | |
| | return image_file.name |
| |
|
| | |
| | with gr.Blocks(title="BytePlus Video Generation", theme=gr.themes.Soft()) as demo: |
| | gr.Markdown(""" |
| | # 🎥 BytePlus Video Generation |
| | Generate stunning videos from images and text prompts using the BytePlus API. |
| | """) |
| | |
| | with gr.Row(): |
| | with gr.Column(scale=1): |
| | |
| | api_key = gr.Textbox( |
| | label="🔑 API Key", |
| | placeholder="Enter your BytePlus API key here", |
| | type="password", |
| | value="key" |
| | ) |
| | |
| | |
| | model_id = gr.Textbox( |
| | label="🤖 Model ID", |
| | value="seedance-1-5-pro-251215", |
| | info="Default model for video generation" |
| | ) |
| | |
| | |
| | image_input = gr.Image( |
| | label="🖼️ Upload Starting Image (Optional)", |
| | type="filepath" |
| | ) |
| | |
| | |
| | image_url_input = gr.Textbox( |
| | label="🔗 Or Enter Image URL", |
| | placeholder="https://example.com/image.jpg", |
| | value="https://ark-doc.tos-ap-southeast-1.bytepluses.com/seepro_i2v%20.png" |
| | ) |
| | |
| | |
| | prompt_input = gr.Textbox( |
| | label="📝 Text Prompt", |
| | placeholder="Describe your video...", |
| | value="At breakneck speed, drones thread through intricate obstacles or stunning natural wonders, delivering an immersive, heart-pounding flying experience. --duration 5 --camerafixed false", |
| | lines=4 |
| | ) |
| | |
| | |
| | generate_btn = gr.Button("🚀 Generate Video", variant="primary") |
| | |
| | with gr.Column(scale=1): |
| | |
| | status_output = gr.Textbox( |
| | label="📊 Status", |
| | placeholder="Generation status will appear here...", |
| | lines=3 |
| | ) |
| | |
| | |
| | video_output = gr.Video( |
| | label="🎬 Generated Video", |
| | interactive=False |
| | ) |
| | |
| | |
| | video_url_output = gr.Textbox( |
| | label="🔗 Video URL", |
| | placeholder="Video URL will appear here...", |
| | lines=2, |
| | interactive=False |
| | ) |
| | |
| | |
| | gr.Markdown(""" |
| | ## 📋 Examples |
| | Try these example prompts: |
| | """) |
| | |
| | with gr.Row(): |
| | example1 = gr.Button("🌄 Nature drone shot") |
| | example2 = gr.Button("🏙️ City flythrough") |
| | example3 = gr.Button("🌊 Ocean waves") |
| | |
| | def set_example1(): |
| | return "Aerial drone shot flying over majestic mountains at sunrise, cinematic lighting, smooth motion --duration 5 --camerafixed false" |
| | |
| | def set_example2(): |
| | return "Fast-paced drone racing through futuristic city streets with neon lights, dynamic angles --duration 5 --camerafixed false" |
| | |
| | def set_example3(): |
| | return "Drone following surfers riding massive waves, slow motion, dramatic ocean views --duration 5 --camerafixed false" |
| | |
| | example1.click(fn=set_example1, outputs=prompt_input) |
| | example2.click(fn=set_example2, outputs=prompt_input) |
| | example3.click(fn=set_example3, outputs=prompt_input) |
| | |
| | |
| | generate_btn.click( |
| | fn=generate_video, |
| | inputs=[api_key, prompt_input, image_url_input, model_id], |
| | outputs=[status_output, video_output] |
| | ).then( |
| | fn=lambda url: url if url else "No URL available", |
| | inputs=[video_output], |
| | outputs=[video_url_output] |
| | ) |
| | |
| | |
| | image_input.change( |
| | fn=upload_image, |
| | inputs=image_input, |
| | outputs=image_url_input |
| | ) |
| |
|
| | if __name__ == "__main__": |
| | demo.launch() |