- Raku 100%
| bin | ||
| examples | ||
| lib | ||
| t | ||
| tools | ||
| .gitignore | ||
| Changes | ||
| dist.ini | ||
| LICENSE | ||
| META6.json | ||
| README.md | ||
FFmpegProgressBar
A Raku module that adds a progress bar to ffmpeg commands.
output.mp4 ████████████░░░░░░ 75% 00:00:05 ETA: 2s
With optional frame/bitrate info:
output.mp4 ████████████░░░░░░ 75% 00:00:05 ETA: 2s [750/1000 (25.5fps)] (2.5Mbps)
Features
- Command-line interface - Use
ffpbcommand to run ffmpeg with a progress bar - Can be used as a library - Use in your Raku scripts
- Progress bar - Shows percentage, elapsed time, and ETA during
encoding
- Optional display features - Show frames, bitrate, or verbose output with CLI flags
- Auto duration detection - Automatically detects video duration from ffprobe or parses -t/-to/-ss arguments
- Multi-input duration - Correctly handles
-ssper input (e.g.,-ss 10 -i a.mp4 -ss 30 -i b.mp4) - Multi-output support - Handles multiple output files (e.g.,
-i input.mp4 output1.mp4 output2.mkv) - -map support - Filters duration detection to relevant inputs when
-mapis used (e.g.,-map 0:v -map 1:a) - Flexible time parsing - Supports HH:MM:SS, MM:SS, and unit formats (1h30m, 45m30s)
- Dotfile config - Set default options in a config file
- Two-pass encoding - Automatically detects and runs pass 1 before showing progress for pass 2
- Progress Tracking API -
get-progress(),progress-supply(),watch-progress()for external monitoring (see section below)
Requirements
- ffmpeg - Must be installed and in PATH
- Raku - Version 6.d or later
- Terminal::Spinners - Progress bar rendering (dependency)
- Terminal::Size - Terminal width detection (dependency)
- Pod::To::Man - Man page
rendering for
--man(dependency)
Installation
zef install ffmpegprogressbar
Installing from source
To install from a local folder:
cd /path/to/FFmpegProgressBar
zef install .
Usage
Command Line
ffpb -i input.mp4 -c:v libx264 output.mp4
Command Line Options
-V,--verbose- Show detected duration and executed command-F,--frames- Show current frame and encoding fps-B,--bitrate- Show output bitrate-S,--style- Set progress bar style (bar, hash, hash-dash, equals)-D,--duration- Set duration in seconds (skip auto-detection)-M,--ffmpeg- Path to ffmpeg binary-P,--ffprobe- Path to ffprobe binary-E,--stderr- Show ffmpeg stderr on success (last 20 lines, use--stderr allfor all)-Q,--quiet- Suppress progress bar rendering (useful when only using progress API)
Library
use FFmpegProgressBar;
my $progress = FfmpegProgress.new(:duration(30), :verbose(True));
$progress.run('-i', 'input.mp4', 'output.mp4');
Or use the subroutine interface:
ffmpeg-progress(
'-i', 'input.mp4',
'-c:v', 'libx264',
'output.mp4',
:duration(30),
:verbose(True)
)
Library Options
$ffmpeg- Path to ffmpeg binary (default: 'ffmpeg')$ffprobe- Path to ffprobe binary (default: 'ffprobe')$duration- Manually set video duration (default: 0, auto-detected)$verbose- Show detected duration and executed command$quiet- Suppress progress bar rendering (useful when only using progress API)$show-frames- Show current frame and encoding fps$show-bitrate- Show output bitrate$bar-type- Progress bar style (bar, hash, hash-dash, equals)$no-color- Disable colored output$stderr-lines- Show ffmpeg stderr on success ('20', '50', 'all', or '' for off)$ffmpeg-loglevel- Set ffmpeg log level (default: 'error')
Library Methods
$ff.quit()- Send 'q' to gracefully stop encoding (call from external code)$ff.quit(:force)- Force kill ffmpeg immediately
use FFmpegProgressBar;
my $ff = FfmpegProgress.new(:duration(30), :verbose(True));
$ff.run('-i', 'input.mp4', 'output.mp4');
# Or control externally:
my $ff2 = FfmpegProgress.new(:ffmpeg('/path/to/ffmpeg'));
$ff2.run('-i', 'input.mp4', 'output.mp4');
# ... in another thread or loop:
$ff2.quit() if $some-condition;
$ff2.quit(:force); # force kill
Progress Tracking API
FFmpegProgressBar provides three ways to monitor encoding progress externally:
watch-progress() (Recommended)
Simple async iteration that yields percent directly. Use :quiet to suppress the progress bar:
use FFmpegProgressBar;
my $p = FfmpegProgress.new(:quiet);
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;
With full snapshots (watch-progress(:emit)):
for $p.watch-progress(:emit) -> $snap {
say $snap.summary;
$p.quit() if $snap.is-stalled;
}
get-progress()
One-off read - returns a ProgressSnapshot:
my $snap = $p.get-progress();
say $snap.percent; # 75.0
say $snap.fps; # 25.0
say $snap.is-complete; # Bool
say $snap.is-failed; # Bool
say $snap.summary;
progress-supply()
Reactive supply for event-driven code:
$p.progress-supply.tap: -> $snap {
say "Progress: {$snap.percent.fmt('%.1f')}%";
};
The progress API returns time-based percentage that matches the progress bar exactly.
Dotfile Configuration
You can create a config file to set default options. The following paths are checked in order:
Unix/Linux/macOS
~/.ffpbrc~/.config/ffpbrc~/.config/ffpb/config/etc/ffpbrc
Windows
%USERPROFILE%\.ffpbrc%USERPROFILE%\.config\ffpbrc%USERPROFILE%\.config\ffpb\config%APPDATA%\ffpb\config%APPDATA%\ffpbrc
Each line should contain one option (like CLI arguments). Lines
starting with # are treated as comments.
Example ~/.ffpbrc:
# Always show verbose info, frame info and use hash style
-V
-F
-S hash
Examples
# Basic encoding
ffpb -i input.mp4 output.mkv
# With verbose output
ffpb -V -i input.mp4 output.mp4
# With frames and bitrate
ffpb -F -B -i input.mp4 output.mp4
# With custom bar style
ffpb -S hash -i input.mp4 output.mp4
# With duration override
ffpb -D 60 -i input.mp4 output.mp4
# With custom ffmpeg/ffprobe paths
ffpb -M /usr/bin/ffmpeg -P /usr/bin/ffprobe -i input.mp4 output.mp4
# Show stderr on success
ffpb -E -i input.mp4 output.mp4
# Last 50 lines
ffpb -E 50 -i input.mp4 output.mp4
# All stderr output
ffpb -E all -i input.mp4 output.mp4
# Two-pass encoding
ffpb -i input.mp4 -c:v libx264 -pass 2 -f mp4 output.mp4
FFmpegProgressBar automatically detects -pass 2 and runs the analysis pass (pass 1) silently before displaying the progress bar for the encoding pass.
Bar styles (use -S or --style)
bar- ████████████░░░░░░ (default)hash- [████████... ]hash-dash- [████████-----]equals- [======== ]
Windows Support
Full Windows support is implemented. The following features work on Windows 10 and later:
- Progress bar - Works in Windows Terminal, VS Code terminal, or modern conhost
- Unicode support - Uses console code page detection
- Non-blocking keyboard input - Uses Win32 Console API
- Binary lookup - Automatically finds ffmpeg with .exe, .bat, .cmd extensions
- Config file locations - Supports %APPDATA% and %USERPROFILE% paths
Requirements on Windows
For best results, use Windows Terminal which has full ANSI/VT support.
Note on Keyboard Input
- Unix/Linux/macOS: Pressing 'q' or Ctrl+C cleanly stops encoding. First Ctrl+C sends 'q' (graceful), second Ctrl+C force-kills ffmpeg, third Ctrl+C exits the program entirely.
- Windows: Pressing 'q' provides graceful shutdown (recommended). Ctrl+C force kills ffmpeg immediately due to limitations with how the native executable wrapper handles console signals on Windows.
AUTHOR
Sasha Abbott sashaa@disroot.org
LICENSE
This library is free software; you can redistribute it and/or modify it under CC0.