Vinh.Vu commited on
Commit
75fc585
Β·
1 Parent(s): c9d361f

Add Technology page

Browse files
.gitignore CHANGED
@@ -137,3 +137,4 @@ mtcnn/
137
  /prepared_dataset
138
  /App/uploads
139
  archive.zip
 
 
137
  /prepared_dataset
138
  /App/uploads
139
  archive.zip
140
+ App/diag_log.txt
App/static/app.jsx CHANGED
@@ -9,16 +9,25 @@ const STATUS_MESSAGES = {
9
  function barClass(s) { return s > 0.8 ? 'bar-green' : s > 0.2 ? 'bar-orange' : 'bar-red'; }
10
  function scoreClass(s) { return s > 0.8 ? 'score-green' : s > 0.2 ? 'score-orange' : 'score-red'; }
11
 
 
 
 
 
 
 
 
 
 
 
 
12
  /* ── Navbar ── */
13
- function Navbar() {
14
  return (
15
  <header className="navbar">
16
- <div className="logo"><span>DF</span>Detect</div>
17
  <nav>
18
- <a href="/" className="active">Product</a>
19
- <a href="#">Examples</a>
20
- <a href="#">Technology</a>
21
- <a href="#">FAQ</a>
22
  </nav>
23
  </header>
24
  );
@@ -146,6 +155,262 @@ function ResultsPanel({ data }) {
146
  );
147
  }
148
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
149
  /* ── Main App ── */
150
  function App() {
151
  const [file, setFile] = useState(null);
@@ -214,13 +479,20 @@ function App() {
214
  }
215
  };
216
 
 
 
217
  return (
218
  <>
219
- <Navbar />
 
 
 
 
 
220
 
221
  <section className="hero">
222
  <div className="hero-left">
223
- <h1 className="hero-title">DFDetect</h1>
224
  <p className="hero-desc">
225
  Free deepfake detection tool for videos. Upload a video and get
226
  per-face authenticity scores in seconds. AI-powered synthetic face detection.
@@ -237,6 +509,10 @@ function App() {
237
  {error && <div className="error-box">{error}</div>}
238
  </div>
239
 
 
 
 
 
240
  </section>
241
 
242
  <VideoComparison
@@ -245,6 +521,8 @@ function App() {
245
  isProcessing={submitting}
246
  />
247
  <ResultsPanel data={result} />
 
 
248
  </>
249
  );
250
  }
 
9
  function barClass(s) { return s > 0.8 ? 'bar-green' : s > 0.2 ? 'bar-orange' : 'bar-red'; }
10
  function scoreClass(s) { return s > 0.8 ? 'score-green' : s > 0.2 ? 'score-orange' : 'score-red'; }
11
 
12
+ /* ── Simple hash-based router ── */
13
+ function useHashRoute() {
14
+ const [route, setRoute] = useState(window.location.hash || '#/');
15
+ useEffect(() => {
16
+ const onHash = () => setRoute(window.location.hash || '#/');
17
+ window.addEventListener('hashchange', onHash);
18
+ return () => window.removeEventListener('hashchange', onHash);
19
+ }, []);
20
+ return route;
21
+ }
22
+
23
  /* ── Navbar ── */
24
+ function Navbar({ route }) {
25
  return (
26
  <header className="navbar">
27
+ <div className="logo"><span>AI</span>-Deepfake Video Detection</div>
28
  <nav>
29
+ <a href="#/" className={route === '#/' || route === '' ? 'active' : ''}>Product</a>
30
+ <a href="#/technology" className={route === '#/technology' ? 'active' : ''}>Technology</a>
 
 
31
  </nav>
32
  </header>
33
  );
 
155
  );
156
  }
157
 
158
+ /* ── Step Diagram SVG ── */
159
+ function StepDiagram({ number, title, color }) {
160
+ return (
161
+ <svg width="80" height="80" viewBox="0 0 80 80" className="step-icon">
162
+ <circle cx="40" cy="40" r="36" fill="none" stroke={color} strokeWidth="2.5" />
163
+ <text x="40" y="46" textAnchor="middle" fill={color} fontSize="28" fontWeight="700">{number}</text>
164
+ </svg>
165
+ );
166
+ }
167
+
168
+ /* ── Pipeline Flow Arrow ── */
169
+ function FlowArrow() {
170
+ return (
171
+ <div className="flow-arrow">
172
+ <svg width="40" height="40" viewBox="0 0 40 40">
173
+ <path d="M10 20 L28 20 M22 13 L30 20 L22 27" fill="none" stroke="#6c8cff" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round"/>
174
+ </svg>
175
+ </div>
176
+ );
177
+ }
178
+
179
+ /* ── Technology Page ── */
180
+ function TechnologyPage() {
181
+ const steps = [
182
+ {
183
+ number: 1,
184
+ title: 'Video to Frames',
185
+ color: '#6c8cff',
186
+ file: '00-convert_video_to_image.py',
187
+ description: 'Raw training videos are split into individual image frames. One frame is extracted per second of video using OpenCV. Each frame is automatically scaled based on its resolution to normalize image sizes across the dataset.',
188
+ details: [
189
+ 'Reads MP4 videos from the FaceForensics++ dataset',
190
+ 'Extracts 1 frame per second (at the video\'s native frame rate)',
191
+ 'Auto-scales: 2Γ— for small frames (<300px), 0.5Γ— for HD, 0.33Γ— for Full HD+',
192
+ 'Saves frames as individual JPG images organized by video',
193
+ ],
194
+ diagram: (
195
+ <svg viewBox="0 0 400 120" className="step-illustration">
196
+ <rect x="10" y="15" width="90" height="90" rx="8" fill="#1a1a2e" stroke="#6c8cff" strokeWidth="1.5"/>
197
+ <polygon points="40,35 40,80 70,57" fill="#6c8cff" opacity="0.8"/>
198
+ <text x="55" y="112" textAnchor="middle" fill="#888" fontSize="11">Video</text>
199
+ <path d="M115 60 L155 60" stroke="#6c8cff" strokeWidth="2" markerEnd="url(#arrow1)"/>
200
+ <defs><marker id="arrow1" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="6" markerHeight="6" orient="auto"><path d="M0,0 L10,5 L0,10 z" fill="#6c8cff"/></marker></defs>
201
+ {[0,1,2,3,4].map(i => (
202
+ <g key={i}>
203
+ <rect x={165 + i*46} y={20 + (i%2)*15} width="38" height="38" rx="4" fill="#1a1a2e" stroke="#4caf50" strokeWidth="1"/>
204
+ <text x={184 + i*46} y={44 + (i%2)*15} textAnchor="middle" fill="#4caf50" fontSize="9">F{i+1}</text>
205
+ </g>
206
+ ))}
207
+ <text x="300" y="112" textAnchor="middle" fill="#888" fontSize="11">Extracted Frames (1/sec)</text>
208
+ </svg>
209
+ ),
210
+ },
211
+ {
212
+ number: 2,
213
+ title: 'Face Detection & Cropping',
214
+ color: '#ff9800',
215
+ file: '01-crop_faces_with_mtcnn.py',
216
+ description: 'MTCNN (Multi-task Cascaded Convolutional Network) scans each extracted frame to detect faces. Detected faces are cropped with a 30% margin around the bounding box to preserve context like hair and jawline, which helps the model detect manipulation artifacts.',
217
+ details: [
218
+ 'Uses MTCNN deep learning face detector for accurate face localization',
219
+ 'Filters low-confidence detections (>95% threshold for multi-face frames)',
220
+ 'Adds 30% margin around each face bounding box',
221
+ 'Crops and saves individual face images for training',
222
+ ],
223
+ diagram: (
224
+ <svg viewBox="0 0 400 120" className="step-illustration">
225
+ <rect x="10" y="10" width="100" height="100" rx="6" fill="#1a1a2e" stroke="#444" strokeWidth="1"/>
226
+ <circle cx="60" cy="45" r="15" fill="none" stroke="#ff9800" strokeWidth="1.5" strokeDasharray="3,2"/>
227
+ <circle cx="60" cy="42" r="6" fill="#ff9800" opacity="0.4"/>
228
+ <ellipse cx="60" cy="55" rx="10" ry="6" fill="#ff9800" opacity="0.3"/>
229
+ <rect x="35" y="25" width="50" height="50" rx="4" fill="none" stroke="#ff9800" strokeWidth="2"/>
230
+ <text x="60" y="112" textAnchor="middle" fill="#888" fontSize="11">Frame + Detection</text>
231
+ <path d="M125 55 L165 55" stroke="#ff9800" strokeWidth="2" markerEnd="url(#arrow2)"/>
232
+ <defs><marker id="arrow2" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="6" markerHeight="6" orient="auto"><path d="M0,0 L10,5 L0,10 z" fill="#ff9800"/></marker></defs>
233
+ <rect x="175" y="20" width="70" height="70" rx="8" fill="#1a1a2e" stroke="#ff9800" strokeWidth="2"/>
234
+ <circle cx="210" cy="45" r="12" fill="none" stroke="#ff9800" strokeWidth="1.5"/>
235
+ <circle cx="210" cy="42" r="5" fill="#ff9800" opacity="0.5"/>
236
+ <ellipse cx="210" cy="52" rx="8" ry="5" fill="#ff9800" opacity="0.4"/>
237
+ <text x="210" y="112" textAnchor="middle" fill="#888" fontSize="11">Cropped Face (+30% margin)</text>
238
+ <text x="340" y="40" fill="#ff9800" fontSize="11" fontWeight="600">βœ“ 95%+ confidence</text>
239
+ <text x="340" y="58" fill="#888" fontSize="10">30% margin padding</text>
240
+ <text x="340" y="76" fill="#888" fontSize="10">Context preserved</text>
241
+ </svg>
242
+ ),
243
+ },
244
+ {
245
+ number: 3,
246
+ title: 'Dataset Preparation',
247
+ color: '#4caf50',
248
+ file: '02-prepare_fake_real_dataset.py',
249
+ description: 'Cropped face images are organized into "real" and "fake" categories based on FaceForensics++ metadata. Small or corrupted images (<90px) are filtered out. The dataset is then split into training (80%), validation (10%), and test (10%) sets using stratified splitting.',
250
+ details: [
251
+ 'Labels faces as REAL or FAKE using FaceForensics++ CSV metadata',
252
+ 'Filters out low-quality images smaller than 90Γ—90 pixels',
253
+ 'Balances fake samples across manipulation methods (Deepfakes, Face2Face, FaceSwap, NeuralTextures, FaceShifter)',
254
+ 'Splits into train/val/test (80/10/10) with stratified random sampling',
255
+ ],
256
+ diagram: (
257
+ <svg viewBox="0 0 400 120" className="step-illustration">
258
+ <g>
259
+ <rect x="10" y="15" width="55" height="40" rx="4" fill="rgba(76,175,80,0.15)" stroke="#4caf50" strokeWidth="1.5"/>
260
+ <text x="37" y="39" textAnchor="middle" fill="#4caf50" fontSize="11" fontWeight="600">REAL</text>
261
+ <rect x="10" y="65" width="55" height="40" rx="4" fill="rgba(244,67,54,0.15)" stroke="#f44336" strokeWidth="1.5"/>
262
+ <text x="37" y="89" textAnchor="middle" fill="#f44336" fontSize="11" fontWeight="600">FAKE</text>
263
+ </g>
264
+ <path d="M80 55 L120 55" stroke="#4caf50" strokeWidth="2" markerEnd="url(#arrow3)"/>
265
+ <defs><marker id="arrow3" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="6" markerHeight="6" orient="auto"><path d="M0,0 L10,5 L0,10 z" fill="#4caf50"/></marker></defs>
266
+ <rect x="130" y="8" width="100" height="28" rx="4" fill="rgba(76,175,80,0.1)" stroke="#4caf50" strokeWidth="1"/>
267
+ <text x="180" y="26" textAnchor="middle" fill="#4caf50" fontSize="10">Train 80%</text>
268
+ <rect x="130" y="44" width="100" height="28" rx="4" fill="rgba(255,152,0,0.1)" stroke="#ff9800" strokeWidth="1"/>
269
+ <text x="180" y="62" textAnchor="middle" fill="#ff9800" fontSize="10">Val 10%</text>
270
+ <rect x="130" y="80" width="100" height="28" rx="4" fill="rgba(108,140,255,0.1)" stroke="#6c8cff" strokeWidth="1"/>
271
+ <text x="180" y="98" textAnchor="middle" fill="#6c8cff" fontSize="10">Test 10%</text>
272
+ <text x="310" y="30" fill="#888" fontSize="10">βœ“ Min 90Γ—90px filter</text>
273
+ <text x="310" y="50" fill="#888" fontSize="10">βœ“ Stratified split</text>
274
+ <text x="310" y="70" fill="#888" fontSize="10">βœ“ Multi-method balance</text>
275
+ <text x="310" y="90" fill="#888" fontSize="10">βœ“ CSV metadata labels</text>
276
+ </svg>
277
+ ),
278
+ },
279
+ {
280
+ number: 4,
281
+ title: 'CNN Training (EfficientNetB0)',
282
+ color: '#f44336',
283
+ file: '03-train_cnn.py',
284
+ description: 'A two-phase transfer learning approach trains an EfficientNetB0-based classifier. Phase 1 freezes the pre-trained ImageNet backbone and trains only the classification head. Phase 2 unfreezes the entire network for fine-tuning with a very low learning rate, achieving ~92% accuracy.',
285
+ details: [
286
+ 'EfficientNetB0 backbone pre-trained on ImageNet (224Γ—224 input)',
287
+ 'Phase 1: Frozen base, train head only (lr=1e-3, up to 15 epochs)',
288
+ 'Phase 2: Full fine-tuning (lr=1e-5, up to 30 epochs)',
289
+ 'Data augmentation: rotation, flip, zoom, shift, brightness',
290
+ 'Class weight balancing for imbalanced datasets',
291
+ 'Callbacks: EarlyStopping, ReduceLROnPlateau, ModelCheckpoint',
292
+ 'Output: binary sigmoid β€” score > 0.5 = REAL, ≀ 0.5 = FAKE',
293
+ ],
294
+ diagram: (
295
+ <svg viewBox="0 0 400 140" className="step-illustration">
296
+ <rect x="10" y="30" width="70" height="80" rx="6" fill="#1a1a2e" stroke="#f44336" strokeWidth="1.5"/>
297
+ <text x="45" y="55" textAnchor="middle" fill="#f44336" fontSize="9" fontWeight="600">224Γ—224</text>
298
+ <text x="45" y="70" textAnchor="middle" fill="#888" fontSize="8">Face Input</text>
299
+ <text x="45" y="95" textAnchor="middle" fill="#666" fontSize="8">preprocess</text>
300
+ <text x="45" y="106" textAnchor="middle" fill="#666" fontSize="8">[-1, 1]</text>
301
+ <path d="M90 70 L115 70" stroke="#f44336" strokeWidth="1.5" markerEnd="url(#arrow4)"/>
302
+ <rect x="120" y="15" width="100" height="110" rx="6" fill="#1a1a2e" stroke="#ff9800" strokeWidth="1.5"/>
303
+ <text x="170" y="35" textAnchor="middle" fill="#ff9800" fontSize="10" fontWeight="600">EfficientNetB0</text>
304
+ <text x="170" y="52" textAnchor="middle" fill="#888" fontSize="8">(ImageNet weights)</text>
305
+ {[0,1,2,3].map(i => (
306
+ <rect key={i} x="135" y={60 + i*14} width="70" height="10" rx="2" fill={`rgba(255,152,0,${0.15 + i*0.1})`} stroke="#ff9800" strokeWidth="0.5"/>
307
+ ))}
308
+ <defs><marker id="arrow4" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="6" markerHeight="6" orient="auto"><path d="M0,0 L10,5 L0,10 z" fill="#f44336"/></marker></defs>
309
+ <path d="M230 70 L255 70" stroke="#f44336" strokeWidth="1.5" markerEnd="url(#arrow4)"/>
310
+ <rect x="260" y="25" width="80" height="90" rx="6" fill="#1a1a2e" stroke="#6c8cff" strokeWidth="1.5"/>
311
+ <text x="300" y="45" textAnchor="middle" fill="#6c8cff" fontSize="9" fontWeight="600">Head</text>
312
+ <text x="300" y="62" textAnchor="middle" fill="#888" fontSize="7">GlobalAvgPool</text>
313
+ <text x="300" y="74" textAnchor="middle" fill="#888" fontSize="7">BatchNorm</text>
314
+ <text x="300" y="86" textAnchor="middle" fill="#888" fontSize="7">Dense(256)+Dropout</text>
315
+ <text x="300" y="98" textAnchor="middle" fill="#888" fontSize="7">Dense(1, sigmoid)</text>
316
+ <path d="M350 70 L375 70" stroke="#4caf50" strokeWidth="1.5" markerEnd="url(#arrow5)"/>
317
+ <defs><marker id="arrow5" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="6" markerHeight="6" orient="auto"><path d="M0,0 L10,5 L0,10 z" fill="#4caf50"/></marker></defs>
318
+ <text x="388" y="65" fill="#4caf50" fontSize="11" fontWeight="700">0–1</text>
319
+ <text x="388" y="80" fill="#888" fontSize="8">Score</text>
320
+ </svg>
321
+ ),
322
+ },
323
+ ];
324
+
325
+ return (
326
+ <section className="tech-page">
327
+ <div className="tech-hero">
328
+ <h1 className="tech-title">How It Works</h1>
329
+ <p className="tech-subtitle">
330
+ Our deepfake detection pipeline processes videos through four stages β€” from raw video
331
+ to a trained AI model that scores each face for authenticity.
332
+ </p>
333
+ </div>
334
+
335
+ {/* Pipeline overview */}
336
+ <div className="pipeline-overview">
337
+ {steps.map((step, i) => (
338
+ <React.Fragment key={step.number}>
339
+ <div className="pipeline-step-mini">
340
+ <StepDiagram number={step.number} title={step.title} color={step.color} />
341
+ <span style={{ color: step.color, fontWeight: 600, fontSize: 13 }}>{step.title}</span>
342
+ </div>
343
+ {i < steps.length - 1 && <FlowArrow />}
344
+ </React.Fragment>
345
+ ))}
346
+ </div>
347
+
348
+ {/* Detailed steps */}
349
+ {steps.map((step) => (
350
+ <div className="tech-step" key={step.number}>
351
+ <div className="tech-step-header">
352
+ <StepDiagram number={step.number} title={step.title} color={step.color} />
353
+ <div>
354
+ <h2 className="tech-step-title" style={{ color: step.color }}>
355
+ Step {step.number}: {step.title}
356
+ </h2>
357
+ <code className="tech-file">{step.file}</code>
358
+ </div>
359
+ </div>
360
+ <p className="tech-step-desc">{step.description}</p>
361
+ <div className="tech-step-diagram">
362
+ {step.diagram}
363
+ </div>
364
+ <ul className="tech-step-details">
365
+ {step.details.map((d, i) => <li key={i}>{d}</li>)}
366
+ </ul>
367
+ </div>
368
+ ))}
369
+
370
+ {/* Inference section */}
371
+ <div className="tech-step">
372
+ <div className="tech-step-header">
373
+ <svg width="80" height="80" viewBox="0 0 80 80" className="step-icon">
374
+ <circle cx="40" cy="40" r="36" fill="none" stroke="#6c8cff" strokeWidth="2.5"/>
375
+ <text x="40" y="46" textAnchor="middle" fill="#6c8cff" fontSize="22" fontWeight="700">β–Ά</text>
376
+ </svg>
377
+ <div>
378
+ <h2 className="tech-step-title" style={{ color: '#6c8cff' }}>
379
+ Real-Time Inference
380
+ </h2>
381
+ <code className="tech-file">App/app.py</code>
382
+ </div>
383
+ </div>
384
+ <p className="tech-step-desc">
385
+ When you upload a video, the app uses YOLOv8 for fast face detection on each frame,
386
+ then feeds cropped faces through the trained EfficientNetB0 model. Each face gets an
387
+ authenticity score (0 = fake, 1 = real), and the processed video shows bounding boxes
388
+ with per-face REAL/FAKE labels overlaid in real time.
389
+ </p>
390
+ <div className="tech-step-diagram">
391
+ <svg viewBox="0 0 400 80" className="step-illustration">
392
+ <rect x="5" y="15" width="65" height="50" rx="6" fill="#1a1a2e" stroke="#6c8cff" strokeWidth="1.5"/>
393
+ <text x="37" y="44" textAnchor="middle" fill="#6c8cff" fontSize="9" fontWeight="600">Upload</text>
394
+ <path d="M80 40 L105 40" stroke="#6c8cff" strokeWidth="1.5" markerEnd="url(#arrowI)"/>
395
+ <rect x="110" y="15" width="65" height="50" rx="6" fill="#1a1a2e" stroke="#ff9800" strokeWidth="1.5"/>
396
+ <text x="142" y="38" textAnchor="middle" fill="#ff9800" fontSize="9" fontWeight="600">YOLOv8</text>
397
+ <text x="142" y="50" textAnchor="middle" fill="#888" fontSize="7">Face Detect</text>
398
+ <path d="M185 40 L210 40" stroke="#ff9800" strokeWidth="1.5" markerEnd="url(#arrowI)"/>
399
+ <rect x="215" y="15" width="65" height="50" rx="6" fill="#1a1a2e" stroke="#f44336" strokeWidth="1.5"/>
400
+ <text x="247" y="38" textAnchor="middle" fill="#f44336" fontSize="8" fontWeight="600">EfficientNet</text>
401
+ <text x="247" y="50" textAnchor="middle" fill="#888" fontSize="7">Predict</text>
402
+ <path d="M290 40 L315 40" stroke="#4caf50" strokeWidth="1.5" markerEnd="url(#arrowI)"/>
403
+ <rect x="320" y="15" width="70" height="50" rx="6" fill="#1a1a2e" stroke="#4caf50" strokeWidth="1.5"/>
404
+ <text x="355" y="38" textAnchor="middle" fill="#4caf50" fontSize="9" fontWeight="600">REAL</text>
405
+ <text x="355" y="50" textAnchor="middle" fill="#f44336" fontSize="9" fontWeight="600">FAKE</text>
406
+ <defs><marker id="arrowI" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="6" markerHeight="6" orient="auto"><path d="M0,0 L10,5 L0,10 z" fill="#6c8cff"/></marker></defs>
407
+ </svg>
408
+ </div>
409
+ </div>
410
+ </section>
411
+ );
412
+ }
413
+
414
  /* ── Main App ── */
415
  function App() {
416
  const [file, setFile] = useState(null);
 
479
  }
480
  };
