Deepfake Authenticator commited on
Commit Β·
bd97ad3
1
Parent(s): cede9a4
fix: AV_MISMATCH hard override always sets verdict to FAKE
Browse files- AV_MISMATCH now bypasses visual threshold entirely
- Confidence boosted to min 72% when AV_MISMATCH fires
- Lowered mismatch trigger: visual >= 0.45 AND audio < 0.55
- Cleaned up broken if/elif syntax in verdict block
- backend/audio_detector.py +2 -3
- backend/detector.py +11 -12
backend/audio_detector.py
CHANGED
|
@@ -340,11 +340,10 @@ class AudioReportAgent:
|
|
| 340 |
# If visual says FAKE (high prob) but audio says HUMAN β mismatch
|
| 341 |
av_mismatch = False
|
| 342 |
av_mismatch_score = 0.0
|
| 343 |
-
if visual_fake_prob >= 0.
|
| 344 |
-
# Visual
|
| 345 |
av_mismatch = True
|
| 346 |
av_mismatch_score = visual_fake_prob * 0.6
|
| 347 |
-
# Boost audio fake probability to reflect the mismatch
|
| 348 |
combined = max(combined, av_mismatch_score)
|
| 349 |
logger.info(
|
| 350 |
f"Audio-visual mismatch detected: visual_fake={visual_fake_prob:.2f} "
|
|
|
|
| 340 |
# If visual says FAKE (high prob) but audio says HUMAN β mismatch
|
| 341 |
av_mismatch = False
|
| 342 |
av_mismatch_score = 0.0
|
| 343 |
+
if visual_fake_prob >= 0.45 and model_prob < 0.55:
|
| 344 |
+
# Visual shows manipulation signs, audio sounds human β face-swap
|
| 345 |
av_mismatch = True
|
| 346 |
av_mismatch_score = visual_fake_prob * 0.6
|
|
|
|
| 347 |
combined = max(combined, av_mismatch_score)
|
| 348 |
logger.info(
|
| 349 |
f"Audio-visual mismatch detected: visual_fake={visual_fake_prob:.2f} "
|
backend/detector.py
CHANGED
|
@@ -446,29 +446,28 @@ class ReportGeneratorAgent:
|
|
| 446 |
audio_prob = 0.0
|
| 447 |
if audio and audio.get("available"):
|
| 448 |
audio_prob = audio.get("fake_probability", 0.0)
|
| 449 |
-
# AV_MISMATCH counts as fake β face-swap with dubbed audio
|
| 450 |
audio_fake = audio.get("result") in ("AI_VOICE", "AV_MISMATCH")
|
| 451 |
|
| 452 |
-
#
|
| 453 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 454 |
if visual_fake and audio_fake:
|
| 455 |
is_fake = True
|
| 456 |
elif not visual_fake and not audio_fake:
|
| 457 |
is_fake = False
|
| 458 |
elif visual_fake and not audio_fake:
|
| 459 |
-
# Audio says real β only keep FAKE if visual is strong
|
| 460 |
is_fake = prob >= (threshold + 0.05)
|
| 461 |
else:
|
| 462 |
-
|
| 463 |
-
|
| 464 |
-
if audio.get("result") == "AV_MISMATCH":
|
| 465 |
-
is_fake = True # face-swap confirmed by mismatch
|
| 466 |
-
else:
|
| 467 |
-
is_fake = audio_prob >= 0.75
|
| 468 |
else:
|
| 469 |
-
is_fake
|
|
|
|
| 470 |
|
| 471 |
-
calibrated = self._calibrate(prob)
|
| 472 |
confidence = round(calibrated * 100, 1)
|
| 473 |
result = "FAKE" if is_fake else "REAL"
|
| 474 |
|
|
|
|
| 446 |
audio_prob = 0.0
|
| 447 |
if audio and audio.get("available"):
|
| 448 |
audio_prob = audio.get("fake_probability", 0.0)
|
|
|
|
| 449 |
audio_fake = audio.get("result") in ("AI_VOICE", "AV_MISMATCH")
|
| 450 |
|
| 451 |
+
# ββ Determine final verdict βββββββββββββββββββββββββββββββββββ
|
| 452 |
+
# AV_MISMATCH is a hard override β face-swap confirmed
|
| 453 |
+
if audio and audio.get("result") == "AV_MISMATCH":
|
| 454 |
+
is_fake = True
|
| 455 |
+
calibrated = self._calibrate(max(prob, 0.72))
|
| 456 |
+
logger.info("AV_MISMATCH hard override β FAKE")
|
| 457 |
+
elif audio and audio.get("available"):
|
| 458 |
if visual_fake and audio_fake:
|
| 459 |
is_fake = True
|
| 460 |
elif not visual_fake and not audio_fake:
|
| 461 |
is_fake = False
|
| 462 |
elif visual_fake and not audio_fake:
|
|
|
|
| 463 |
is_fake = prob >= (threshold + 0.05)
|
| 464 |
else:
|
| 465 |
+
is_fake = audio_prob >= 0.75
|
| 466 |
+
calibrated = self._calibrate(prob)
|
|
|
|
|
|
|
|
|
|
|
|
|
| 467 |
else:
|
| 468 |
+
is_fake = visual_fake
|
| 469 |
+
calibrated = self._calibrate(prob)
|
| 470 |
|
|
|
|
| 471 |
confidence = round(calibrated * 100, 1)
|
| 472 |
result = "FAKE" if is_fake else "REAL"
|
| 473 |
|