|
import os, cv2, tempfile |
|
import gradio as gr |
|
from moviepy.editor import ImageSequenceClip |
|
from insightface.app import FaceAnalysis |
|
from insightface.model_zoo import get_model |
|
|
|
os.environ["XDG_RUNTIME_DIR"] = "/tmp/runtime-dir" |
|
|
|
|
|
app = FaceAnalysis(name="buffalo_l", providers=["CUDAExecutionProvider","CPUExecutionProvider"]) |
|
app.prepare(ctx_id=0, det_size=(1024,1024)) |
|
|
|
onnx_model_path = "inswapper_128.onnx" |
|
swap_model = get_model(onnx_model_path, |
|
providers=["CUDAExecutionProvider","CPUExecutionProvider"]) |
|
|
|
def face_swap_api(source_image, target_video): |
|
src_img = cv2.imread(source_image) |
|
src_faces = app.get(src_img) |
|
if len(src_faces) == 0: |
|
return None |
|
src_face = src_faces[0] |
|
|
|
frames_dir = tempfile.mkdtemp() |
|
cap = cv2.VideoCapture(target_video) |
|
fps = cap.get(cv2.CAP_PROP_FPS) |
|
frames = [] |
|
idx = 0 |
|
while cap.isOpened(): |
|
ret, frame = cap.read() |
|
if not ret: break |
|
frame_path = os.path.join(frames_dir, f"frame_{idx:04d}.png") |
|
cv2.imwrite(frame_path, frame) |
|
frames.append(frame_path) |
|
idx += 1 |
|
cap.release() |
|
|
|
swapped_frames = [] |
|
for fpath in frames: |
|
frame = cv2.imread(fpath) |
|
faces = app.get(frame) |
|
for face in faces: |
|
frame = swap_model.get(frame, face, src_face, paste_back=True) |
|
swapped_frames.append(frame) |
|
|
|
out_path = os.path.join(tempfile.gettempdir(), "swapped_output.mp4") |
|
clip = ImageSequenceClip( |
|
[cv2.cvtColor(f, cv2.COLOR_BGR2RGB) for f in swapped_frames], fps=fps |
|
) |
|
clip.write_videofile(out_path, codec="libx264", audio=False, verbose=False) |
|
return out_path |
|
|
|
demo = gr.Interface( |
|
fn=face_swap_api, |
|
inputs=[gr.Image(type="filepath", label="Source Face"), |
|
gr.Video(label="Target Video")], |
|
outputs=gr.Video(label="Swapped Output Video"), |
|
title="Face Swap API", |
|
description="Upload a face photo and a video. Returns a face-swapped MP4." |
|
) |
|
|
|
if __name__ == "__main__": |
|
demo.launch() |
|
|