File size: 2,649 Bytes
679913c | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 | 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() |