| title | DeepFake Detect |
|---|---|
| emoji | π |
| colorFrom | red |
| colorTo | gray |
| sdk | docker |
| app_port | 7860 |
| short_description | Face-level deepfake video detection with a Docker-based web app. |
A Python-based deepfake video detection project with two main parts:
- An offline training pipeline that extracts frames, crops faces, prepares labeled data, and trains a binary classifier.
- A Flask web application that accepts uploaded videos, analyzes faces, returns authenticity scores, and generates a processed preview video with face boxes.
The current repository is focused on face-level deepfake detection rather than general-purpose video understanding.
- Takes videos as input and samples frames once per second.
- Uses
MTCNNto detect and crop faces from extracted frames. - Uses FaceForensics++ CSV metadata to label face samples as
REALorFAKE. - Filters out very small face crops and builds
train / val / testdatasets. - Trains an
EfficientNetB0-based classifier with transfer learning and fine-tuning. - Provides a Flask web app for interactive video analysis.
- Backend:
Flask - Deep learning:
TensorFlow / Keras - Main classifier:
EfficientNetB0 - Face detection for training/inference crops:
MTCNN - Face detection for preview overlays:
YOLOv8 face - Video processing:
OpenCV,ffmpegviaimageio-ffmpeg - Dataset splitting:
split-folders
Script: 00-convert_video_to_image.py
- Reads videos from subfolders under
train_sample_videos/FaceForensics++_C23/. - Extracts 1 frame per second.
- Dynamically rescales each frame based on source resolution:
- Width
< 300: scale to2x - Width
> 1900: scale to0.33x - Width
1000 ~ 1900: scale to0.5x - Otherwise: keep original size
- Width
- Stores extracted PNG frames in a per-video directory.
Script: 01-crop_faces_with_mtcnn.py
- Runs
MTCNNon every extracted frame. - If a frame contains only one face, that detection is kept.
- If a frame contains multiple faces, only detections with confidence above
0.95are kept. - Expands each bounding box by
30%to preserve more facial context. - Saves cropped faces into a
faces/subdirectory for each video.
Script: 02-prepare_fake_real_dataset.py
- Reads labels from
csv/*.csv. - Copies face crops into:
prepared_dataset/realprepared_dataset/fake
- Filters out any image with width or height smaller than
90px. - Splits the final dataset with
split-foldersinto:split_dataset/trainsplit_dataset/valsplit_dataset/test
Script: 03-train_cnn.py
- Input size:
224x224 - Backbone:
EfficientNetB0(weights="imagenet") - Output: single-unit
sigmoidbinary classifier - Training strategy:
- Phase 1: freeze the backbone and train only the head with learning rate
1e-3 - Phase 2: unfreeze the full model and fine-tune with learning rate
1e-5
- Phase 1: freeze the backbone and train only the head with learning rate
- Data augmentation includes:
- rotation
- horizontal flip
- zoom
- translation
- brightness jitter
- Uses:
EarlyStoppingModelCheckpointReduceLROnPlateau
- Applies class weights to reduce
fake/realimbalance.
The best trained model is saved to:
tmp_checkpoint/best_model.keras
This is the canonical model output path used by the training pipeline.
App entry point: App/app.py
Routes: App/route.py
Frontend files:
When a video is uploaded, the backend performs these steps:
- Validates the file type:
mp4,avi,mov,mkv,wmv - Re-encodes the uploaded video to browser-friendly
H.264 - Reads frames roughly once per second
- Uses
MTCNNto extract faces for classification - Runs
EfficientNetB0inference on each face crop - Sorts all face scores from highest to lowest and averages the top
30% - If the averaged score is
> 0.5, the video is labeledREAL; otherwiseFAKE - Returns:
- final label
- confidence
- model score
- number of faces analyzed
- face thumbnails with per-face scores
- Uses
YOLOv8 faceto generate a preview video with face bounding boxes
Notes:
MTCNNis used for the actual face crops fed into the classifier.YOLOv8 faceis currently used for visualization in the processed preview video, not as the classifier itself.
DeepFake-Detect/
βββ 00-convert_video_to_image.py
βββ 01-crop_faces_with_mtcnn.py
βββ 02-prepare_fake_real_dataset.py
βββ 03-train_cnn.py
βββ tmp_checkpoint/
β βββ best_model.keras
β βββ best_model_phase1.keras
βββ App/
β βββ app.py
β βββ route.py
β βββ yolov8n-face.pt
β βββ static/
β βββ templates/
βββ train_sample_videos/
β βββ FaceForensics++_C23/
βββ best_model.keras
βββ pyproject.toml
βββ uv.lock
The training scripts expect the dataset root at:
train_sample_videos/FaceForensics++_C23/
The repository currently contains these visible subdirectories:
originalDeepfakesDeepFakeDetectionFace2FaceFaceSwapFaceShifterNeuralTexturescsv
CSV files include fields such as:
File PathLabelFrame CountWidthHeightCodecFile Size(MB)
- Python
>= 3.12 uvis recommended- For training, an NVIDIA GPU that TensorFlow can detect is strongly recommended
- For the web app, a working
ffmpegruntime is required; the project accesses it throughimageio-ffmpeg
uv syncpython -m venv .venv
source .venv/bin/activate
pip install -e .The web app resolves the model in this order:
tmp_checkpoint/best_model.keras
best_model.keras
tmp_checkpoint/best_model.keras is the canonical location. The root-level best_model.keras is treated as a compatibility fallback only.
If you want the project to use the standard training output path, place the model here:
mkdir -p tmp_checkpoint
cp best_model.keras tmp_checkpoint/best_model.kerasIf you want to train from scratch, follow the training sequence below. The training script will generate this file automatically.
uv run python App/app.pyThen open:
http://127.0.0.1:5001
The app now defaults to port 5001. You can override it with an environment variable:
PORT=5050 uv run python App/app.pyThis repository is now prepared for a Docker-based Hugging Face Space.
Deployment files:
The Space configuration is defined in the YAML header at the top of this README:
sdk: dockerapp_port: 7860
Container runtime behavior:
- The container runs the Flask app with
python App/app.py - The Docker image sets
PORT=7860 - The Docker image sets
ENABLE_PREVIEW_FACE_DETECTOR=0 - The app itself already supports
PORT, so it matches Hugging Face Spaces routing
Recommended deployment steps:
- Create a new Hugging Face Space and choose
Dockeras the SDK. - Push this repository to that Space repository.
- Wait for the image build to complete.
- Open the Space once the container becomes healthy.
Notes for this project on Spaces:
- The Docker build excludes local training data and the duplicate root-level
best_model.kerasfrom the build context. - The canonical runtime model remains
tmp_checkpoint/best_model.keras. - The app uses CPU by default unless you assign GPU hardware to the Space.
- To keep the Docker image smaller and easier to build, the Space disables YOLO-based preview overlays by default and falls back to a re-encoded original video.
Local Docker smoke test:
docker build -t deepfake-detect-space .
docker run --rm -p 7860:7860 deepfake-detect-spaceThen open:
http://127.0.0.1:7860
To reproduce the full training pipeline, run the scripts in this order:
uv run python 00-convert_video_to_image.py
uv run python 01-crop_faces_with_mtcnn.py
uv run python 02-prepare_fake_real_dataset.py
uv run python 03-train_cnn.py- Frame extraction output: per-video frame folders
- Face crops:
faces/inside each processed video folder - Aggregated dataset:
prepared_dataset/ - Train/validation/test splits:
split_dataset/ - Trained model:
tmp_checkpoint/best_model.keras - Phase 1 checkpoint:
tmp_checkpoint/best_model_phase1.keras - Compatibility fallback model:
best_model.keras - Web upload directory:
App/uploads/ - Inference diagnostics log:
App/diag_log.txt
These details matter when understanding the current system:
- This is a face-crop-based binary classifier, not an end-to-end video transformer.
- The model score semantics are: values closer to
1mean more likely real, values closer to0mean more likely fake. - The video-level decision is not a plain average across all faces; it uses the mean of the highest-scoring subset.
- The upload endpoint enforces a
200 MBlimit. - The app cleans old uploaded files, so
App/uploads/should not be treated as persistent storage.
- Both training and inference depend heavily on face detection quality.
- The current sampling strategy uses only 1 frame per second, which may miss short-lived manipulation artifacts.
- The repository does not currently provide a standalone CLI inference script; the primary entry point is the Flask app.
- The canonical model path is
tmp_checkpoint/best_model.keras, but the app also supportsbest_model.kerasin the repository root as a fallback. - This README is based on the current codebase behavior. If UI text and code behavior differ, trust the code.
- Add a CLI inference entry point
- Move paths, thresholds, and input/output directories into configuration
- Persist training metrics and experiment logs
- Add batch video inference support
- Add Docker and deployment documentation
No explicit license file is present in the repository at the moment. If you plan to publish or use this project commercially, add a proper license first.