File size: 5,420 Bytes
99c30b7
342ea4d
 
 
9358900
56225c5
bd55878
 
 
9c93e59
 
 
 
9358900
342ea4d
bd55878
 
 
 
 
 
 
9358900
bd55878
 
 
 
 
 
 
9358900
342ea4d
 
 
 
 
9358900
 
 
bd55878
342ea4d
9358900
 
 
342ea4d
 
bd55878
 
 
 
 
 
9358900
342ea4d
9358900
342ea4d
 
 
 
 
9358900
 
 
342ea4d
9358900
 
 
342ea4d
 
bd55878
 
 
 
 
 
 
9358900
bd55878
56225c5
 
 
 
 
bd55878
56225c5
342ea4d
bd55878
342ea4d
 
 
bd55878
342ea4d
 
 
 
 
 
56225c5
9c93e59
 
342ea4d
 
 
 
 
 
 
 
9358900
 
 
 
 
342ea4d
9358900
 
 
342ea4d
bd55878
342ea4d
 
 
 
 
 
 
 
 
 
 
 
 
56225c5
bd55878
 
 
 
342ea4d
56225c5
 
342ea4d
 
 
bd55878
 
 
99c30b7
9c93e59
 
 
 
 
 
99c30b7
342ea4d
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
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
import gradio as gr
from detector.face import verify_faces, analyze_face
from detector.voice import verify_voices
from detector.video import verify_faces_in_video
from reports.pdf_report import generate_pdf_report
from utils.youtube_utils import download_youtube_video
import modal
verify_faces_remote = modal.Function.lookup("deepface-agent", "verify_faces_remote")


# Holds latest results
last_face_result = None
last_voice_result = None
last_video_results = None

# @app.local_entrypoint()
def compare_faces(img1_path: str, img2_path: str) -> str:
    """Use this tool to compare to faces for a match
    Args:
        img1_path: The path to the first image
        img2_path: The path to the second image
    """
    global last_face_result
    
    # Read image files as bytes
    with open(img1_path, "rb") as f1, open(img2_path, "rb") as f2:
        img1_bytes = f1.read()
        img2_bytes = f2.read()
        
    result = verify_faces_remote.remote(img1_bytes, img2_bytes)
    result_text = ""

    if "error" in result:
        return f"โŒ Error: {result['error']}"

    if result["verified"]:
        result_text = f"โœ… Match! Distance: {result['distance']:.4f} (Threshold: {result['threshold']})"
        last_face_result = result_text
        return result_text

    else:
        result_text = f"โŒ No Match. Distance: {result['distance']:.4f} (Threshold: {result['threshold']})"
        last_face_result = result_text
        return result_text


def compare_voices(audio1: str, audio2: str) -> str:
    """Use this tool to compare two voices for a match
    Args:
        audio1: The path to the first audio file
        audio2: The path to the second audio file
    """
    global last_voice_result
    result = verify_voices(audio1, audio2)
    result_text = ""

    if "error" in result:
        return f"โŒ Error: {result['error']}"

    if result["match"]:
        result_text = f"โœ… Same speaker detected. Similarity: {result['similarity']} (Threshold: {result['threshold']})"
        last_voice_result = result_text
        return result_text
    else:
        result_text = f"โŒ Different speakers. Similarity: {result['similarity']} (Threshold: {result['threshold']})"
        last_voice_result = result_text
        return result_text


def scan_video(video_file: str, ref_img: str, youtube_url="") -> str:
    """Use this tool to scan a video for deepfake face swaps
    Args:
        video_file: The path to the video file
        ref_img: The path to the reference image
        youtube_url: The YouTube URL (optional)
    """
    global last_video_results

    if youtube_url:
        try:
            video_file = download_youtube_video(youtube_url)
        except Exception as e:
            return f"โŒ Error downloading YouTube video: {str(e)}"

    results = verify_faces_in_video(video_file, ref_img)
    report = ""
    last_video_results = results
    for r in results:
        if "error" in r:
            report += f"\nโš ๏ธ Frame {r['frame']}: {r['error']}"

        else:
            status = "โœ… Match" if r["verified"] else "โŒ Mismatch"
            report += f"\n๐Ÿ–ผ Frame {r['frame']}: {status} (Distance: {r['distance']})"

    return report


def generate_report():
    return generate_pdf_report(last_face_result, last_voice_result, last_video_results)


with gr.Blocks(title="Deepfake Watchdog") as demo:
    gr.Markdown("# ๐Ÿ›ก๏ธDeepfake Watchdog ๐Ÿค—")
    gr.Markdown("## Upload your image and/or voice to scan for deepfake misuse online.")

    # Face Verification
    with gr.Tab("Face Verification"):
        image1 = gr.Image(label="Upload your face", type="filepath")
        # audio = gr.Audio(label="Upload your voice (optional)", type="filepath")
        image2 = gr.Image(label="Upload another face", type="filepath")

        # face_btn = gr.Button("Compare Faces")

        run_button = gr.Button("Compare Faces")
        output_text = gr.Textbox(label="Result")
        # output_gallery = gr.Gallery(label="Matched Results")

        run_button.click(compare_faces, inputs=[image1, image2], outputs=[output_text])

    # Voice Verification
    with gr.Tab("๐ŸŽค Voice Verification"):
        gr.Markdown("Upload two audio files to check if the voices match.")

        audio1 = gr.Audio(type="filepath", label="Voice Sample 1")
        audio2 = gr.Audio(type="filepath", label="Voice Sample 2")

        voice_btn = gr.Button("Compare Voices")
        voice_output = gr.Textbox(label="Result")

        voice_btn.click(compare_voices, inputs=[audio1, audio2], outputs=voice_output)

    with gr.Tab("๐Ÿ“น Video Deepfake Scan"):
        gr.Markdown(
            "๐Ÿ” Upload a video or paste a YouTube link and we'll analyze it for deepfake face swaps."
        )

        ref_img = gr.Image(type="filepath", label="Reference Face")
        video_input = gr.Video(label="Video File (optional)")
        youtube_url = gr.Textbox(label="YouTube URL (optional)")
        scan_btn = gr.Button("Scan Video")
        scan_output = gr.Textbox(label="Scan Results", lines=10)

        scan_btn.click(
            scan_video, inputs=[video_input, ref_img, youtube_url], outputs=scan_output
        )

    with gr.Tab("๐Ÿ“„ Generate Report"):
        report_btn = gr.Button("Generate PDF Report")
        report_output = gr.File(label="Download Report")

        report_btn.click(generate_report, outputs=report_output)


demo.launch(mcp_server=True)