FFmpegProgressBar

NAME

FFmpegProgressBar - Add a progress bar to ffmpeg commands

DESCRIPTION

Provides a progress bar for ffmpeg encoding operations. Uses Terminal::Spinners for rendering and detects duration automatically via ffprobe or by parsing -t/-to/-ss arguments.

Supports graceful shutdown via 'q' or Ctrl+C (Unix), preserving partial output.

SUBROUTINES

  • sub ffmpeg-progress(*@args, *%opts) is export

Convenience wrapper. Equivalent to:

FfmpegProgress.new(|%opts).run(@args);

Valid %opts keys (any FfmpegProgress attribute):

  • duration - Numeric duration in seconds

  • ffmpeg - Str path to ffmpeg binary (default: 'ffmpeg')

  • ffprobe - Str path to ffprobe binary (default: 'ffprobe')

  • bar-type - Str 'bar', 'hash', 'hash-dash', or 'equals'

  • show-frames - Bool show frame count

  • show-bitrate - Bool show bitrate

  • no-color - Bool disable colors

  • verbose - Bool show detected duration and command

Note: Extra keys in %opts are silently ignored. Use named parameters with the module for validation, e.g. FfmpegProgress.new(:verbose).

Example:

ffmpeg-progress('-i', 'input.mp4', '-c:v', 'libx264', 'output.mp4');

ATTRIBUTES

  • $!ffmpeg - Path to ffmpeg binary (default: "ffmpeg")

  • $!ffprobe - Path to ffprobe binary (default: "ffprobe")

  • $!duration - Manually set duration in seconds (default: 0, auto-detected)

  • $!verbose - Show detected duration and executed command

  • $.show-frames - Show current frame and encoding fps

  • $.show-bitrate - Show output bitrate

  • $.stderr-lines - Number of stderr lines to show on success (default: '', 20 lines if --stderr used)

  • $!bar-type - Progress bar style: bar, hash, hash-dash, or equals

  • $.output-throttle - Minimum time between output updates (default: 0.1 seconds)

  • $!no-color - Disable colored output

  • $.dry-run - Validate args without running ffmpeg

  • $.eta-percent-threshold - Percent threshold for ETA calculation (default: 5)

  • $.eta-time-threshold - Time threshold (seconds) for ETA calculation (default: 4)

  • EncodeSkipped - Output file(s) already exist and -n was passed; ffmpeg did nothing

METHODS

  • method new(...) - Create FfmpegProgress instance

  • method run(*@args --> Int) - Run ffmpeg with progress bar, returns exit code

  • sub ffmpeg-progress(*@args --> Int) - Convenience function wrapper

  • method color(Str $name) - Get ANSI color code by name (reset, green, red, yellow, cyan, bold)

  • method bar-length() - Returns appropriate bar length for terminal width

  • method get-duration(Str $file) - Get video duration via ffprobe

  • method get-frame-count(Str $file) - Get video frame count via ffprobe

  • method quit(Bool :$force = False) - Quit the running ffmpeg process. Use :force for immediate kill.

Progress Tracking API

FFmpegProgressBar provides a progress API for external code to monitor encoding:

  • method get-progress(--> ProgressSnapshot) - Get current progress as an immutable snapshot. Returns a ProgressSnapshot object with: percent, elapsed, fps, speed, frame-count, total-frames, bitrate, status, is-stalled, last-error, eta.

  • method progress-supply(--> Supply) - Get a Supply that emits ProgressSnapshot updates. Use this for reactive/async progress monitoring.

  • method watch-progress(Numeric :$interval = 0.1, Bool :$emit = False --> Supply) - Simple progress iteration. By default yields percent (0-100). Use :emit to yield full ProgressSnapshot instead. Recommended for most use cases - no manual promise management needed.

Example: Using watch-progress() (Simplest)

use FFmpegProgressBar;

my $p = FfmpegProgress.new(:quiet);  # Suppress progress bar, use API only
my $promise = start { $p.run('-i', 'input.mp4', 'output.mp4') };

for $p.watch-progress(:interval(0.5)) -> $percent {
    say "Progress: {$percent.fmt('%.1f')}%";
    $p.quit() if $percent >= 50;
}

await $promise;
say $p.get-progress().summary;

Quitting early based on progress:

for $p.watch-progress(:emit) -> $snap {
    $p.quit() if $snap.percent >= 50;
    $p.quit() if $snap.is-stalled;
}

Alternative: get-progress() (One-off)

For one-off reads:

my $snap = $p.get-progress();
say $snap.percent;
say $snap.is-complete;

ProgressSnapshot Methods

  • method summary() - Human-readable one-line summary (e.g., "75.0% [500/1000 25.0fps] @ 2.5Mbps ETA: 3s")

  • method remaining-seconds(--> Numeric) - Estimated seconds remaining

  • method completion-time(--> DateTime) - Estimated DateTime when encoding will finish

  • method is-complete(--> Bool) - True if encoding finished successfully

  • method is-failed(--> Bool) - True if encoding failed or was aborted

Example: External Progress Monitoring with Quit

This example shows how to monitor progress externally and quit early based on progress:

use FFmpegProgressBar;

my $p = FfmpegProgress.new;

# Start encoding in background
my $promise = start {
    $p.run('-i', 'input.mp4', '-c:v', 'libx264', 'output.mp4');
};

# Poll progress until quit condition or completion
loop {
    last if $promise.status ~~ Kept | Broken;
    
    my $snap = $p.get-progress();
    say "Progress: {$snap.percent.fmt('%.1f')}% - {$snap.status}";
    
    # Quit at 50% if some external condition is met
    if $snap.percent >= 50 && $snap.percent < 75 {  # e.g. quit between 50-75%
        say "Quitting at 50%!";
        $p.quit();
        last;
    }
    
    if $snap.is-complete || $snap.is-failed {
        last;
    }
    
    sleep 0.1;
}

await $promise;

my $final = $p.get-progress();
say "Final: {$final.summary}";
say "Final status: {$final.status}";

For reactive monitoring using Supply:

use FFmpegProgressBar;

my $p = FfmpegProgress.new;

# Start encoding and subscribe to progress updates
my $promise = start {
    $p.run('-i', 'input.mp4', 'output.mp4');
};

$p.progress-supply.tap: -> $snap {
    say "Progress: {$snap.percent.fmt('%.1f')}% - ETA: {$snap.eta // '?'}s";
};

await $promise;
  • method run-pass1(Array $args --> Int) - Run first pass of two-pass encoding

  • method detect-duration(Numeric $duration, Numeric $output-duration, Numeric $seek-start, Bool $has-shortest, @input-groups, $mapped-inputs, Numeric $output-seek = 0) - Detect effective duration from multiple sources (considers -map and -ss/-t/-to to filter relevant inputs)

SIGNAL HANDLING

  • Unix/Linux/macOS: First Ctrl+C sends 'q' (graceful), second force-kills ffmpeg, third exits program. During two-pass pass 1, Ctrl+C aborts the analysis pass.

  • Windows: Press 'q' for graceful shutdown. Ctrl+C force kills ffmpeg immediately.

TWO-PASS ENCODING

When -pass 2 is detected in the arguments, FFmpegProgressBar automatically runs the first (analysis) pass before showing the progress bar for the second (encoding) pass. Signal handling works during both passes.

COMMAND-LINE USAGE

The module installs the ffpb command for CLI usage:

ffpb -i input.mp4 output.mp4
    ffpb -V -F -B -i input.mp4 output.mp4
    ffpb -S hash -D 60 -i input.mp4 output.mp4
    ffpb -M /usr/bin/ffmpeg -P /usr/bin/ffprobe -i input.mp4 output.mp4
    ffpb -E -i input.mp4 output.mp4

Use ffpb --help for options, or ffpb --man for the full manual.

CLI OPTIONS

  • -h, --help - Show help message

  • -V, --verbose - Show detected duration and executed command

  • -F, --frames - Show current frame and encoding fps

  • -B, --bitrate - Show output bitrate

  • -S, --style=style - Set progress bar style (bar, hash, hash-dash, equals)

  • -D, --duration=seconds - Set duration in seconds (skip auto-detection)

  • -M, --ffmpeg=path - Path to ffmpeg binary

  • -P, --ffprobe=path - Path to ffprobe binary

  • -E, --stderr[=N|all] - Show ffmpeg stderr on successful completion. Without value: last 20 lines. With value: N lines or 'all'.

  • --version - Show version information

  • --man - Show full manual page

CONFIG FILES

Config files are checked in the following order:

Unix/Linux/macOS

Windows

Each line should contain one option (like CLI arguments). Lines starting with # are treated as comments.

SEE ALSO

FFmpegProgressBar::Parser, FFmpegProgressBar::Formatter, FFmpegProgressBar::Probe, FFmpegProgressBar::Terminal

FFmpegProgressBar v0.0.7

Add a progress bar to ffmpeg commands

Authors

  • Sasha Abbott

License

CC0-1.0

Dependencies

Pod::To::Man:ver<1.2.1>:auth<zef:samy>Terminal::Spinners:ver<1.6.0>:auth<github:ryn1x>Terminal::Size:ver<1.0.1>:auth<zef:demayl>Terminal::WCWidth:ver<0.1.5>:auth<zef:raku-community-modules>

Test Dependencies

Provides

  • FFmpegProgressBar
  • FFmpegProgressBar::FFmpegFlags
  • FFmpegProgressBar::Formatter
  • FFmpegProgressBar::Parser
  • FFmpegProgressBar::Probe
  • FFmpegProgressBar::ProgressSnapshot
  • FFmpegProgressBar::Terminal

Documentation

The Camelia image is copyright 2009 by Larry Wall. "Raku" is a trademark of the Yet Another Society. All rights reserved.

Built with Podlite โ€” the markup and publishing tools behind this site.