11import os
2+ from typing import List , Optional
23
34import httpx
45from fastapi import HTTPException , UploadFile
56
67OPENFAKE_API_URL = os .getenv (
78 "OPENFAKE_API_URL" ,
8- "https://complexdatalab-openfakedemo.hf.space /api/predict" ,
9+ "https://deepfake-detector.ai4.institute /api/predict" ,
910)
1011
1112ALLOWED_TYPES = {
2021}
2122
2223
24+ def _as_float (value : object , default : float = 0.0 ) -> float :
25+ try :
26+ return float (value )
27+ except (TypeError , ValueError ):
28+ return default
29+
30+
31+ def _verdict_from_score (p_fake : float ) -> str :
32+ if p_fake >= 0.75 :
33+ return "Likely fake"
34+ if p_fake >= 0.45 :
35+ return "Uncertain"
36+ return "Likely real"
37+
38+
39+ def _frame_probs_from_frames (frames : object ) -> Optional [List [float ]]:
40+ if not isinstance (frames , list ):
41+ return None
42+
43+ frame_probs = []
44+ for frame in frames :
45+ if isinstance (frame , dict ) and "p_fake" in frame :
46+ frame_probs .append (_as_float (frame .get ("p_fake" )))
47+
48+ return frame_probs or None
49+
50+
2351async def verify_media_with_openfake (file : UploadFile ) -> dict :
2452 if file .content_type not in ALLOWED_TYPES :
2553 raise HTTPException (
@@ -29,7 +57,6 @@ async def verify_media_with_openfake(file: UploadFile) -> dict:
2957
3058 await file .seek (0 )
3159
32- # This forwards the uploaded file object to OpenFake
3360 files = {
3461 "file" : (
3562 file .filename ,
@@ -45,30 +72,38 @@ async def verify_media_with_openfake(file: UploadFile) -> dict:
4572 )
4673
4774 if response .status_code != 200 :
75+ detail = "OpenFake detector failed"
76+ try :
77+ error_data = response .json ()
78+ detail = error_data .get ("detail" ) or error_data .get ("error" ) or detail
79+ except ValueError :
80+ pass
81+
4882 raise HTTPException (
4983 status_code = 502 ,
50- detail = "OpenFake detector failed" ,
84+ detail = detail ,
5185 )
5286
5387 data = response .json ()
5488
55- p_fake = float (data .get ("p_fake" , 0 ))
56- reliability = float (data .get ("reliability" , 1 - p_fake ))
57-
58- if p_fake >= 0.75 :
59- verdict = "Likely fake"
60- elif p_fake >= 0.45 :
61- verdict = "Uncertain"
62- else :
63- verdict = "Likely real"
89+ p_fake = _as_float (data .get ("p_fake" ))
90+ reliability = _as_float (data .get ("reliability" ), 1 - p_fake )
91+ frame_probs = data .get ("frame_probs" ) or _frame_probs_from_frames (data .get ("frames" ))
6492
6593 return {
6694 "media_type" : data .get ("media_type" ),
6795 "p_fake" : p_fake ,
96+ "p_real" : data .get ("p_real" ),
97+ "p_localized" : data .get ("p_localized" ),
98+ "p_full_synthetic" : data .get ("p_full_synthetic" ),
99+ "p_fake_max" : data .get ("p_fake_max" ),
100+ "generators" : data .get ("generators" , []),
68101 "reliability" : reliability ,
69102 "reliability_score" : round (reliability * 100 ),
70- "verdict" : verdict ,
103+ "verdict" : _verdict_from_score ( p_fake ) ,
71104 "n_frames" : data .get ("n_frames" ),
72- "frame_probs" : data .get ("frame_probs" ),
73- "explanation" : (f"The detector estimates a { round (p_fake * 100 )} % probability " f"that this media is fake." ),
105+ "frame_probs" : frame_probs ,
106+ "frames" : data .get ("frames" ),
107+ "mask" : data .get ("mask" ),
108+ "explanation" : (f"The detector estimates a { round (p_fake * 100 )} % probability that this media is fake." ),
74109 }
0 commit comments