a28f75994a
Kokoro has been stale upstream since April 2025 (`requires_python<3.13`), which broke the Python 3.14 build. Piper is the active replacement: maintained by OHF/Home Assistant, depends only on onnxruntime + pathvalidate (no torch, no spacy, no transformers), and has cp314 support today. Dockerfile: - Add `pip install piper-tts` after the STT install. - Bundle two default voices (en_US-amy-medium, en_US-ryan-medium) into /opt/piper-voices at build. Additional voices can be downloaded into /data/voices via the admin UI (separate commit). - Image add over the STT-only baseline: ~150 MB. services/tts.py — full rewrite: - New voice-discovery layer scans /opt/piper-voices + /data/voices for .onnx + .onnx.json pairs. /data wins over /opt for the same id so admin-downloaded voices can override bundled defaults. - Single PiperVoice kept warm; switches via _switch_voice() when the user changes their voice_tts_voice setting. - list_voices() returns metadata read from .onnx.json sidecars (label derived from filename, language, quality, sample_rate). - synthesise() uses piper's SynthesisConfig; converts kokoro-shaped `speed` multiplier to piper's `length_scale` (1.0 / speed). - `voice_blend` parameter accepted but ignored — piper has no blend equivalent; first entry's voice is used if anything is passed. - Dropped: HuggingFace commit-hash tracking (~80 lines), the daily check_for_kokoro_updates task, voice-tensor blending math. routes/voice.py: - tts_backend reports "piper" in /api/voice/status. - /api/voice/voices no longer requires tts_available() — even with the active voice failed to load, the catalog still lets the user pick a different one. - Synthesise request body dropped the voice_blend field; speed and voice still supported. alembic 0047_reset_voice_tts_settings: - Deletes any stored voice_tts_voice (kokoro IDs that don't map to piper) and voice_tts_blend (no piper equivalent) rows. Both re-default cleanly on next read. frontend: - VoiceBlendEntry type removed from api/client.ts. - synthesiseSpeech() signature dropped the voiceBlend parameter. - SettingsView.vue Voice Blend section removed entirely (slider, preview, slot management). voice_tts_blend save path removed. - Default voice id changed from "af_heart" to "en_US-amy-medium". - VoiceEntry gains optional language/quality/sample_rate fields from the richer piper sidecar metadata. Voice paths remain lazily guarded — `VOICE_ENABLED=false` (default) starts the app cleanly regardless of which TTS deps are present. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
69 lines
2.7 KiB
Docker
69 lines
2.7 KiB
Docker
# syntax=docker/dockerfile:1
|
|
# Stage 1: Build Vue frontend
|
|
FROM node:22-alpine AS build-frontend
|
|
WORKDIR /build
|
|
COPY frontend/package.json frontend/package-lock.json* ./
|
|
RUN npm ci --quiet
|
|
COPY frontend/ .
|
|
RUN npm run build
|
|
|
|
# Stage 2: Python runtime
|
|
# Tracks CI image (ci-python:3.14) so test results stay representative.
|
|
FROM python:3.14-slim AS runtime
|
|
WORKDIR /app
|
|
|
|
COPY pyproject.toml .
|
|
COPY src/ src/
|
|
RUN --mount=type=cache,target=/root/.cache/pip \
|
|
pip install .
|
|
|
|
# Speech-to-text (faster-whisper + soundfile). faster-whisper is pure
|
|
# Python; the actual inference engine is ctranslate2 (C++) which has
|
|
# cp314 wheels as of v4.7.2 (2026-05-19). No torch needed — ctranslate2
|
|
# does its own CPU inference. Image add: ~150 MB.
|
|
RUN --mount=type=cache,target=/root/.cache/pip \
|
|
pip install faster-whisper soundfile
|
|
|
|
# Text-to-speech (piper-tts). Replaces kokoro, which has been
|
|
# stale upstream since April 2025 (requires_python<3.13). Piper depends
|
|
# only on onnxruntime (already pulled in for STT via faster-whisper) and
|
|
# pathvalidate — total Python overhead is tiny. Voice models are separate
|
|
# .onnx + .onnx.json files bundled below.
|
|
RUN --mount=type=cache,target=/root/.cache/pip \
|
|
pip install piper-tts
|
|
|
|
# Bundle two default voices in the image so first-run TTS works offline.
|
|
# Additional voices can be downloaded at runtime into /data/voices via the
|
|
# admin UI (see services/tts.py for the voice-discovery logic).
|
|
# Voice catalog: https://huggingface.co/rhasspy/piper-voices
|
|
RUN mkdir -p /opt/piper-voices && cd /opt/piper-voices && \
|
|
for VOICE in en_US-amy-medium en_US-ryan-medium; do \
|
|
DATASET="${VOICE#en_US-}"; DATASET="${DATASET%-medium}"; \
|
|
BASE="https://huggingface.co/rhasspy/piper-voices/resolve/main/en/en_US/${DATASET}/medium"; \
|
|
curl -fsSL -o "${VOICE}.onnx" "${BASE}/${VOICE}.onnx"; \
|
|
curl -fsSL -o "${VOICE}.onnx.json" "${BASE}/${VOICE}.onnx.json"; \
|
|
done
|
|
|
|
# Build the fable-mcp wheel so it can be served for download
|
|
COPY fable-mcp/ fable-mcp/
|
|
RUN --mount=type=cache,target=/root/.cache/pip \
|
|
pip install build hatchling \
|
|
&& python -m build --wheel ./fable-mcp --outdir /app/dist/ \
|
|
&& pip uninstall -y build \
|
|
&& rm -rf fable-mcp/
|
|
|
|
COPY --from=build-frontend /build/dist/ src/fabledassistant/static/
|
|
COPY alembic.ini .
|
|
COPY alembic/ alembic/
|
|
|
|
# Ensure Python finds the source tree (where static files live) before site-packages
|
|
ENV PYTHONPATH=/app/src
|
|
|
|
# Version is injected at build time via --build-arg BUILD_VERSION=YY.MM.DD.N
|
|
# Falls back to "dev" for local / untagged builds
|
|
ARG BUILD_VERSION=dev
|
|
ENV APP_VERSION=$BUILD_VERSION
|
|
|
|
EXPOSE 5000
|
|
CMD ["sh", "-c", "alembic upgrade head && hypercorn 'fabledassistant.app:create_app()' --bind 0.0.0.0:5000 --keep-alive 600"]
|