Spaces:
Running
Running
| 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): | |
| 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="Deep Fake Video", | |
| description=""" | |
| by [Tony Assi](https://www.tonyassi.com/) | |
| 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. tony.assi.media@gmail.com for business inquiries. | |
| """, | |
| 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() |