worldsight has asked for the wisdom of the Perl Monks concerning the following question:

What kind of Perl modules are available to stick together thousands of images into a movie file? I want to avoid the disk I/O associated with generating all the images, writing them to disk, and then using separate encoding software.

I've got some perl that's already capable of generating thousands (millions actually) of images (using ImageMagick).

Audio is of no concern.

Does anyone know of a module that just uses an open filehandle and can have images written to it? Almost like frameserving?

I don't need any compression, I just want to make a series of images into a movie file. Basically, I'd like to append frames to an existing movie file.

I can already generate the movies if I create a few hundred images, fork a shell to an encoder, then make a movie file.

Is there a way to do this all in memory and not write anything but the movie to disk?

Replies are listed 'Best First'.
Re: Encoding Video
by Corion (Patriarch) on Jun 19, 2008 at 12:38 UTC

    I open a filehandle to ffmpeg for that:

    package External::FFmpeg; use parent 'Class::Accessor'; __PACKAGE__->mk_accessors(qw(width height depth pid stream texture_id +file)); sub spawn { my ($self,$cmd) = @_; my $pid = open my $stream, $cmd or die "Couldn't spawn '$cmd': $!/$?"; binmode $stream; return ($pid,$stream) }; sub DESTROY { if (my $pid = $_[0]->pid) { kill 9, $pid }; }; package Target::FFmpeg; use strict; use parent -norequire => 'External::FFmpeg'; sub new { my ($class,%args) = @_; my $file = delete $args{filename}; my $width = delete $args{width} || 352; my $height = delete $args{height} || 288; my $in_width = delete $args{in_width} || $width; my $in_height = delete $args{in_height} || $height; my $depth = 3; my ($pid,$stream) = $class->spawn(qq{| bin\\ffmpeg-old.exe -y -f r +awvideo -pix_fmt rgb24 -s ${in_width}x${in_height} -i "-" -f mpeg2vid +eo -s ${width}x${height} "$file"}); my $self = $class->SUPER::new({ width => $width, height => $height, depth => $depth, stream => $stream, pid => $pid, %args, }); $self };

    Then I just print each frame (in RGB-format) to the filehandle and let ffmpeg work its magic. You could also try to get FFMpeg to compile+install, but I found using a binary far more convenient.

Re: Encoding Video
by zentara (Cardinal) on Jun 19, 2008 at 13:13 UTC
    Look at gstreamer It has a Perl module for the library. It is quite advanced, and thus more complicated to figure out, but it does have a good maillist (where at least the c libs are discussed). That is probably your best bet. If you can get someone there to show a way in c, or with the commandline program, you can probably convert it to Perl.

    However, since you already are using ImageMagick to generate the frames(and don't care about sound), I would dig deep into it's docs and examples to find a way with it. IM supports writing to Perl filehandles, in memory images(blobs), and the avi format..... so there may be a way. The problem with IM is the docs are so scattered and unorganized. You may be able to open an animated gif as a blob in memory, write to it, and when done change it's -magick option to avi, then print it. You really have to experiment with IM to get the right combination to work as intended.

    I would also look at mencoder (not Perl but it is widely used).


    I'm not really a human, but I play one on earth CandyGram for Mongo
Re: Encoding Video
by moritz (Cardinal) on Jun 19, 2008 at 12:44 UTC
    If you are on Linux, and IO is your only concern, and you have enough memory available, create a ram disk somewhere and write the images there.

    It has a couple of drawbacks (for example losing data on power outage), but it's a very simple solution for performance problems with temporary files.