Files
homeclaw/Dockerfile.voice
2026-05-05 17:46:17 +09:00

177 lines
6.5 KiB
Docker
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# ============================================================
# SmallClaw Voice – Dockerfile.voice
# ============================================================
# Voice-enabled build with ffmpeg, whisper.cpp (STT), and Piper (TTS).
# Use this when deploying with voice support on a capable server.
#
# Build:
# docker build -f Dockerfile.voice -t smallclaw-voice .
#
# Run:
# docker run -d --name smallclaw-voice \
# -p 18789:18789 \
# -v smallclaw_data:/data \
# -v smallclaw_workspace:/data/workspace \
# -v ~/.localclaw:/root/.localclaw \
# -e OLLAMA_HOST=http://host.docker.internal:11434 \
# smallclaw-voice
#
# Or with docker compose (see docker-compose.voice.yml):
# docker compose -f docker-compose.voice.yml up -d
# ============================================================
# ── Stage 1: Builder ────────────────────────────────────────
FROM node:20-slim AS builder
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci
COPY tsconfig.json ./
COPY src/ ./src/
RUN npm run build
# ── Stage 2: Runtime ────────────────────────────────────────
FROM node:20-slim AS runtime
# System deps: Playwright/Chromium + Tesseract OCR + ffmpeg (for voice audio conversion)
RUN apt-get update && apt-get install -y --no-install-recommends \
ca-certificates \
curl \
wget \
ffmpeg \
fonts-liberation \
libatk-bridge2.0-0 \
libatk1.0-0 \
libcairo2 \
libcups2 \
libdbus-1-3 \
libdrm2 \
libexpat1 \
libgbm1 \
libglib2.0-0 \
libgtk-3-0 \
libnspr4 \
libnss3 \
libpango-1.0-0 \
libpangocairo-1.0-0 \
libx11-6 \
libx11-xcb1 \
libxcb1 \
libxcomposite1 \
libxdamage1 \
libxext6 \
libxfixes3 \
libxrandr2 \
libxrender1 \
libxss1 \
libxtst6 \
xdg-utils \
tesseract-ocr \
&& rm -rf /var/lib/apt/lists/*
WORKDIR /app
# Production deps only
COPY package.json package-lock.json ./
RUN npm ci --omit=dev
# Install Playwright browser binaries
RUN npx playwright install chromium --with-deps 2>/dev/null || true
# ── Voice: Piper TTS ────────────────────────────────────────
# Install Piper binary + shared libs + Korean voice model
RUN ARCH=$(dpkg --print-architecture) && \
if [ "$ARCH" = "amd64" ]; then PIPER_ARCH="x86_64"; \
elif [ "$ARCH" = "arm64" ]; then PIPER_ARCH="aarch64"; \
elif [ "$ARCH" = "armhf" ]; then PIPER_ARCH="armv7l"; \
else PIPER_ARCH="$ARCH"; fi && \
cd /tmp && \
curl -L "https://github.com/rhasspy/piper/releases/download/2023.11.14-2/piper_linux_${PIPER_ARCH}.tar.gz" -o piper.tar.gz && \
tar xzf piper.tar.gz && \
cp piper/piper /usr/local/bin/piper && \
chmod +x /usr/local/bin/piper && \
cp piper/libespeak-ng.so* /usr/local/lib/ && \
cp piper/libonnxruntime.so* /usr/local/lib/ && \
cp piper/libpiper_phonemize.so* /usr/local/lib/ && \
cp piper/espeak-ng /usr/local/lib/ && \
cp -r piper/espeak-ng-data /usr/local/lib/ && \
ldconfig && \
rm -rf piper piper.tar.gz && \
mkdir -p /usr/local/share/piper-voices && \
curl -L "https://huggingface.co/neurlang/piper-onnx-kss-korean/resolve/main/piper-kss-korean.onnx" \
-o /usr/local/share/piper-voices/ko_KR-kss-medium.onnx && \
curl -L "https://huggingface.co/neurlang/piper-onnx-kss-korean/raw/main/piper-kss-korean.onnx.json" \
-o /usr/local/share/piper-voices/ko_KR-kss-medium.onnx.json
# ── Voice: whisper.cpp (STT) ────────────────────────────────
# Build from source (no pre-built Linux binary available)
RUN apt-get update && apt-get install -y --no-install-recommends cmake git build-essential && \
cd /tmp && \
git clone https://github.com/ggml-org/whisper.cpp.git && \
cd whisper.cpp && \
cmake -B build && \
cmake --build build --config Release -j$(nproc) && \
cp build/bin/whisper-cli /usr/local/bin/whisper-cli && \
rm -rf /tmp/whisper.cpp && \
apt-get remove -y git build-essential && \
apt-get autoremove -y && \
rm -rf /var/lib/apt/lists/* && \
mkdir -p /usr/local/share/whisper-models && \
curl -L "https://huggingface.co/ggerganov/whisper.cpp/resolve/main/ggml-base.bin" \
-o /usr/local/share/whisper-models/ggml-base.bin
# ── Voice: espeak-ng-data symlink ────────────────────────────
# Piper expects espeak-ng-data at /usr/share/espeak-ng-data
RUN ln -sf /usr/local/lib/espeak-ng-data /usr/share/espeak-ng-data
# ── Voice: Telegram DNS fix ───────────────────────────────────
# Some networks block 149.154.166.110; use working IP instead
RUN echo "149.154.167.220 api.telegram.org" >> /etc/hosts
# ── App ──────────────────────────────────────────────────────
COPY --from=builder /app/dist ./dist
# Static web UI
COPY web-ui/ ./web-ui/
# Data directories (overridden by volumes in compose)
RUN mkdir -p /data/workspace /data/logs /root/.localclaw
# ── Environment defaults ──────────────────────────────────────
ENV NODE_ENV=production \
DOCKER_CONTAINER=true \
SMALLCLAW_DATA_DIR=/data \
SMALLCLAW_WORKSPACE_DIR=/data/workspace \
GATEWAY_PORT=18789 \
GATEWAY_HOST=0.0.0.0 \
PLAYWRIGHT_BROWSERS_PATH=/root/.cache/ms-playwright \
\
SMALLCLAW_PROVIDER=ollama \
\
OLLAMA_HOST=http://ollama:11434 \
\
LM_STUDIO_ENDPOINT=http://host.docker.internal:1234 \
LM_STUDIO_API_KEY="" \
LM_STUDIO_MODEL="" \
\
LLAMA_CPP_ENDPOINT=http://host.docker.internal:8080 \
LLAMA_CPP_MODEL="" \
\
OPENAI_API_KEY="" \
OPENAI_MODEL=gpt-4o \
\
CODEX_MODEL=gpt-5.3-codex \
\
PIPER_MODEL_PATH=/usr/local/share/piper-voices/ko_KR-kss-medium.onnx \
PIPER_CONFIG_PATH=/usr/local/share/piper-voices/ko_KR-kss-medium.onnx.json \
WHISPER_MODEL_PATH=/usr/local/share/whisper-models/ggml-base.bin
EXPOSE 18789
HEALTHCHECK --interval=30s --timeout=10s --start-period=30s --retries=3 \
CMD curl -f http://localhost:18789/health || exit 1
CMD ["node", "dist/cli/index.js", "gateway"]