const ffmpeg = require("fluent-ffmpeg"); const ffmpegPath = require("ffmpeg-static"); ffmpeg.setFfmpegPath(ffmpegPath); module.exports = { name: "extract-speaker-snippets", type: "audio", displayname: "Extract Speaker Snippets", async function(parameter) { return new Promise(async (resolve, reject) => { let output = {} console.log("Extract Speaker Snippets\n"); // Pfade const AUDIO_PATH = parameter.audioPath; // Gesamt-Audio const JSON_PATH = parameter.jsonPath; // json summary const OUTPUT_DIR = path.join(__dirname, "/../../../storage/audio/speakerSnippets"); if (!AUDIO_PATH || !JSON_PATH) { console.error("no audioPath or jsonPath available"); return; } // Output-Ordner if (!fs.existsSync(OUTPUT_DIR)) { fs.mkdirSync(OUTPUT_DIR, { recursive: true }); } // JSON laden let entries; try { entries = JSON.parse(fs.readFileSync(JSON_PATH, "utf8")); } catch (err) { console.error("JSON reading failed", err); return; } if (!Array.isArray(entries)) { console.error("JSON is not an Array"); return; } // Pro Speaker genau EINEN Satz merken const speakerMap = {}; for (const item of entries) { if (!speakerMap[item.speaker]) { speakerMap[item.speaker] = item; } } // FFmpeg pro Speaker ausführen (sequenziell) for (const speaker of Object.keys(speakerMap)) { const data = speakerMap[speaker]; // ms → Sekunden const startSec = data.start / 1000; const durationSec = (data.end - data.start) / 1000; if (durationSec <= 0) { console.log(`invalid times for Speaker ${speaker}`); continue; } const outFile = path.join(OUTPUT_DIR, `speaker_${speaker}.wav`); await new Promise((res, rej) => { ffmpeg(AUDIO_PATH) .setStartTime(startSec) .setDuration(durationSec) .output(outFile) .on("end", () => { output[`speaker${speaker}`] = {src: outFile, name: `speaker${speaker}`} console.log(`Snippet erstellt: speaker_${speaker}.wav`); res(); }) .on("error", (err) => { console.error(`FFmpeg Fehler (${speaker})`, err.message); rej(); }) .run(); }); } resolve(output) console.log("\nAlle Speaker-Snippets erstellt\n"); }) } };