# Session Resumee - AudioEngineHub Project Refactoring **Date:** Donnerstag, 4. Dezember 2025 **Objective:** Refactor the AudioEngineHub project to follow best practices for containerization, error handling, and project structure, based on a provided `guide.md` document. --- ### Initial Project State & Overview The project was a modular FastAPI-based TTS server with a `TTSEngineBase` interface. Key initial findings: * `piper` was functional. * `styletts` and `chattts` were dummy implementations. * `f5_tts` was implemented but inactive. * Configuration was scattered and hardcoded. * Error handling was basic. * Tests (`pytest` and `unittest`) existed but were limited and inconsistent. * No containerization strategy was in place, leading to potential dependency hell. ### Refactoring Phase 1: Robustness & Configuration 1. **Centralized Configuration:** * Replaced hardcoded values with `pydantic-settings` for `.env` file management. * `config.py` created (later moved to `app/config.py`). * `IMAGE_NAME` in `Makefile` was also user-configurable. * `requirements.txt` was updated with `pydantic-settings`. * `docker-compose.yml` was updated to use `.env`. 2. **Configurable Engines Feature:** * Implemented dynamic `ENGINE_REGISTRY` loading based on `ACTIVE_ENGINES` setting in `.env`. * Allows easy activation/deactivation of TTS engines. 3. **Robust Error Handling:** * Implemented comprehensive input validation in the `/tts` endpoint (checking engine, model, speaker existence). * Added dependency checks (e.g., `ffmpeg`, `piper` executables) to engines, reporting `HTTP 503` for unavailable engines. * Secured `tempfile.mktemp` usage by replacing it with `tempfile.NamedTemporaryFile`. * Wrapped synthesis logic in `try-except` blocks to catch and propagate engine-specific errors as `HTTP 500`. 4. **Asynchronous Operations:** * Changed `TTSEngineBase.synthesize` and `selftest` to `async`. * Refactored all concrete engine implementations (`piper`, `f5_tts`, `styletts`, `chattts`) to use `async def` methods. * Updated `app/main.py`'s `/tts` endpoint to be `async` and use `await` for engine calls and `asyncio.gather` for concurrent chunk synthesis. * Wrapped blocking I/O (file ops, `ffmpeg`) and CPU-bound tasks in `asyncio.to_thread`. * Updated `tests/test_f5_tts.py` to correctly `await` async calls. ### Refactoring Phase 2: Containerization & Workflow (Based on `guide.md`) 1. **Integrated `Makefile`:** * Created a `Makefile` with targets for `build`, `run`, `stop`, `logs`, `shell`, `up`, `down`, `test`, `tag`, `push`, `clean`, `help`. * Included robust shell functions for port checking (`check_traefik_ports_free`, `check_app_port_free`). * Set `SHELL := /bin/bash` in `Makefile` to ensure correct shell interpretation. * Ensured `PYTHONPATH=$(PWD)` is set for `make test`. 2. **Adopted Multi-Stage `Dockerfile`:** * Implemented a multi-stage `Dockerfile` (builder/runner stages). * `builder` stage creates a Python virtual environment and installs `requirements.txt` (including `gunicorn`). * `runner` stage uses `python:3.11-slim`, installs runtime system dependencies (`ffmpeg`), creates an unprivileged `appuser`, and sets the production `CMD` to `gunicorn` with `uvicorn` workers. 3. **Refactored Project Structure (`app/` package):** * Created an `app/` directory. * Moved `main.py`, `config.py`, `engines/`, `models/`, `utils/` into `app/`. * Created `app/__init__.py`. * Updated all Python import paths (`from app.config import settings`, `from app.engines.piper import PiperEngine`, etc.). * Updated internal references in engine files (e.g., `model_dir`, `voices_dir`). 4. **Refined `docker-compose.yml` with Traefik:** * Integrated `traefik` service for dynamic reverse proxying during local development. * Modified `app` service with Traefik `labels` and connected both services to a `web` network. * Adjusted Docker `volumes` mounts to match the new `app/` structure (e.g., `./models:/home/appuser/app/models`). * Updated `app` service `command` for Uvicorn hot-reloading in dev. 5. **Centralized Testing Workflow:** * Removed `test_run.sh`. * Integrated `make test` for running `pytest --cov=. app/ tests/`. 6. **Dedicated Documentation:** * Created `docs/` directory. * Moved `guide.md` to `docs/guide.md`. ### Verification & Troubleshooting * **Tests:** All unit/integration tests (`make test`) are passing. * **Local Run (Virtual Env):** Initial local runs (`python app/main.py`) failed due to `ModuleNotFoundError` (fixed by `python -m app.main`) and `PermissionError` (fixed by needing to mock or redirect `settings.AUDIO_CACHE_DIR` for local direct execution, but not strictly needed for successful app execution through `uvicorn`). The current approach is to verify in Docker. * **Docker Compose:** * Initial `make up` failures were due to an outdated `docker-compose` client (`1.29.2`) and later, `Makefile` syntax issues (fixed by setting `SHELL := /bin/bash` and fixing macros). * `docker-compose` was eventually updated to the `docker compose` CLI plugin (v5.0.0). * `make up` command finally succeeded in bringing up containers. * The `curl http://localhost/health` command returned `404 page not found`. This indicates a potential routing issue with Traefik or the application not being responsive on the expected path within the container. (This is the last unresolved issue). --- **Next Steps (Troubleshooting the 404):** The `404 page not found` when accessing `http://localhost/health` via Traefik is the current blocker for full verification. I need to investigate the logs of the `audio-engine-hub_app` container (the FastAPI app) to determine if the application itself is starting correctly and serving the `/health` endpoint as expected. If the app is indeed serving, the issue lies with Traefik's routing configuration.