diff --git a/server.py b/server.py
index 2c575e1..2445641 100644
--- a/server.py
+++ b/server.py
@@ -1974,7 +1974,7 @@ def _transcribe_audio(src: Path, settings: dict, backend: str = "configured") ->
headers=hdrs,
timeout=_STT_REQUEST_TIMEOUT,
)
- if resp.status_code in {400, 404, 422} and model != "whisper-1":
+ if resp.status_code in {400, 404, 422, 500} and model != "whisper-1":
with src.open("rb") as f:
resp = requests.post(
f"{stt_url}/v1/audio/transcriptions",
diff --git a/static/app.js b/static/app.js
index aa27df6..a51a417 100644
--- a/static/app.js
+++ b/static/app.js
@@ -8227,12 +8227,27 @@ $('s-import-voices-file')?.addEventListener('change', async function () {
// ── Populate STT backends ────────────────────────────────────────────────
async function loadConvSttBackends() {
if (!sttSel) return;
+ const prev = sttSel.value;
try {
const d = await fetch('/api/stt-backends').then(r => r.json());
- const avail = (d.backends || []).filter(b => b.available);
- sttSel.innerHTML = avail.length
- ? avail.map(b => ``).join('')
- : '';
+ const all = d.backends || [];
+ if (!all.length) {
+ sttSel.innerHTML = '';
+ return;
+ }
+ sttSel.innerHTML = all.map(b => {
+ const icon = b.available ? '✓' : '✗';
+ const label = `${icon} ${escHtml(b.label)}`;
+ const disabled = !b.available;
+ return ``;
+ }).join('');
+ // Restore prev selection or pick first available
+ const opt = sttSel.querySelector(`option[value="${CSS.escape(prev)}"]`);
+ if (opt && !opt.disabled) { sttSel.value = prev; }
+ else {
+ const first = sttSel.querySelector('option:not([disabled])');
+ if (first) sttSel.value = first.value;
+ }
} catch(_) {
sttSel.innerHTML = '';
}
@@ -8241,10 +8256,22 @@ $('s-import-voices-file')?.addEventListener('change', async function () {
// ── Populate TTS backends (reuse global _ttsBackends) ───────────────────
function populateConvTtsBackends() {
if (!ttsBkSel) return;
- const avail = availableTtsBackends();
- ttsBkSel.innerHTML = avail.length
- ? avail.map(b => ``).join('')
- : '';
+ const prev = ttsBkSel.value;
+ const all = window._ttsBackends || [];
+ if (!all.length) {
+ ttsBkSel.innerHTML = '';
+ return;
+ }
+ ttsBkSel.innerHTML = all.map(b => {
+ const icon = b.available ? '✓' : '✗';
+ return ``;
+ }).join('');
+ const opt = ttsBkSel.querySelector(`option[value="${CSS.escape(prev)}"]`);
+ if (opt && !opt.disabled) { ttsBkSel.value = prev; }
+ else {
+ const first = ttsBkSel.querySelector('option:not([disabled])');
+ if (first) ttsBkSel.value = first.value;
+ }
}
// ── Fetch LLM models ─────────────────────────────────────────────────────