File size: 3,380 Bytes
0a7d313
b098d52
9f28bcd
 
ad62ac1
6fa4ded
f3a76a1
b098d52
d5144c2
0a14ee3
 
 
0a7d313
 
 
d5144c2
 
0a7d313
0a4e356
495a7a7
f3a76a1
ad62ac1
495a7a7
f00c22f
 
0a14ee3
 
f00c22f
0a14ee3
f00c22f
0a14ee3
 
 
 
495a7a7
 
f00c22f
495a7a7
9f28bcd
495a7a7
 
 
 
f00c22f
495a7a7
 
 
 
f00c22f
6fa4ded
 
 
 
f00c22f
0a14ee3
f00c22f
 
495a7a7
6fa4ded
 
 
f00c22f
495a7a7
 
 
f00c22f
6fa4ded
f00c22f
6fa4ded
 
f00c22f
f3a76a1
 
 
 
0a4e356
f3a76a1
495a7a7
 
f00c22f
9f28bcd
495a7a7
ae78b79
9f28bcd
d5144c2
495a7a7
 
 
 
 
 
 
b0cfea0
 
495a7a7
 
b098d52
 
5638557
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
import os
import gradio as gr
import cv2
import numpy as np
from insightface.app import FaceAnalysis
import tempfile
from moviepy.editor import VideoFileClip

# Désactiver les avertissements d'Albumentations
os.environ["NO_ALBUMENTATIONS_UPDATE"] = "1"

# Rediriger les chemins problématiques
os.environ['MPLCONFIGDIR'] = '/tmp/matplotlib'
os.environ['FONTCONFIG_PATH'] = '/tmp/fontconfig'

os.makedirs('/tmp/matplotlib', exist_ok=True)
os.makedirs('/tmp/fontconfig', exist_ok=True)

# Forcer InsightFace à utiliser un répertoire accessible
os.environ['INSIGHTFACE_ROOT'] = '/tmp/.insightface'
os.environ["ORT_DISABLE_CUDA"] = "1"  # Désactiver CUDA si GPU indisponible

def swap_face(source_face, target_face, frame):
    src_emb = source_face.normed_embedding
    tgt_bbox = target_face.bbox.astype(int)
    resized_face = cv2.resize(source_face.img, (tgt_bbox[2] - tgt_bbox[0], tgt_bbox[3] - tgt_bbox[1]))

    mask = np.zeros_like(resized_face)
    center = (mask.shape[1] // 2, mask.shape[0] // 2)
    radius = int(min(mask.shape) * 0.45)
    cv2.circle(mask, center, radius, (255, 255, 255), -1)
    mask = cv2.GaussianBlur(mask, (15, 15), 5)

    center = ((tgt_bbox[0] + tgt_bbox[2]) // 2, (tgt_bbox[1] + tgt_bbox[3]) // 2)
    result = cv2.seamlessClone(resized_face, frame, mask, center, cv2.NORMAL_CLONE)
    return result

def process_video(source_img, target_video):
    try:
        face_app = FaceAnalysis(name="buffalo_l", root="/tmp/.insightface")
        face_app.prepare(ctx_id=0, det_size=(640, 640))

        source_faces = face_app.get(source_img)
        if not source_faces:
            raise ValueError("Aucun visage trouvé dans l'image source.")
        source_face = source_faces[0]

        temp_output = tempfile.NamedTemporaryFile(suffix=".mp4", delete=False)

        cap = cv2.VideoCapture(target_video)
        fps = cap.get(cv2.CAP_PROP_FPS)
        frame_width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
        frame_height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))

        fourcc = cv2.VideoWriter_fourcc(*'avc1')  # Codec compatible H.264
        out = cv2.VideoWriter(temp_output.name, fourcc, fps, (frame_width, frame_height))

        while True:
            ret, frame = cap.read()
            if not ret:
                break

            target_faces = face_app.get(frame)
            for face in target_faces:
                frame = swap_face(source_face, face, frame)

            out.write(frame)

        cap.release()
        out.release()

        print(f"Taille de la vidéo temporaire : {os.path.getsize(temp_output.name)} octets")

        # Réencodage final pour compatibilité Gradio
        clip = VideoFileClip(temp_output.name)
        final_path = tempfile.mktemp(suffix=".mp4")
        clip.write_videofile(final_path, codec="libx264", audio_codec="aac", verbose=False, logger=None)

        return final_path

    except Exception as e:
        print(f"Erreur lors du traitement : {str(e)}")
        return None

# Interface Gradio
demo = gr.Interface(
    fn=process_video,
    inputs=[
        gr.Image(label="Visage Source", type="numpy"),
        gr.Video(label="Vidéo Cible"),
    ],
    outputs=gr.Video(label="Vidéo Résultat"),
    title="🎬 FaceSwap Pro",
    description="Échangez des visages dans une vidéo.",
    allow_flagging="never"
)

if __name__ == "__main__":
    demo.launch(share=True)