Spaces:
Running
Running
File size: 3,761 Bytes
eeb0d4a 03de52f 0731858 eeb0d4a dfe8f97 eeb0d4a 0731858 eeb0d4a 0731858 eeb0d4a |
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 113 114 |
import gradio as gr
import os, uuid, time
from gradio_client import Client, handle_file
from moviepy.editor import VideoFileClip # NEW
hf_token = os.environ.get("TOKEN")
output_dir = "uploads/output"
os.makedirs(output_dir, exist_ok=True)
client = Client("tonyassi/vfs2-cpu", hf_token=hf_token, download_files=output_dir)
# ββ helper βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
def preprocess_video(path: str, target_fps: int = 12,
target_size: int = 800, target_len: int = 4) -> str:
"""
Returns a path to a temp-file that is
β€ target_len seconds, target_fps FPS,
and resized so the longest side == target_size.
"""
clip = VideoFileClip(path)
# 1) trim
if clip.duration > target_len:
clip = clip.subclip(0, target_len)
# 2) resize (longest side)
w, h = clip.size
if w >= h:
clip = clip.resize(width=target_size)
else:
clip = clip.resize(height=target_size)
# 3) FPS
clip = clip.set_fps(target_fps)
# 4) write to temp file
out_path = os.path.join(
output_dir, f"pre_{uuid.uuid4().hex}.mp4"
)
clip.write_videofile(
out_path,
codec="libx264",
audio_codec="aac",
fps=target_fps,
verbose=False,
logger=None
)
clip.close()
return out_path
# ββ main generate ββββββββββββββββββββββββββββββββββββββββββββββββββββ
def generate(input_image, input_video, gender):
gr.Warning('Skip the line, generate 1-5 minute HD face swap videos at <a href="https://www.face-swap.co/" target="_blank" style="color:#007bff; text-decoration:none;">face-swap.co</a>')
if (gender=="all"): gender = None
try:
# β’ preprocess video locally
pre_video = preprocess_video(input_video)
# β’ submit job to remote Space
job = client.submit(
input_image=handle_file(input_image),
input_video={"video": handle_file(pre_video)},
device='cpu',
selector='many',
gender=gender,
race=None,
order=None,
api_name="/predict"
)
# wait for completion
while not job.done():
print("Waiting for remote job to finish...")
time.sleep(5)
if not job.status().success:
print("Job failed or was cancelled:", job.status())
return None
video_path = job.outputs()[0]["video"]
return video_path
except Exception as e:
print("Error occurred:", e)
return None
# ββ Gradio interface (unchanged) βββββββββββββββββββββββββββββββββββββ
demo = gr.Interface(
fn=generate,
title="Video Face Swap",
description="""
### [face-swap.co](https://www.face-swap.co/)
***Skip the line, generate 1-5 minute HD videos starting at $3.00***
---
Swaps the source image face onto the target video. Videos get downsampled to 800 pixels, 4 sec, and 12 fps to cut down render time (~5 minutes). Please β€οΈ this Space.
""",
inputs=[
gr.Image(type="filepath", label="Source Image"),
gr.Video(label="Target Video"),
gr.Radio(choices=["all", "female", "male"], label="Gender", value="all"),
],
outputs=gr.Video(label="Result"),
flagging_mode="never",
examples=[['bella.jpg', 'wizard.mp4', 'all']],
cache_examples=True,
)
if __name__ == "__main__":
demo.launch() |