| | <!DOCTYPE html> |
| | <html lang="en"> |
| | <head> |
| | <meta charset="UTF-8"> |
| | <meta name="viewport" content="width=device-width, initial-scale=1.0"> |
| | <title>DeepTrust - Deepfake Detection</title> |
| | <script src="https://cdn.tailwindcss.com"></script> |
| | <link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css" rel="stylesheet"> |
| | <style> |
| | @import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap'); |
| | body { font-family: 'Inter', sans-serif; overflow-x: hidden; } |
| | .bg-dark { background: linear-gradient(135deg, #0a0a0f 0%, #111827 100%); } |
| | .upload-area { |
| | transition: border-color 0.2s ease; |
| | border: 2px dashed #4b5563; |
| | } |
| | .upload-area:focus-within, |
| | .upload-area.dragover { |
| | border-color: #3b82f6; |
| | background: rgba(59, 130, 246, 0.05); |
| | } |
| | .result-card { background: rgba(17, 24, 39, 0.95); backdrop-filter: blur(10px); } |
| | .progress-bar { transition: width 0.3s ease; } |
| | .tab-btn { transition: all 0.2s ease; } |
| | .tab-btn.active { background: #2563eb; color: white; } |
| | main { min-height: calc(100vh - 200px); } |
| | </style> |
| | </head> |
| | <body class="bg-dark text-white min-h-screen"> |
| |
|
| | |
| | <header class="p-6 border-b border-gray-800"> |
| | <nav class="max-w-6xl mx-auto flex justify-between items-center"> |
| | <div class="flex items-center space-x-3"> |
| | <i class="fas fa-shield-halved text-xl text-blue-500"></i> |
| | <h1 class="text-xl font-semibold">DeepTrust</h1> |
| | <span class="text-xs bg-blue-900/50 px-2 py-0.5 rounded text-blue-200 font-medium">Forensics AI</span> |
| | </div> |
| | <div class="hidden md:flex space-x-6 text-sm text-gray-400"> |
| | <a href="#" class="hover:text-white transition-colors">Documentation</a> |
| | <a href="#" class="hover:text-white transition-colors">API</a> |
| | </div> |
| | </nav> |
| | </header> |
| |
|
| | |
| | <main class="max-w-4xl mx-auto px-4 py-12 pb-24 flex-grow"> |
| | <div class="text-center mb-12"> |
| | <h2 class="text-3xl md:text-4xl font-bold mb-4 text-gray-100">Deepfake Detection</h2> |
| | <p class="text-lg text-gray-400 max-w-2xl mx-auto"> |
| | Forensic analysis of images, videos, text, and documents using advanced AI models. |
| | </p> |
| | </div> |
| |
|
| | |
| | <div class="flex gap-2 mb-8 p-1 bg-gray-900/50 rounded-xl border border-gray-800"> |
| | <button onclick="switchTab('media')" id="tab-media" class="tab-btn active flex-1 py-3 px-4 rounded-lg text-sm font-medium"> |
| | <i class="fas fa-photo-film mr-2"></i>Image / Video |
| | </button> |
| | <button onclick="switchTab('text')" id="tab-text" class="tab-btn flex-1 py-3 px-4 rounded-lg text-sm font-medium text-gray-400"> |
| | <i class="fas fa-align-left mr-2"></i>Text |
| | </button> |
| | <button onclick="switchTab('pdf')" id="tab-pdf" class="tab-btn flex-1 py-3 px-4 rounded-lg text-sm font-medium text-gray-400"> |
| | <i class="fas fa-file-pdf mr-2"></i>PDF / Document |
| | </button> |
| | </div> |
| |
|
| | |
| | <div id="panel-media"> |
| | <div id="uploadSection" class="result-card rounded-2xl p-8 md:p-12 mb-12 shadow-xl"> |
| | <div id="uploadArea" class="upload-area rounded-xl p-12 text-center cursor-pointer mb-8 hover:border-gray-400 transition-colors" |
| | onclick="document.getElementById('fileInput').click()"> |
| | <i class="fas fa-cloud-arrow-up text-4xl text-gray-500 mb-6"></i> |
| | <h3 class="text-xl font-semibold mb-3 text-gray-200">Drop file here or click to browse</h3> |
| | <p class="text-gray-500 mb-8">Supports JPG, PNG, MP4 (max 50MB)</p> |
| | <div class="flex justify-center space-x-6 text-sm text-gray-500"> |
| | <span><i class="fas fa-image mr-1"></i> Image</span> |
| | <span><i class="fas fa-video mr-1"></i> Video</span> |
| | </div> |
| | </div> |
| | <input type="file" id="fileInput" accept="image/*,video/*" class="hidden"> |
| |
|
| | <div id="previewSection" class="hidden mb-8 p-6 bg-gray-900/50 rounded-xl"> |
| | <div class="flex flex-col lg:flex-row gap-6 items-start"> |
| | <img id="previewImg" class="hidden flex-1 max-h-80 object-contain rounded-lg shadow-md mx-auto lg:mx-0" alt="Preview"> |
| | <video id="previewVideo" class="hidden flex-1 max-h-80 rounded-lg shadow-md mx-auto lg:mx-0" controls muted></video> |
| | <div id="fileInfo" class="flex-1 min-w-0"></div> |
| | </div> |
| | </div> |
| |
|
| | <button id="analyzeBtn" class="hidden w-full bg-blue-600 hover:bg-blue-700 text-white font-medium py-4 px-8 rounded-xl text-lg transition-colors"> |
| | <i class="fas fa-magnifying-glass mr-2"></i>Analyze for Deepfakes |
| | </button> |
| | </div> |
| | </div> |
| |
|
| | |
| | <div id="panel-text" class="hidden"> |
| | <div class="result-card rounded-2xl p-8 md:p-12 mb-12 shadow-xl"> |
| | <h3 class="text-lg font-semibold text-gray-200 mb-2">Paste Text to Analyze</h3> |
| | <p class="text-gray-500 text-sm mb-6">Works for news articles, social media posts, government notices, or any written content.</p> |
| | <textarea id="textInput" rows="10" |
| | class="w-full bg-gray-900 border border-gray-700 rounded-xl p-4 text-gray-200 text-sm resize-none focus:outline-none focus:border-blue-500 transition-colors" |
| | placeholder="Paste your text here... (news article, government document, social media post, etc.)"></textarea> |
| | <div class="flex justify-between items-center mt-3 mb-6"> |
| | <span id="charCount" class="text-xs text-gray-500">0 characters</span> |
| | <span class="text-xs text-gray-500">Max 4000 characters analyzed</span> |
| | </div> |
| | <button id="analyzeTextBtn" class="w-full bg-blue-600 hover:bg-blue-700 text-white font-medium py-4 px-8 rounded-xl text-lg transition-colors disabled:opacity-50 disabled:cursor-not-allowed"> |
| | <i class="fas fa-magnifying-glass mr-2"></i>Analyze Text |
| | </button> |
| | </div> |
| | </div> |
| |
|
| | |
| | <div id="panel-pdf" class="hidden"> |
| | <div class="result-card rounded-2xl p-8 md:p-12 mb-12 shadow-xl"> |
| | <div id="pdfUploadArea" class="upload-area rounded-xl p-12 text-center cursor-pointer mb-8 hover:border-gray-400 transition-colors" |
| | onclick="document.getElementById('pdfInput').click()"> |
| | <i class="fas fa-file-pdf text-4xl text-red-400 mb-6"></i> |
| | <h3 class="text-xl font-semibold mb-3 text-gray-200">Upload PDF Document</h3> |
| | <p class="text-gray-500 mb-4">Government docs, news articles, official notices (max 50MB)</p> |
| | <p class="text-xs text-yellow-400"><i class="fas fa-clock mr-1"></i>PDF analysis takes ~30-60s (text + images analyzed)</p> |
| | </div> |
| | <input type="file" id="pdfInput" accept=".pdf,application/pdf" class="hidden"> |
| |
|
| | <div id="pdfPreview" class="hidden mb-8 p-4 bg-gray-900/50 rounded-xl border border-gray-700"> |
| | <div class="flex items-center gap-3"> |
| | <i class="fas fa-file-pdf text-red-400 text-2xl"></i> |
| | <div> |
| | <p id="pdfFileName" class="text-gray-200 font-medium text-sm"></p> |
| | <p id="pdfFileSize" class="text-gray-500 text-xs"></p> |
| | </div> |
| | </div> |
| | </div> |
| |
|
| | <button id="analyzePdfBtn" class="hidden w-full bg-blue-600 hover:bg-blue-700 text-white font-medium py-4 px-8 rounded-xl text-lg transition-colors"> |
| | <i class="fas fa-magnifying-glass mr-2"></i>Analyze Document |
| | </button> |
| | </div> |
| | </div> |
| |
|
| | |
| | <div id="progressSection" class="hidden result-card rounded-2xl p-12 mb-12"> |
| | <div class="text-center mb-8"> |
| | <div class="w-12 h-12 border-4 border-blue-500/20 border-t-blue-500 rounded-full animate-spin mx-auto mb-6"></div> |
| | <p class="text-2xl font-semibold text-gray-100">Analyzing</p> |
| | <p id="progressLabel" class="text-gray-500 mt-2 text-sm"></p> |
| | </div> |
| | <div class="w-full bg-gray-800 rounded-lg h-2.5 overflow-hidden"> |
| | <div id="progressBar" class="progress-bar bg-blue-600 h-2.5 w-0"></div> |
| | </div> |
| | <p id="progressText" class="text-center text-sm text-gray-500 mt-3">0%</p> |
| | </div> |
| |
|
| | |
| | <div id="resultsSection" class="hidden"> |
| | <div class="result-card rounded-2xl p-8 md:p-12"> |
| |
|
| | |
| | <div class="flex items-start mb-6"> |
| | <div id="resultIcon" class="w-12 h-12 rounded-lg flex items-center justify-center text-xl mr-4 flex-shrink-0 mt-1"></div> |
| | <div> |
| | <h3 id="resultTitle" class="text-2xl font-bold text-gray-100"></h3> |
| | <p id="resultSubtitle" class="text-gray-400 mt-1"></p> |
| | </div> |
| | </div> |
| |
|
| | |
| | <div id="confidenceWarning" class="hidden mb-6 p-4 rounded-xl border text-sm font-medium"></div> |
| |
|
| | |
| | <div class="grid grid-cols-2 gap-4 mb-10"> |
| | <div class="text-center p-5 bg-gray-900/50 rounded-xl border border-gray-700"> |
| | <div id="scoreReal" class="text-3xl font-bold text-green-400 mb-1"></div> |
| | <p class="text-gray-500 text-sm">Authentic</p> |
| | </div> |
| | <div class="text-center p-5 bg-gray-900/50 rounded-xl border border-gray-700"> |
| | <div id="scoreFake" class="text-3xl font-bold text-red-400 mb-1"></div> |
| | <p class="text-gray-500 text-sm">Fabricated</p> |
| | </div> |
| | </div> |
| |
|
| | |
| | <div class="mb-10"> |
| | <h4 class="text-sm font-semibold text-gray-400 uppercase tracking-wider mb-4">Model Breakdown</h4> |
| | <div id="modelBreakdown" class="space-y-4"></div> |
| | </div> |
| |
|
| | |
| | <div id="groqReasoningSection" class="hidden mb-10"> |
| | <h4 class="text-sm font-semibold text-gray-400 uppercase tracking-wider mb-4">AI Reasoning</h4> |
| | <div id="groqReasoning" class="p-4 bg-gray-900/50 rounded-xl border border-gray-700 text-sm text-gray-300 leading-relaxed"></div> |
| | </div> |
| |
|
| | |
| | <div class="p-5 bg-gray-900/50 rounded-xl border border-gray-700 mb-10 text-sm text-gray-400 space-y-2"> |
| | <h4 class="text-sm font-semibold text-gray-400 uppercase tracking-wider mb-3">Forensic Details</h4> |
| | <p><span class="text-gray-500">SHA256:</span> <span id="hashValue" class="font-mono text-xs break-all"></span></p> |
| | <p id="metadataRiskRow"><span class="text-gray-500">Metadata Risk:</span> <span id="metadataRisk"></span></p> |
| | <p id="framesRow" class="hidden"><span class="text-gray-500">Frames Analyzed:</span> <span id="framesAnalyzed"></span></p> |
| | <p id="durationRow" class="hidden"><span class="text-gray-500">Video Duration:</span> <span id="videoDuration"></span></p> |
| | <p><span class="text-gray-500">Models Used:</span> <span id="modelsUsed"></span></p> |
| | </div> |
| |
|
| | <div class="flex flex-col sm:flex-row gap-4"> |
| | <button onclick="resetUI()" class="flex-1 bg-gray-700 hover:bg-gray-600 text-white font-medium py-3 px-6 rounded-xl border border-gray-600 transition-colors"> |
| | <i class="fas fa-redo mr-2"></i> Analyze Another |
| | </button> |
| | </div> |
| | </div> |
| | </div> |
| | </main> |
| |
|
| | <footer class="border-t border-gray-800 p-8 text-center text-xs text-gray-500 bg-gray-900/50"> |
| | DeepTrust Forensics | Advanced AI Detection | 2026 |
| | </footer> |
| |
|
| | <script> |
| | |
| | let currentTab = 'media'; |
| | |
| | function switchTab(tab) { |
| | ['media', 'text', 'pdf'].forEach(t => { |
| | document.getElementById(`panel-${t}`).classList.add('hidden'); |
| | const btn = document.getElementById(`tab-${t}`); |
| | btn.classList.remove('active'); |
| | btn.classList.add('text-gray-400'); |
| | }); |
| | document.getElementById(`panel-${tab}`).classList.remove('hidden'); |
| | const activeBtn = document.getElementById(`tab-${tab}`); |
| | activeBtn.classList.add('active'); |
| | activeBtn.classList.remove('text-gray-400'); |
| | currentTab = tab; |
| | document.getElementById('resultsSection').classList.add('hidden'); |
| | } |
| | |
| | |
| | const uploadArea = document.getElementById('uploadArea'); |
| | const fileInput = document.getElementById('fileInput'); |
| | const analyzeBtn = document.getElementById('analyzeBtn'); |
| | |
| | ['dragenter', 'dragover', 'dragleave', 'drop'].forEach(e => { |
| | uploadArea.addEventListener(e, ev => { ev.preventDefault(); ev.stopPropagation(); }); |
| | }); |
| | ['dragenter', 'dragover'].forEach(e => uploadArea.addEventListener(e, () => uploadArea.classList.add('dragover'))); |
| | ['dragleave', 'drop'].forEach(e => uploadArea.addEventListener(e, () => uploadArea.classList.remove('dragover'))); |
| | uploadArea.addEventListener('drop', e => handleFiles(e.dataTransfer.files)); |
| | fileInput.addEventListener('change', e => handleFiles(e.target.files)); |
| | |
| | function handleFiles(files) { |
| | if (!files.length) return; |
| | const file = files[0]; |
| | if (file.size > 50 * 1024 * 1024) { alert('File exceeds 50MB limit.'); return; } |
| | showPreview(file); |
| | } |
| | |
| | function showPreview(file) { |
| | const url = URL.createObjectURL(file); |
| | const isVideo = file.type.startsWith('video/'); |
| | const imgEl = document.getElementById('previewImg'); |
| | const videoEl = document.getElementById('previewVideo'); |
| | |
| | if (isVideo) { |
| | imgEl.classList.add('hidden'); |
| | videoEl.classList.remove('hidden'); |
| | videoEl.src = url; |
| | } else { |
| | videoEl.classList.add('hidden'); |
| | imgEl.classList.remove('hidden'); |
| | imgEl.src = url; |
| | } |
| | |
| | document.getElementById('fileInfo').innerHTML = ` |
| | <div class="space-y-2"> |
| | <div class="flex items-center text-sm"> |
| | <i class="fas fa-${isVideo ? 'video' : 'image'} mr-2 text-blue-400"></i> |
| | <span class="font-semibold text-gray-200 truncate">${file.name}</span> |
| | </div> |
| | <p class="text-gray-500 text-sm">${formatBytes(file.size)}</p> |
| | ${isVideo ? '<p class="text-yellow-400 text-xs mt-2"><i class="fas fa-clock mr-1"></i>Video analysis takes ~30-60s (5 frames)</p>' : ''} |
| | </div>`; |
| | |
| | document.getElementById('previewSection').classList.remove('hidden'); |
| | analyzeBtn.classList.remove('hidden'); |
| | document.getElementById('progressLabel').textContent = isVideo |
| | ? 'Analyzing 5 key frames with Groq Llama 4 Vision...' |
| | : 'Running forensic analysis with Groq Llama 4 Vision...'; |
| | } |
| | |
| | analyzeBtn.addEventListener('click', async () => { |
| | const file = fileInput.files[0]; |
| | if (!file) return; |
| | const isVideo = file.type.startsWith('video/'); |
| | |
| | document.getElementById('uploadArea').style.display = 'none'; |
| | document.getElementById('previewSection').style.display = 'none'; |
| | analyzeBtn.style.display = 'none'; |
| | startProgress(isVideo ? 1 : 3); |
| | |
| | const formData = new FormData(); |
| | formData.append("file", file); |
| | await submitAndShow(formData); |
| | }); |
| | |
| | |
| | const textInput = document.getElementById('textInput'); |
| | const charCount = document.getElementById('charCount'); |
| | |
| | textInput.addEventListener('input', () => { |
| | charCount.textContent = textInput.value.length + ' characters'; |
| | }); |
| | |
| | document.getElementById('analyzeTextBtn').addEventListener('click', async () => { |
| | const text = textInput.value.trim(); |
| | if (!text) { alert('Please paste some text first.'); return; } |
| | if (text.length < 50) { alert('Text is too short for analysis. Please paste at least 50 characters.'); return; } |
| | |
| | document.getElementById('panel-text').style.display = 'none'; |
| | document.getElementById('progressLabel').textContent = 'Analyzing text with RoBERTa + Groq Llama 3...'; |
| | startProgress(2); |
| | |
| | const formData = new FormData(); |
| | formData.append("text", text); |
| | await submitAndShow(formData); |
| | }); |
| | |
| | |
| | const pdfInput = document.getElementById('pdfInput'); |
| | |
| | pdfInput.addEventListener('change', e => { |
| | const file = e.target.files[0]; |
| | if (!file) return; |
| | if (file.size > 50 * 1024 * 1024) { alert('File exceeds 50MB limit.'); return; } |
| | document.getElementById('pdfFileName').textContent = file.name; |
| | document.getElementById('pdfFileSize').textContent = formatBytes(file.size); |
| | document.getElementById('pdfPreview').classList.remove('hidden'); |
| | document.getElementById('analyzePdfBtn').classList.remove('hidden'); |
| | }); |
| | |
| | const pdfUploadArea = document.getElementById('pdfUploadArea'); |
| | ['dragenter', 'dragover', 'dragleave', 'drop'].forEach(e => { |
| | pdfUploadArea.addEventListener(e, ev => { ev.preventDefault(); ev.stopPropagation(); }); |
| | }); |
| | ['dragenter', 'dragover'].forEach(e => pdfUploadArea.addEventListener(e, () => pdfUploadArea.classList.add('dragover'))); |
| | ['dragleave', 'drop'].forEach(e => pdfUploadArea.addEventListener(e, () => pdfUploadArea.classList.remove('dragover'))); |
| | pdfUploadArea.addEventListener('drop', e => { |
| | const file = e.dataTransfer.files[0]; |
| | if (file && file.type === 'application/pdf') { |
| | pdfInput.files = e.dataTransfer.files; |
| | document.getElementById('pdfFileName').textContent = file.name; |
| | document.getElementById('pdfFileSize').textContent = formatBytes(file.size); |
| | document.getElementById('pdfPreview').classList.remove('hidden'); |
| | document.getElementById('analyzePdfBtn').classList.remove('hidden'); |
| | } |
| | }); |
| | |
| | document.getElementById('analyzePdfBtn').addEventListener('click', async () => { |
| | const file = pdfInput.files[0]; |
| | if (!file) return; |
| | |
| | document.getElementById('pdfUploadArea').style.display = 'none'; |
| | document.getElementById('pdfPreview').style.display = 'none'; |
| | document.getElementById('analyzePdfBtn').style.display = 'none'; |
| | document.getElementById('progressLabel').textContent = 'Extracting text & images from PDF, analyzing with RoBERTa + Groq...'; |
| | startProgress(1); |
| | |
| | const formData = new FormData(); |
| | formData.append("file", file); |
| | await submitAndShow(formData); |
| | }); |
| | |
| | |
| | let progressInterval = null; |
| | |
| | function startProgress(increment) { |
| | document.getElementById('resultsSection').classList.add('hidden'); |
| | document.getElementById('progressSection').classList.remove('hidden'); |
| | let progress = 0; |
| | progressInterval = setInterval(() => { |
| | progress += increment; |
| | if (progress > 90) progress = 90; |
| | document.getElementById('progressBar').style.width = progress + '%'; |
| | document.getElementById('progressText').textContent = progress + '%'; |
| | }, 400); |
| | } |
| | |
| | async function submitAndShow(formData) { |
| | try { |
| | const response = await fetch("/analyze", { method: "POST", body: formData }); |
| | if (!response.ok) throw new Error("Server error"); |
| | const data = await response.json(); |
| | |
| | clearInterval(progressInterval); |
| | document.getElementById('progressBar').style.width = '100%'; |
| | document.getElementById('progressText').textContent = '100%'; |
| | |
| | setTimeout(() => { |
| | document.getElementById('progressSection').classList.add('hidden'); |
| | showResults(data); |
| | }, 400); |
| | |
| | } catch (error) { |
| | clearInterval(progressInterval); |
| | document.getElementById('progressSection').classList.add('hidden'); |
| | console.error(error); |
| | alert("Analysis failed. Check backend."); |
| | } |
| | } |
| | |
| | |
| | function showResults(data) { |
| | const section = document.getElementById('resultsSection'); |
| | section.classList.remove('hidden'); |
| | section.scrollIntoView({ behavior: 'smooth' }); |
| | |
| | const isAuthentic = data.authenticity > 50; |
| | const type = data.type; |
| | const iconEl = document.getElementById('resultIcon'); |
| | |
| | |
| | const warningEl = document.getElementById('confidenceWarning'); |
| | if (data.confidence_level === 'low') { |
| | warningEl.classList.remove('hidden'); |
| | warningEl.className = 'mb-6 p-4 rounded-xl border text-sm font-medium bg-yellow-900/30 border-yellow-700 text-yellow-400'; |
| | warningEl.innerHTML = '<i class="fas fa-triangle-exclamation mr-2"></i>Low confidence — model could not confidently determine authenticity. Result may not be reliable.'; |
| | } else if (data.confidence_level === 'medium') { |
| | warningEl.classList.remove('hidden'); |
| | warningEl.className = 'mb-6 p-4 rounded-xl border text-sm font-medium bg-blue-900/30 border-blue-700 text-blue-400'; |
| | warningEl.innerHTML = '<i class="fas fa-circle-info mr-2"></i>Medium confidence — result is moderately reliable.'; |
| | } else { |
| | warningEl.classList.add('hidden'); |
| | } |
| | |
| | |
| | const titles = { |
| | image: ['Authentic Media Detected', 'Potential Deepfake Detected'], |
| | video: ['Authentic Video Detected', 'Potential Deepfake Video Detected'], |
| | text: ['Authentic Text Detected', 'Potentially Fake / AI-Generated Text'], |
| | pdf: ['Authentic Document Detected', 'Potentially Forged / AI-Generated Document'], |
| | }; |
| | |
| | if (isAuthentic) { |
| | iconEl.innerHTML = '<i class="fas fa-check text-green-500 text-2xl"></i>'; |
| | document.getElementById('resultTitle').textContent = titles[type]?.[0] || 'Authentic'; |
| | document.getElementById('resultSubtitle').textContent = 'No signs of manipulation or AI generation found.'; |
| | } else { |
| | iconEl.innerHTML = '<i class="fas fa-triangle-exclamation text-orange-500 text-2xl"></i>'; |
| | document.getElementById('resultTitle').textContent = titles[type]?.[1] || 'Suspicious'; |
| | document.getElementById('resultSubtitle').textContent = 'Signs of fabrication or AI generation detected.'; |
| | } |
| | |
| | document.getElementById('scoreReal').textContent = Math.round(data.authenticity) + '%'; |
| | document.getElementById('scoreFake').textContent = Math.round(data.fake) + '%'; |
| | document.getElementById('hashValue').textContent = data.sha256; |
| | document.getElementById('modelsUsed').textContent = (data.models_used || []).join(', '); |
| | |
| | |
| | if (type === 'video') { |
| | document.getElementById('metadataRiskRow').classList.add('hidden'); |
| | document.getElementById('framesRow').classList.remove('hidden'); |
| | document.getElementById('durationRow').classList.remove('hidden'); |
| | document.getElementById('framesAnalyzed').textContent = data.details.frames_analyzed + ' frames'; |
| | document.getElementById('videoDuration').textContent = data.details.video_duration + 's'; |
| | } else { |
| | document.getElementById('metadataRiskRow').classList.remove('hidden'); |
| | document.getElementById('framesRow').classList.add('hidden'); |
| | document.getElementById('durationRow').classList.add('hidden'); |
| | document.getElementById('metadataRisk').textContent = data.details.metadata_risk; |
| | } |
| | |
| | |
| | const modelDiv = document.getElementById('modelBreakdown'); |
| | modelDiv.innerHTML = ''; |
| | |
| | |
| | let models = []; |
| | if (type === 'text' || type === 'pdf') { |
| | models = [ |
| | { name: 'RoBERTa Fake News', icon: 'fa-newspaper', color: 'text-purple-400', score: data.details.roberta_fakenews_score }, |
| | { name: 'RoBERTa AI Detector', icon: 'fa-robot', color: 'text-blue-400', score: data.details.roberta_aidetector_score }, |
| | { name: 'Groq Llama 3 (Text)', icon: 'fa-brain', color: 'text-orange-400', score: data.details.groq_score === 'see breakdown' ? 'unavailable' : data.details.groq_score }, |
| | ]; |
| | } else { |
| | models = [ |
| | { name: `Groq Llama 4 Vision${type === 'video' ? ' (avg 5 frames)' : ''}`, icon: 'fa-brain', color: 'text-orange-400', score: data.details.groq_score }, |
| | ]; |
| | } |
| | |
| | models.forEach(({ name, icon, color, score }) => { |
| | const isUnavailable = score === 'unavailable' || score === null; |
| | const pct = isUnavailable ? 0 : Math.round(score * 100); |
| | const barColor = isUnavailable ? 'bg-gray-600' : score > 0.5 ? 'bg-red-500' : 'bg-green-500'; |
| | const textColor = isUnavailable ? 'text-gray-500' : score > 0.5 ? 'text-red-400' : 'text-green-400'; |
| | modelDiv.innerHTML += ` |
| | <div class="p-4 bg-gray-900/50 rounded-xl border border-gray-700"> |
| | <div class="flex justify-between items-center mb-2"> |
| | <span class="text-sm text-gray-300 font-medium"> |
| | <i class="fas ${icon} mr-2 ${color}"></i>${name} |
| | </span> |
| | <span class="text-sm font-bold ${textColor}"> |
| | ${isUnavailable ? 'Unavailable' : pct + '% fake'} |
| | </span> |
| | </div> |
| | <div class="w-full bg-gray-800 rounded-full h-2"> |
| | <div class="${barColor} h-2 rounded-full" style="width: ${pct}%"></div> |
| | </div> |
| | </div>`; |
| | }); |
| | |
| | |
| | if (data.details.groq_reasoning) { |
| | document.getElementById('groqReasoningSection').classList.remove('hidden'); |
| | document.getElementById('groqReasoning').textContent = data.details.groq_reasoning; |
| | } else { |
| | document.getElementById('groqReasoningSection').classList.add('hidden'); |
| | } |
| | } |
| | |
| | |
| | function formatBytes(bytes) { |
| | if (bytes === 0) return '0 B'; |
| | const sizes = ['B', 'KB', 'MB']; |
| | const i = Math.floor(Math.log(bytes) / Math.log(1024)); |
| | return (bytes / Math.pow(1024, i)).toFixed(1) + ' ' + sizes[i]; |
| | } |
| | |
| | function resetUI() { |
| | document.getElementById('resultsSection').classList.add('hidden'); |
| | document.getElementById('confidenceWarning').classList.add('hidden'); |
| | document.getElementById('groqReasoningSection').classList.add('hidden'); |
| | document.getElementById('progressBar').style.width = '0%'; |
| | document.getElementById('progressText').textContent = '0%'; |
| | |
| | |
| | document.getElementById('uploadArea').style.display = 'block'; |
| | document.getElementById('previewSection').classList.add('hidden'); |
| | document.getElementById('previewSection').style.display = ''; |
| | document.getElementById('analyzeBtn').classList.add('hidden'); |
| | document.getElementById('analyzeBtn').style.display = ''; |
| | document.getElementById('previewImg').classList.add('hidden'); |
| | document.getElementById('previewVideo').classList.add('hidden'); |
| | fileInput.value = ''; |
| | |
| | |
| | document.getElementById('panel-text').style.display = ''; |
| | textInput.value = ''; |
| | charCount.textContent = '0 characters'; |
| | |
| | |
| | document.getElementById('pdfUploadArea').style.display = 'block'; |
| | document.getElementById('pdfPreview').classList.add('hidden'); |
| | document.getElementById('pdfPreview').style.display = ''; |
| | document.getElementById('analyzePdfBtn').classList.add('hidden'); |
| | document.getElementById('analyzePdfBtn').style.display = ''; |
| | pdfInput.value = ''; |
| | } |
| | </script> |
| | </body> |
| | </html> |