CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-fluent-ffmpeg

A fluent API to FFMPEG for audio and video manipulation with chainable methods

Pending
Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Pending

The risk profile of this skill

Overview
Eval results
Files

processing-control.mddocs/

Processing Control

Execute FFmpeg commands with full control over the process lifecycle, including execution methods, streaming, progress monitoring, and process management.

Capabilities

Command Execution

Execute the configured FFmpeg command.

/**
 * Execute the FFmpeg command
 * @returns FfmpegCommand instance (for event handling)
 * @emits 'start', 'progress', 'stderr', 'codecData', 'error', 'end'
 */
run() // → FfmpegCommand
// Aliases: exec, execute

Usage Examples:

// Basic execution with events
ffmpeg('input.avi')
  .videoCodec('libx264')
  .save('output.mp4')
  .on('start', (commandLine) => {
    console.log('Spawned FFmpeg with command: ' + commandLine);
  })
  .on('progress', (progress) => {
    console.log('Processing: ' + progress.percent + '% done');
  })
  .on('end', () => {
    console.log('Processing finished successfully');
  })
  .on('error', (err, stdout, stderr) => {
    console.error('Error occurred: ' + err.message);
  });

// Promise-based execution
const processVideo = () => {
  return new Promise((resolve, reject) => {
    ffmpeg('input.mp4')
      .videoCodec('libx264')
      .save('output.mp4')
      .on('end', resolve)
      .on('error', reject);
  });
};

Save to File

Execute command and save output to a specific file.

/**
 * Execute command and save to file
 * @param output - Output file path
 * @returns FfmpegCommand instance (for event handling)
 */
save(output) // → FfmpegCommand
// Aliases: saveToFile

Usage Examples:

// Simple save operation
ffmpeg('input.avi').save('output.mp4');

// Save with configuration
ffmpeg('input.mov')
  .videoCodec('libx264')
  .audioBitrate('128k')
  .save('converted.mp4')
  .on('progress', (progress) => {
    console.log(`Progress: ${progress.percent}%`);
  });

// Multiple saves (different outputs)
ffmpeg('source.avi')
  .save('copy1.mp4')
  .save('copy2.avi');

Stream Processing

Execute command and pipe output to streams.

/**
 * Execute command and pipe to stream
 * @param stream - Optional target writable stream
 * @param options - Optional pipe options
 * @returns WritableStream (the output stream)
 */
pipe(stream?, options?) // → WritableStream
// Aliases: stream, writeToStream

Usage Examples:

const fs = require('fs');
const express = require('express');

// Pipe to file stream
const outputStream = fs.createWriteStream('output.mp4');
ffmpeg('input.avi')
  .videoCodec('libx264')
  .format('mp4')
  .pipe(outputStream);

// Pipe to HTTP response (streaming video)
app.get('/video', (req, res) => {
  res.contentType('video/mp4');
  
  ffmpeg('source.mkv')
    .videoCodec('libx264')
    .format('mp4')
    .outputOptions('-movflags', 'frag_keyframe+empty_moov')  // Streaming-friendly
    .pipe(res);
});

// Get output stream for custom handling
const outputStream = ffmpeg('input.avi')
  .videoCodec('libx264')
  .format('mp4')
  .pipe();

outputStream.on('data', (chunk) => {
  // Handle video data chunks
  console.log(`Received ${chunk.length} bytes`);
});

// Pipe with options
ffmpeg('input.mp4')
  .format('webm')
  .pipe(outputStream, { end: false });  // Don't end stream when done

Process Control

Control the FFmpeg process during execution.

/**
 * Kill the FFmpeg process
 * @param signal - Optional kill signal (default: 'SIGKILL')
 * @returns FfmpegCommand instance
 */
kill(signal?) // → FfmpegCommand

/**
 * Change process niceness (priority)
 * @param niceness - New niceness value (-20 to 20)
 * @returns FfmpegCommand instance
 */
renice(niceness) // → FfmpegCommand

Usage Examples:

// Graceful termination
const command = ffmpeg('long_video.mp4')
  .save('output.mp4')
  .on('progress', (progress) => {
    if (progress.percent > 50) {
      command.kill('SIGINT');  // Graceful stop
    }
  });

// Force kill on timeout
const command = ffmpeg('input.avi').save('output.mp4');

setTimeout(() => {
  command.kill();  // Force kill (SIGKILL)
}, 30000);  // 30 second timeout

// Adjust process priority
ffmpeg('input.mp4')
  .renice(10)  // Lower priority (higher niceness)
  .save('background_conversion.mp4');

Command Cloning

Create identical copies of configured commands.

/**
 * Create identical command copy
 * @returns New FfmpegCommand with same configuration
 */
clone() // → FfmpegCommand

Usage Example:

// Base configuration
const baseCommand = ffmpeg('input.avi')
  .videoCodec('libx264')
  .audioCodec('aac');

// Create variations
const hdCommand = baseCommand.clone().size('1920x1080').save('hd.mp4');
const sdCommand = baseCommand.clone().size('854x480').save('sd.mp4');
const audioCommand = baseCommand.clone().noVideo().save('audio.mp3');

// Run all conversions
hdCommand.run();
sdCommand.run();
audioCommand.run();

Event Handling

Progress Monitoring

Monitor processing progress and statistics.

/**
 * Progress event data
 */
