or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

audio-processing.mdconfiguration.mdindex.mdinput-management.mdoutput-management.mdprocessing-control.mdspecial-features.mdvideo-processing.md
tile.json

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
}