Automate-Animate-FFmpeg

 view release on metacpan or  search on metacpan

Changes  view on Meta::CPAN

0.03    23-12-2023 23:30
        Duh in packing.

0.04    27-12-2023 20:00
        Enhanced documentation especially regarding installation
        and that ffmpeg is a prerequisite.

0.05    27-12-2023 22:00
        Enhanced documentation for the provided script.
        Added more test logic in t/900-scripts.t
        A first attempt is made to add support for unicode pathnames.

0.06    28-12-2023 13:00
        Enhanced documentation.

0.07    03-01-2023 13:00
        Added omitted Test2::Plugin::UTF8 and Encode as a dependency in Makefile.PL
	Unicode normalisation is now done prior to comparing unicode'd filenames, see e.g. t/100-input-patterns.t

0.08    04-01-2023 02:00
        Fixed a pod error.

0.09    12-03-2024 17:00
        Trying to fix double encoding of unicoded filenames in M$ the attempted fix is at line 286 of lib/Automate/Animate/FFmpeg.pm

0.10    15-03-2024 13:00
        Still trying to fix double encoding of unicoded filenames in M$ the attempted fix is at line 286 of lib/Automate/Animate/FFmpeg.pm

0.11    12-04-2024 13:00
        Still trying to fix double encoding of unicoded filenames in M$ the attempted fix is at line 286 of lib/Automate/Animate/FFmpeg.pm
        Changes in t/100-input-patterns.t to debug this.

0.12    15-10-2024 17:00
        The issue of v0.11 seems to have gone but an eye is kept on it.
        The detection of ffmpeg executable is done in Makefile.PL
        Now make exits(1) if no ffmpeg executable is found.

0.13    05-03-2025 20:00
        Switched to using Test::TempDir::Tiny in test files.
	Fixed urls in Makefile.PL thanks to mohawk2's for spotting it.

README  view on Meta::CPAN

    input_pattern() can be combined with input_patterns() and
    input_images(). The input images list will increase in the order they
    are called.

    Caveat: the regex is parsed, compiled and passed on to
    File::Find::Rule. Escaping of special characters (e.g. the backslash)
    may be required.

    Caveat: the order of the matched input images is entirely up to
    File::Find::Rule. There may be unexpected results when filenames
    contain unicode characters. Consider these orderings for example:

      * blue.png, κίτρινο.png, red.png,

      * blue.png, γάμμα.png, κίτρινο.png, red.png,

      * blue.png, κίτρινο.png, γαμμα.png red.png,

    Return value:

      * 0 on failure, 1 on success.

README.md  view on Meta::CPAN


`input_pattern()` can be combined with `input_patterns()`
and `input_images()`. The input images list will increase
in the order they are called.

