71 lines
2.2 KiB
TypeScript
71 lines
2.2 KiB
TypeScript
/**
|
|
* POST /api/coach/speak
|
|
* Empfängt text → FreeTTS (Microsoft Neural Voices, kostenlos) → gibt base64 Audio zurück
|
|
*/
|
|
export default defineEventHandler(async (event) => {
|
|
await requireUser(event);
|
|
|
|
const body = await readBody(event);
|
|
const { text } = body as { text: string };
|
|
|
|
if (!text?.trim()) {
|
|
throw createError({ statusCode: 400, message: "text fehlt" });
|
|
}
|
|
|
|
// Max 4096 Zeichen
|
|
const trimmed = text.slice(0, 4096);
|
|
|
|
try {
|
|
// FreeTTS API - free, no key required
|
|
const response = await fetch("https://freetts.org/api/tts", {
|
|
method: "POST",
|
|
headers: {
|
|
"Content-Type": "application/json",
|
|
},
|
|
body: JSON.stringify({
|
|
text: trimmed,
|
|
voice: "de-DE-KatjaNeural",
|
|
speed: 1.0,
|
|
output: "mp3",
|
|
}),
|
|
});
|
|
|
|
const responseText = await response.text();
|
|
console.log("[speak] FreeTTS response status:", response.status);
|
|
console.log("[speak] FreeTTS response body:", responseText);
|
|
|
|
if (!response.ok) {
|
|
console.error("[speak] FreeTTS error:", response.status, responseText);
|
|
throw createError({ statusCode: 502, message: `TTS fehlgeschlagen: ${responseText}` });
|
|
}
|
|
|
|
// FreeTTS returns a file_id to download
|
|
const result = JSON.parse(responseText);
|
|
|
|
if (!result.file_id) {
|
|
console.error("[speak] FreeTTS no file_id:", result);
|
|
throw createError({ statusCode: 502, message: "TTS fehlgeschlagen: no file_id" });
|
|
}
|
|
|
|
// Download the audio file from correct endpoint
|
|
console.log("[speak] Downloading audio file:", result.file_id);
|
|
const audioResponse = await fetch(`https://freetts.org/api/audio/${result.file_id}`);
|
|
|
|
if (!audioResponse.ok) {
|
|
console.error("[speak] Audio download failed:", audioResponse.status);
|
|
throw createError({ statusCode: 502, message: "TTS fehlgeschlagen: download failed" });
|
|
}
|
|
|
|
const audioBuffer = await audioResponse.arrayBuffer();
|
|
const base64 = Buffer.from(audioBuffer).toString("base64");
|
|
|
|
return { audio: `data:audio/mp3;base64,${base64}` };
|
|
} catch (err: any) {
|
|
console.error("[speak] TTS error:", err?.message || err);
|
|
throw createError({
|
|
statusCode: 502,
|
|
message: err?.message || "TTS fehlgeschlagen",
|
|
});
|
|
}
|
|
});
|