Riz0030's picture
Create app.py
679913c verified
import os
import torch
import gradio as gr
import numpy as np
from PIL import Image
import imageio
from diffusers import StableVideoDiffusionPipeline
# =========================
# CONFIG
# =========================
MODEL_ID = "stabilityai/stable-video-diffusion-img2vid"
OUTPUT_DIR = "output"
NUM_FRAMES = 14 # AMAN untuk CPU
FPS = 7
SEED = 42
os.makedirs(OUTPUT_DIR, exist_ok=True)
DEVICE = "cuda" if torch.cuda.is_available() else "cpu"
DTYPE = torch.float16 if DEVICE == "cuda" else torch.float32
# =========================
# LOAD MODEL (SAFE)
# =========================
pipe = StableVideoDiffusionPipeline.from_pretrained(
MODEL_ID,
torch_dtype=DTYPE
)
pipe.to(DEVICE)
pipe.enable_attention_slicing()
if DEVICE == "cuda":
pipe.enable_model_cpu_offload()
generator = torch.Generator(device=DEVICE).manual_seed(SEED)
# =========================
# SAVE VIDEO (NO CV2)
# =========================
def save_video(frames, path, fps):
imageio.mimsave(path, frames, fps=fps)
# =========================
# IMAGE β†’ VIDEO FUNCTION
# =========================
def images_to_videos(files):
if files is None or len(files) == 0:
return None
output_videos = []
for idx, file in enumerate(files):
image = Image.open(file.name).convert("RGB")
image = image.resize((768, 432)) # CPU SAFE SIZE
with torch.autocast(DEVICE if DEVICE == "cuda" else "cpu"):
result = pipe(
image=image,
num_frames=NUM_FRAMES,
generator=generator
)
frames = [
(frame * 255).astype(np.uint8)
for frame in result.frames[0]
]
out_path = os.path.join(OUTPUT_DIR, f"video_{idx}.mp4")
save_video(frames, out_path, FPS)
output_videos.append(out_path)
return output_videos
# =========================
# GRADIO UI
# =========================
with gr.Blocks(title="Image to Video (HF Spaces Safe)") as demo:
gr.Markdown(
"""
## πŸŽ₯ Image β†’ Video AI (Hugging Face Spaces)
- Upload **multiple images**
- Output **MP4**
- CPU & GPU compatible
"""
)
image_input = gr.File(
file_types=["image"],
file_count="multiple",
label="Upload Images"
)
video_output = gr.Video(label="Generated Video")
generate_btn = gr.Button("πŸš€ Generate")
def process(files):
videos = images_to_videos(files)
return videos[0] if videos else None
generate_btn.click(
fn=process,
inputs=image_input,
outputs=video_output
)
demo.launch()