File Coverage

blib/lib/Video/Generator.pm
Criterion Covered Total %
statement 63 83 75.9
branch 4 20 20.0
condition n/a
subroutine 14 15 93.3
pod 2 2 100.0
total 83 120 69.1


line stmt bran cond sub pod time code
1             package Video::Generator;
2              
3             # Pragmas.
4 3     3   93740 use strict;
  3         8  
  3         112  
5 3     3   20 use warnings;
  3         7  
  3         126  
6              
7             # Modules.
8 3     3   3105 use Class::Utils qw(set_params);
  3         95462  
  3         77  
9 3     3   221 use Error::Pure qw(err);
  3         6  
  3         124  
10 3     3   2639 use FFmpeg::Command;
  3         181412  
  3         26  
11 3     3   117 use File::Path qw(rmtree);
  3         6  
  3         179  
12 3     3   2487 use File::Spec::Functions qw(catfile);
  3         2469  
  3         196  
13 3     3   3498 use File::Temp qw(tempdir);
  3         61520  
  3         205  
14 3     3   2306 use IO::CaptureOutput qw(capture_exec);
  3         5528  
  3         156  
15 3     3   2205 use Image::Random;
  3         125487  
  3         38  
16 3     3   129 use Readonly;
  3         8  
  3         164  
17 3     3   2627 use Video::Delay::Const;
  3         665  
  3         33  
18 3     3   2445 use Video::Pattern;
  3         5564  
  3         33  
19              
20             # Constants.
21             Readonly::Scalar our $SPACE => q{ };
22              
23             # Version.
24             our $VERSION = 0.08;
25              
26             # Constructor.
27             sub new {
28 9     9 1 24811 my ($class, @params) = @_;
29              
30             # Create object.
31 9         27 my $self = bless {}, $class;
32              
33             # Delay generator.
34 9         31 $self->{'delay_generator'} = undef;
35              
36             # Duration.
37 9         22 $self->{'duration'} = 10000;
38              
39             # Frames per second.
40 9         20 $self->{'fps'} = 60;
41              
42             # FFmpeg pixel format.
43 9         23 $self->{'ffmpeg_pixel_format'} = undef;
44              
45             # FFmpeg video codec.
46 9         19 $self->{'ffmpeg_video_codec'} = undef;
47              
48             # Image generator.
49 9         24 $self->{'image_generator'} = undef;
50              
51             # Image type.
52 9         26 $self->{'image_type'} = 'bmp';
53              
54             # Temporary dir.
55 9         32 $self->{'temp_dir'} = undef;
56              
57             # Verbose mode.
58 9         21 $self->{'verbose'} = 0;
59              
60             # Video pattern generator.
61 9         17 $self->{'video_pattern'} = undef;
62              
63             # Sizes.
64 9         18 $self->{'height'} = 1080;
65 9         17 $self->{'width'} = 1920;
66              
67             # Process params.
68 9         40 set_params($self, @params);
69              
70             # Temporary directory.
71 7 50       90 if (! defined $self->{'temp_dir'}) {
72 7         56 $self->{'temp_dir'} = tempdir();
73             }
74              
75             # Image generator.
76 7 50       3240 if (! defined $self->{'image_generator'}) {
77             $self->{'image_generator'} = Image::Random->new(
78             'height' => $self->{'height'},
79             'type' => $self->{'image_type'},
80 7         50 'width' => $self->{'width'},
81             );
82             }
83              
84             # Delay generator.
85 6 50       15354 if (! defined $self->{'delay_generator'}) {
86 6         50 $self->{'delay_generator'} = Video::Delay::Const->new(
87             'const' => 1000,
88             );
89             }
90              
91             # Video pattern generator.
92 6 50       165 if (! defined $self->{'video_pattern'}) {
93             $self->{'video_pattern'} = Video::Pattern->new(
94             'delay_generator' => $self->{'delay_generator'},
95             'duration' => $self->{'duration'},
96             'fps' => $self->{'fps'},
97 6         50 'image_generator' => $self->{'image_generator'},
98             );
99             }
100              
101             # Object.
102 1         94 return $self;
103             }
104              
105             # Create random video.
106             sub create {
107 0     0 1   my ($self, $out_path) = @_;
108              
109             # Create images.
110 0           $self->{'video_pattern'}->create($self->{'temp_dir'});
111 0 0         if ($self->{'verbose'}) {
112 0           print "Video pattern generator created images for video in ".
113             "temporary directory.\n";
114             }
115              
116             # Create video.
117 0           my $ffmpeg = FFmpeg::Command->new;
118             my $images_path = catfile($self->{'temp_dir'},
119 0           '%03d.'.$self->{'image_type'});
120             my @command_options = ('-loglevel', 'error', '-r', $self->{'fps'},
121             '-i', $images_path,
122             $self->{'ffmpeg_video_codec'}
123             ? ('-c:v', $self->{'ffmpeg_video_codec'})
124             : (),
125             $self->{'ffmpeg_pixel_format'}
126 0 0         ? ('-pix_fmt', $self->{'ffmpeg_pixel_format'})
    0          
127             :(),
128             '-pix_fmt', 'yuv420p',
129             $out_path);
130 0           $ffmpeg->options(@command_options);
131 0           $ffmpeg->exec;
132 0 0         if ($ffmpeg->stderr) {
133 0           my @stderr = split m/\n/ms, $ffmpeg->stderr;
134 0           my $command = join $SPACE, @command_options;
135             err "Error with command 'ffmpeg $command'.",
136 0           map { ('STDERR', $_) } @stderr;
  0            
137             }
138 0 0         if ($self->{'verbose'}) {
139 0           print "Created video file.\n";
140             }
141              
142             # Remove temporary directory.
143 0           rmtree $self->{'temp_dir'};
144 0 0         if ($self->{'verbose'}) {
145 0           print "Removed temporary directory.\n";
146             }
147              
148 0           return;
149             }
150              
151             1;
152              
153             __END__