Skip to content

@flussence /ffrec.pl
Last active

Embed URL

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
ffmpeg screen recorder
#!/usr/bin/env perl
use 5.012;
use warnings;
use autodie qw(:default exec);
my %window = get_window_info();
my $metadata = sprintf('-metadata title="screencap of window: %s"', $window{title});
chomp(my $datetime = `date +%F_%a_%H.%M.%S.%N`);
my $output_dir = "$ENV{HOME}/ffrec";
mkdir($output_dir) unless -d $output_dir;
my $output_file = sprintf('%s/%s-%dx%d-%s.mkv',
$output_dir,
$datetime,
@window{qw(width height)},
flatten_filename($window{title}),
);
=pod
Few notes:
* libx264rgb doesn't multithread and the presets range from too much IO to too much CPU
* libvpx with realtime settings can't keep up, so it destroys the quality instead
=cut
# Crude framerate limiting heuristic based on pixel count. 480p gets 60fps, 720p gets 25.
sub framelimit {
my ($w, $h, $base) = @_;
$base //= 60;
return int( (848/$w) * (480/$h) * $base / 5 ) * 5;
}
my @params = (
threads => '-threads 0',
audio_input => '-f pulse -i default',
video_input =>
sprintf('-f x11grab -video_size %dx%d -i :0.0+%d,%d -framerate %d',
@window{qw(width height top left)}, framelimit(@window{qw(width height)}, 60)
),
audio_codec => '-codec:a flac',
#video_codec => '-codec:v libvpx',
#vp8_flags => '-quality realtime -speed 0 -slices 3',
video_codec => '-codec:v libx264rgb -preset ultrafast -tune animation -qp 0',
#video_codec => '-codec:v libx264 -preset ultrafast -tune animation -qmax 25',
#x264_flags =>
# '-x264opts '.flatten_ffmpeg_opts({ 'open-gop' => undef, 'non-deterministic' => undef }),
metadata => $metadata,
output_file => $output_file,
);
my @cmdline;
push @cmdline, qw(schedtool -R -p 1 -e) if -e '/usr/bin/schedtool';
push @cmdline, qw(ionice -c 2 -n 0) if -e '/usr/bin/ionice';
push @cmdline, 'ffmpeg';
my $pid = fork // die 'Fork error';
exit if $pid;
open(STDOUT, q{>}, "$output_dir/ffrec.out");
open(STDERR, q{>}, "$output_dir/ffrec.err");
system('start-pulseaudio-x11');
exec '/bin/sh' => '-c', join(q{ }, @cmdline, @params[grep {$_ % 2} 0..$#params]);
sub get_window_info {
my $cmd_output = `xwininfo`;
my %window = (
top => 'Absolute upper-left X',
left => 'Absolute upper-left Y',
width => 'Width',
height => 'Height',
);
for ( keys %window ) {
($window{$_}) = $cmd_output =~ /\Q$window{$_}\E: \s+ (\d+)/x;
}
($window{title}) = $cmd_output =~ /Window id: 0x\w+ "(.+)"$/m;
return %window;
}
sub flatten_filename {
my $name = shift;
$name =~ tr/[a-zA-Z0-9]/_/cs;
return $name;
}
sub flatten_ffmpeg_opts {
my $opts = shift;
my %strings = @_ || (
key_prefix => q{},
opt_sep => q{:},
kv_sep => q{=},
);
my $ret = '';
while ( my ($k, $v) = each %{$opts} ) {
$ret .= $strings{opt_sep} if $ret;
$ret .= $strings{key_prefix}.$k;
$ret .= $strings{kv_sep}.$v if defined $v;
}
return $ret;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.