hetchyy's picture
Restructure src/ for cleaner modularity
0351f22
"""Quran Aligner — Automatic Quran recitation segmentation and alignment."""
import sys
from pathlib import Path
# Add paths for imports BEFORE importing anything else
_app_path = Path(__file__).parent.resolve()
sys.path.insert(0, str(_app_path))
# Build Cython extensions in-place (falls back to pure Python if it fails)
import subprocess
subprocess.run(
[sys.executable, str(_app_path / "setup.py"), "build_ext", "--inplace"],
cwd=str(_app_path),
capture_output=True,
)
from src.ui.interface import build_interface
# =============================================================================
# Module-level demo for Gradio hot-reload (`gradio app.py`)
# =============================================================================
demo = build_interface()
# =============================================================================
# Main
# =============================================================================
if __name__ == "__main__":
import argparse
import numpy as np
import librosa
from config import PORT, IS_HF_SPACE, RESAMPLE_TYPE
from src.core.zero_gpu import ZERO_GPU_AVAILABLE
from src.segmenter.segmenter_model import load_segmenter
from src.segmenter.segmenter_aoti import apply_aoti_compiled
from src.pipeline import test_aoti_compilation_gpu
from src.alignment.phoneme_asr import load_phoneme_asr
from src.alignment.ngram_index import get_ngram_index
from src.alignment.phoneme_matcher_cache import preload_all_chapters
parser = argparse.ArgumentParser()
parser.add_argument("--share", action="store_true", help="Create public link")
parser.add_argument("--port", type=int, default=PORT, help="Port to run on")
args = parser.parse_args()
port = 7860
print(f"ZeroGPU available: {ZERO_GPU_AVAILABLE}")
print(f"Launching Gradio on port {port}")
# Preload models and caches at startup so first request is fast
print("Preloading models...")
load_segmenter()
load_phoneme_asr("Base")
load_phoneme_asr("Large")
print("Models preloaded.")
print("Preloading caches...")
get_ngram_index()
preload_all_chapters()
print("Caches preloaded.")
# Warm up soxr resampler so first request doesn't pay initialization cost
_dummy = librosa.resample(np.zeros(1600, dtype=np.float32),
orig_sr=44100, target_sr=16000, res_type=RESAMPLE_TYPE)
del _dummy
print("Resampler warmed up.")
# AoT compilation for VAD model (requires GPU lease)
if IS_HF_SPACE and ZERO_GPU_AVAILABLE:
print("Running AoT compilation for VAD model...")
try:
aoti_result = test_aoti_compilation_gpu()
print(f"AoT compile result: {aoti_result}")
# Apply compiled model OUTSIDE GPU lease (critical for persistence)
if aoti_result.get("compiled"):
apply_aoti_compiled(aoti_result["compiled"])
except Exception as e:
print(f"AoT compilation failed (non-fatal): {e}")
demo.launch(
server_name="0.0.0.0",
server_port=port,
share=args.share,
allowed_paths=["/tmp"],
)