enver/tajweedsst
TajweedSST — Quranic Letter-Level Alignment & Tajweed Physics Engine
CTC Forced Alignment + Acoustic Physics Validation for Quranic Recitation
Overview
TajweedSST is a Python pipeline that produces letter-level timing data for Quranic recitation audio. It combines wav2vec2 CTC forced alignment with acoustic physics validation (Tajweed rules) to generate timing files consumed by MahQuranApp for real-time letter highlighting.
Pipeline Architecture
┌─────────────────────────────────────────────────────────────┐
│ TajweedSST Pipeline │
│ │
│ 1. CTC Forced Alignment (wav2vec2) │
│ └─ Word-level timestamps from audio │
│ │
│ 2. Character Expansion │
│ └─ Word timestamps → individual character timing │
│ │
│ 3. Grapheme Matching │
│ └─ Merge base + diacritics to match App.tsx rendering │
│ │
│ 4. Tajweed Parsing │
│ └─ Map letters to Tajweed rules (Qalqalah, Ghunnah..) │
│ │
│ 5. Physics Validation │
│ └─ RMS bounce, duration, formant analysis │
│ │
│ 6. Export to MahQuranApp format │
│ └─ JSON with idx, char, ayah, start(ms), end, wordIdx │
└─────────────────────────────────────────────────────────────┘Quick Start
Prerequisites
cd /path/to/tajweedsst
python3 -m venv venv
source venv/bin/activate
pip install torch torchaudio ctc-forced-aligner librosaSingle Surah
# Align Surah 90 (Al-Balad) for Abdul Basit
python ctc_align_91.py # Template scriptBatch All Surahs
# Process all 114 surahs for Abdul Basit
python batch_align_all.pyOutput Format
Each letter_timing_XX.json contains an array of timing entries:
{
"idx": 0,
"char": "لَ",
"ayah": 1,
"start": 3360,
"end": 3410,
"duration": 50,
"wordIdx": 0,
"weight": 1.0
}Fields
Critical: Grapheme Matching
The timing data must match the grapheme count produced by MahQuranApp's splitIntoGraphemes() function. This function combines base Arabic letters with their following diacritics:
App.tsx Diacritics Set:
ً ٌ ٍ َ ُ ِ ّ ْ ٰ ۖ ۗ ۘ ۙ ۚ ۛ ۜ ٔ ٓ ـPlus Unicode ranges: 0x064B–0x0652 and 0x0610–0x061A
Example: The word لَآ splits into 2 graphemes: ['لَ', 'آ']
If the timing count doesn't match the grapheme count, highlighting will drift!
Physics Validation
TajweedSST validates timing against acoustic physics:
Project Structure
tajweedsst/
├── src/
│ ├── tajweed_parser.py # Tajweed rule detection
│ ├── physics_validator.py # Acoustic validation
│ └── duration_model.py # Duration calibration
├── tests/ # 34 unit/integration tests
├── ctc_align_90.py # Single surah alignment
├── ctc_align_91.py # Template with physics
├── batch_align_all.py # Batch all surahs
└── README.mdReciter Support
Currently supported:
- Abdul Basit (114 surahs)
License
MIT