interface ProgressInfo {
  frames: number;         // Number of frames transcoded
  currentFps: number;     // Current processing FPS
  currentKbps: number;    // Current processing speed (kbps)
  targetSize: number;     // Target output size in KB
  timemark: string;       // Current processing time (HH:MM:SS.mmm)
  percent: number;        // Progress percentage (0-100)
}

Usage Examples:

ffmpeg('input.mp4')
  .save('output.mp4')
  .on('progress', (progress) => {
    console.log(`
      Progress: ${progress.percent.toFixed(1)}%
      Frames: ${progress.frames}
      FPS: ${progress.currentFps}
      Speed: ${progress.currentKbps} kbps
      Time: ${progress.timemark}
      Size: ${progress.targetSize} KB
    `);
  });

// Progress bar implementation
ffmpeg('long_video.mp4')
  .save('output.mp4')
  .on('progress', (progress) => {
    const bar = '='.repeat(Math.floor(progress.percent / 2));
    const spaces = ' '.repeat(50 - bar.length);
    process.stdout.write(`\r[${bar}${spaces}] ${progress.percent.toFixed(1)}%`);
  })
  .on('end', () => {
    console.log('\nProcessing complete!');
  });

Error Handling

Handle processing errors and diagnostics.

/**
 * Error event handler
 * @param error - Error object with message
 * @param stdout - FFmpeg stdout output
 * @param stderr - FFmpeg stderr output
 */
.on('error', (error, stdout, stderr) => void)

Usage Examples:

ffmpeg('input.mp4')
  .save('output.mp4')
  .on('error', (err, stdout, stderr) => {
    console.error('FFmpeg error occurred:');
    console.error('Error message:', err.message);
    console.error('FFmpeg stdout:', stdout);
    console.error('FFmpeg stderr:', stderr);
    
    // Handle specific error types
    if (err.message.includes('No such file')) {
      console.error('Input file not found');
    } else if (err.message.includes('Permission denied')) {
      console.error('Permission error - check file access');
    }
  });

// Retry on error
const processWithRetry = (input, output, retries = 3) => {
  return new Promise((resolve, reject) => {
    const attempt = (retriesLeft) => {
      ffmpeg(input)
        .save(output)
        .on('end', resolve)
        .on('error', (err) => {
          if (retriesLeft > 0) {
            console.log(`Retry ${3 - retriesLeft + 1}/${3}`);
            setTimeout(() => attempt(retriesLeft - 1), 1000);
          } else {
            reject(err);
          }
        });
    };
    attempt(retries);
  });
};

Complete Event Coverage

Handle all available events for comprehensive monitoring.

/**
 * All available events
 */
.on('start', (commandLine) => void)           // Process started
.on('codecData', (data) => void)              // Input codec info
.on('progress', (progress) => void)           // Progress update
.on('stderr', (stderrLine) => void)           // Raw stderr line
.on('error', (err, stdout, stderr) => void)   // Error occurred
.on('end', (stdout, stderr) => void)          // Processing complete

Usage Example:

ffmpeg('input.mp4')
  .save('output.mp4')
  .on('start', (commandLine) => {
    console.log('Started:', commandLine);
  })
  .on('codecData', (data) => {
    console.log('Input codec info:', data);
  })
  .on('progress', (progress) => {
    console.log(`Progress: ${progress.percent}%`);
  })
  .on('stderr', (stderrLine) => {
    console.log('FFmpeg stderr:', stderrLine);
  })
  .on('error', (err, stdout, stderr) => {
    console.error('Processing failed:', err.message);
  })
  .on('end', (stdout, stderr) => {
    console.log('Processing completed successfully');
    console.log('Final stdout:', stdout);
  });

Processing Types

/**
 * Kill signals for process termination
 */
type KillSignal = 
  | 'SIGTERM'     // Graceful termination (default for most systems)
  | 'SIGINT'      // Interrupt (Ctrl+C equivalent)  
  | 'SIGKILL'     // Force kill (cannot be caught)
  | 'SIGUSR1'     // User-defined signal 1
  | string;       // Any valid system signal

/**
 * Process niceness range
 */
type Niceness = number; // -20 (highest priority) to 20 (lowest priority)

/**
 * Pipe options for streaming
 */
interface PipeOptions {
  end?: boolean;          // End target stream when FFmpeg finishes (default: true)
  allowHalfOpen?: boolean; // Keep stream open for writing after reading ends
  objectMode?: boolean;    // Object mode for streams
}

/**
 * Codec data structure from codecData event
 */
interface CodecData {
  format: string;         // Input format name
  duration: string;       // Input duration
  audio?: AudioCodecInfo; // Audio stream information
  video?: VideoCodecInfo; // Video stream information
}

/**
 * Audio codec information
 */
interface AudioCodecInfo {
  codec: string;          // Audio codec name
  sample_fmt: string;     // Sample format
  sample_rate: string;    // Sample rate
  channels: number;       // Channel count
  channel_layout: string; // Channel layout description
}

/**
 * Video codec information  
 */
interface VideoCodecInfo {
  codec: string;          // Video codec name
  pix_fmt: string;        // Pixel format
  resolution: string;     // Video resolution (WxH)
  fps: number;           // Frame rate
}

docs

audio-processing.md

configuration.md

index.md

input-management.md

output-management.md

processing-control.md

special-features.md

video-processing.md

tile.json