**Caveat**: the regex is parsed, compiled and passed on to [File::Find::Rule](https://metacpan.org/pod/File%3A%3AFind%3A%3ARule).
Escaping of special characters (e.g. the backslash) may be required.

**Caveat**: the order of the matched input images is entirely up
to [File::Find::Rule](https://metacpan.org/pod/File%3A%3AFind%3A%3ARule). There may be unexpected results
when filenames contain unicode characters. Consider
these orderings for example:

- `blue.png, κίτρινο.png, red.png`,
- `blue.png, γάμμα.png, κίτρινο.png, red.png`,
- `blue.png, κίτρινο.png, γαμμα.png red.png`,

Return value:

- 0 on failure, 1 on success.

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

use utf8; # filenames can be in utf8

binmode STDERR, ':encoding(UTF-8)';
binmode STDOUT, ':encoding(UTF-8)';

use File::Temp;
use File::Find::Rule;
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 = {

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

	if( $_pattern =~ m!^regex\(/(.*?)/(.*?)\)$! ){
		# see https://www.perlmonks.org/?node_id=1210675
		my $pa = $1; my $mo = $2;
		if( $mo!~/^[msixpodualn]+$/ ){ print STDERR "${whoami} (via $parent), line ".__LINE__." : error, illegal modifiers ($mo) to the specified regex detected.\n"; return 0 }
		# the modifiers are entered as (?...) before the regex pattern
		$pattern = qr/(?${mo})${pa}/;
	} else { $pattern = $_pattern }
	if( $verbos > 1 ){ print "${whoami} (via $parent), line ".__LINE__." : searching under dir '$indir' with pattern '".$pattern."' ...\n" }

	if( ! defined $self->input_images([
		# this little piglet does not support unicode
		# or, rather, readdir() needs some patching
		# additionally, it fails in M$ as the unicoded
		# filenames get doubly encoded, let's see if this will fix it:
		($^O eq 'MSWin32')
			?
			    File::Find::Rule
				->file()
				->name($pattern)
				->in($indir)
			:
			    map { Encode::decode_utf8($_) }
			    File::Find::Rule

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

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){
			if( ! -e $af ){ print STDERR "${whoami} (via $parent), line ".__LINE__." : warning/1, input image '$af' does not exist on disk and will be ignored.\n"; next }
			push @{$self->{'input-images'}}, _my_abs_path($af);
		}
	} elsif( $rf eq 'HASH' ){
		for my $af (values %$m){
			if( ! -e $af ){ print STDERR "${whoami} (via $parent), line ".__LINE__." : warning/2, input image '$af' does not exist on disk and will be ignored.\n"; next }

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

		if( ! -e $m ){ print STDERR "${whoami} (via $parent), line ".__LINE__." : warning/3, input image '$m' does not exist on disk and will be ignored.\n"; }
		else { push @{$self->{'input-images'}}, _my_abs_path($m) }
	} else { print STDERR "${whoami} (via $parent), line ".__LINE__." : error, input can be an arrayref of input image filenames, a hashref whose values are filenames or a single filename in the form of a scalar."; return undef }
	if( $verbos > 1 ){ print STDOUT perl2dump($self->{'input-images'})."${whoami} (via $parent), line ".__LINE__." : called and added some images, above is a list of all input images to create the animation.\n" }
	return $self->{'input-images'}
}

sub _my_cwd {
	return cwd()
}
# NOTE: unicode filenames may not be canonicalised
# e.g. iota-including-accent and iota with separate accent.
# the OS will not care but if you do comparisons you will fail
# So, consider canonicalising the filenames if you are doing comparison
# e.g. in the tests
# see https://perlmonks.org/?node_id=11156629
# Also, Cwd needs utf8 decode but Cwd::utf8 doesn't
# And File::Find::Rule needs also utf8 decoce unless it is chained to abs_path
sub _my_abs_path {
	#return Encode::decode_utf8(abs_path($_[0])) # for plain Cwd
	return abs_path($_[0]) # for Cwd::utf8

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


C<input_pattern()> can be combined with C<input_patterns()>
and C<input_images()>. The input images list will increase
in the order they are called.

B<Caveat>: the regex is parsed, compiled and passed on to L<File::Find::Rule>.
Escaping of special characters (e.g. the backslash) may be required.

B<Caveat>: the order of the matched input images is entirely up
to L<File::Find::Rule>. There may be unexpected results
when filenames contain unicode characters. Consider
these orderings for example:

=over 2

=item * C<blue.png, κίτρινο.png, red.png>,

=item * C<blue.png, γάμμα.png, κίτρινο.png, red.png>,

=item * C<blue.png, κίτρινο.png, γαμμα.png red.png>,

script/automate-animate-ffmpeg.pl  view on Meta::CPAN

use strict;
use warnings;

our $VERSION = '0.13';

use Getopt::Long;
use Text::ParseWords;
use Encode;
use Automate::Animate::FFmpeg;

use Data::Roundtrip qw/perl2dump no-unicode-escape-permanently/;

my $constructor_params = {
	'input-images' => undef,
	'input-pattern' => undef,
	'output-filename' => undef,
	'verbosity' => 0,
	'ffmpeg-extra-params' => undef,
	'frame-duration' => 0,
};

t/100-input-patterns.t  view on Meta::CPAN


use lib 'blib/lib';

use Test::More;
use Test2::Plugin::UTF8;

use Cwd;
use FindBin;
use File::Basename;
use Encode;
use Data::Roundtrip qw/perl2dump no-unicode-escape-permanently/;

use Automate::Animate::FFmpeg;

our $VERSION = '0.13';

my $curdir = Cwd::abs_path($FindBin::Bin);

my $anim_outfile = 'abc';
my $VERBOSITY = 10;

t/100-input-patterns.t  view on Meta::CPAN

is_deeply($s1, $s2, 'input_pattern()'." : called and got the images expected.") or BAIL_OUT("got:\n".perl2dump($s1)."\nexpected:\n".perl2dump($s2)."see above");
$aaFF->clear_input_images();

is($aaFF->input_patterns([
  [qw!regex(/.+?\.PNG$/i)!, File::Spec->catdir($curdir, 't-data')],
  [qw!regex(/.+?\.JPG$/i)!, File::Spec->catdir($curdir, 't-data')],
]), 1, 'input_pattern()'." : called and got good result.");
$s1 = { map { $_ => 1 } @{ $aaFF->input_images() } };
$s2 = { map { $_ => 1 } (@inpimages,File::Spec->catfile($curdir, 't-data', 'images', 'green.jpg')) };
is_deeply($s1, $s2, 'input_pattern()'." : called and got the images expected.") or BAIL_OUT("got:\n".perl2dump($s1)."\nexpected:\n".perl2dump($s2)."see above");
# the above fails in some Windows when filenames contain unicode
# not bothering
$aaFF->clear_input_images();

# END
done_testing;

t/900-scripts.t  view on Meta::CPAN


use Test::More;
use Test2::Plugin::UTF8;
use Test::Script;
use Test::TempDir::Tiny;
use File::Spec;
use FindBin;
use Cwd;
use Encode;
use File::Basename;
use Data::Roundtrip qw/perl2dump no-unicode-escape-permanently/;

use Automate::Animate::FFmpeg;

our $VERSION = '0.13';

my $curdir = $FindBin::Bin;

my $aaFF = Automate::Animate::FFmpeg->new();
ok(defined $aaFF, 'Automate::Animate::FFmpeg->new()'." : called and got defined result.") or BAIL_OUT;
my $exe; if( !defined($exe=$aaFF->ffmpeg_executable()) || ($exe=~/^\s*$/) || (! -x $exe) ){



( run in 0.940 second using v1.01-cache-2.11-cpan-88abd93f124 )