Spaces:
Runtime error
Runtime error
import runpod | |
import os | |
import sys | |
from pathlib import Path | |
import torch | |
import gradio as gr | |
import tempfile | |
from PIL import Image | |
import numpy as np | |
import yaml | |
from typing import Dict, Any, Optional | |
import threading | |
# Add the MuseV directory to the Python path | |
musev_path = str(Path(__file__).parent.parent) | |
sys.path.append(musev_path) | |
# Import MuseV modules (adjust these imports based on the actual module structure) | |
from musev.pipelines import MuseVPipeline | |
class MuseVService: | |
def __init__(self): | |
self.device = "cuda" if torch.cuda.is_available() else "cpu" | |
self.pipeline = None | |
self.load_model() | |
def load_model(self): | |
# Initialize the MuseV pipeline (adjust parameters as needed) | |
self.pipeline = MuseVPipeline.from_pretrained( | |
"TMElyralab/MuseV", | |
torch_dtype=torch.float16, | |
device=self.device | |
) | |
self.pipeline.to(self.device) | |
def generate_video( | |
self, | |
condition_image: Image.Image, | |
prompt: str, | |
height: Optional[int] = None, | |
width: Optional[int] = None, | |
num_frames: int = 16, | |
eye_blinks_factor: float = 1.8, | |
) -> str: | |
# Process inputs | |
if height is None or width is None: | |
width, height = condition_image.size | |
aspect_ratio = width / height | |
if width > height: | |
width = min(width, 1024) | |
height = int(width / aspect_ratio) | |
else: | |
height = min(height, 1024) | |
width = int(height * aspect_ratio) | |
# Create temporary directory for output | |
with tempfile.TemporaryDirectory() as temp_dir: | |
# Save condition image | |
condition_image_path = os.path.join(temp_dir, "condition.png") | |
condition_image.save(condition_image_path) | |
# Prepare configuration | |
config = { | |
"condition_images": condition_image_path, | |
"prompt": prompt, | |
"height": height, | |
"width": width, | |
"eye_blinks_factor": eye_blinks_factor, | |
"img_length_ratio": 1.0, | |
"ipadapter_image": condition_image_path, | |
"refer_image": condition_image_path, | |
} | |
# Generate video | |
output_path = os.path.join(temp_dir, "output.mp4") | |
self.pipeline.generate(config, output_path) | |
# Read the video file and return as bytes | |
with open(output_path, "rb") as f: | |
video_bytes = f.read() | |
return video_bytes | |
# Initialize the service | |
service = MuseVService() | |
def handler(event): | |
""" | |
RunPod handler function for API requests | |
""" | |
try: | |
# Get the input data | |
job_input = event["input"] | |
# Process the input image | |
image_data = job_input.get("image") | |
if not image_data: | |
raise ValueError("No image provided") | |
# Convert base64 image to PIL | |
import base64 | |
from io import BytesIO | |
image = Image.open(BytesIO(base64.b64decode(image_data))) | |
# Generate video | |
video_bytes = service.generate_video( | |
condition_image=image, | |
prompt=job_input.get("prompt", ""), | |
height=job_input.get("height"), | |
width=job_input.get("width"), | |
eye_blinks_factor=job_input.get("eye_blinks_factor", 1.8), | |
) | |
# Encode video as base64 | |
video_base64 = base64.b64encode(video_bytes).decode() | |
return { | |
"status": "success", | |
"output": { | |
"video": video_base64 | |
} | |
} | |
except Exception as e: | |
return { | |
"status": "error", | |
"error": str(e) | |
} | |
def create_gradio_interface(): | |
""" | |
Create Gradio interface | |
""" | |
def generate_video_gradio(image, prompt, height, width, eye_blinks_factor): | |
try: | |
video_bytes = service.generate_video( | |
condition_image=Image.fromarray(image), | |
prompt=prompt, | |
height=height if height > 0 else None, | |
width=width if width > 0 else None, | |
eye_blinks_factor=eye_blinks_factor | |
) | |
# Save video to temporary file | |
temp_file = tempfile.NamedTemporaryFile(delete=False, suffix=".mp4") | |
temp_file.write(video_bytes) | |
temp_file.close() | |
return temp_file.name | |
except Exception as e: | |
raise gr.Error(str(e)) | |
# Create the interface | |
interface = gr.Interface( | |
fn=generate_video_gradio, | |
inputs=[ | |
gr.Image(label="Input Image", type="numpy"), | |
gr.Textbox(label="Prompt", placeholder="Enter your prompt here..."), | |
gr.Number(label="Height (optional)", value=0), | |
gr.Number(label="Width (optional)", value=0), | |
gr.Slider(minimum=0.0, maximum=3.0, value=1.8, label="Eye Blinks Factor") | |
], | |
outputs=gr.Video(label="Generated Video"), | |
title="MuseV Video Generation", | |
description="Generate videos from images using MuseV", | |
examples=[ | |
[ | |
"path/to/example/image.jpg", | |
"(masterpiece, best quality, highres:1),(1person, solo:1),(eye blinks:1.8),(head wave:1.3)", | |
512, | |
512, | |
1.8 | |
] | |
] | |
) | |
return interface | |
if __name__ == "__main__": | |
# Start both the RunPod handler and Gradio interface | |
interface = create_gradio_interface() | |
# Start Gradio in a separate thread | |
threading.Thread( | |
target=interface.launch, | |
kwargs={ | |
"server_name": "0.0.0.0", | |
"server_port": 3000, | |
"share": False | |
}, | |
daemon=True | |
).start() | |
# Start the RunPod handler | |
runpod.serverless.start({"handler": handler}) |