extract shared whisper transcribe helper, use in file-browser and pi stt routes
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -7,6 +7,7 @@ import * as errors from '@@/custom-errors';
|
||||
import { readTtsConfig } from '@@/api/server-settings/tts';
|
||||
import { readSttConfig } from '@@/api/server-settings/stt';
|
||||
import { readOcrConfig } from '@@/api/server-settings/ocr';
|
||||
import { transcribeAudio } from '@@/api/stt/transcribe';
|
||||
import { getUserSettings } from 'officerdb';
|
||||
|
||||
async function getUserTtsVoice(userId: number): Promise<string | null> {
|
||||
@@ -794,45 +795,17 @@ router.post('/transcribe', async (ctx) => {
|
||||
const whisperUrl = sttConfig?.url;
|
||||
if (!whisperUrl) throw errors.BAD_REQUEST('Whisper not configured — set it up in Settings → Speech to Text');
|
||||
|
||||
const audioFile = Bun.file(absPath);
|
||||
|
||||
// Step 1: Detect language
|
||||
const detectForm = new FormData();
|
||||
detectForm.append('file', audioFile);
|
||||
detectForm.append('temperature', '0.0');
|
||||
detectForm.append('response_format', 'verbose_json');
|
||||
detectForm.append('detect_language', 'true');
|
||||
|
||||
const detectRes = await fetch(`${whisperUrl}/inference`, { method: 'POST', body: detectForm });
|
||||
if (!detectRes.ok) throw errors.BAD_REQUEST('Language detection failed');
|
||||
|
||||
const detectJson = (await detectRes.json()) as { language?: string };
|
||||
const detectedLang = detectJson.language ?? 'en';
|
||||
|
||||
// Step 2: Check user's spoken languages to decide if translation is needed
|
||||
let shouldTranslate = false;
|
||||
const settings = await getUserSettings(user.id);
|
||||
const spokenLanguages = (settings.languages as { spoken?: string[] })?.spoken ?? [];
|
||||
if (spokenLanguages.length > 0 && !spokenLanguages.includes(detectedLang)) {
|
||||
shouldTranslate = true;
|
||||
|
||||
let text: string;
|
||||
try {
|
||||
const result = await transcribeAudio({ file: Bun.file(absPath), whisperUrl, spokenLanguages });
|
||||
text = result.text;
|
||||
} catch (err) {
|
||||
throw errors.BAD_REQUEST(err instanceof Error ? err.message : 'Transcription failed');
|
||||
}
|
||||
|
||||
// Step 3: Full transcription
|
||||
const transcribeForm = new FormData();
|
||||
transcribeForm.append('file', audioFile);
|
||||
transcribeForm.append('temperature', '0.0');
|
||||
transcribeForm.append('temperature_inc', '0.2');
|
||||
transcribeForm.append('response_format', 'text');
|
||||
transcribeForm.append('language', detectedLang);
|
||||
if (shouldTranslate) {
|
||||
transcribeForm.append('translate', 'true');
|
||||
}
|
||||
|
||||
const res = await fetch(`${whisperUrl}/inference`, { method: 'POST', body: transcribeForm });
|
||||
if (!res.ok) throw errors.BAD_REQUEST('Transcription request failed');
|
||||
|
||||
const text = (await res.text()).trim();
|
||||
|
||||
await mkdir(dirname(cacheAbs), { recursive: true });
|
||||
await Bun.write(cacheAbs, text);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user