Files
Void-Homelab/lib/voice/whisper.js
root e29bacbda1 feat(dross): voice Phase 2a — local whisper transcribe + mic (2.12.0)
faster-whisper (small.en, GPU+CPU fallback) on CT 102 → POST
/api/voice/transcribe (multer→whisper client) → mic in the bubble
records (MediaRecorder), uploads, drops the transcript into the input
to review-and-send. Infra scripts in deploy/whisper/. Retention (P2b)
next. NOTE: mic needs a secure context (the https domain), not the LAN IP.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-10 01:00:10 +10:00

23 lines
988 B
JavaScript

// Thin client for the local faster-whisper service on CT 102 (the Ollama box).
// GPU with CPU fallback lives in the service itself; here we just POST the audio
// buffer and return the transcript. LAN-only endpoint.
const WHISPER_URL = process.env.WHISPER_URL || 'http://192.168.1.185:8001';
export async function transcribe(buffer, filename = 'clip.webm', mime = 'audio/webm') {
const fd = new FormData();
fd.append('file', new Blob([buffer], { type: mime }), filename);
const res = await fetch(`${WHISPER_URL}/transcribe`, {
method: 'POST', body: fd, signal: AbortSignal.timeout(120000)
});
if (!res.ok) throw new Error(`whisper ${res.status}`);
const j = await res.json();
return { text: (j.text || '').trim(), duration: j.duration, device: j.device };
}
export async function health() {
try {
const res = await fetch(`${WHISPER_URL}/health`, { signal: AbortSignal.timeout(5000) });
return res.ok ? await res.json() : null;
} catch { return null; }
}