Spaces:
Sleeping
Sleeping
Download app.py from Riz0030/Image_to_Video_Generated: direct link, hf CLI and curl.
- Browser
- Download file 2.65 kB
-
https://huggingface.co/spaces/Riz0030/Image_to_Video_Generated/resolve/main/app.py
- Command line
-
hf download hf://spaces/Riz0030/Image_to_Video_Generated/app.py
-
curl -L -o app.py https://huggingface.co/spaces/Riz0030/Image_to_Video_Generated/resolve/main/app.py
2.65 kB
| 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() |