Automate-Animate-FFmpeg

 view release on metacpan or  search on metacpan

lib/Automate/Animate/FFmpeg.pm  view on Meta::CPAN

use IPC::Run;
use Text::ParseWords;
use Encode;
use Data::Roundtrip qw/perl2dump no-unicode-escape-permanently/;
use Cwd::utf8 qw/abs_path cwd/;

sub	new {
	my $class = $_[0];
	my $params = $_[1];

	my $parent = ( caller(1) )[3] || "N/A";
	my $whoami = ( caller(0) )[3];

	my $self = {
		'input-images' => [],
		'output-filename' => undef,
		'verbosity' => 0,
		# params to ffmpeg must be given as an arrayref
		# these are our standard params, they are read only and must
		# be supplied here as an ARRAYref
		'ffmpeg-standard-params' => ['-c', 'copy', '-c:v', 'copy', '-c:a', 'copy', '-q:a', '0', '-q:v', '1'],
		# extra params to ffmpeg can be specified by the caller

lib/Automate/Animate/FFmpeg.pm  view on Meta::CPAN

		if( $verbos > 1 ){ print "${whoami} (via $parent), line ".__LINE__." : parameter '$ak' set to : ".$params->{$ak}."\n"; }
	}

	return $self
}
# it spawns ffmpeg as external command via IPC::Run::run(@cmd)
# requires that at least 1 input image was specified before.
# returns 0 on failure, 1 on success
sub	make_animation {
	my $self = $_[0];
	my $parent = ( caller(1) )[3] || "N/A";
	my $whoami = ( caller(0) )[3];
	my $verbos = $self->verbosity();

	my $cmdret = $self->_build_ffmpeg_cmdline();
	if( ! defined $cmdret ){ print STDERR "${whoami} (via $parent), line ".__LINE__." : error, failed to build ffmpeg command line, call to ".'_build_ffmpeg_cmdline()'." has failed.\n"; return 0 }
	my $cmdline = $cmdret->{'cmdline'};
	my $tmpfile = $cmdret->{'tmpfile'};
	if( $verbos > 0 ){ print "${whoami} (via $parent), line ".__LINE__." : executing system command:\n".join(' ',@$cmdline)."\n" }
	my ($in, $out, $err);
	my $ret = IPC::Run::run($cmdline, \$in, \$out, \$err);
	if( ! $ret ){ 

lib/Automate/Animate/FFmpeg.pm  view on Meta::CPAN

	if( $verbos > 0 ){
		if( $verbos > 1 ){ print $out."\n" }
		print "${whoami} (via $parent), line ".__LINE__." : done, success. Output animation of ".$self->num_input_images()." input images is in '".$self->output_filename()."'.\n"
	}
	unlink($tmpfile);

	return 1;
}
sub	_build_ffmpeg_cmdline {
	my $self = $_[0];
	my $parent = ( caller(1) )[3] || "N/A";
	my $whoami = ( caller(0) )[3];
	my $verbos = $self->verbosity();

	if( $self->num_input_images() == 0 ){ print STDERR "${whoami} (via $parent), line ".__LINE__." : error, no input images in store.\n"; return undef }
	if( ! defined $self->output_filename() ){ print STDERR "${whoami} (via $parent), line ".__LINE__." : error, no output filename specified.\n"; return undef }

	my $execu = $self->ffmpeg_executable();
	if( ! defined $execu ){ print STDERR "$whoami() (via $parent), line ".__LINE__." : error, the path to the ffmpeg executable is undefined. That means that the external, 3rd-party dependency 'ffmpeg' was not located during installation. First you need...

	# get a tmp file - only drawback is it is in current working dir
	# but on the other hand we do not want caller to delete a directory!

lib/Automate/Animate/FFmpeg.pm  view on Meta::CPAN

	$self->{'ffmpeg-extra-params'} = $ret;
	return $ret
}
sub	ffmpeg_standard_params { return $_[0]->{'ffmpeg-standard-params'} }
sub	num_input_images { return scalar @{$_[0]->{'input-images'}} }
# specify a text file which holds image filenames, one per line to be added
# hash-comments are understood, empty/only-space lines are removed
# returns 1 on success, 0 on failure
sub	input_file_with_images {
	my ($self, $infile) = @_;
	my $parent = ( caller(1) )[3] || "N/A";
	my $whoami = ( caller(0) )[3];
	my $verbos = $self->verbosity();
	if( ! defined $infile ){ print STDERR "${whoami} (via $parent), line ".__LINE__." : error, an input filename of input image filenames is expected.\n"; return 0 }
	my $fh;
	if( ! open($fh, '<:encoding(UTF-8)', $infile) ){ print STDERR "${whoami} (via $parent), line ".__LINE__." : error, could not open input file '$infile' for reading, $!\n"; return 0 }
	while( <$fh> ){
		chomp;
		s/#.*$//;
		s/^\s*$//;
		$self->input_images($_) unless /^\s*$/;
	} close $fh;
	return 1
}
sub	clear_input_images { $#{ $_[0]->{'input-images'} } = -1 }
# Add using a single pattern/searchdir
# add image files via a pattern and an input dir, e.g. '*.png', '/x/y/z/'
# make sure that the order you expect is what you get during the pattern materialisation
# the search dir is optional, default is Cwd::cwd
sub	input_pattern {
	my ($self, $params) = @_;
	my $parent = ( caller(1) )[3] || "N/A";
	my $whoami = ( caller(0) )[3];
	my $verbos = $self->verbosity();
	my ($_pattern, $indir) = @$params;
	my $indir_need_encode_utf8 = 0;
	if( ! defined $indir ){
		$indir = _my_cwd();
		if( $verbos > 0 ){ print STDERR "${whoami} (via $parent), line ".__LINE__." : warning, no search dir was specified and using current dir '$indir'.\n" }
	} else { $indir_need_encode_utf8 = 1 }
	my $pattern;
	# allows for /pattern/modifiers
	if( $_pattern =~ m!^regex\(/(.*?)/(.*?)\)$! ){

lib/Automate/Animate/FFmpeg.pm  view on Meta::CPAN

				->in(Encode::encode_utf8($indir))
	]) ){ print STDERR "${whoami} (via $parent), line ".__LINE__." : error, call to input_images() has failed.\n"; return 0 }

	return 1 # success
}
# This adds many patterns:
# the input is an ARRAY of 1-or-2-item arrays
# each subarray must consist of a pattern and optionally a search dir (else current dir will be used)
sub	input_patterns {
	my ($self, $specs) = @_;
	my $parent = ( caller(1) )[3] || "N/A";
	my $whoami = ( caller(0) )[3];
	my $verbos = $self->verbosity();
	for my $as (@$specs){
		if( (scalar(@$as)==0)
		 || (scalar(@$as)>2)
		){ print STDERR perl2dump($as)."${whoami} (via $parent), line ".__LINE__." : error, the spec must contain at least a pattern and optionally a search-dir as an array, see above.\n"; return 0; }
		if( ! $self->input_pattern($as) ){ print STDERR "${whoami} (via $parent), line ".__LINE__." : error, call to input_pattern() has failed for this spec: @$as\n"; return 0 }
	}
	return 1 # success
}
# if no parameter is specified then it returns the current list of input images as an arrayref
# Otherwise:
# specify one or more input filenames (of images) via a single scalar, an arrayref or
# a hashref whose values are image filenames, to convert them into video
# in this case returns undef on failure or the current, updated list of input images on success
sub	input_images {
	my ($self, $m) = @_;
	if( ! defined $m ){ return $self->{'input-images'} }
	my $parent = ( caller(1) )[3] || "N/A";
	my $whoami = ( caller(0) )[3];
	my $verbos = $self->verbosity();
	if( $verbos > 0 ){
		if( $verbos > 1 ){ print STDOUT perl2dump($m)."${whoami} (via $parent), line ".__LINE__." : called with input images as shown above ...\n" }
		else { print STDOUT "${whoami} (via $parent), line ".__LINE__." : called ...\n" }
	}
	# NOTE: Cwd::abs_path() messes up on unicode filenames and requires Encode::decode_utf8()
	# but there is also Cwd::utf8 to consider sometime...
	my $rf = ref $m;
	if( $rf eq 'ARRAY' ){
		for my $af (@$m){



( run in 0.294 second using v1.01-cache-2.11-cpan-a9ef4e587e4 )