/** * DeepShield AI — script.js (SupCon SOTA Version) */ const API_URL = ""; async function checkServerStatus() { const statusMenu = document.getElementById("server-status"); const statusText = document.getElementById("status-text"); const dropZone = document.getElementById("drop-zone"); if (!statusMenu) return; try { const res = await fetch(`${API_URL}/health`); if (!res.ok) throw new Error("Server not OK"); const data = await res.json(); statusMenu.className = "server-status"; if (data.model_loaded === true) { statusMenu.classList.add("status-connected"); statusText.textContent = "AI Ready ✓"; dropZone.style.pointerEvents = "auto"; dropZone.style.opacity = "1"; document.querySelector(".drop-title").innerHTML = "Drop your video or photo here"; } else { statusMenu.classList.add("status-error"); statusText.textContent = "Model Missing"; dropZone.style.pointerEvents = "none"; dropZone.style.opacity = "0.5"; document.querySelector(".drop-title").innerHTML = "⚠️ Model Not Uploaded"; document.querySelector(".drop-sub").textContent = "Upload best_model.pth from scripts3."; } } catch (err) { statusMenu.className = "server-status status-error"; statusText.textContent = "Starting Server..."; dropZone.style.pointerEvents = "none"; dropZone.style.opacity = "0.5"; } } checkServerStatus(); setInterval(checkServerStatus, 10000); const MAX_FILE_MB = 30; const MAX_FILE_BYTES = MAX_FILE_MB * 1024 * 1024; let currentFile = null; function showSection(id) { ["upload-section", "loading-section", "results-section", "error-section"].forEach(s => { document.getElementById(s).classList.toggle("hidden", s !== id); }); } function onDragOver(e) { e.preventDefault(); document.getElementById("drop-zone").classList.add("dragging"); } function onDragLeave() { document.getElementById("drop-zone").classList.remove("dragging"); } function onDrop(e) { e.preventDefault(); document.getElementById("drop-zone").classList.remove("dragging"); const file = e.dataTransfer?.files?.[0]; if (file) processFile(file); } function onFileSelected(e) { const file = e.target.files?.[0]; if (file) processFile(file); } function processFile(file) { const allowedExt = [".mp4", ".mov", ".avi", ".mkv", ".jpg", ".jpeg", ".png", ".webp"]; const ext = "." + file.name.split(".").pop().toLowerCase(); if (!allowedExt.includes(ext)) { showError(`❌ Unsupported file type. Use Video (MP4/MOV/AVI) or Photo (JPG/PNG).`); return; } if (file.size > MAX_FILE_BYTES) { showError(`❌ File too large. Max: ${MAX_FILE_MB} MB.`); return; } currentFile = file; document.getElementById("file-name").textContent = file.name; document.getElementById("file-size").textContent = (file.size / (1024*1024)).toFixed(1) + " MB"; const url = URL.createObjectURL(file); const isVideo = [".mp4", ".mov", ".avi", ".mkv"].includes(ext); const videoPrev = document.getElementById("video-preview"); const videoCont = document.getElementById("video-container"); // Check if image-preview element exists, if not create it let imgPrev = document.getElementById("image-preview"); if (!imgPrev) { imgPrev = document.createElement("img"); imgPrev.id = "image-preview"; imgPrev.className = "video-preview"; // reuse styling videoCont.appendChild(imgPrev); } if (isVideo) { videoPrev.src = url; videoPrev.style.display = "block"; imgPrev.style.display = "none"; } else { videoPrev.style.display = "none"; imgPrev.src = url; imgPrev.style.display = "block"; } document.getElementById("drop-zone").classList.add("hidden"); document.getElementById("file-preview").classList.remove("hidden"); } function resetUpload() { currentFile = null; document.getElementById("file-input").value = ""; showSection("upload-section"); document.getElementById("drop-zone").classList.remove("hidden"); document.getElementById("file-preview").classList.add("hidden"); document.getElementById("ring-fill").style.strokeDashoffset = "314"; } async function analyzeVideo() { if (!currentFile) return; showSection("loading-section"); const formData = new FormData(); formData.append("file", currentFile); try { const res = await fetch(`${API_URL}/predict`, { method: "POST", body: formData }); if (!res.ok) throw new Error("Analysis failed on server."); const data = await res.json(); renderResults(data); showSection("results-section"); } catch (err) { showError(err.message); } } function renderResults(data) { const isFake = data.verdict === "FAKE"; const fakePct = data.fake_probability; document.getElementById("verdict-card").className = "verdict-card " + (isFake ? "is-fake" : "is-real"); document.getElementById("verdict-pct").textContent = `${fakePct}%`; document.getElementById("verdict-label").textContent = data.verdict; document.getElementById("verdict-badge").textContent = isFake ? "⚠ FAKE DETECTED" : "✅ REAL CONTENT"; document.getElementById("verdict-badge").className = "verdict-badge " + (isFake ? "fake" : "real"); const ring = document.getElementById("ring-fill"); ring.style.stroke = isFake ? "#ef4444" : "#22c55e"; ring.style.strokeDashoffset = 314 - (fakePct / 100) * 314; document.getElementById("stat-fake").textContent = `${fakePct}%`; document.getElementById("stat-real").textContent = `${data.real_probability}%`; document.getElementById("stat-frames").textContent = data.frame_count; document.getElementById("stat-size").textContent = data.file_size_mb + " MB"; renderFrameChart(data.per_frame_scores || []); } function renderFrameChart(scores) { const container = document.getElementById("frame-chart"); container.innerHTML = ""; scores.forEach((s, i) => { const bar = document.createElement("div"); bar.className = "bar-wrap"; bar.innerHTML = `
`; container.appendChild(bar); }); } function showError(msg) { document.getElementById("error-msg").textContent = msg; showSection("error-section"); }