Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
677bfcd2a9 | ||
|
|
e49be6d04e | ||
|
|
1efabe03b1 |
21
Dockerfile
21
Dockerfile
@@ -10,8 +10,14 @@ ENV DEBIAN_FRONTEND=noninteractive \
|
|||||||
DISPLAY=:1 \
|
DISPLAY=:1 \
|
||||||
PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD=1 \
|
PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD=1 \
|
||||||
PATH=/opt/venv/bin:/root/.bun/bin:/usr/local/bin:/usr/bin:/bin \
|
PATH=/opt/venv/bin:/root/.bun/bin:/usr/local/bin:/usr/bin:/bin \
|
||||||
NVIDIA_VISIBLE_DEVICES=all \
|
NVIDIA_VISIBLE_DEVICES=all
|
||||||
NVIDIA_DRIVER_CAPABILITIES=compute,utility
|
|
||||||
|
# `video` is REQUIRED for NVENC/NVDEC: it tells the NVIDIA Container Toolkit to
|
||||||
|
# inject libnvidia-encode.so.1 / libnvidia-decode.so.1 into the container. With
|
||||||
|
# only `compute,utility` you get CUDA (ollama/whisper/melo) + nvidia-smi, but the
|
||||||
|
# Go-Live broadcast's h264_nvenc fails with "Cannot load libnvidia-encode.so.1".
|
||||||
|
# Applies on both Linux (CDI) and Windows Docker Desktop (WSL2).
|
||||||
|
ENV NVIDIA_DRIVER_CAPABILITIES=compute,utility,video
|
||||||
|
|
||||||
# --- System packages: desktop, VNC, Chrome deps, ffmpeg, python, ocr ---
|
# --- System packages: desktop, VNC, Chrome deps, ffmpeg, python, ocr ---
|
||||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||||
@@ -63,7 +69,11 @@ RUN ls -d /opt/venv/lib/python*/site-packages/nvidia/cublas/lib \
|
|||||||
# Heavy layer (torch CPU + transformers + MeCab); placed before the app
|
# Heavy layer (torch CPU + transformers + MeCab); placed before the app
|
||||||
# COPY so it stays cached across source-only changes. ---
|
# COPY so it stays cached across source-only changes. ---
|
||||||
COPY docker/setup-melo.sh /app/docker/setup-melo.sh
|
COPY docker/setup-melo.sh /app/docker/setup-melo.sh
|
||||||
RUN bash /app/docker/setup-melo.sh
|
# Strip CR before running: a Windows checkout (autocrlf) yields CRLF, which makes
|
||||||
|
# bash read line 18 as `set -euxo pipefail\r` and abort with
|
||||||
|
# "set: pipefail: invalid option name". .gitattributes pins *.sh to LF, but this
|
||||||
|
# keeps the build working even on a not-yet-renormalised working tree.
|
||||||
|
RUN sed -i 's/\r$//' /app/docker/setup-melo.sh && bash /app/docker/setup-melo.sh
|
||||||
|
|
||||||
# --- Human input + window management for the on-screen Chrome control tool.
|
# --- Human input + window management for the on-screen Chrome control tool.
|
||||||
# Placed AFTER the heavy melo layer so it doesn't bust that cache. xdotool
|
# Placed AFTER the heavy melo layer so it doesn't bust that cache. xdotool
|
||||||
@@ -81,6 +91,11 @@ RUN cd /app/bot && bun install --frozen-lockfile || bun install
|
|||||||
COPY . /app
|
COPY . /app
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
|
# Normalise all container shell scripts to LF. On a Windows checkout (autocrlf)
|
||||||
|
# these arrive as CRLF, which would break their shebangs at runtime (entrypoint,
|
||||||
|
# run-*.sh) the same way it broke setup-melo.sh at build time.
|
||||||
|
RUN find /app/docker /app/scripts -name '*.sh' -exec sed -i 's/\r$//' {} +
|
||||||
|
|
||||||
# --- Default Piper voice (best-effort at build; entrypoint retries if absent) ---
|
# --- Default Piper voice (best-effort at build; entrypoint retries if absent) ---
|
||||||
RUN bash docker/download-piper.sh || true
|
RUN bash docker/download-piper.sh || true
|
||||||
|
|
||||||
|
|||||||
@@ -150,12 +150,17 @@ def _ensure_brain():
|
|||||||
compute = os.environ.get("WHISPER_COMPUTE_TYPE", "auto")
|
compute = os.environ.get("WHISPER_COMPUTE_TYPE", "auto")
|
||||||
try:
|
try:
|
||||||
whisper = WhisperModel(cfg.whisper_model, device=device, compute_type=compute)
|
whisper = WhisperModel(cfg.whisper_model, device=device, compute_type=compute)
|
||||||
|
# Log the device actually resolved by CTranslate2 (device="auto"
|
||||||
|
# picks cuda when available) so a silent CPU load is visible.
|
||||||
|
resolved = str(getattr(getattr(whisper, "model", None), "device", device)).lower()
|
||||||
|
print(f"[bridge] whisper loaded on {resolved} (compute={compute})", flush=True)
|
||||||
except Exception as ge:
|
except Exception as ge:
|
||||||
# GPU not available / unsupported -> fall back to CPU so the
|
# GPU not available / unsupported -> fall back to CPU so the
|
||||||
# bridge still works without a GPU passed to the container.
|
# bridge still works without a GPU passed to the container.
|
||||||
if device != "cpu":
|
if device != "cpu":
|
||||||
print(f"[bridge] whisper device='{device}' failed ({ge}); falling back to CPU", flush=True)
|
print(f"[bridge] whisper device='{device}' failed ({ge}); falling back to CPU", flush=True)
|
||||||
whisper = WhisperModel(cfg.whisper_model, device="cpu", compute_type="int8")
|
whisper = WhisperModel(cfg.whisper_model, device="cpu", compute_type="int8")
|
||||||
|
print("[bridge] whisper loaded on cpu (compute=int8)", flush=True)
|
||||||
else:
|
else:
|
||||||
raise
|
raise
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user