ArA-DF-Baseline
Arabic deepfake audio detector for the
ArA-DF 2026 shared task,
published under the
ArabicSpeech organization.
Architecture: wav2vec2 XLS-R 300M frontend + AASIST backend.
Benchmark results
Split EER ↓ (%) # utterances track-1_development_test 14.65 16,023 track-1_test 14.54 144,210 track-2_development_test 27.21 14,193 track-2_test 27.11 127,746
track-1_development_test / track-1_test — Track 1 development / evaluation phases (CodaBench).
track-2_development_test / track-2_test — Track 2 development / evaluation phases (CodaBench).
Repository contents
File Description best_model.pthTrained DeepFense checkpoint xlsr2_300m.ptFairseq XLS-R 300M frontend weights config.yamlDeepFense config — fill in your parquet_files paths before use build_parquets.pyStandalone parquet generation script (no DeepFense install needed) results.jsonPublished metrics on the two test tracks above
Architecture
Raw waveform (16 kHz)
│
▼
wav2vec2 XLS-R 300M (xlsr2_300m.pt, fairseq)
frame-level features → (T, 1024)
│
▼
AASIST backend
Linear(1024 → 128)
RawNet2 encoder — 6 residual blocks on a 2-D (freq × time) map
Spectral attention — soft attention along frequency axis → spectral graph nodes
Temporal attention — soft attention along time axis → temporal graph nodes
GAT_S / GAT_T — independent graph attention on each graph
HtrgGAT ×4 — heterogeneous cross-graph attention with learnable master nodes
Graph pooling + readout: max & mean over S, T, and master → 160-d embedding
│
▼
CrossEntropy head → P(bonafide) / P(spoof)
The AASIST backend is from
Jung et al., ICASSP 2022 .
This checkpoint uses mean pooling on XLS-R frame features before the backend.
Step 0 — Install DeepFense
1 git clone https://github.com/Yaselley/deepfense-framework.git
2 cd deepfense-framework
3 conda create -n deepfense python = 3.10 -y
4 conda activate deepfense
5 pip install deepfense
Download this model (same root as the dataset — see Step 1):
huggingface-cli download ArabicSpeech/ArA-DF-Baseline --local-dir ArA-DF-2026/models/ArA-DF-Baseline
or
hf download ArabicSpeech/ArA-DF-Baseline --local-dir ArA-DF-2026/models/ArA-DF-Baseline
All tutorial paths use ArA-DF-2026 under your home directory (no root/write access needed).
On a cluster you can substitute e.g. /data/ArA-DF-2026 if you have write permission there — keep paths consistent across steps.
Step 1 — Download the ArA-DF 2026 dataset
The audio is distributed as WebDataset TAR shards on Hugging Face.
1 huggingface-cli download ArabicSpeech/ArA-DF-2026 \
2 --repo-type dataset \
3 --local-dir ArA-DF-2026
or
1 hf download ArabicSpeech/ArA-DF-2026 \
2 --repo-type dataset \
3 --local-dir ArA-DF-2026
After the download, the layout on disk is:
ArA-DF-2026/
├── data/
│ ├── train/
│ ├── dev/
│ ├── track-1_development_test/
│ ├── track-1_test/
│ ├── track-2_development_test/
│ └── track-2_test/
├── metadata/
│ ├── train.parquet
│ ├── dev.parquet
│ ├── track-1_development_test.parquet
│ ├── track-1_test.parquet
│ ├── track-2_development_test.parquet
│ └── track-2_test.parquet
└── models/
└── ArA-DF-Baseline/ ← from Step 0
├── config.yaml
├── best_model.pth
└── xlsr2_300m.pt
Step 2 — Extract the audio
Extract every TAR in-place (same command for all splits):
1 for split in train dev track-1_development_test track-1_test track-2_development_test track-2_test ; do
2 cd ArA-DF-2026/data/ $split
3 for tar in *.tar ; do tar -xf " $tar " ; done
4 cd -
5 done
After extraction, FLACs may land flat (directly in the split folder) or in shard sub-folders — both work. build_parquets.py auto-detects either layout.
Flat example:
ArA-DF-2026/data/track-1_test/
├── track-1_test-000000.tar
├── test_0000008.flac
├── test_0000031.flac
└── ...
Argument Value --data_rootArA-DF-2026/data--meta_rootArA-DF-2026/metadata
Step 3 — Generate DeepFense parquet files
Parquet files hold the metadata DeepFense reads at training/evaluation time.
Each row has: ID, path (absolute path to audio), label (1 as bonafide or 0 as spoof), dataset_name.
Label convention (HF metadata, parquets, and this model's training):
Class HF label DeepFense label_map bonafide 11 (bonafide)spoof 00 (spoof)
A standalone build_parquets.py script is included in this repo. It only needs pandas and pyarrow:
1 pip install pandas pyarrow
2
3 cd ArA-DF-2026/models/ArA-DF-Baseline
4 python build_parquets.py \
5 --data_root .. / .. /data \
6 --meta_root .. / .. /metadata \
7 --output_dir .. / .. /parquets
Output:
ArA-DF-2026/parquets/
├── aradf_train.parquet
├── aradf_val.parquet
├── aradf_track-1_development_test.parquet ← Track 1, CodaBench dev phase
├── aradf_track-1_test.parquet ← Track 1, CodaBench eval phase
├── aradf_track-2_development_test.parquet ← Track 2, CodaBench dev phase
└── aradf_track-2_test.parquet ← Track 2, CodaBench eval phase
Test-only (skip train/dev):
1 python build_parquets.py \
2 --data_root .. / .. /data \
3 --meta_root .. / .. /metadata \
4 --output_dir .. / .. /parquets \
5 --splits track-1_development_test track-1_test track-2_development_test track-2_test
Step 4 — Fill in config.yaml
After downloading, all files live under ArA-DF-2026/models/ArA-DF-Baseline/:
ArA-DF-2026/models/ArA-DF-Baseline/
├── config.yaml
├── best_model.pth
└── xlsr2_300m.pt ← Fairseq XLS-R 300M frontend (bundled)
Fairseq / XLS-R checkpoint (absolute path required )
Set ckpt_path to the absolute path of xlsr2_300m.pt on your machine:
1 model :
2 frontend :
3 args :
4 source : fairseq
5 ckpt_path : ArA - DF - 2026/models/ArA - DF - Baseline/xlsr2_300m.pt
Expand ~ to your home directory, e.g. /home/you/ArA-DF-2026/models/ArA-DF-Baseline/xlsr2_300m.pt.
Do not use a relative path — train.py / test.py may fail depending on the working directory.
Parquet paths (required for training / local evaluation)
Replace the placeholder parquet paths under data.train, data.val, and data.test:
1 data :
2 train :
3 parquet_files :
4 - ArA - DF - 2026/parquets/aradf_train.parquet
5 val :
6 parquet_files :
7 - ArA - DF - 2026/parquets/aradf_val.parquet
8 test :
9 dataset_names :
10 - track - 1_development_test
11 - track - 1_test
12 - track - 2_development_test
13 - track - 2_test
14 parquet_files :
15 - ArA - DF - 2026/parquets/aradf_track - 1_development_test.parquet
16 - ArA - DF - 2026/parquets/aradf_track - 1_test.parquet
17 - ArA - DF - 2026/parquets/aradf_track - 2_development_test.parquet
18 - ArA - DF - 2026/parquets/aradf_track - 2_test.parquet
run_inference.py only needs --config and --checkpoint — it does not read the parquet paths.
Competition Submission (no labels required)
For the ArA-DF 2026 shared task you submit a ZIP file containing one CSV per track.
CodaBench expects a continuous bonafide score per utterance — not hard 0/1 labels.
Use the bundled run_inference.py script. DeepFense must be installed (see Step 0).
Point --audio_dir at the folder for the current CodaBench phase .
1
2 # Track 1 — development phase
3 # set Model to the absolute path of models/ArA-DF-Baseline
4 MODEL = "/netscratch/yelkheir/DeepFense/ArA-DF-2026/models/ArA-DF-Baseline"
5 cd ArA-DF-2026/models/ArA-DF-Baseline
6
7 python run_inference.py \
8 --audio_dir .. / .. /data/track-1_development_test \
9 --config $MODEL /config.yaml \
10 --checkpoint $MODEL /best_model.pth \
11 --output track1_preds.csv
12 zip submission_track1.zip track1_preds.csv
13
14 # Track 1 — evaluation phase (re-run with track-1_test/)
15 python run_inference.py \
16 --audio_dir .. / .. /data/track-1_test \
17 --config $MODEL /config.yaml \
18 --checkpoint $MODEL /best_model.pth \
19 --output track1_preds.csv
20 zip submission_track1.zip track1_preds.csv
21
22 # Track 2 — development phase
23 python run_inference.py \
24 --audio_dir .. / .. /data/track-2_development_test \
25 --config $MODEL /config.yaml \
26 --checkpoint $MODEL /best_model.pth \
27 --output track2_preds.csv
28 zip submission_track2.zip track2_preds.csv
29
30 # Track 2 — evaluation phase (re-run with track-2_test/)
31 python run_inference.py \
32 --audio_dir .. / .. /data/track-2_test \
33 --config $MODEL /config.yaml \
34 --checkpoint $MODEL /best_model.pth \
35 --output track2_preds.csv
36 zip submission_track2.zip track2_preds.csv
Upload submission_track1.zip / submission_track2.zip on the My Submissions tab of the matching CodaBench competition.
Output format:
1 audio_id , logit
2 test_0000008 , 1.45364702
3 test_0000031 , -1.95676708
audio_id — utterance ID (filename stem, without .flac)
logit — bonafide score from DeepFense (CrossEntropy.get_score, same as test.py / outputs["scores"]). Label map: bonafide=1, spoof=0 (matches HF metadata) → higher = more likely bonafide
The column is named logit to match the CodaBench submission format
No thresholding — CodaBench computes EER from the raw scores
run_inference.py searches recursively inside --audio_dir (works with the shard sub-folders)
Note: test.py (below) requires a label column in the parquet for local EER.
Use run_inference.py for CodaBench submissions.
Evaluate (with labels)
1 cd deepfense-framework
2 python test.py \
3 --config ArA-DF-2026/models/ArA-DF-Baseline/config.yaml \
4 --checkpoint ArA-DF-2026/models/ArA-DF-Baseline/best_model.pth
Metrics are printed and saved to results.json. Per-sample scores are written to results/predictions/<dataset_name>_predictions.txt.
Train from scratch
1 cd deepfense-framework
2 python train.py --config ArA-DF-2026/models/ArA-DF-Baseline/config.yaml
The best checkpoint is saved to outputs/<exp_name>_<timestamp>/best_model.pth. Evaluate with:
1 python test.py \
2 --config ArA-DF-2026/models/ArA-DF-Baseline/config.yaml \
3 --checkpoint outputs/ < exp_name > _*/best_model.pth
Multi-GPU (PyTorch DDP):
torchrun --nproc_per_node=4 train.py --config /path/to/config.yaml
Citation
1 @inproceedings{jung2022aasist,
2 title={AASIST: Audio Anti-Spoofing using Integrated Spectro-Temporal Graph Attention Networks},
3 author={Jung, Jee-weon and others},
4 booktitle={ICASSP},
5 year={2022}
6 }
Links