/** * POST /api/telephony/recordings/transcribe { file, language?: 'de'|'en'|'es'|'auto', force? } * Starts the transcription of ONE recording with the shared whisper.cpp pipeline * (cached per file, serial per process) and waits a short moment for it, so a * short call still comes back in a single request. Anything longer answers * `202 pending` — the client then polls `transcribe-status` (the edge nginx cuts * requests at 60 s, see recordings.ts). Staff only. */ import { gateFromEvent } from '../../../utils/chatAccess' import { startTranscription, waitForTranscription, validRecordingName } from '../../../utils/telephony/recordings' import { statusResponse } from '../../../utils/telephony/transcriptionResponse' const WAIT_MS = 20000 export default defineEventHandler(async (event) => { try { await gateFromEvent(event) } catch (err: any) { return { status: err?.statusCode || 403, message: 'Forbidden' } } const body: any = await readBody(event).catch(() => ({})) const file = validRecordingName(body?.file) if (!file) return { status: 400, message: 'Invalid recording name' } const language = ['de', 'en', 'es', 'auto'].includes(String(body?.language)) ? String(body.language) : 'de' try { let status = await startTranscription(file, language, body?.force === true) if (status.state === 'pending') status = await waitForTranscription(file, WAIT_MS) return statusResponse(file, status) } catch (err: any) { console.warn('[recordings] transcribe start failed:', file, err?.message || err) return { status: 502, file, message: err?.message || 'Transcription failed' } } })