Added some improved commentary

This commit is contained in:
MikeHughes-BIN
2025-11-02 17:46:36 +01:00
parent 461998cd66
commit 029f40057a
+26 -17
View File
@@ -3,39 +3,40 @@ import ffmpeg from 'fluent-ffmpeg';
import path from 'path'; import path from 'path';
import fs from 'fs'; import fs from 'fs';
import cliProgress from 'cli-progress'; import cliProgress from 'cli-progress';
// Source for the base code: https://docs.yemreak.com/arsiv/programming/extract-audio-from-video-with-typescript-and-ffmpeg
// Testfile command: npx ts-node /Users/mikehughes/PROJ/video2document/services/modules/extraction/ffmpegExtractor.ts /Users/mikehughes/Downloads/sweetHomeAlabama.mp4 // Base code reference: https://docs.yemreak.com/arsiv/programming/extract-audio-from-video-with-typescript-and-ffmpeg
// Test command: npx ts-node ffmpegExtractor.ts /path/to/video.mp4
/** /**
* Extracts audio from a video file and saves it as an wav file. * Extracts audio from a video file and saves it as WAV.
* @param videoFilePath - The path to the video file. * @param videoFilePath Path to the input video file.
* @param outputAudioPath - The path where the extracted audio file should be saved. * @param outputAudioPath Path where the output WAV audio will be saved.
*/ */
// If the ffmpeg binary is not found, throw an error
// Ensure ffmpeg binary is available
if (!ffmpegPath) { if (!ffmpegPath) {
throw new Error('FFmpeg binary not found!'); throw new Error('FFmpeg binary not found!');
} }
ffmpeg.setFfmpegPath(ffmpegPath); ffmpeg.setFfmpegPath(ffmpegPath);
// If the input video path is not provided, exit the script // Ensure an input video path is provided via CLI
if (process.argv.length < 3) { if (process.argv.length < 3) {
console.error('Usage: ts-node ffmpegExtractor.ts <input-video-path>'); console.error('Usage: ts-node ffmpegExtractor.ts <input-video-path>');
process.exit(1); process.exit(1);
} }
// Ensure the output directory exists (./storage/audio - always start command from project root) // Prepare output directory (always relative to project root)
const outputDir = path.join(process.cwd(), 'storage', 'audio'); const outputDir = path.join(process.cwd(), 'storage', 'audio');
if (!fs.existsSync(outputDir)) { if (!fs.existsSync(outputDir)) {
fs.mkdirSync(outputDir, { recursive: true }); fs.mkdirSync(outputDir, { recursive: true });
} }
// Get input video path from command line arguments // Derive input and output paths
const inputVideoPath = process.argv[2]; const inputVideoPath = process.argv[2];
// Derive output audio path from input video path
const inputVideoName = path.basename(inputVideoPath, path.extname(inputVideoPath)); const inputVideoName = path.basename(inputVideoPath, path.extname(inputVideoPath));
// Define output audio path
const outputAudioPath = path.join(outputDir, `${inputVideoName}.wav`); const outputAudioPath = path.join(outputDir, `${inputVideoName}.wav`);
// Initialize progress bar // Initialize CLI progress bar
const progressBar = new cliProgress.SingleBar({ const progressBar = new cliProgress.SingleBar({
format: 'Processing |{bar}| {percentage}% | {timemark}', format: 'Processing |{bar}| {percentage}% | {timemark}',
barCompleteChar: '\u2588', barCompleteChar: '\u2588',
@@ -43,32 +44,40 @@ const progressBar = new cliProgress.SingleBar({
hideCursor: true hideCursor: true
}); });
// Function to extract audio from video. Possible parameters are videoFilePath and outputAudioPath. Ouptput format is wav. /**
* 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)
*/
function extractAudioFromVideo(videoFilePath: string, outputAudioPath: string): Promise<void> { function extractAudioFromVideo(videoFilePath: string, outputAudioPath: string): Promise<void> {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
ffmpeg(videoFilePath) ffmpeg(videoFilePath)
.outputFormat('wav') // Set the output format .outputFormat('wav') // Set output format to WAV
.on('progress', (progress) => { .on('progress', (progress) => {
// Start progress bar if not already active
if (!progressBar.isActive) progressBar.start(100, 0, { timemark: '00:00:00' }); if (!progressBar.isActive) progressBar.start(100, 0, { timemark: '00:00:00' });
if (progress.percent) { if (progress.percent) {
progressBar.update(progress.percent, { timemark: progress.timemark }); progressBar.update(progress.percent, { timemark: progress.timemark });
} }
}) })
.on('end', () => { .on('end', () => {
// Finish progress bar
progressBar.update(100, { timemark: 'done' }); progressBar.update(100, { timemark: 'done' });
progressBar.stop(); progressBar.stop();
console.log(`Extraction completed: ${outputAudioPath}`); console.log(`Extraction completed: ${outputAudioPath}`);
resolve(); resolve();
}) })
.on('error', (err) => { .on('error', (err) => {
// Show extraction errors in a clear format
console.error(`failed_audio_extraction: ${err.message}`); console.error(`failed_audio_extraction: ${err.message}`);
reject(err); reject(err);
}) })
.save(outputAudioPath); // Specify the output file path .save(outputAudioPath); // Save output file
}); });
} }
// Call the function to extract audio. // Run extraction
extractAudioFromVideo(inputVideoPath, outputAudioPath) extractAudioFromVideo(inputVideoPath, outputAudioPath)
.then(() => console.log('Audio extraction successful.')) .then(() => console.log('Audio extraction successful.'))
.catch((err) => console.error(err)); .catch((err) => console.error(err));