Fix STT health check incorrectly marking Open WebUI as whisper.cpp
Port 8080 is Open WebUI — it passes /health + /v1/models checks but returns 405 on POST /v1/audio/transcriptions. Updated probe logic to: - treat 405 as 'endpoint missing, try next path' - treat non-JSON 500 as broken, JSON-500 with detail as 'audio too short' (ok) - use 500ms silence WAV instead of 1-frame (too tiny for alignment models) Changed whisper.cpp default from :8080 to :8085 to avoid clash with Open WebUI. Updated s-llms.html placeholder and code snippet accordingly. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
8f9060d025
commit
d16be50cc9
39
server.py
39
server.py
@ -48,7 +48,7 @@ _NVIDIA_CLONE_DEFAULT = os.environ.get("NVIDIA_TTS_CLONE_URL", "http://host.dock
|
||||
_NVIDIA_ZEROSHOT_DEFAULT = os.environ.get("NVIDIA_ZEROSHOT_TTS_URL", _NVIDIA_CLONE_DEFAULT)
|
||||
_NVIDIA_FLOW_DEFAULT = os.environ.get("NVIDIA_FLOW_TTS_URL", "http://host.docker.internal:8094")
|
||||
_FASTER_WHISPER_DEFAULT = os.environ.get("FASTER_WHISPER_URL", "http://host.docker.internal:8000")
|
||||
_WHISPER_CPP_DEFAULT = os.environ.get("WHISPER_CPP_URL", "http://host.docker.internal:8080")
|
||||
_WHISPER_CPP_DEFAULT = os.environ.get("WHISPER_CPP_URL", "http://host.docker.internal:8085")
|
||||
_GROQ_STT_ENDPOINT = "https://api.groq.com/openai/v1"
|
||||
_KOKORO_DEFAULT = os.environ.get("KOKORO_URL", "http://host.docker.internal:8880/v1")
|
||||
_VIBEVOICE_DEFAULT = os.environ.get("VIBEVOICE_URL", "http://192.168.178.8:8027")
|
||||
@ -1903,15 +1903,15 @@ def _stt_backend_api_key(settings: dict, backend: str) -> str:
|
||||
return settings.get("whisper_api_key", "").strip()
|
||||
|
||||
|
||||
def _make_minimal_wav() -> bytes:
|
||||
"""44-byte WAV header with 1 frame of silence — smallest valid WAV."""
|
||||
import struct
|
||||
num_frames = 1
|
||||
data = b"\x00\x00"
|
||||
def _make_minimal_wav(duration_ms: int = 500) -> bytes:
|
||||
"""Minimal WAV: mono 16-bit 16kHz silence of given duration."""
|
||||
sample_rate = 16000
|
||||
num_frames = sample_rate * duration_ms // 1000
|
||||
data = b"\x00\x00" * num_frames
|
||||
header = struct.pack(
|
||||
"<4sI4s4sIHHIIHH4sI",
|
||||
b"RIFF", 36 + len(data), b"WAVE",
|
||||
b"fmt ", 16, 1, 1, 16000, 32000, 2, 16,
|
||||
b"fmt ", 16, 1, 1, sample_rate, sample_rate * 2, 2, 16,
|
||||
b"data", len(data),
|
||||
)
|
||||
return header + data
|
||||
@ -1942,9 +1942,11 @@ def _stt_backend_health(url: str) -> tuple[bool, list[str]]:
|
||||
if not ok:
|
||||
return False, models
|
||||
# Verify the transcription endpoint actually works (catches broken builds like
|
||||
# CTranslate2 containers compiled without CUDA that pass /health but fail on load)
|
||||
# CTranslate2 containers compiled without CUDA that pass /health but fail on load,
|
||||
# and LLM servers that expose /v1/models but no transcription endpoint)
|
||||
try:
|
||||
wav = _make_minimal_wav()
|
||||
endpoint_found = False
|
||||
for path in ("/v1/audio/transcriptions", "/transcribe"):
|
||||
try:
|
||||
r = requests.post(
|
||||
@ -1953,14 +1955,29 @@ def _stt_backend_health(url: str) -> tuple[bool, list[str]]:
|
||||
data={"model": "whisper-1", "response_format": "text"},
|
||||
timeout=8,
|
||||
)
|
||||
if r.status_code in {404, 405}:
|
||||
continue # try next path — endpoint missing or wrong method
|
||||
if r.status_code == 500:
|
||||
ok = False # backend is broken (model load failed etc.)
|
||||
break # 200, 400, 404, 422 all mean the endpoint exists and model loaded
|
||||
# Distinguish backend crash from "couldn't process empty audio":
|
||||
# a JSON detail that isn't the generic FastAPI text means the
|
||||
# model loaded and responded — treat as ok (audio was just bad)
|
||||
try:
|
||||
detail = r.json().get("detail", "")
|
||||
ok = bool(detail) and detail.lower() != "internal server error"
|
||||
except Exception:
|
||||
ok = False # non-JSON 500 → backend likely broken
|
||||
else:
|
||||
ok = True # 200, 400, 415, 422 → endpoint works
|
||||
endpoint_found = True
|
||||
break
|
||||
except requests.exceptions.ConnectionError:
|
||||
ok = False
|
||||
endpoint_found = True
|
||||
break
|
||||
except Exception:
|
||||
pass # timeout or other — don't mark as broken, just skip
|
||||
pass # timeout — don't penalise slow model loads
|
||||
if not endpoint_found:
|
||||
ok = False # all paths returned 404/405 — not an STT backend
|
||||
except Exception:
|
||||
pass
|
||||
return ok, models
|
||||
|
||||
@ -350,7 +350,7 @@ Check "Enable CORS" for browser access</pre>
|
||||
<p class="llm-local-desc">Minimal C++ Whisper with a built-in HTTP server. CPU or Metal/CUDA. Low memory, fast on consumer hardware.</p>
|
||||
<div class="llm-local-url">
|
||||
<span class="llm-local-url-label">URL</span>
|
||||
<input class="llm-local-url-inp" type="text" placeholder="http://localhost:8080" data-llm-local-key="whisper-cpp" data-llm-local-default="http://localhost:8080" spellcheck="false">
|
||||
<input class="llm-local-url-inp" type="text" placeholder="http://localhost:8085" data-llm-local-key="whisper-cpp" data-llm-local-default="http://localhost:8085" spellcheck="false">
|
||||
<button class="llm-local-ping" data-ping-key="whisper-cpp" title="Test connection">Connect</button>
|
||||
</div>
|
||||
<div class="llm-local-actions">
|
||||
@ -359,12 +359,12 @@ Check "Enable CORS" for browser access</pre>
|
||||
<div class="llm-local-snippet">
|
||||
<div class="llm-snippet-bar">
|
||||
<span>Build & run</span>
|
||||
<button class="llm-copy-btn" data-copy="git clone https://github.com/ggml-org/whisper.cpp cd whisper.cpp && cmake -B build && cmake --build build -j ./build/bin/whisper-server -m models/ggml-large-v3.bin --port 8080">Copy</button>
|
||||
<button class="llm-copy-btn" data-copy="git clone https://github.com/ggml-org/whisper.cpp cd whisper.cpp && cmake -B build && cmake --build build -j ./build/bin/whisper-server -m models/ggml-large-v3.bin --port 8085">Copy</button>
|
||||
</div>
|
||||
<pre>git clone https://github.com/ggml-org/whisper.cpp
|
||||
cd whisper.cpp && cmake -B build && cmake --build build -j
|
||||
./build/bin/whisper-server \
|
||||
-m models/ggml-large-v3.bin --port 8080</pre>
|
||||
-m models/ggml-large-v3.bin --port 8085</pre>
|
||||
</div>
|
||||
<a class="llm-local-link" href="https://github.com/ggml-org/whisper.cpp" target="_blank" rel="noopener">github.com/ggml-org/whisper.cpp <span class="mdi mdi-open-in-new link-icon"></span></a>
|
||||
</div>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user