Deepfake Authenticator commited on
Commit Β·
7f580a0
1
Parent(s): 03f204c
fix: AV_MISMATCH shows as DEEPFAKE (red) not yellow warning
Browse files- Frontend: AV_MISMATCH uses same red color + gpp_bad icon as AI_VOICE
- Verdict label shows 'DEEPFAKE (AV MISMATCH)'
- Backend: AV_MISMATCH overrides visual REAL verdict to FAKE
- Both AI_VOICE and AV_MISMATCH count as audio_fake in final decision
- backend/detector.py +8 -5
- frontend-vanilla/index.html +7 -6
backend/detector.py
CHANGED
|
@@ -446,22 +446,25 @@ class ReportGeneratorAgent:
|
|
| 446 |
audio_prob = 0.0
|
| 447 |
if audio and audio.get("available"):
|
| 448 |
audio_prob = audio.get("fake_probability", 0.0)
|
| 449 |
-
|
|
|
|
| 450 |
|
| 451 |
# Final verdict: visual is primary, audio can upgrade OR downgrade
|
| 452 |
if audio and audio.get("available"):
|
| 453 |
-
# Both agree β high confidence
|
| 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 |
-
# Disagreement β visual wins but audio nudges the score
|
| 459 |
elif visual_fake and not audio_fake:
|
| 460 |
# Audio says real β only keep FAKE if visual is strong
|
| 461 |
is_fake = prob >= (threshold + 0.05)
|
| 462 |
else:
|
| 463 |
-
# Visual says real but audio says AI
|
| 464 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 465 |
else:
|
| 466 |
is_fake = visual_fake
|
| 467 |
|
|
|
|
| 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 |
|
frontend-vanilla/index.html
CHANGED
|
@@ -1219,14 +1219,15 @@ function renderTimeline(frames) {
|
|
| 1219 |
function renderAudio(audio) {
|
| 1220 |
const isAI = audio.result === 'AI_VOICE';
|
| 1221 |
const isMismatch = audio.result === 'AV_MISMATCH';
|
| 1222 |
-
const
|
|
|
|
| 1223 |
|
| 1224 |
const icon = document.getElementById('audioIcon');
|
| 1225 |
-
icon.textContent =
|
| 1226 |
icon.style.color = color;
|
| 1227 |
|
| 1228 |
const verdict = document.getElementById('audioVerdict');
|
| 1229 |
-
verdict.textContent = isMismatch ? '
|
| 1230 |
verdict.style.color = color;
|
| 1231 |
|
| 1232 |
document.getElementById('audioConfidence').textContent =
|
|
@@ -1247,9 +1248,9 @@ function renderAudio(audio) {
|
|
| 1247 |
if (audio.details && audio.details.length) {
|
| 1248 |
detailsEl.innerHTML = audio.details.map(d => `
|
| 1249 |
<div class="flex items-start gap-3 p-3 bg-surface-container-low/50 border border-outline-variant/30 rounded-DEFAULT"
|
| 1250 |
-
style="${
|
| 1251 |
-
<span class="material-symbols-outlined text-[16px] mt-0.5" style="color:${color};">
|
| 1252 |
-
<span class="font-data-mono text-data-mono text-sm" style="color:
|
| 1253 |
</div>`).join('');
|
| 1254 |
} else {
|
| 1255 |
detailsEl.innerHTML = '';
|
|
|
|
| 1219 |
function renderAudio(audio) {
|
| 1220 |
const isAI = audio.result === 'AI_VOICE';
|
| 1221 |
const isMismatch = audio.result === 'AV_MISMATCH';
|
| 1222 |
+
const isFakeAudio = isAI || isMismatch; // both mean FAKE
|
| 1223 |
+
const color = isFakeAudio ? '#ffb4ab' : '#00ff9c';
|
| 1224 |
|
| 1225 |
const icon = document.getElementById('audioIcon');
|
| 1226 |
+
icon.textContent = isFakeAudio ? 'gpp_bad' : 'record_voice_over';
|
| 1227 |
icon.style.color = color;
|
| 1228 |
|
| 1229 |
const verdict = document.getElementById('audioVerdict');
|
| 1230 |
+
verdict.textContent = isMismatch ? 'DEEPFAKE (AV MISMATCH)' : (isAI ? 'AI_VOICE' : 'HUMAN_VOICE');
|
| 1231 |
verdict.style.color = color;
|
| 1232 |
|
| 1233 |
document.getElementById('audioConfidence').textContent =
|
|
|
|
| 1248 |
if (audio.details && audio.details.length) {
|
| 1249 |
detailsEl.innerHTML = audio.details.map(d => `
|
| 1250 |
<div class="flex items-start gap-3 p-3 bg-surface-container-low/50 border border-outline-variant/30 rounded-DEFAULT"
|
| 1251 |
+
style="${isFakeAudio ? 'border-color:rgba(255,180,171,0.3);background:rgba(255,180,171,0.04);' : ''}">
|
| 1252 |
+
<span class="material-symbols-outlined text-[16px] mt-0.5" style="color:${color};">chevron_right</span>
|
| 1253 |
+
<span class="font-data-mono text-data-mono text-sm" style="color:#b9cbbc;">${escHtml(d)}</span>
|
| 1254 |
</div>`).join('');
|
| 1255 |
} else {
|
| 1256 |
detailsEl.innerHTML = '';
|