# sidneyowallah/dholuo-tts architecture

> Architecture diagram of the GitHub repository sidneyowallah/dholuo-tts, generated by GitDiagram from its file tree, README and a sample of source files (last updated 2026-08-12). It is an AI-made overview: check details against the source.

- Interactive diagram: https://gitdiagram.com/sidneyowallah/dholuo-tts
- Repository: https://github.com/sidneyowallah/dholuo-tts

## Overview

#### Purpose and Entry Points
This repository builds and serves a POS-aware Dholuo text-to-speech system. Raw text is grammatically tagged, converted to tone-marked IPA, then synthesized by gender-specific VITS models. Primary runtime entry points are the FastAPI app in `api/main.py`, local pipeline CLI scripts such as `train_vits.py`, and the Next.js demo in `web/app/page.tsx`.

#### Linguistic Inference Pipeline
`tagger.py` loads the fine-tuned AfroXLMR POS model and emits `(word, POS)` pairs. `phonemizer.py` applies Dholuo grapheme rules, digraph handling, vowel normalization, and POS-driven tone injection; it can invoke the tagger for raw-text input. This boundary isolates linguistic normalization from acoustic inference.
Paths: `tagger.py`, `phonemizer.py`, `generate_lexicon.py`.

#### Dataset Preparation and Training
The offline pipeline transcribes DhoNam audio, cleans/splits records by gender, applies POS labels, creates IPA metadata, and trains separate VITS voices. POS training is independently managed from TTS training, allowing the tagger and acoustic checkpoints to evolve separately.
Paths: `transcribe_audio.py`, `apply_pos_tags.py`, `create_vits_metadata.py`, `train_pos_local.py`, `train_vits.py`.

#### Model and Artifact Lifecycle
Inference expects a POS model plus male/female TTS checkpoints. Model acquisition is designed to work from local artifacts or the Hugging Face Hub, avoiding model files in the repository. Training uses AfroXLMR (`Davlan/afro-xlmr-large-76L`) for tagging and VITS for acoustic generation; GPU training targets NVIDIA hardware.
Paths: `api/models.py`, `api/inference.py`, `scripts/upload_models_to_hub.py`.

#### Serving API
FastAPI initializes application configuration and routes, coordinates model loading, runs text → POS → IPA → waveform inference, and returns synthesized audio plus linguistic information for the UI. A cache layer prevents repeated expensive synthesis/model work. API concerns are kept under `api/`, separate from reusable NLP modules at the repository root.
Paths: `api/main.py`, `api/routes.py`, `api/inference.py`, `api/cache.py`, `api/config.py`.

#### Web Demo Client
The standalone Next.js frontend accepts text and selected voice, calls the API through a client abstraction, and renders playback plus linguistic/phonetic output. Its runtime boundary is an environment-configured API endpoint rather than direct Python/model access.
Paths: `web/app/page.tsx`, `web/hooks/useTts.ts`, `web/lib/api.ts`, `web/components/LinguisticPanel.tsx`.

#### Deployment and Infrastructure
Production deployment uses Docker Compose for the API, Redis cache, and Nginx reverse proxy. A separate Space-oriented Dockerfile supports Hugging Face hosting; the frontend is intended for Vercel deployment. External dependencies include Hugging Face Hub, Redis, espeak-ng, PyTorch/Coqui TTS, and Transformers.
Paths: `docker/docker-compose.yml`, `docker/Dockerfile`, `docker/Dockerfile.space`, `docker/nginx.conf`.

Main entry points: [`api/inference.py`](https://github.com/sidneyowallah/dholuo-tts/blob/main/api/inference.py) (Synthesis orchestration), [`api/routes.py`](https://github.com/sidneyowallah/dholuo-tts/blob/main/api/routes.py) (TTS routes), [`web/hooks/useTts.ts`](https://github.com/sidneyowallah/dholuo-tts/blob/main/web/hooks/useTts.ts) (TTS client hook), [`api/main.py`](https://github.com/sidneyowallah/dholuo-tts/blob/main/api/main.py) (FastAPI app)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_offline["Offline training"]
  node_audio[("DhoNam audio<br/>training data")]
  node_transcribe["Transcription<br/>dataset preparation"]
  node_pos_training["POS training<br/>AfroXLMR training<br/>[train_pos_local.py]"]
  node_pos_tagging["POS labeling<br/>dataset enrichment<br/>[apply_pos_tags.py]"]
  node_metadata["VITS metadata<br/>IPA dataset builder"]
  node_vits_training["Voice training<br/>VITS training<br/>[train_vits.py]"]
  node_hub_upload["Model publishing<br/>Hub upload"]
end

subgraph group_api["Python API"]
  node_api_main["FastAPI app<br/>application entry point<br/>[main.py]"]
  node_routes["TTS routes<br/>HTTP interface<br/>[routes.py]"]
  node_inference["Synthesis orchestration<br/>inference service<br/>[inference.py]"]
  node_models["Model loader<br/>artifact resolver<br/>[models.py]"]
  node_cache["Synthesis cache<br/>cache adapter<br/>[cache.py]"]
end

subgraph group_web["Web demo"]
  node_web_page["Demo page<br/>Next.js entry point<br/>[page.tsx]"]
  node_web_tts["TTS client hook<br/>frontend state<br/>[useTts.ts]"]
  node_web_api["API client<br/>frontend transport<br/>[api.ts]"]
  node_linguistic_panel["Linguistic panel<br/>UI component"]
end

subgraph group_deploy["Deployment"]
  node_compose["Production stack<br/>Docker Compose<br/>[docker-compose.yml]"]
  node_space_image["Space image<br/>Hugging Face Docker image<br/>[Dockerfile.space]"]
end

node_model_artifacts[("POS and VITS artifacts<br/>model checkpoints")]
node_tagger["POS tagger<br/>NLP module<br/>[tagger.py]"]
node_phonemizer["Tone IPA phonemizer<br/>NLP module<br/>[phonemizer.py]"]

node_audio -->|"transcribe"| node_transcribe
node_transcribe -->|"clean and split"| node_pos_tagging
node_pos_training -->|"trains POS model"| node_model_artifacts
node_pos_tagging -->|"labeled records"| node_metadata
node_metadata -->|"IPA metadata"| node_vits_training
node_vits_training -->|"trains voice checkpoints"| node_model_artifacts
node_model_artifacts -->|"publish"| node_hub_upload
node_model_artifacts -->|"load"| node_models
node_models -->|"POS model"| node_tagger
node_tagger -->|"POS pairs"| node_phonemizer
node_api_main -->|"registers"| node_routes
node_routes -->|"check/store"| node_cache
node_routes -->|"synthesis request"| node_inference
node_inference -->|"tag raw text"| node_tagger
node_inference -->|"generate tone IPA"| node_phonemizer
node_inference -->|"select voice model"| node_models
node_web_page -->|"submits text and voice"| node_web_tts
node_web_tts -->|"request synthesis"| node_web_api
node_web_api -->|"HTTP API"| node_routes
node_web_tts -->|"render linguistic output"| node_linguistic_panel
node_compose -->|"hosts API"| node_api_main
node_compose -->|"provides Redis"| node_cache
node_space_image -->|"hosts API"| node_api_main

click node_transcribe "https://github.com/sidneyowallah/dholuo-tts/blob/main/transcribe_audio.py"
click node_pos_training "https://github.com/sidneyowallah/dholuo-tts/blob/main/train_pos_local.py"
click node_pos_tagging "https://github.com/sidneyowallah/dholuo-tts/blob/main/apply_pos_tags.py"
click node_metadata "https://github.com/sidneyowallah/dholuo-tts/blob/main/create_vits_metadata.py"
click node_vits_training "https://github.com/sidneyowallah/dholuo-tts/blob/main/train_vits.py"
click node_hub_upload "https://github.com/sidneyowallah/dholuo-tts/blob/main/scripts/upload_models_to_hub.py"
click node_tagger "https://github.com/sidneyowallah/dholuo-tts/blob/main/tagger.py"
click node_phonemizer "https://github.com/sidneyowallah/dholuo-tts/blob/main/phonemizer.py"
click node_api_main "https://github.com/sidneyowallah/dholuo-tts/blob/main/api/main.py"
click node_routes "https://github.com/sidneyowallah/dholuo-tts/blob/main/api/routes.py"
click node_inference "https://github.com/sidneyowallah/dholuo-tts/blob/main/api/inference.py"
click node_models "https://github.com/sidneyowallah/dholuo-tts/blob/main/api/models.py"
click node_cache "https://github.com/sidneyowallah/dholuo-tts/blob/main/api/cache.py"
click node_web_page "https://github.com/sidneyowallah/dholuo-tts/blob/main/web/app/page.tsx"
click node_web_tts "https://github.com/sidneyowallah/dholuo-tts/blob/main/web/hooks/useTts.ts"
click node_web_api "https://github.com/sidneyowallah/dholuo-tts/blob/main/web/lib/api.ts"
click node_linguistic_panel "https://github.com/sidneyowallah/dholuo-tts/blob/main/web/components/LinguisticPanel.tsx"
click node_compose "https://github.com/sidneyowallah/dholuo-tts/blob/main/docker/docker-compose.yml"
click node_space_image "https://github.com/sidneyowallah/dholuo-tts/blob/main/docker/Dockerfile.space"

classDef toneNeutral fill:#f8fafc,stroke:#334155,stroke-width:1.5px,color:#0f172a
classDef toneBlue fill:#dbeafe,stroke:#2563eb,stroke-width:1.5px,color:#172554
classDef toneAmber fill:#fef3c7,stroke:#d97706,stroke-width:1.5px,color:#78350f
classDef toneMint fill:#dcfce7,stroke:#16a34a,stroke-width:1.5px,color:#14532d
classDef toneRose fill:#ffe4e6,stroke:#e11d48,stroke-width:1.5px,color:#881337
classDef toneIndigo fill:#e0e7ff,stroke:#4f46e5,stroke-width:1.5px,color:#312e81
classDef toneTeal fill:#ccfbf1,stroke:#0f766e,stroke-width:1.5px,color:#134e4a
class node_audio,node_transcribe,node_pos_training,node_pos_tagging,node_metadata,node_vits_training,node_hub_upload toneBlue
class node_api_main,node_routes,node_inference,node_models,node_cache toneAmber
class node_web_page,node_web_tts,node_web_api,node_linguistic_panel toneMint
class node_compose,node_space_image toneRose
class node_model_artifacts,node_tagger,node_phonemizer toneNeutral
```

## Components

### Offline training

Dataset, POS, and VITS training pipelines.

- **DhoNam audio**: training data
- [Transcription](https://github.com/sidneyowallah/dholuo-tts/blob/main/transcribe_audio.py): dataset preparation · `transcribe_audio.py`
- [POS training](https://github.com/sidneyowallah/dholuo-tts/blob/main/train_pos_local.py): AfroXLMR training · Independently produces the POS model artifact. · `train_pos_local.py`
- [POS labeling](https://github.com/sidneyowallah/dholuo-tts/blob/main/apply_pos_tags.py): dataset enrichment · `apply_pos_tags.py`
- [VITS metadata](https://github.com/sidneyowallah/dholuo-tts/blob/main/create_vits_metadata.py): IPA dataset builder · `create_vits_metadata.py`
- [Voice training](https://github.com/sidneyowallah/dholuo-tts/blob/main/train_vits.py): VITS training · Trains separate male and female voices. · `train_vits.py`
- [Model publishing](https://github.com/sidneyowallah/dholuo-tts/blob/main/scripts/upload_models_to_hub.py): Hub upload · `scripts/upload_models_to_hub.py`

### Python API

Serving and inference boundary.

- [FastAPI app](https://github.com/sidneyowallah/dholuo-tts/blob/main/api/main.py): application entry point · `api/main.py`
- [TTS routes](https://github.com/sidneyowallah/dholuo-tts/blob/main/api/routes.py): HTTP interface · `api/routes.py`
- [Synthesis orchestration](https://github.com/sidneyowallah/dholuo-tts/blob/main/api/inference.py): inference service · Runs text through POS, IPA, and selected voice synthesis. · `api/inference.py`
- [Model loader](https://github.com/sidneyowallah/dholuo-tts/blob/main/api/models.py): artifact resolver · Loads local or Hub POS and VITS models. · `api/models.py`
- [Synthesis cache](https://github.com/sidneyowallah/dholuo-tts/blob/main/api/cache.py): cache adapter · `api/cache.py`

### Web demo

Standalone Next.js client.

- [Demo page](https://github.com/sidneyowallah/dholuo-tts/blob/main/web/app/page.tsx): Next.js entry point · `web/app/page.tsx`
- [TTS client hook](https://github.com/sidneyowallah/dholuo-tts/blob/main/web/hooks/useTts.ts): frontend state · `web/hooks/useTts.ts`
- [API client](https://github.com/sidneyowallah/dholuo-tts/blob/main/web/lib/api.ts): frontend transport · Uses an environment-configured API endpoint. · `web/lib/api.ts`
- [Linguistic panel](https://github.com/sidneyowallah/dholuo-tts/blob/main/web/components/LinguisticPanel.tsx): UI component · Displays POS and phonetic output. · `web/components/LinguisticPanel.tsx`

### Deployment

Container and hosting topology.

- [Production stack](https://github.com/sidneyowallah/dholuo-tts/blob/main/docker/docker-compose.yml): Docker Compose · Runs API, Redis, and Nginx. · `docker/docker-compose.yml`
- [Space image](https://github.com/sidneyowallah/dholuo-tts/blob/main/docker/Dockerfile.space): Hugging Face Docker image · `docker/Dockerfile.space`

### Other components

- **POS and VITS artifacts**: model checkpoints · Local artifacts or Hugging Face Hub models.
- [POS tagger](https://github.com/sidneyowallah/dholuo-tts/blob/main/tagger.py): NLP module · Emits word and POS pairs using fine-tuned AfroXLMR. · `tagger.py`
- [Tone IPA phonemizer](https://github.com/sidneyowallah/dholuo-tts/blob/main/phonemizer.py): NLP module · Applies grapheme rules and POS-driven tone injection. · `phonemizer.py`

## Connections

- DhoNam audio → Transcription: transcribe
- Transcription → POS labeling: clean and split
- POS training → POS and VITS artifacts: trains POS model
- POS labeling → VITS metadata: labeled records
- VITS metadata → Voice training: IPA metadata
- Voice training → POS and VITS artifacts: trains voice checkpoints
- POS and VITS artifacts → Model publishing: publish
- POS and VITS artifacts → Model loader: load
- Model loader → POS tagger: POS model
- POS tagger → Tone IPA phonemizer: POS pairs
- FastAPI app → TTS routes: registers
- TTS routes → Synthesis cache: check/store
- TTS routes → Synthesis orchestration: synthesis request
- Synthesis orchestration → POS tagger: tag raw text
- Synthesis orchestration → Tone IPA phonemizer: generate tone IPA
- Synthesis orchestration → Model loader: select voice model
- Demo page → TTS client hook: submits text and voice
- TTS client hook → API client: request synthesis
- API client → TTS routes: HTTP API
- TTS client hook → Linguistic panel: render linguistic output
- Production stack → FastAPI app: hosts API
- Production stack → Synthesis cache: provides Redis
- Space image → FastAPI app: hosts API
