(async function () { "use strict"; const sdk = await import("microsoft-cognitiveservices-speech-sdk"); const readline = require("readline"); const { exec } = require("child_process"); const path = require("path"); const fs = require("fs"); const rawFile = "tts_raw.wav"; const asteriskFile = "tts_asterisk.wav"; // Aufruf: // node tts.js -> background.wav, falls vorhanden // node tts.js meine-musik.mp3 -> diese Musik // node tts.js --no-music -> ohne Musik (auch: none, -n) const arg = process.argv[2]; const noMusic = ["--no-music", "none", "-n"].includes(arg); const musicFile = noMusic ? null : (arg || "background.wav"); const musicVolume = 0.15; const introMs = 2000; // Musik-Vorlauf vor der Sprache const speechConfig = sdk.SpeechConfig.fromSubscription( "c0d12660f15c4869bf2572fda3cb91ab", "germanywestcentral" ); const audioConfig = sdk.AudioConfig.fromAudioFileOutput(rawFile); const voiceName = "de-AT-IngridNeural"; const language = "de-AT"; speechConfig.speechSynthesisVoiceName = voiceName; const synthesizer = new sdk.SpeechSynthesizer(speechConfig, audioConfig); const rl = readline.createInterface({ input: process.stdin, output: process.stdout }); rl.question("Enter text with SSML break tags:\n> ", function (userInput) { rl.close(); const ssml = ` ${userInput} `; synthesizer.speakSsmlAsync( ssml, function (result) { synthesizer.close(); if (result.reason !== sdk.ResultReason.SynthesizingAudioCompleted) { console.error("TTS failed:", result.errorDetails); return; } const hasMusic = !noMusic && fs.existsSync(musicFile); if (!noMusic && !hasMusic) { console.warn(`Hinweis: "${musicFile}" nicht gefunden -> ohne Musik.`); } console.log( "Azure TTS done → converting for Asterisk" + (hasMusic ? ` (mit Musik: ${musicFile})...` : " (ohne Musik)...") ); let cmd; if (hasMusic) { cmd = `ffmpeg -y -i "${rawFile}" -stream_loop -1 -i "${musicFile}" ` + `-filter_complex "[0:a]adelay=${introMs}:all=1[sp];` + `[1:a]volume=${musicVolume}[bg];` + `[sp][bg]amix=inputs=2:duration=first:dropout_transition=0,` + `areverse,afade=t=in:d=2,areverse" ` + `-acodec pcm_s16le -ar 8000 -ac 1 "${asteriskFile}"`; } else { cmd = `ffmpeg -y -i "${rawFile}" -acodec pcm_s16le -ar 8000 -ac 1 "${asteriskFile}"`; } exec(cmd, (error, stdout, stderr) => { if (error) { console.error("FFmpeg error:", error); return; } console.log("Asterisk-compatible file created:", asteriskFile); fs.unlinkSync(rawFile); }); }, function (err) { console.error("Error:", err); synthesizer.close(); } ); console.log("Synthesizing..."); }); })();