// Author: Dr Hamid MADANI // // POST /api/record/audio — append an audio chunk to the per-session file. // // Headers expected : // X-Session-Id : opaque id grouping all chunks of one record // X-Chunk-Idx : monotonic chunk index (informational only) // Content-Type : MIME of the chunk (e.g. audio/webm;codecs=opus) // // Storage : ./data/records/.webm (relative to the studio cwd). import { NextRequest, NextResponse } from 'next/server' import { promises as fs } from 'fs' import path from 'path' export const runtime = 'nodejs' // Node fs append needs Node runtime export const dynamic = 'force-dynamic' const ROOT = path.join(process.cwd(), 'data', 'records') const SAFE = /^[a-zA-Z0-9_-]{1,128}$/ export async function POST(req: NextRequest) { const sessionId = req.headers.get('x-session-id') if (!sessionId || !SAFE.test(sessionId)) { return NextResponse.json({ error: 'invalid X-Session-Id' }, { status: 400 }) } const mime = req.headers.get('content-type') ?? 'audio/webm' const ext = mime.includes('ogg') ? 'ogg' : 'webm' await fs.mkdir(ROOT, { recursive: true }) const filePath = path.join(ROOT, `${sessionId}.${ext}`) const body = await req.arrayBuffer() if (body.byteLength === 0) { return NextResponse.json({ ok: true, bytes: 0 }) } await fs.appendFile(filePath, Buffer.from(body)) return NextResponse.json({ ok: true, bytes: body.byteLength }) }