initial commit

This commit is contained in:
2026-02-28 19:44:58 +01:00
commit c1fbcdf6b1
13 changed files with 2422 additions and 0 deletions

209
generate-audio.js Normal file
View File

@@ -0,0 +1,209 @@
#!/usr/bin/env node
/**
* Generate MP3 audio files for all German questions using ElevenLabs TTS API.
*
* Usage:
* 1. Get your API key from https://elevenlabs.io/app/settings/api-keys
* 2. Run: ELEVENLABS_API_KEY=your-key-here node generate-audio.js
*
* Output: src/public/audio/<topic_id>_<index>.mp3
*
* Free tier: ~10,000 characters/month — enough for all 60 questions (~2,500 chars total).
*/
const fs = require("fs");
const path = require("path");
const API_KEY = process.env.ELEVENLABS_API_KEY;
if (!API_KEY) {
console.error("Error: set ELEVENLABS_API_KEY environment variable");
console.error(" ELEVENLABS_API_KEY=your-key node generate-audio.js");
process.exit(1);
}
// Same questions as in index.html
const TOPICS = [
{
id: "alltag",
questions: [
"Wie sieht dein typischer Morgen aus?",
"Was machst du normalerweise in deiner Freizeit?",
"Wie oft kochst du zu Hause und was bereitest du gerne zu?",
"Beschreibe deinen Tagesablauf an einem Werktag.",
"Welche Aufgaben im Haushalt magst du und welche nicht?",
"Wie verbringst du deinen Feierabend?",
"Machst du regelmäßig Sport? Was und wie oft?",
"Wie oft triffst du dich mit Freunden oder Familie?",
"Was liest du gerne Bücher, Zeitungen oder Online-Artikel?",
"Wie entspannst du dich nach einem stressigen Tag?",
],
},
{
id: "arbeit",
questions: [
"Was machst du beruflich und was gefällt dir an deiner Arbeit?",
"Wie sieht dein Arbeitsplatz aus Büro, Homeoffice oder beides?",
"Was sind die größten Herausforderungen in deinem Job?",
"Wie lange arbeitest du täglich und wie ist die Work-Life-Balance?",
"Hast du nette Kollegen? Wie ist das Arbeitsklima?",
"Welche Fähigkeiten brauchst du für deinen Beruf?",
"Was würdest du beruflich ändern, wenn du könntest?",
"Wie wichtig ist Karriere für dich im Vergleich zu Freizeit?",
"Hast du schon mal den Job gewechselt? Warum?",
"Was sind deine beruflichen Ziele für die Zukunft?",
],
},
{
id: "reisen",
questions: [
"Wohin bist du zuletzt gereist und wie war es?",
"Reist du lieber alleine oder mit anderen? Warum?",
"Was ist dein Traumreiseziel und warum?",
"Bevorzugst du Strand, Berge oder Städtereisen?",
"Wie planst du normalerweise deine Reisen?",
"Was nimmst du immer mit auf Reisen?",
"Hast du schon mal einen Kulturschock erlebt?",
"Welches Essen aus einem anderen Land hat dir besonders gefallen?",
"Wie wichtig ist es für dich, die Landessprache zu kennen?",
"Erzähl von einem unvergesslichen Reiseerlebnis.",
],
},
{
id: "schweiz",
questions: [
"Was magst du am Leben in der Schweiz besonders?",
"Wie unterscheidet sich das Schweizerdeutsch vom Hochdeutsch?",
"Was sind typisch schweizerische Gewohnheiten oder Traditionen?",
"Welche Sehenswürdigkeiten in Bern kennst du?",
"Was ist das Besondere am schweizerischen Bildungssystem?",
"Wie ist das öffentliche Verkehrsnetz in der Schweiz?",
"Was denkst du über die Mehrsprachigkeit in der Schweiz?",
"Welche Schweizer Gerichte kennst du und magst du?",
"Wie erleben Ausländer das Einleben in der Schweiz?",
"Was sind Vor- und Nachteile der direkten Demokratie?",
],
},
{
id: "gesundheit",
questions: [
"Wie wichtig ist dir deine Gesundheit im Alltag?",
"Treibst du Sport für die Gesundheit oder zum Spaß?",
"Wie ernährst du dich bewusst oder eher spontan?",
"Wie gehst du mit Stress um?",
"Schläfst du gut? Was machst du für besseren Schlaf?",
"Gehst du regelmäßig zum Arzt für Vorsorgeuntersuchungen?",
"Was meinst du wie viel Einfluss hat man auf die eigene Gesundheit?",
"Wie beeinflusst das Wetter deine Stimmung und Gesundheit?",
"Hast du Allergien oder besondere gesundheitliche Themen?",
"Was ist für dich gesunde Ernährung?",
],
},
{
id: "meinungen",
questions: [
"Was denkst du über soziale Medien Fluch oder Segen?",
"Glaubst du, dass Homeoffice die Produktivität steigert?",
"Was meinst du: Ist lebenslanges Lernen wichtig?",
"Wie stehst du zu vegetarischer oder veganer Ernährung?",
"Glaubst du, dass KI unsere Arbeitswelt stark verändern wird?",
"Was hältst du von öffentlichem Nahverkehr statt Autofahren?",
"Ist es wichtig, mehrere Sprachen zu sprechen? Warum?",
"Was denkst du über die vier-Tage-Arbeitswoche?",
"Sollten mehr Menschen ehrenamtlich arbeiten?",
"Wie wichtig ist lokales Einkaufen für die Umwelt?",
],
},
];
// ElevenLabs voice ID — "Daniel" (German male, clear, natural)
// Browse voices at https://elevenlabs.io/voice-library and replace if needed
const VOICE_ID = "onwK4e9ZLuTAKqWW03F9";
const MODEL_ID = "eleven_multilingual_v2";
const OUTPUT_DIR = path.join(__dirname, "src", "public", "audio");
async function generateAudio(text, outputPath) {
const response = await fetch(
`https://api.elevenlabs.io/v1/text-to-speech/${VOICE_ID}`,
{
method: "POST",
headers: {
"xi-api-key": API_KEY,
"Content-Type": "application/json",
Accept: "audio/mpeg",
},
body: JSON.stringify({
text,
model_id: MODEL_ID,
language_code: "de",
voice_settings: {
stability: 0.6,
similarity_boost: 0.8,
speed: 0.9,
},
}),
}
);
if (!response.ok) {
const error = await response.text();
throw new Error(`ElevenLabs API error ${response.status}: ${error}`);
}
const buffer = Buffer.from(await response.arrayBuffer());
fs.writeFileSync(outputPath, buffer);
}
async function main() {
fs.mkdirSync(OUTPUT_DIR, { recursive: true });
let total = 0;
let generated = 0;
let skipped = 0;
for (const topic of TOPICS) {
total += topic.questions.length;
}
console.log(`Generating ${total} audio files...\n`);
for (const topic of TOPICS) {
for (let i = 0; i < topic.questions.length; i++) {
const filename = `${topic.id}_${i}.mp3`;
const outputPath = path.join(OUTPUT_DIR, filename);
// Skip if already exists (resume support)
if (fs.existsSync(outputPath)) {
skipped++;
console.log(` [skip] ${filename} (already exists)`);
continue;
}
const question = topic.questions[i];
process.stdout.write(
` [${generated + skipped + 1}/${total}] ${filename} ... `
);
try {
await generateAudio(question, outputPath);
generated++;
console.log("OK");
} catch (err) {
console.log(`FAILED: ${err.message}`);
console.log(" Stopping. Re-run to continue from where you left off.");
process.exit(1);
}
// Delay to respect rate limits
await new Promise((r) => setTimeout(r, 500));
}
}
console.log(
`\nDone! Generated: ${generated}, Skipped: ${skipped}, Total: ${total}`
);
console.log(`Files saved to: ${OUTPUT_DIR}`);
}
main();