kimhyunwoo's picture
Update app.py
60f2b33 verified
Raw
History Blame Contribute Delete
5.14 kB
import os
import gc
import torch
import gradio as gr
from PIL import Image
from diffusers import DiffusionPipeline
# --- [์ดˆํ•ต์‹ฌ ํฌ๋ฆฌํ‹ฐ์ปฌ ์„ธํŒ…] ---
# PyTorch๊ฐ€ safetensors๋ฅผ ๋กœ๋“œํ•  ๋•Œ ์Šคํ† ๋ฆฌ์ง€ ํŒŒ์ผ ๋งคํ•‘(mmap)์œผ๋กœ RAM์„ ์ค‘๋ณต ํ• ๋‹นํ•˜๋Š” ๊ฒƒ์„ ๋ฐฉ์ง€
os.environ["SAFETENSORS_FAST_GPU"] = "0"
DEVICE = "cuda" if torch.cuda.is_available() else "cpu"
print(f"๐Ÿ–ฅ๏ธ [System] ํ˜„์žฌ ๊ฐ์ง€๋œ ์‹คํ–‰ ๋””๋ฐ”์ด์Šค: {DEVICE.upper()}")
def clean_memory():
"""๊ฐ€๋น„์ง€ ์ปฌ๋ ‰์…˜์„ ์•„์ฃผ ๊ฐ•๋ ฅํ•˜๊ฒŒ ์ˆ˜๋™ ํŠธ๋ฆฌ๊ฑฐ"""
gc.collect()
if torch.cuda.is_available():
torch.cuda.empty_cache()
# --- 2. ํŒŒ์ดํ”„๋ผ์ธ ์ดˆ๊ธฐํ™” ๋กœ๋” (RAM 96GB ์„ธ์ด๋ธŒ ๋ชจ๋“œ) ---
print("๐Ÿš€ [System] ์ŠคํŠœ๋””์˜ค ํŒŒ์ดํ”„๋ผ์ธ ์ตœ์ ํ™” ์ดˆ๊ธฐํ™” ์‹œ์ž‘...")
# [Step 1] FireRed Image Edit ๋กœ๋“œ
print("๐Ÿ“ฆ [1/2] FireRed Image Edit ๋ชจ๋ธ ๋กœ๋“œ ์ค‘...")
pipe_edit = DiffusionPipeline.from_pretrained(
"FireRedTeam/FireRed-Image-Edit-1.1",
torch_dtype=torch.float16 if DEVICE == "cuda" else torch.float32,
low_cpu_mem_usage=True, # RAM ๋ฒ„์ŠคํŠธ ๋ฐฉ์–ด
)
if DEVICE == "cuda":
pipe_edit.to("cuda")
else:
# CPU ํ™˜๊ฒฝ์ผ ๋•Œ RAM ์šฉ๋Ÿ‰์ด ํ„ฐ์ง€์ง€ ์•Š๋„๋ก ๋ ˆ์ด์–ด ๋‹จ์œ„ CPU ์˜คํ”„๋กœ๋“œ ๊ฐ•์ œ
pipe_edit.enable_model_cpu_offload()
print("โœ… [System] FireRed Image Edit ๋กœ๋“œ ์™„๋ฃŒ.")
clean_memory() # 1๋ฒˆ ๋ชจ๋ธ ๋กœ๋“œ ํ›„ ์ฐŒ๊บผ๊ธฐ ์ฆ‰์‹œ ์‚ญ์ œ
# [Step 2] Wan 2.2 14B ๋กœ๋“œ
print("๐Ÿ“ฆ [2/2] Wan 2.2 14B ๋ชจ๋ธ ๋กœ๋“œ ์ค‘...")
# CPU ํ™˜๊ฒฝ์ผ ๋•Œ๋Š” fp8 ์ปค๋„์ด ์—๋Ÿฌ๋ฅผ ๋‚ด๋ฏ€๋กœ ์ „์šฉ ์˜ต์…˜์„ ๊ฐ€๋ณ€์ ์œผ๋กœ ๋งคํ•‘
wan_kwargs = {
"torch_dtype": torch.bfloat16 if DEVICE == "cuda" else torch.float32,
"low_cpu_mem_usage": True,
"device_map": "auto"
}
if DEVICE == "cuda":
wan_kwargs["variant"] = "fp8"
pipe_wan = DiffusionPipeline.from_pretrained(
"Wan-Video/Wan2.2-I2V-14B",
**wan_kwargs
)
if DEVICE == "cuda":
pipe_wan.enable_model_cpu_offload()
else:
# CPU ๋นŒ๋“œ์ผ ๋•Œ 96GB RAM ์„ธ์ด๋ธŒ๋ฅผ ์œ„ํ•œ ์ตœ์ข… ๋ณ‘๊ธฐ
# ํŒŒ์ดํ”„๋ผ์ธ ๋‚ด๋ถ€์˜ ์ค‘๋ณต ์ปดํฌ๋„ŒํŠธ๋ฅผ ์ฒญ์†Œ
pipe_wan.to("cpu")
print("โœ… [System] Wan 2.2 14B ๋กœ๋“œ ์™„๋ฃŒ.")
clean_memory()
# --- 3. ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง ---
def process_studio_pipeline(input_image, edit_prompt, video_prompt, num_frames=81, progress=gr.Progress()):
if input_image is None:
raise gr.Error("๋จผ์ € ์›๋ณธ ์ด๋ฏธ์ง€๋ฅผ ์—…๋กœ๋“œํ•ด์ฃผ์„ธ์š”!")
# [Step 1] FireRed ์ด๋ฏธ์ง€ ํŽธ์ง‘
progress(0.1, desc="FireRed๋กœ ์ด๋ฏธ์ง€ ํŽธ์ง‘ ์ค‘...")
pil_img = Image.fromarray(input_image).convert("RGB")
edited_image = pipe_edit(
prompt=edit_prompt,
image=pil_img,
num_inference_steps=20 if DEVICE == "cuda" else 3 # CPU์ผ ๋• ์ตœ์†Œ ์—ฐ์‚ฐ
).images[0]
clean_memory()
# [Step 2] Wan 2.2 14B ๋น„๋””์˜ค ์ƒ์„ฑ
progress(0.5, desc="Wan 2.2๋กœ ๋น„๋””์˜ค ์ƒ์„ฑ ์ค‘...")
video_frames = pipe_wan(
prompt=video_prompt,
image=edited_image,
num_frames=int(num_frames) if DEVICE == "cuda" else 16, # CPU ์—ฐ์‚ฐ ์ตœ์†Œํ™”
num_inference_steps=30 if DEVICE == "cuda" else 3,
guidance_scale=6.0
).frames[0]
clean_memory()
# [Step 3] ๋น„๋””์˜ค ํŒŒ์ผ ์ €์žฅ
progress(0.9, desc="๋น„๋””์˜ค ๋ Œ๋”๋ง ์ค‘...")
output_video_path = "studio_output.mp4"
from diffusers.utils import export_to_video
export_to_video(video_frames, output_video_path, fps=16)
return edited_image, output_video_path
# --- 4. Gradio UI Layout ---
with gr.Blocks(theme=gr.themes.Soft()) as demo:
gr.Markdown("# ๐ŸŽฌ iE2V Fast Studio (RAM Dynamic Build)")
if DEVICE == "cpu":
gr.Warning("โš ๏ธ ์ธํ”„๋ผ๊ฐ€ CPU ๋ชจ๋“œ๋กœ ์ œํ•œ๋˜์–ด RAM 96GB ํฌ๋ž˜์‹œ ๋ฐฉ์–ด ๋ชจ๋“œ๊ฐ€ ์ž‘๋™ ์ค‘์ž…๋‹ˆ๋‹ค. ์ •์ƒ ์ถ”๋ก ์„ ์œ„ํ•ด์„œ๋Š” Space Settings์—์„œ GPU ํ• ๋‹น์„ ๊ผญ ํ™•๋ณดํ•ด ์ฃผ์„ธ์š”.")
with gr.Row():
with gr.Column():
input_img_slot = gr.Image(label="1. ์›๋ณธ ์ด๋ฏธ์ง€ ์—…๋กœ๋“œ", type="numpy")
edit_prompt_slot = gr.Textbox(label="2. ์ด๋ฏธ์ง€ ํŽธ์ง‘ ํ”„๋กฌํ”„ํŠธ (FireRed)", placeholder="๋ฐฐ๊ฒฝ์„ ๋ฐค๊ฑฐ๋ฆฌ๋กœ ๋ณ€๊ฒฝ...")
video_prompt_slot = gr.Textbox(label="3. ๋น„๋””์˜ค ์—ฐ์ถœ ํ”„๋กฌํ”„ํŠธ (Wan 2.2)", placeholder="์นด๋ฉ”๋ผ๊ฐ€ ์„œ์„œํžˆ ์คŒ์ธ๋˜๋ฉฐ...")
with gr.Accordion("๐ŸŽฅ ๊ณ ๊ธ‰ ์„ธํŒ…", open=False):
frames_slider = gr.Slider(minimum=16, maximum=81, step=4, value=81 if DEVICE == "cuda" else 16, label="ํ”„๋ ˆ์ž„ ์ˆ˜")
submit_btn = gr.Button("โšก ์œตํ•ฉ ์ƒ์„ฑ ์‹œ์ž‘", variant="primary")
with gr.Column():
edited_img_output = gr.Image(label="ํŽธ์ง‘๋œ ์ด๋ฏธ์ง€ ๊ฒฐ๊ณผ")
video_output = gr.Video(label="์ตœ์ข… ์ƒ์„ฑ ๋น„๋””์˜ค")
submit_btn.click(
fn=process_studio_pipeline,
inputs=[input_img_slot, edit_prompt_slot, video_prompt_slot, frames_slider],
outputs=[edited_img_output, video_output]
)
if __name__ == "__main__":
demo.queue().launch(server_name="0.0.0.0", server_port=7860)