alisaeedx3/arabic-text-from-images-extractor

Python

0

4 commits

updated Jul 5, 2026

See the code

README

Arabic OCR Studio — استوديو استخراج النصوص

A self-hosted web app for extracting Arabic (and English) text from images and PDFs using local AI models on your own GPU. No accounts, no cloud, no API keys — your computer is the backend, and you can share it with friends through an ngrok tunnel.

CI license models gpu

Highlights

  • 🧠 Three local models: two Arabic-tuned vision-language models + classic EasyOCR
  • 📄 PDF support — pages are rendered and OCR'd like images
  • 📱 Arabic-first UI (full RTL) with a one-click English toggle — mobile-friendly, drag & drop and paste
  • ⏱ Live token-by-token streaming — watch the text appear as the model reads
  • 🗂 Per-browser history (no sign-in), stored in SQLite or SQL Server
  • 🔁 One shared GPU queue with live queue positions — safe to share with friends

Models

ModelBest forSize
QARI-OCR v0.3 (NAMAA-Space/Qari-OCR-v0.3-VL-2B-Instruct)Printed Arabic — books, documents, screenshots. Keeps diacritics (tashkeel).~4.4 GB
Arabic-English Handwritten OCR v3 (sherif1313/Arabic-English-handwritten-OCR-v3)Handwriting — notes, letters, manuscripts (AR + EN). Runs 4-bit quantized.~7.5 GB
EasyOCR (ar+en)Fast printed text — signs, labels, simple docs.~120 MB

Models download automatically on first use (with a progress bar in the UI). Only one large model is kept in GPU memory at a time; switching models swaps them automatically — a 10 GB GPU (e.g. RTX 3080) runs everything.

Requirements

  • Python 3.10–3.13 (3.12 recommended)
  • NVIDIA GPU with ~8 GB+ VRAM recommended. Without one, the start script installs CPU-only PyTorch and everything still works — EasyOCR stays quick, the two large models get slow but usable for occasional pages.
  • Windows, Linux or macOS. SQL Server is optional (history falls back to a local SQLite file with zero configuration).

Run it

Windows

start.bat

Linux / macOS

./start.sh

That's it. The first run creates a Python environment and installs everything (it detects whether you have an NVIDIA GPU and picks the right PyTorch build). Then open http://localhost:41720.

To stop the server, press Ctrl+C in its window, or run stop.bat (Windows) / ./stop.sh (Linux / macOS) — they kill whatever is listening on the app's port.

Optional: copy .env.example to .env to change the port or point history at SQL Server. With no .env the app uses a local SQLite file — it works out of the box.

Accepted files: any image Pillow can decode — JPG/JFIF, PNG, WEBP, HEIC/HEIF (iPhone photos), AVIF, BMP, TIFF, GIF, ICO… — plus PDF documents (each page is rendered and read separately). Files are validated by content, not extension, and phone photos are auto-rotated via EXIF.

The port 41720 was picked deliberately: it's not a well-known service port and sits below the Windows ephemeral range (49152+), so nothing else should ever claim it. Change it with OCR_PORT in .env if you ever need to.

Use it from your phone / another device on the same Wi-Fi

  1. Windows: run allow-lan-access.bat once, as administrator (right-click → Run as administrator). It adds a firewall rule for TCP 41720. Linux: open the port in your firewall if you use one (e.g. sudo ufw allow 41720/tcp).
  2. Start the app — it prints an "On your network" address like http://192.168.1.23:41720.
  3. Open that address on any device connected to the same network. The UI is fully responsive/mobile-friendly.

Share it with friends over the internet (ngrok)

  1. Install ngrok (winget install ngrok.ngrok on Windows) and add your authtoken (ngrok config add-authtoken <token> — free account at ngrok.com).
  2. While the server is running:
    ngrok http 41720
    
  3. Send the https://xxxx.ngrok-free.app URL to your friends.

Notes:

  • On the free ngrok plan visitors see a one-time "Visit Site" interstitial page — that's normal.
  • Jobs from all users share one GPU queue; the UI shows each user their queue position.
  • Anyone with the URL can use the app. History is separated per browser (an anonymous ID in localStorage), not per account — treat the URL like a key.

How it works

  • Backend — FastAPI (Python) in backend/: job queue with one GPU worker, token-by-token streaming of VLM output so users see text appear live, Hugging Face download progress reporting, PDF page rendering via pypdfium2.
  • Frontend — vanilla HTML/JS/CSS in frontend/, no build step: Arabic-first RTL UI with an English toggle, drag & drop / paste, model + effort dropdowns, live progress, per-image results with copy/download, history with one-click re-run of past images.
  • Database — SQL Server (configured in .env, database auto-created) stores job history. If SQL Server is unreachable or not configured, the app automatically falls back to SQLite (data/history.db) and keeps working. The active backend shows as a badge in the UI header.
  • Uploads are stored under data/uploads/<job-id>/ with generated thumbnails, and removed when the job is deleted from history.

