const EventEmitter = require('events'); const audioEvents = new EventEmitter(); // Ensure ffmpeg binary is available if (!ffmpegPath) { throw new Error('FFmpeg binary not found!'); } ffmpeg.setFfmpegPath(ffmpegPath); // Prepare output directory (always storage/audio under project root) const outputDir = `${__dirname}/../../../storage/audio`; if (!fs.existsSync(outputDir)) { fs.mkdirSync(outputDir, { recursive: true }); } module.exports = { name:"extraction-video-to-audio", // Unique name for our function that will later be used to get the function from the map via "mapFunctions.get("example").function()" type:"extractor", // value used to differentiate each module to order them in the UI displayname:"Default extractor", // The displayname used within the UI async function(parameter){ /* parameter structure: { inputVideoPath: String, // Path to the file outputType: String // Audio file output format } */ let progressBar = new cliProgress.SingleBar({ format: 'Processing |{bar}| {percentage}% | {timemark}', barCompleteChar: '\u2588', barIncompleteChar: '\u2591', hideCursor: true }); try { // if (meta.url === `file://${process.argv[1]}`) { this.extractAudioFromVideo(parameter.inputVideoPath, progressBar, parameter.outputType) .then(() => console.log('Audio extraction successful.')) .catch((err) => console.error(err)); // } } catch (error) { console.log(parameter.outputType); } }, // Derive input and output paths // const inputVideoPath = process.argv[2]; // console.log(process.argv); /** * Extracts audio from a video using ffmpeg. * - Converts video to WAV (16 kHz, Mono, PCM optional if needed) * - Shows CLI progress bar * - Handles errors gracefully (without errors) */ extractAudioFromVideo: async function (videoFilePath, progressBar, outputType){ let inputVideoName = path.basename(videoFilePath, path.extname(videoFilePath)); let outputAudioPath = path.join(outputDir, `${inputVideoName}.${outputType}`); return new Promise((resolve, reject) => { try { ffmpeg(videoFilePath) .outputFormat(outputType) // .audioCodec('pcm_s16le') .audioChannels(1) .audioFrequency(16000) // .setFfmpegPath("./ffmpeg.exe") .on('progress', (progress) => { if (!progressBar.isActive) progressBar.start(100, 0, { timemark: '00:00:00' }); if (progress.percent) { progressBar.update(progress.percent, { timemark: progress.timemark }); } }) .on('end', () => { progressBar.update(100, { timemark: 'done' }); progressBar.stop(); console.log(`Extraction completed: ${outputAudioPath}`); audioEvents.emit('audio_ready', { sessionId: inputVideoName, audioPath: outputAudioPath }); resolve(); }) .on('error', (err) => { progressBar.stop(); console.error(`failed_audio_extraction on type ${outputType}: ${err.message}`); reject(err); }) .save(outputAudioPath); } catch (error) { console.log(); } }); }, audioEvents: audioEvents }