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

Files changed (2) hide show
  1. backend/audio_detector.py +2 -3
  2. 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.55 and model_prob < 0.50:
344
- # Visual strongly fake, audio sounds human β†’ classic face-swap
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
- # Final verdict: visual is primary, audio can upgrade OR downgrade
453
- if audio and audio.get("available"):
 
 
 
 
 
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
- # Visual says real but audio says AI/mismatch
463
- # AV_MISMATCH is a very strong signal β€” override visual
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 = visual_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