From 2a0e2f8fe3a1cf86f56f9cfa3dc355e2c62def86 Mon Sep 17 00:00:00 2001 From: Ettore Di Giacinto Date: Fri, 12 Jun 2026 21:04:58 +0000 Subject: [PATCH] feat(crispasr): bundle espeak-ng and add piper TTS voices to the gallery CrispASR's piper backend phonemizes non-English text via espeak-ng (dlopen, the MIT-clean path; English uses a built-in G2P). The FROM scratch crispasr image shipped none of it, so non-English piper voices loaded but failed synthesis with "phonemization failed". Bundle the espeak-ng runtime so they work: - Dockerfile.golang: install espeak-ng-data + libespeak-ng1 and its libpcaudio0 / libsonic0 deps in the crispasr builder (espeak's dlopen fails without the latter two). - package.sh: copy libespeak-ng.so.1, libpcaudio.so.0, libsonic.so.0 into package/lib/ and the espeak-ng-data dir into the package root. - run.sh: export CRISPASR_ESPEAK_DATA_PATH so the bundled data is found. Add 9 single-speaker piper voices (de/en/it, incl. Italian paola + riccardo) to the gallery, run through backend:piper, hosted at LocalAI-Community/piper-voices-GGUF (converted from rhasspy/piper-voices with CrispASR's convert-piper-to-gguf.py). Only single-speaker low/medium voices are included; the engine does not yet support multi-speaker or high-quality piper decoders. All 9 verified end-to-end: each synthesizes a WAV at the model's native sample rate using only the image-bundled espeak payload. Signed-off-by: Ettore Di Giacinto Assisted-by: Claude:claude-opus-4-8 [Claude Code] --- backend/Dockerfile.golang | 10 ++ backend/go/crispasr/package.sh | 26 ++++ backend/go/crispasr/run.sh | 5 + gallery/index.yaml | 243 +++++++++++++++++++++++++++++++++ 4 files changed, 284 insertions(+) diff --git a/backend/Dockerfile.golang b/backend/Dockerfile.golang index af704d375478..75fc3a0d958e 100644 --- a/backend/Dockerfile.golang +++ b/backend/Dockerfile.golang @@ -206,6 +206,16 @@ RUN if [ "${BACKEND}" = "opus" ]; then \ apt-get clean && rm -rf /var/lib/apt/lists/*; \ fi +# CrispASR's piper TTS backend dlopens libespeak-ng at runtime to phonemize +# non-English text (the MIT-clean path; English uses a built-in G2P). Install +# the espeak-ng runtime + its libpcaudio/libsonic deps + voice data so +# package.sh can bundle them into the FROM scratch image. +RUN if [ "${BACKEND}" = "crispasr" ]; then \ + apt-get update && apt-get install -y --no-install-recommends \ + espeak-ng-data libespeak-ng1 libpcaudio0 libsonic0 && \ + apt-get clean && rm -rf /var/lib/apt/lists/*; \ +fi + COPY . /LocalAI RUN git config --global --add safe.directory /LocalAI diff --git a/backend/go/crispasr/package.sh b/backend/go/crispasr/package.sh index 09e95f13ac1a..baee12944faa 100755 --- a/backend/go/crispasr/package.sh +++ b/backend/go/crispasr/package.sh @@ -51,6 +51,32 @@ else exit 1 fi +# Bundle espeak-ng (+ its libpcaudio/libsonic runtime deps) and its voice data so +# the piper TTS backend can phonemize non-English text. CrispASR dlopens +# libespeak-ng.so.1 at runtime (the MIT-clean path); the dlopen succeeds loading +# libespeak-ng but FAILS if libpcaudio/libsonic are absent, so all three .so are +# required. run.sh points CRISPASR_ESPEAK_DATA_PATH at the bundled data dir. +# Best-effort: only copied when present, so a local dev build without espeak-ng +# installed still packages the rest (English voices keep working). +ESPEAK_LIBDIR="" +for d in /usr/lib/x86_64-linux-gnu /usr/lib/aarch64-linux-gnu; do + if [ -f "$d/libespeak-ng.so.1" ]; then + ESPEAK_LIBDIR="$d" + break + fi +done +if [ -n "$ESPEAK_LIBDIR" ]; then + echo "Bundling espeak-ng from $ESPEAK_LIBDIR ..." + cp -arfLv "$ESPEAK_LIBDIR/libespeak-ng.so.1" $CURDIR/package/lib/ + cp -arfLv "$ESPEAK_LIBDIR/libpcaudio.so.0" $CURDIR/package/lib/ + cp -arfLv "$ESPEAK_LIBDIR/libsonic.so.0" $CURDIR/package/lib/ + if [ -d "$ESPEAK_LIBDIR/espeak-ng-data" ]; then + cp -arfLv "$ESPEAK_LIBDIR/espeak-ng-data" $CURDIR/package/ + fi +else + echo "espeak-ng not found; non-English piper voices will not phonemize" +fi + # Package GPU libraries based on BUILD_TYPE # The GPU library packaging script will detect BUILD_TYPE and copy appropriate GPU libraries GPU_LIB_SCRIPT="${REPO_ROOT}/scripts/build/package-gpu-libs.sh" diff --git a/backend/go/crispasr/run.sh b/backend/go/crispasr/run.sh index 942b418a3584..ccb264833581 100755 --- a/backend/go/crispasr/run.sh +++ b/backend/go/crispasr/run.sh @@ -41,6 +41,11 @@ fi export LD_LIBRARY_PATH=$CURDIR/lib:$LD_LIBRARY_PATH export CRISPASR_LIBRARY=$LIBRARY +# Point piper's espeak-ng phonemizer at the bundled voice data. The variable +# names the directory CONTAINING espeak-ng-data (package.sh drops it next to +# this script). Harmless when espeak-ng wasn't bundled. +export CRISPASR_ESPEAK_DATA_PATH=$CURDIR + # If there is a lib/ld.so, use it if [ -f $CURDIR/lib/ld.so ]; then echo "Using lib/ld.so" diff --git a/gallery/index.yaml b/gallery/index.yaml index e4131b5164e6..9b5a63779483 100644 --- a/gallery/index.yaml +++ b/gallery/index.yaml @@ -33177,6 +33177,249 @@ - filename: snac-24khz.gguf uri: huggingface://cstr/snac-24khz-GGUF/snac-24khz.gguf sha256: b4b044631df62ececa86ab080516b3e619cd8f93caabd5f6758c7eae14981bd8 +- name: piper-it_IT-riccardo-x_low-crispasr + url: github:mudler/LocalAI/gallery/virtual.yaml@master + urls: + - https://huggingface.co/rhasspy/piper-voices + - https://huggingface.co/LocalAI-Community/piper-voices-GGUF + icon: https://github.com/rhasspy/piper/raw/master/etc/logo.png + description: | + Piper (rhasspy VITS) Italian male voice "riccardo", x_low quality, synthesized through the CrispASR backend. Fast, lightweight (~10 MB) local neural TTS producing 16 kHz mono audio. Runs end-to-end on CPU. + tags: + - crispasr + - tts + - text-to-speech + - piper + - gguf + overrides: + backend: crispasr + known_usecases: + - tts + name: piper-it_IT-riccardo-x_low-crispasr + options: + - "backend:piper" + parameters: + model: piper-it_IT-riccardo-x_low-f16.gguf + files: + - filename: piper-it_IT-riccardo-x_low-f16.gguf + uri: huggingface://LocalAI-Community/piper-voices-GGUF/piper-it_IT-riccardo-x_low-f16.gguf + sha256: 9b904f5d75c324274093c9049f240579b255eb638d9cc8ac7c704c0e712ac312 +- name: piper-it_IT-paola-medium-crispasr + url: github:mudler/LocalAI/gallery/virtual.yaml@master + urls: + - https://huggingface.co/rhasspy/piper-voices + - https://huggingface.co/LocalAI-Community/piper-voices-GGUF + icon: https://github.com/rhasspy/piper/raw/master/etc/logo.png + description: | + Piper (rhasspy VITS) Italian female voice "paola", medium quality, synthesized through the CrispASR backend. Fast, lightweight (~31 MB) local neural TTS producing 22.05 kHz mono audio. Runs end-to-end on CPU. + tags: + - crispasr + - tts + - text-to-speech + - piper + - gguf + overrides: + backend: crispasr + known_usecases: + - tts + name: piper-it_IT-paola-medium-crispasr + options: + - "backend:piper" + parameters: + model: piper-it_IT-paola-medium-f16.gguf + files: + - filename: piper-it_IT-paola-medium-f16.gguf + uri: huggingface://LocalAI-Community/piper-voices-GGUF/piper-it_IT-paola-medium-f16.gguf + sha256: be5c51fca389af212595d88930d8c5198629293f4e078b564549f94b40261d5c +- name: piper-en_US-lessac-medium-crispasr + url: github:mudler/LocalAI/gallery/virtual.yaml@master + urls: + - https://huggingface.co/rhasspy/piper-voices + - https://huggingface.co/LocalAI-Community/piper-voices-GGUF + icon: https://github.com/rhasspy/piper/raw/master/etc/logo.png + description: | + Piper (rhasspy VITS) American English voice "lessac", medium quality, synthesized through the CrispASR backend. Uses a built-in English G2P (no espeak-ng needed). Fast, lightweight (~31 MB) local neural TTS producing 22.05 kHz mono audio. Runs end-to-end on CPU. + tags: + - crispasr + - tts + - text-to-speech + - piper + - gguf + overrides: + backend: crispasr + known_usecases: + - tts + name: piper-en_US-lessac-medium-crispasr + options: + - "backend:piper" + parameters: + model: piper-en_US-lessac-medium-f16.gguf + files: + - filename: piper-en_US-lessac-medium-f16.gguf + uri: huggingface://LocalAI-Community/piper-voices-GGUF/piper-en_US-lessac-medium-f16.gguf + sha256: 31fda50337445ac5a48e6e304f8345590db95dfdc9890f3e3096f6dc728e7329 +- name: piper-en_GB-cori-medium-crispasr + url: github:mudler/LocalAI/gallery/virtual.yaml@master + urls: + - https://huggingface.co/rhasspy/piper-voices + - https://huggingface.co/LocalAI-Community/piper-voices-GGUF + icon: https://github.com/rhasspy/piper/raw/master/etc/logo.png + description: | + Piper (rhasspy VITS) British English female voice "cori", medium quality, synthesized through the CrispASR backend. Uses a built-in English G2P (no espeak-ng needed). Fast, lightweight (~31 MB) local neural TTS producing 22.05 kHz mono audio. Runs end-to-end on CPU. + tags: + - crispasr + - tts + - text-to-speech + - piper + - gguf + overrides: + backend: crispasr + known_usecases: + - tts + name: piper-en_GB-cori-medium-crispasr + options: + - "backend:piper" + parameters: + model: piper-en_GB-cori-medium-f16.gguf + files: + - filename: piper-en_GB-cori-medium-f16.gguf + uri: huggingface://LocalAI-Community/piper-voices-GGUF/piper-en_GB-cori-medium-f16.gguf + sha256: b432146300f4f6dc216653adfb92e7007b0d542efe567ae91f77ef01d6f252a4 +- name: piper-de_DE-thorsten-medium-crispasr + url: github:mudler/LocalAI/gallery/virtual.yaml@master + urls: + - https://huggingface.co/rhasspy/piper-voices + - https://huggingface.co/LocalAI-Community/piper-voices-GGUF + icon: https://github.com/rhasspy/piper/raw/master/etc/logo.png + description: | + Piper (rhasspy VITS) German male voice "thorsten", medium quality, synthesized through the CrispASR backend. Fast, lightweight (~31 MB) local neural TTS producing 22.05 kHz mono audio. Runs end-to-end on CPU. + tags: + - crispasr + - tts + - text-to-speech + - piper + - gguf + overrides: + backend: crispasr + known_usecases: + - tts + name: piper-de_DE-thorsten-medium-crispasr + options: + - "backend:piper" + parameters: + model: piper-de_DE-thorsten-medium-f16.gguf + files: + - filename: piper-de_DE-thorsten-medium-f16.gguf + uri: huggingface://LocalAI-Community/piper-voices-GGUF/piper-de_DE-thorsten-medium-f16.gguf + sha256: f4fd0cd694f1f6f0192b903ab2ef52bb1692204334526fd32ca9379a9e655f8b +- name: piper-de_DE-kerstin-low-crispasr + url: github:mudler/LocalAI/gallery/virtual.yaml@master + urls: + - https://huggingface.co/rhasspy/piper-voices + - https://huggingface.co/LocalAI-Community/piper-voices-GGUF + icon: https://github.com/rhasspy/piper/raw/master/etc/logo.png + description: | + Piper (rhasspy VITS) German female voice "kerstin", low quality, synthesized through the CrispASR backend. Fast, lightweight (~31 MB) local neural TTS producing 16 kHz mono audio. Runs end-to-end on CPU. + tags: + - crispasr + - tts + - text-to-speech + - piper + - gguf + overrides: + backend: crispasr + known_usecases: + - tts + name: piper-de_DE-kerstin-low-crispasr + options: + - "backend:piper" + parameters: + model: piper-de_DE-kerstin-low-f16.gguf + files: + - filename: piper-de_DE-kerstin-low-f16.gguf + uri: huggingface://LocalAI-Community/piper-voices-GGUF/piper-de_DE-kerstin-low-f16.gguf + sha256: d1ceb8f5f6cc908887f33916054e58247e70955350178ae0118c422345e040a5 +- name: piper-de_DE-eva_k-x_low-crispasr + url: github:mudler/LocalAI/gallery/virtual.yaml@master + urls: + - https://huggingface.co/rhasspy/piper-voices + - https://huggingface.co/LocalAI-Community/piper-voices-GGUF + icon: https://github.com/rhasspy/piper/raw/master/etc/logo.png + description: | + Piper (rhasspy VITS) German female voice "eva_k", x_low quality, synthesized through the CrispASR backend. Fast, lightweight (~10 MB) local neural TTS producing 16 kHz mono audio. Runs end-to-end on CPU. + tags: + - crispasr + - tts + - text-to-speech + - piper + - gguf + overrides: + backend: crispasr + known_usecases: + - tts + name: piper-de_DE-eva_k-x_low-crispasr + options: + - "backend:piper" + parameters: + model: piper-de_DE-eva_k-x_low-f16.gguf + files: + - filename: piper-de_DE-eva_k-x_low-f16.gguf + uri: huggingface://LocalAI-Community/piper-voices-GGUF/piper-de_DE-eva_k-x_low-f16.gguf + sha256: c37839b7f88054c5c6e306bd4e91bbf7aa56d6267a0037c10c732dfcb67e769c +- name: piper-de_DE-karlsson-low-crispasr + url: github:mudler/LocalAI/gallery/virtual.yaml@master + urls: + - https://huggingface.co/rhasspy/piper-voices + - https://huggingface.co/LocalAI-Community/piper-voices-GGUF + icon: https://github.com/rhasspy/piper/raw/master/etc/logo.png + description: | + Piper (rhasspy VITS) German male voice "karlsson", low quality, synthesized through the CrispASR backend. Fast, lightweight (~31 MB) local neural TTS producing 16 kHz mono audio. Runs end-to-end on CPU. + tags: + - crispasr + - tts + - text-to-speech + - piper + - gguf + overrides: + backend: crispasr + known_usecases: + - tts + name: piper-de_DE-karlsson-low-crispasr + options: + - "backend:piper" + parameters: + model: piper-de_DE-karlsson-low-f16.gguf + files: + - filename: piper-de_DE-karlsson-low-f16.gguf + uri: huggingface://LocalAI-Community/piper-voices-GGUF/piper-de_DE-karlsson-low-f16.gguf + sha256: 1832edb65f63a34b1345b07b598c081ee6e717e2daefd49162e16d9af29e391b +- name: piper-de_DE-ramona-low-crispasr + url: github:mudler/LocalAI/gallery/virtual.yaml@master + urls: + - https://huggingface.co/rhasspy/piper-voices + - https://huggingface.co/LocalAI-Community/piper-voices-GGUF + icon: https://github.com/rhasspy/piper/raw/master/etc/logo.png + description: | + Piper (rhasspy VITS) German female voice "ramona", low quality, synthesized through the CrispASR backend. Fast, lightweight (~31 MB) local neural TTS producing 16 kHz mono audio. Runs end-to-end on CPU. + tags: + - crispasr + - tts + - text-to-speech + - piper + - gguf + overrides: + backend: crispasr + known_usecases: + - tts + name: piper-de_DE-ramona-low-crispasr + options: + - "backend:piper" + parameters: + model: piper-de_DE-ramona-low-f16.gguf + files: + - filename: piper-de_DE-ramona-low-f16.gguf + uri: huggingface://LocalAI-Community/piper-voices-GGUF/piper-de_DE-ramona-low-f16.gguf + sha256: c5f71091e58ebe59f8f4ad47d3b444659c4e8281e86d20e153955b895b5f6921 - name: hubert-crispasr url: github:mudler/LocalAI/gallery/virtual.yaml@master urls: