# TranscriptX: recommended way to run with Docker (primary install route).
#
# Volumes:
#   ./data:/data — project data root (cache, groups, speaker_profiles, …)
#   HOST_CONFIG_DIR — project settings (config.json, interface menus, profiles);
#     default ./data/.transcriptx. Prefer an absolute path outside the clone so
#     saved custom questions and other Settings survive wiping ./data.
#   HOST_*_DIR mounts — map host folders into TRANSCRIPTX_*_DIR paths (see environment).
#   HOST_RECORDINGS_DIR is required — point at a folder outside the repo (see .env.example).
#   Transcripts default to read-only at /mnt/transcripts; use docker-compose.override.yml
#   locally if you need the web UI to write .speaker_map.json sidecars beside JSON files.
#
# Non-root: services run as host user (UID/GID) so mounted dirs stay owned correctly.
#
# Web: docker compose up → http://localhost:8501

services:
  transcriptx-web:
    build:
      context: .
      args:
        TRANSCRIPTX_TORCH_VARIANT: ${TRANSCRIPTX_TORCH_VARIANT:-default}
    image: transcriptx:latest
    init: true
    user: "${UID:-1000}:${GID:-1000}"
    working_dir: /data
    volumes:
      - ./data:/data
      # Settings / metadata (config.json includes saved custom questions). More
      # specific than ./data:/data so HOST_CONFIG_DIR can live outside the clone.
      - ${HOST_CONFIG_DIR:-./data/.transcriptx}:/data/.transcriptx
      - transcriptx_cache:/home/transcriptx/.cache
      # HOST_*_DIR vars (from .env) set the host-side mount source.
      # TRANSCRIPTX_*_DIR vars in environment: set the container-side paths.
      # Separate names avoid Docker Compose .env-vs-environment precedence issues.
      - ${HOST_TRANSCRIPTS_DIR:-./data/transcripts}:/mnt/transcripts:ro
      # External inbox for Import Transcript → Import all from folder (must not be under /mnt/transcripts).
      - ${HOST_TRANSCRIPT_INBOX_DIR:-./data/transcript-inbox}:/mnt/transcript-inbox:ro
      - ${HOST_OUTPUT_DIR:-./data/outputs}:/mnt/outputs
      # Source audio lives only on the host outside the repo; set HOST_RECORDINGS_DIR in .env (see .env.example).
      - ${HOST_RECORDINGS_DIR:?Set HOST_RECORDINGS_DIR in .env to your host recordings folder outside the repo}:/mnt/recordings
      # Imports (uploaded files) are writable so we can delete after backup; recordings root stays :ro.
      - ${HOST_RECORDINGS_DIR:?Set HOST_RECORDINGS_DIR in .env to your host recordings folder outside the repo}/imports:/mnt/recordings/imports
      - ${HOST_WAV_BACKUP_DIR:-./data/backups/wav}:/mnt/wav
    environment:
      - STREAMLIT_BROWSER_GATHER_USAGE_STATS=false
      # Allow 500 MB per file (matches .streamlit/config.toml; container has no config file)
      - STREAMLIT_SERVER_MAX_UPLOAD_SIZE=500
      - TRANSCRIPTX_DATA_DIR=/data
      - TRANSCRIPTX_CONFIG_DIR=/data/.transcriptx
      - TRANSCRIPTX_TRANSCRIPTS_DIR=/mnt/transcripts
      - TRANSCRIPTX_OUTPUT_DIR=/mnt/outputs
      - TRANSCRIPTX_RECORDINGS_DIR=/mnt/recordings
      - TRANSCRIPTX_IMPORTS_DIR=/mnt/recordings/imports
      - TRANSCRIPTX_WAV_BACKUP_DIR=/mnt/wav
      - TRANSCRIPTX_USE_EMOJIS=0
      # Full image (requirements.txt); allow HF/spaCy auto-download into writable /data caches.
      - TRANSCRIPTX_CORE=0
      - TRANSCRIPTX_DISABLE_DOWNLOADS=${TRANSCRIPTX_DISABLE_DOWNLOADS:-0}
      - HF_HOME=/data/.cache/huggingface
      # Keep Playwright browser binaries in writable project cache.
      - PLAYWRIGHT_BROWSERS_PATH=/data/.cache/ms-playwright
      - MPLCONFIGDIR=/data/.cache/matplotlib
      - NLTK_DATA=/opt/venv/nltk_data
      # Librosa uses Numba with cache=True; Numba probes the cache dir via
      # tempfile.TemporaryFile().close(). On Docker Desktop, that probe raises EIO on
      # virtiofs-mounted ./data, so /data/.cache/numba is not a usable locator and
      # voice_contours fails with "no locator available for file .../librosa/...".
      # Keep the cache on the container overlay (/tmp), not a host bind mount.
      - NUMBA_CACHE_DIR=/tmp/numba_cache
      # Optional model overrides from host .env (see docs/runtime/models.md).
      - TRANSCRIPTX_SPACY_MODEL=${TRANSCRIPTX_SPACY_MODEL:-}
      - TRANSCRIPTX_SEMANTIC_MODEL=${TRANSCRIPTX_SEMANTIC_MODEL:-}
      - TRANSCRIPTX_SEMANTIC_SIMILARITY_MODEL=${TRANSCRIPTX_SEMANTIC_SIMILARITY_MODEL:-}
      - TRANSCRIPTX_EMOTION_MODEL=${TRANSCRIPTX_EMOTION_MODEL:-}
      - TRANSCRIPTX_SENTIMENT_BACKEND=${TRANSCRIPTX_SENTIMENT_BACKEND:-}
      - TRANSCRIPTX_BERTOPIC_EMBEDDING_MODEL=${TRANSCRIPTX_BERTOPIC_EMBEDDING_MODEL:-}
      # Optional LLM / Ollama overrides from host .env (see docs/runtime/llm.md).
      - TRANSCRIPTX_LLM_ENABLED=${TRANSCRIPTX_LLM_ENABLED:-}
      - TRANSCRIPTX_LLM_PROVIDER=${TRANSCRIPTX_LLM_PROVIDER:-}
      - TRANSCRIPTX_LLM_MODEL=${TRANSCRIPTX_LLM_MODEL:-}
      - TRANSCRIPTX_LLM_BASE_URL=${TRANSCRIPTX_LLM_BASE_URL:-}
      - TRANSCRIPTX_LLM_SEED=${TRANSCRIPTX_LLM_SEED:-}
      # Corrections Studio LLM discovery (see docs/runtime/corrections-llm.md).
      - TRANSCRIPTX_CORRECTIONS_LLM_ENABLED=${TRANSCRIPTX_CORRECTIONS_LLM_ENABLED:-}
    ports:
      # Default loopback only. LAN: TRANSCRIPTX_BIND_HOST=0.0.0.0 (unauthenticated).
      - "${TRANSCRIPTX_BIND_HOST:-127.0.0.1}:8501:8501"
    healthcheck:
      test: ["CMD", "python", "-c", "import urllib.request; urllib.request.urlopen('http://localhost:8501/_stcore/health')"]
      interval: 10s
      timeout: 5s
      retries: 3
      start_period: 15s
    command: ["--host", "0.0.0.0"]

volumes:
  transcriptx_cache:
