| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273 |
- import { NextRequest } from 'next/server';
- import { transcribeAudio } from '@/lib/audio/asr-providers';
- import { resolveASRApiKey, resolveASRBaseUrl } from '@/lib/server/provider-config';
- import type { ASRProviderId } from '@/lib/audio/types';
- import { createLogger } from '@/lib/logger';
- import { apiError, apiSuccess } from '@/lib/server/api-response';
- import { validateUrlForSSRF } from '@/lib/server/ssrf-guard';
- const log = createLogger('Transcription');
- export const maxDuration = 60;
- export async function POST(req: NextRequest) {
- let resolvedProviderId: string | undefined;
- let resolvedModelId: string | undefined;
- try {
- const formData = await req.formData();
- const audioFile = formData.get('audio') as File;
- const providerId = formData.get('providerId') as ASRProviderId | null;
- const modelId = formData.get('modelId') as string | null;
- const language = formData.get('language') as string | null;
- const apiKey = formData.get('apiKey') as string | null;
- const baseUrl = formData.get('baseUrl') as string | null;
- if (!audioFile) {
- return apiError('MISSING_REQUIRED_FIELD', 400, 'Audio file is required');
- }
- // providerId is required from the client — no server-side store to fall back to
- const effectiveProviderId = providerId || ('openai-whisper' as ASRProviderId);
- resolvedProviderId = effectiveProviderId;
- resolvedModelId = modelId ?? undefined;
- const clientBaseUrl = baseUrl || undefined;
- if (clientBaseUrl && process.env.NODE_ENV === 'production') {
- const ssrfError = await validateUrlForSSRF(clientBaseUrl);
- if (ssrfError) {
- return apiError('INVALID_URL', 403, ssrfError);
- }
- }
- const config = {
- providerId: effectiveProviderId,
- modelId: modelId || undefined,
- language: language || 'auto',
- apiKey: clientBaseUrl
- ? apiKey || ''
- : resolveASRApiKey(effectiveProviderId, apiKey || undefined),
- baseUrl: clientBaseUrl
- ? clientBaseUrl
- : resolveASRBaseUrl(effectiveProviderId, baseUrl || undefined),
- };
- // Convert audio file to buffer
- const arrayBuffer = await audioFile.arrayBuffer();
- const buffer = Buffer.from(arrayBuffer);
- // Transcribe using the provider system
- const result = await transcribeAudio(config, buffer);
- return apiSuccess({ text: result.text });
- } catch (error) {
- log.error(
- `Transcription failed [provider=${resolvedProviderId ?? 'unknown'}, model=${resolvedModelId ?? 'default'}]:`,
- error,
- );
- return apiError(
- 'TRANSCRIPTION_FAILED',
- 500,
- 'Transcription failed',
- error instanceof Error ? error.message : 'Unknown error',
- );
- }
- }
|