mars(kittentts): local STT add-on — faster-whisper in the audio side-venv

Telegram voice-note transcription on mars, no cloud: faster-whisper 1.2.1
(ctranslate2 CPU) installed into the SAME kittentts side-venv via
stt-requirements.txt (appended by the provisioning unit; input stamp
extended). Second auto-patchelf pass RPATHs the newly installed
ctranslate2/av binaries. Container env gains
PYTHONPATH=/opt/data/kittentts-venv/... so hermes's local-stt provider
imports faster-whisper in-process (the image venv is read-only for uid
986, so the built-in lazy installer cannot work there).

Validated live: Telegram voice note transcribed on CPU (i5-4460,
lang=en, text exact) with the same pins.
This commit is contained in:
2026-09-19 13:31:26 +00:00
parent 22caa06904
commit 2b2f0994e9
2 changed files with 41 additions and 1 deletions
+24 -1
View File
@@ -93,6 +93,12 @@ let
kittenttsReqs = pkgs.writeText "kittentts-requirements.txt" ( kittenttsReqs = pkgs.writeText "kittentts-requirements.txt" (
builtins.readFile ./kittentts/requirements.txt builtins.readFile ./kittentts/requirements.txt
); );
# STT add-on: faster-whisper (CPU) for Telegram voice-note transcription,
# same side-venv, appended by the provisioning unit. Keeps one venv + one
# stamp for the whole local-audio stack. See kittentts/stt-requirements.txt.
kittenttsSttReqs = pkgs.writeText "kittentts-stt-requirements.txt" (
builtins.readFile ./kittentts/stt-requirements.txt
);
kittenttsStub = pkgs.writeText "kitten-tts-stub.py" ( kittenttsStub = pkgs.writeText "kitten-tts-stub.py" (
builtins.readFile ./kittentts/kitten-misaki-stub.py builtins.readFile ./kittentts/kitten-misaki-stub.py
); );
@@ -311,6 +317,13 @@ in
# forbid network — no model drift, no boot-time fetch (review #4). # forbid network — no model drift, no boot-time fetch (review #4).
HF_HOME = "/opt/data/kittentts-hf"; HF_HOME = "/opt/data/kittentts-hf";
HF_HUB_OFFLINE = "1"; HF_HUB_OFFLINE = "1";
# STT (local whisper): expose the side-venv's site-packages to Hermes's
# own interpreter so faster-whisper imports in-process. PYTHONPATH dirs
# don't run .pth auto-imports, but faster-whisper has no dead imports —
# it imports cleanly from a plain path injection (unlike kittentts,
# which is driven through the command wrapper for exactly that reason).
PYTHONPATH = "/opt/data/kittentts-venv/lib/python3.13/site-packages";
}; };
environmentFiles = [ config.sops.templates."hermes-agent.env".path ]; environmentFiles = [ config.sops.templates."hermes-agent.env".path ];
cmd = [ "gateway" "run" ]; cmd = [ "gateway" "run" ];
@@ -572,7 +585,7 @@ in
# Input key: requirements + wheel + stub + model files + resolved script. # Input key: requirements + wheel + stub + model files + resolved script.
# Review #5 a miss on the old requirements-only stamp let a changed # Review #5 a miss on the old requirements-only stamp let a changed
# wheel/stub/model URL keep running the stale install forever. # wheel/stub/model URL keep running the stale install forever.
inputHash=$({ cat ${kittenttsReqs} ${kittenttsWheel} ${kittenttsStub} \ inputHash=$({ cat ${kittenttsReqs} ${kittenttsSttReqs} ${kittenttsWheel} ${kittenttsStub} \
${kittenttsModelOnnx} ${kittenttsModelVoices} ${kittenttsModelConfig} ${kittenttsModelOnnx} ${kittenttsModelVoices} ${kittenttsModelConfig}
echo ${kittenttsRuntimeLibs}; } | sha256sum | cut -d' ' -f1) echo ${kittenttsRuntimeLibs}; } | sha256sum | cut -d' ' -f1)
stampFile=$stageDir/provision.stamp stampFile=$stageDir/provision.stamp
@@ -636,6 +649,16 @@ in
# PyPI manylinux .so's (numpy, onnxruntime) need libstdc++, which the # PyPI manylinux .so's (numpy, onnxruntime) need libstdc++, which the
# Nix loader never finds, on the host or in the container. # Nix loader never finds, on the host or in the container.
auto-patchelf --paths "$stageVenv" --libs ${kittenttsRuntimeLibs} auto-patchelf --paths "$stageVenv" --libs ${kittenttsRuntimeLibs}
# STT add-on: faster-whisper into the SAME venv (shares the
# numpy/onnxruntime pins; see kittentts/stt-requirements.txt).
UV_CACHE_DIR=$stageDir/uv-cache \
uv pip install --python "$stageVenv/bin/python" --quiet \
--requirement ${kittenttsSttReqs}
# av's bundled ffmpeg libs also need the stdc++/zlib link (already
# covered by the auto-patchelf pass above rerun it so the newly
# installed ctranslate2/av binaries get RPATHs too).
auto-patchelf --paths "$stageVenv" --libs ${kittenttsRuntimeLibs}
fi fi
# Stage the full delivered hub tree (exact hf_hub_download layout: # Stage the full delivered hub tree (exact hf_hub_download layout:
+17
View File
@@ -0,0 +1,17 @@
# STT add-on pins for the KittenTTS side-venv on mars (faster-whisper CPU).
#
# APPENDED to hosts/mars/kittentts/requirements.txt by the provisioning unit
# (see hermes-agent.nix, KittenTTS section) so ONE venv covers the entire
# local-audio stack: TTS (KittenTTS) + STT (faster-whisper). Shares the
# numpy/onnxruntime pins already frozen there — no version conflicts.
#
# faster-whisper runs CTranslate2 on CPU; the tiny/base model (~150 MB)
# downloads once from the HF hub then works fully offline. Validated
# 2026-09-19 with a live Telegram voice note transcribed on i5-4460 CPU.
#
# NOTE on av: PyP AV 18.x needs libz/libstdc++ from the host. On NixOS those
# come via the nix store — the provisioning unit exports LD_LIBRARY_PATH with
# them at runtime (see hermes-agent.nix's kittenttsLDLibraryPath).
faster-whisper==1.2.1
ctranslate2==4.8.2
av==18.1.0