481
 
482
+ const route = useHashRoute();
483
+
484
  return (
485
  <>
486
+ <Navbar route={route} />
487
+
488
+ {route === '#/technology' ? (
489
+ <TechnologyPage />
490
+ ) : (
491
+ <>
492
 
493
  <section className="hero">
494
  <div className="hero-left">
495
+ <h1 className="hero-title">AI-Deepfake Video Detection</h1>
496
  <p className="hero-desc">
497
  Free deepfake detection tool for videos. Upload a video and get
498
  per-face authenticity scores in seconds. AI-powered synthetic face detection.
 
509
  {error && <div className="error-box">{error}</div>}
510
  </div>
511
 
512
+ <div className="hero-right">
513
+ <img src="/static/images.png" alt="AI Deepfake Detection" className="hero-image" />
514
+ </div>
515
+
516
  </section>
517
 
518
  <VideoComparison
 
521
  isProcessing={submitting}
522
  />
523
  <ResultsPanel data={result} />
524
+ </>
525
+ )}
526
  </>
527
  );
528
  }
App/static/images.png ADDED

Git LFS Details

  • SHA256: 7274ea83d72c7de3177271bee46025db8c95cb9763420ada73a005dc62cf1e43
  • Pointer size: 131 Bytes
  • Size of remote file: 605 kB
App/static/style.css CHANGED
@@ -41,6 +41,11 @@ input[type="file"] { display: none; }
41
  .video-preview video {
42
  max-width: 100%; max-height: 400px; border-radius: 12px; border: 1px solid #1e1e35; background: #111122;
43
  }
 
 
 
 
 
44
  .preview-placeholder {
45
  width: 100%; max-width: 460px; height: 280px; border-radius: 12px; background: #111122;
46
  border: 1px solid #1e1e35; display: flex; align-items: center; justify-content: center; color: #333; font-size: 48px;
@@ -89,7 +94,54 @@ input[type="file"] { display: none; }
89
  @media (max-width: 768px) {
90
  .hero { flex-direction: column; padding: 0 20px; margin-top: 30px; gap: 30px; }
91
  .hero-left { max-width: 100%; } .hero-title { font-size: 32px; }
 
92
  .results-section { padding: 0 20px; } .results-panel { padding: 20px; }
93
  .navbar { padding: 14px 20px; } .navbar nav a { margin-left: 16px; font-size: 13px; }
94
  .compare-grid { flex-direction: column; }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
95
  }
 
41
  .video-preview video {
42
  max-width: 100%; max-height: 400px; border-radius: 12px; border: 1px solid #1e1e35; background: #111122;
43
  }
44
+ .hero-right { flex: 1; display: flex; justify-content: center; align-items: stretch; }
45
+ .hero-image {
46
+ width: 100%; height: 100%; border-radius: 14px; border: 1px solid #1e1e35;
47
+ object-fit: cover; box-shadow: 0 8px 32px rgba(108,140,255,0.10);
48
+ }
49
  .preview-placeholder {
50
  width: 100%; max-width: 460px; height: 280px; border-radius: 12px; background: #111122;
51
  border: 1px solid #1e1e35; display: flex; align-items: center; justify-content: center; color: #333; font-size: 48px;
 
94
  @media (max-width: 768px) {
95
  .hero { flex-direction: column; padding: 0 20px; margin-top: 30px; gap: 30px; }
96
  .hero-left { max-width: 100%; } .hero-title { font-size: 32px; }
97
+ .hero-right { display: none; }
98
  .results-section { padding: 0 20px; } .results-panel { padding: 20px; }
99
  .navbar { padding: 14px 20px; } .navbar nav a { margin-left: 16px; font-size: 13px; }
100
  .compare-grid { flex-direction: column; }
101
+ .pipeline-overview { flex-direction: column; align-items: center; }
102
+ .flow-arrow { transform: rotate(90deg); }
103
+ .tech-step-header { flex-direction: column; align-items: center; text-align: center; }
104
+ .tech-page { padding: 0 16px; }
105
+ }
106
+
107
+ /* ── Technology Page ── */
108
+ .tech-page { max-width: 900px; margin: 0 auto; padding: 0 40px 60px; }
109
+ .tech-hero { text-align: center; margin: 50px 0 40px; }
110
+ .tech-title { font-size: 42px; font-weight: 800; color: #fff; margin-bottom: 14px; }
111
+ .tech-subtitle { font-size: 15px; color: #999; line-height: 1.7; max-width: 600px; margin: 0 auto; }
112
+
113
+ .pipeline-overview {
114
+ display: flex; align-items: center; justify-content: center; gap: 12px;
115
+ margin-bottom: 50px; flex-wrap: wrap;
116
+ }
117
+ .pipeline-step-mini {
118
+ display: flex; flex-direction: column; align-items: center; gap: 8px; text-align: center; width: 110px;
119
+ }
120
+ .flow-arrow { display: flex; align-items: center; color: #6c8cff; }
121
+
122
+ .tech-step {
123
+ background: #111122; border: 1px solid #1e1e35; border-radius: 14px;
124
+ padding: 30px 36px; margin-bottom: 28px;
125
+ }
126
+ .tech-step-header { display: flex; align-items: center; gap: 20px; margin-bottom: 16px; }
127
+ .tech-step-title { font-size: 22px; font-weight: 700; margin-bottom: 4px; }
128
+ .tech-file {
129
+ font-size: 12px; color: #6c8cff; background: rgba(108,140,255,0.1);
130
+ padding: 3px 10px; border-radius: 4px; font-family: 'Consolas', monospace;
131
+ }
132
+ .tech-step-desc { font-size: 14px; color: #aaa; line-height: 1.7; margin-bottom: 20px; }
133
+ .tech-step-diagram {
134
+ background: #0b0b1a; border: 1px solid #1a1a2e; border-radius: 10px;
135
+ padding: 20px; margin-bottom: 20px; text-align: center; overflow-x: auto;
136
+ }
137
+ .step-illustration { max-width: 100%; height: auto; }
138
+ .step-icon { flex-shrink: 0; }
139
+ .tech-step-details {
140
+ list-style: none; padding: 0;
141
+ }
142
+ .tech-step-details li {
143
+ font-size: 13px; color: #bbb; padding: 6px 0 6px 20px; position: relative; line-height: 1.5;
144
+ }
145
+ .tech-step-details li::before {
146
+ content: 'β†’'; position: absolute; left: 0; color: #6c8cff; font-weight: 700;
147
  }
App/templates/index.html CHANGED
@@ -3,7 +3,7 @@
3
  <head>
4
  <meta charset="UTF-8">
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
- <title>DFDetect - DeepFake Detector</title>
7
  <script src="https://unpkg.com/react@18/umd/react.production.min.js" crossorigin></script>
8
  <script src="https://unpkg.com/react-dom@18/umd/react-dom.production.min.js" crossorigin></script>
9
  <script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
 
3
  <head>
4
  <meta charset="UTF-8">
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>AI-Deepfake Video Detection</title>
7
  <script src="https://unpkg.com/react@18/umd/react.production.min.js" crossorigin></script>
8
  <script src="https://unpkg.com/react-dom@18/umd/react-dom.production.min.js" crossorigin></script>
9
  <script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>