Effort levels

EffortWhat it changes
Fast سريعLower image resolution fed to the model, shorter output budget
Balanced متوازنDefault resolution/tokens
Quality جودةHighest resolution + longest output budget (slowest)

Configuration

All settings live in .env (copy from .env.example): OCR_PORT, OCR_MSSQL_SERVER, OCR_MSSQL_DATABASE, OCR_MSSQL_USER, OCR_MSSQL_PASSWORD, OCR_MSSQL_DRIVER. Everything is optional — without SQL Server credentials, history is stored in SQLite. .env is gitignored; never commit real credentials.

API (for scripting)

Interactive docs are served at /docs (FastAPI's built-in Swagger UI).

  • GET /api/models — available models + upload limits
  • POST /api/jobs — multipart: files (images/PDFs), model, effort; header X-Client-Id
  • GET /api/jobs/{id} — live status, progress, partial text, results
  • DELETE /api/jobs/{id} — cancel
  • GET /api/history, DELETE /api/history/{id} — per-client history
  • GET /api/health

Example:

curl -X POST http://localhost:41720/api/jobs \
  -H "X-Client-Id: my-script" \
  -F "[email protected]" -F "model=qari" -F "effort=balanced"

Troubleshooting

  • "Python not found" — install Python 3.12 from python.org and check Add python.exe to PATH in the installer.
  • No GPU / "CPU mode" badge — the app works on CPU; use EasyOCR for speed. If you do have an NVIDIA GPU, make sure its driver is installed (nvidia-smi should work), delete the .venv folder and start again so the CUDA PyTorch build gets installed.
  • Out of GPU memory — close other GPU apps (games, other model servers). The handwritten model already runs 4-bit quantized to fit 10 GB cards.
  • HEIC photos don't upload from Windows Explorer — they do; the preview thumbnail may show a placeholder icon, but the server decodes them fine.
  • First extraction is slow — the model is downloading (progress shows in the UI) and then loading into GPU memory. Later runs are much faster.
  • Dependencies changed after git pull — the start scripts re-install automatically when backend/requirements.txt changes.

Contributing

Issues and PRs are welcome — model suggestions especially (the model registry in backend/ocr/ makes new engines easy to add: subclass OCRModel, register it in backend/ocr/__init__.py).

CI runs a lint (ruff check backend) and an API smoke test (ci/smoke_test.py) that works without a GPU.

License

MIT

alisaeedx3/arabic-text-from-images-extractor

Python

0

4 commits

updated Jul 5, 2026

See the code

README

Arabic OCR Studio — استوديو استخراج النصوص

A self-hosted web app for extracting Arabic (and English) text from images and PDFs using local AI models on your own GPU. No accounts, no cloud, no API keys — your computer is the backend, and you can share it with friends through an ngrok tunnel.

CI license models gpu

Highlights

  • 🧠 Three local models: two Arabic-tuned vision-language models + classic EasyOCR
  • 📄 PDF support — pages are rendered and OCR'd like images
  • 📱 Arabic-first UI (full RTL) with a one-click English toggle — mobile-friendly, drag & drop and paste
  • ⏱ Live token-by-token streaming — watch the text appear as the model reads
  • 🗂 Per-browser history (no sign-in), stored in SQLite or SQL Server
  • 🔁 One shared GPU queue with live queue positions — safe to share with friends

Models

ModelBest forSize
QARI-OCR v0.3 (NAMAA-Space/Qari-OCR-v0.3-VL-2B-Instruct)Printed Arabic — books, documents, screenshots. Keeps diacritics (tashkeel).~4.4 GB
Arabic-English Handwritten OCR v3 (sherif1313/Arabic-English-handwritten-OCR-v3)Handwriting — notes, letters, manuscripts (AR + EN). Runs 4-bit quantized.~7.5 GB
EasyOCR (ar+en)Fast printed text — signs, labels, simple docs.~120 MB

Models download automatically on first use (with a progress bar in the UI). Only one large model is kept in GPU memory at a time; switching models swaps them automatically — a 10 GB GPU (e.g. RTX 3080) runs everything.

Requirements

  • Python 3.10–3.13 (3.12 recommended)
  • NVIDIA GPU with ~8 GB+ VRAM recommended. Without one, the start script installs CPU-only PyTorch and everything still works — EasyOCR stays quick, the two large models get slow but usable for occasional pages.
  • Windows, Linux or macOS. SQL Server is optional (history falls back to a local SQLite file with zero configuration).

Run it

Windows

start.bat

Linux / macOS

./start.sh

That's it. The first run creates a Python environment and installs everything (it detects whether you have an NVIDIA GPU and picks the right PyTorch build). Then open http://localhost:41720.

To stop the server, press Ctrl+C in its window, or run stop.bat (Windows) / ./stop.sh (Linux / macOS) — they kill whatever is listening on the app's port.

Optional: copy .env.example to .env to change the port or point history at SQL Server. With no .env the app uses a local SQLite file — it works out of the box.

Accepted files: any image Pillow can decode — JPG/JFIF, PNG, WEBP, HEIC/HEIF (iPhone photos), AVIF, BMP, TIFF, GIF, ICO… — plus PDF documents (each page is rendered and read separately). Files are validated by content, not extension, and phone photos are auto-rotated via EXIF.

The port 41720 was picked deliberately: it's not a well-known service port and sits below the Windows ephemeral range (49152+), so nothing else should ever claim it. Change it with OCR_PORT in .env if you ever need to.

Use it from your phone / another device on the same Wi-Fi

  1. Windows: run allow-lan-access.bat once, as administrator (right-click → Run as administrator). It adds a firewall rule for TCP 41720. Linux: open the port in your firewall if you use one (e.g. sudo ufw allow 41720/tcp).
  2. Start the app — it prints an "On your network" address like http://192.168.1.23:41720.
  3. Open that address on any device connected to the same network. The UI is fully responsive/mobile-friendly.

Share it with friends over the internet (ngrok)

  1. Install ngrok (winget install ngrok.ngrok on Windows) and add your authtoken (ngrok config add-authtoken <token> — free account at ngrok.com).
  2. While the server is running:
    ngrok http 41720
    
  3. Send the https://xxxx.ngrok-free.app URL to your friends.

Notes:

  • On the free ngrok plan visitors see a one-time "Visit Site" interstitial page — that's normal.
  • Jobs from all users share one GPU queue; the UI shows each user their queue position.
  • Anyone with the URL can use the app. History is separated per browser (an anonymous ID in localStorage), not per account — treat the URL like a key.

How it works

  • Backend — FastAPI (Python) in backend/: job queue with one GPU worker, token-by-token streaming of VLM output so users see text appear live, Hugging Face download progress reporting, PDF page rendering via pypdfium2.
  • Frontend — vanilla HTML/JS/CSS in frontend/, no build step: Arabic-first RTL UI with an English toggle, drag & drop / paste, model + effort dropdowns, live progress, per-image results with copy/download, history with one-click re-run of past images.
  • Database — SQL Server (configured in .env, database auto-created) stores job history. If SQL Server is unreachable or not configured, the app automatically falls back to SQLite (data/history.db) and keeps working. The active backend shows as a badge in the UI header.
  • Uploads are stored under data/uploads/<job-id>/ with generated thumbnails, and removed when the job is deleted from history.

Effort levels

EffortWhat it changes
Fast سريعLower image resolution fed to the model, shorter output budget
Balanced متوازنDefault resolution/tokens
Quality جودةHighest resolution + longest output budget (slowest)

Configuration

All settings live in .env (copy from .env.example): OCR_PORT, OCR_MSSQL_SERVER, OCR_MSSQL_DATABASE, OCR_MSSQL_USER, OCR_MSSQL_PASSWORD, OCR_MSSQL_DRIVER. Everything is optional — without SQL Server credentials, history is stored in SQLite. .env is gitignored; never commit real credentials.

API (for scripting)

Interactive docs are served at /docs (FastAPI's built-in Swagger UI).

  • GET /api/models — available models + upload limits
  • POST /api/jobs — multipart: files (images/PDFs), model, effort; header X-Client-Id
  • GET /api/jobs/{id} — live status, progress, partial text, results
  • DELETE /api/jobs/{id} — cancel
  • GET /api/history, DELETE /api/history/{id} — per-client history
  • GET /api/health

Example:

curl -X POST http://localhost:41720/api/jobs \
  -H "X-Client-Id: my-script" \
  -F "[email protected]" -F "model=qari" -F "effort=balanced"

Troubleshooting

  • "Python not found" — install Python 3.12 from python.org and check Add python.exe to PATH in the installer.
  • No GPU / "CPU mode" badge — the app works on CPU; use EasyOCR for speed. If you do have an NVIDIA GPU, make sure its driver is installed (nvidia-smi should work), delete the .venv folder and start again so the CUDA PyTorch build gets installed.
  • Out of GPU memory — close other GPU apps (games, other model servers). The handwritten model already runs 4-bit quantized to fit 10 GB cards.
  • HEIC photos don't upload from Windows Explorer — they do; the preview thumbnail may show a placeholder icon, but the server decodes them fine.
  • First extraction is slow — the model is downloading (progress shows in the UI) and then loading into GPU memory. Later runs are much faster.
  • Dependencies changed after git pull — the start scripts re-install automatically when backend/requirements.txt changes.

Contributing

Issues and PRs are welcome — model suggestions especially (the model registry in backend/ocr/ makes new engines easy to add: subclass OCRModel, register it in backend/ocr/__init__.py).

CI runs a lint (ruff check backend) and an API smoke test (ci/smoke_test.py) that works without a GPU.

License

MIT