making a video (animated plot)

classic Classic list List threaded Threaded
12 messages Options
Reply | Threaded
Open this post in threaded view
|

making a video (animated plot)

Francesco Potortì
I have used the script below for making movies for ten years.  I wonder
if as of today I can get rid of it and use something more standard.  But
looking around on the web I have not found anything that looks stable,
nor Debian seems to be shipping a video package for Octave.

Am I missing something, or in fact we don't have yet a "standard"
package for creating movies (animated plots) in Octave?

--
IPIN'19 http://ipin2019.isti.cnr.it    Voice:  +39.050.621.3058
Francesco Potortì (ricercatore)        Mobile: +39.348.8283.107
ISTI - Area della ricerca CNR          Skype:  wnlabisti
via G. Moruzzi 1, I-56124 Pisa         Web:    http://fly.isti.cnr.it



===File /scratch/ftp/pub/software/octave/movie.m============
## Copyright (C) 2008, 2009 Francesco Potortì

## -*- texinfo -*-
## @deftypefn {Function File} {} movie (@var{action})
## @deftypefnx {Function File} {} movie (@var{action}, @var{mvf})
## @deftypefnx {Function File} {} movie (@var{action}, @var{mvf}, @var{arg})
## Create a movie from plots
##
## Example usage:
## @example
##   figure("visible","off"); movie("init","square.mp4")
##   n=100; a=zeros(n,n); a(1:20,41:60)=1;
##   for i=1:n; imshow(shift(a,i)); movie("add","square.mp4"); endfor
##   movie("close","square.mp4",24); close; system("mplayer square.mp4")
## @end example
##
## @var{action} takes one of three string values: @code{init},
## @code{add}, @code{close}. For each, @var{mvf} specifies the file name
## produced; the file name suffix sets the type of movie.
##
## If @var{mvf} is missing, it defaults to @file{octave_movie.mp4}. The
## suffix @file{.dir} creates a directory containing a png file per
## frame, the type @file{.zip} archives it using @command{zip}.  A
## suffix of @file{.mp4}, @file{.ogg}, @file{.mov}, @file{.mjpeg},
## @file{.avi}, @file{.flv} creates a movie using @command{ffmpeg};
## @file{.mng}, @file{.gif} create a movie using @command{convert}; type
## @file{.swf} creates a movie using @command{png2swf}. You must have
## the relevant program installed when using a given extension; no
## program is required for @file{.dir}.
##
## With the @var{init} action, a third arguments specifies the first
## frame number, which defaults to 0.
##
## With the @var{add} action, a third arguments specifies the current
## frame number, which defaults to the previous one plus one.
##
## With the @var{close} action, a third arguments specifies the frame
## rate (defaulting to 5 frames/second).
##
## @end deftypefn

## Author: Francesco Potortì <[hidden email]>
## $Revision: 1.15 $
## License: GPL version 3 or later

function movie (action, mvf='octave_movie.mp4', arg=NA)

  verbose = false;

  if (nargin == 0)
    print_usage ();
  elseif (nargin >= 2 && !ischar(mvf))
    error("second arg must be a string");
  endif
  [mpath mname mtype] = fileparts(mvf);
  mtype = mtype(2:end); # remove the initial dot

  mdir = fullfile(mpath, [mname '.d']);
  ppat = '%06d.png';
  mpat = fullfile(mdir, ppat);
  mglob = fullfile(mdir, strrep(sprintf(ppat,0),'0','[0-9]'));
  fnof = fullfile(mdir, "+frame-number+");

  switch (action)

    case "init" # init a movie
      if (isdir(mvf))
        cleandir(mvf, verbose)
      else
        unlink(mvf);
      endif
      while (!([allgood msg] = mkdir(mdir)))
        if (stat(fnof) && load(fnof).frameno == 0)
          error("while creating dir '%s': %s", mdir, msg);
        else
          cleandir(mdir, verbose);
        endif
      endwhile
      if isna(arg)
        frameno = 0;
      else
        frameno = arg;
      endif
      save('-text',fnof,'frameno');
      if (verbose) printf("Directory '%s' created.\n", mdir); endif

    case "add" # add a frame
      if isna(arg)
        load(fnof); # read frameno from file
      else
        frameno = arg;
      endif
      pmpat = strrep(mpat, '\', '\\'); # quote backslashes
      mfile = sprintf(pmpat, ++frameno);
      print(mfile,'-dpng');
      save('-text',fnof,'frameno');
      if (verbose) printf("Frame '%s' added.\n", mfile); endif

    case "close" # close the movie
      if isna(arg)
        rate = 5;
      else
        rate = arg;
      endif
      load(fnof); # read frameno from file
      switch (mtype)
        case {'mp4', 'ogg', 'mov', 'mjpeg', 'avi', 'flv'}
          cmd = sprintf("ffmpeg -y -r %d -i %s -qscale 0 %s 2>&1", rate, mpat, mvf);
        case {'mng', 'gif'}
          cmd = sprintf("convert %s -adjoin %s'[1-%d]' %s 2>&1", mglob, mpat, frameno, mvf);
        case 'zip'
          cmd = sprintf("zip -qr9 %s %s 2>&1", mvf, mglob);
        case 'swf'
          cmd = sprintf("png2swf -z -r %d -o %s %s", rate, mvf, mglob);
        case 'dir'
          rename(mdir, mvf); return
        otherwise
          print_usage();
      endswitch
      if (verbose) printf("\nExecuting %s\n", cmd); endif
      [status output] = system(cmd);
      if (status != 0)
        error("Creation of movie '%s' containing %d frames failed:\n%s",
              mvf, frameno, output);
      endif
      if (verbose) printf("Movie '%s' contains %d frames:\n%s",
                          mvf, frameno, output); endif
      cleandir(mdir, verbose);

    otherwise
      print_usage();

  endswitch
endfunction


function cleandir(mdir, verbose)
  unwind_protect
    save_crr = confirm_recursive_rmdir(false);
    [allgood msg] = rmdir(mdir,"s");
    if (!allgood)
      error("while removing dir '%s': %s", mdir, msg); endif
  unwind_protect_cleanup
    confirm_recursive_rmdir(save_crr);
  end_unwind_protect
  if (verbose) printf("Directory '%s' removed\n", mdir); endif
endfunction
============================================================


Reply | Threaded
Open this post in threaded view
|

Re: making a video (animated plot)

Andreas Weber-6
Am 27.09.19 um 22:34 schrieb Francesco Potortì:
> I have used the script below for making movies for ten years.

Why don't you use the forge video package with getframe + addframe?

I've started a new interface using OpenCV functions, see this branch
https://sourceforge.net/p/octave/video/ci/devel/tree/

But no one seems interested

-- Andy


Reply | Threaded
Open this post in threaded view
|

Re: making a video (animated plot)

BGreen
This has been interesting to read about and will be useful in the future. Thank you for sharing these!

- Brett Green


On Sat, Sep 28, 2019 at 12:30 AM Andreas Weber <[hidden email]> wrote:
Am 27.09.19 um 22:34 schrieb Francesco Potortì:
> I have used the script below for making movies for ten years.

Why don't you use the forge video package with getframe + addframe?

I've started a new interface using OpenCV functions, see this branch
https://sourceforge.net/p/octave/video/ci/devel/tree/

But no one seems interested

-- Andy




Reply | Threaded
Open this post in threaded view
|

Re: making a video (animated plot)

Pantxo
In reply to this post by Andreas Weber-6
Andreas Weber-6 wrote
> I've started a new interface using OpenCV functions, see this branch
> https://sourceforge.net/p/octave/video/ci/devel/tree/
>
> But no one seems interested
>
> -- Andy

What makes you think no one is interested?  On the contrary, I think many
people would be very happy to have a standardized way to produce videos
straight from Octave.
Like Francesco, for years, I have been using my own recipe which consisted
in printing each frame to png (fastidious) and using ffmpeg (or avconv) to
pack them into a video (e.g. "avconv -r 10 -i im%03d.png -b:v 1000k
test.mp4").

I'd be very happy to help you get VideoWriter to work but I am (as most
people on this list) completely ignorant when it comes to installing/testing
a package without a proper tarball?

Can you give instructions on how to test the new functionalities?

Thanks,

Pantxo
 




--
Sent from: https://octave.1599824.n4.nabble.com/Octave-General-f1599825.html


Reply | Threaded
Open this post in threaded view
|

Re: making a video (animated plot)

Pantxo
Pantxo wrote

> I'd be very happy to help you get VideoWriter to work but I am (as most
> people on this list) completely ignorant when it comes to
> installing/testing
> a package without a proper tarball?
>
> Can you give instructions on how to test the new functionalities?
>
>
> --
> Sent from:
> https://octave.1599824.n4.nabble.com/Octave-General-f1599825.html

Andy,

I managed to install the package using:

hg clone http://hg.code.sf.net/p/octave/video octave-video
cd octave-video
hg update devel
make dist
octave
>>pkg install video-2.0.0.tar.gz
>>pkg load video

But then I was unable to produce a readable video using examples provided in
ML doc.
Can you provided a working example to start with and explain the current
limitations?

Pantxo



--
Sent from: https://octave.1599824.n4.nabble.com/Octave-General-f1599825.html


Reply | Threaded
Open this post in threaded view
|

Re: making a video (animated plot)

Andreas Weber-6
Dear Pantxo,

Am 03.10.19 um 15:56 schrieb Pantxo:
> I managed to install the package using:
>
> hg clone http://hg.code.sf.net/p/octave/video octave-video
> cd octave-video
> hg update devel
> make dist

no need to go the "make dist" way, you can use it without installation
from the ./src path or "make run"

> Can you provided a working example to start with and explain the current
> limitations?

The classdef wrappers VideoWriter hast "writeVideo" implemented,
VideoReader is just a skeleton. I use the low level private functions
doit.m and doit2.m (have a look at them)

I can write a more complete answer tomorrow, Andy


Reply | Threaded
Open this post in threaded view
|

Re: making a video (animated plot)

Pantxo
Andreas Weber-6 wrote
> Dear Pantxo,
>
> Am 03.10.19 um 15:56 schrieb Pantxo:
>
> The classdef wrappers VideoWriter hast "writeVideo" implemented,
> VideoReader is just a skeleton. I use the low level private functions
> doit.m and doit2.m (have a look at them)
>
> I can write a more complete answer tomorrow, Andy

Thanks. Indeed, the VideoWriter works for me too with the synthetic data
from doit.m, but for some reason I am unable to use data obtained from
getframe, e.g. the example from movie.m won't produce a readable video:
---------------------------------------
w = VideoWriter ("foo.mp4", "");

z = sombrero ();
hs = surf (z);
axis manual
nframes = 50;

for ii = 1:nframes
  set (hs, "zdata", z * sin (2*pi*ii/nframes));
  writeVideo (w, getframe ().cdata);
endfor

close (w)
--------------------------------------

Here "writeVideo" always returns 0. Am I doing something wrong?

Pantxo



--
Sent from: https://octave.1599824.n4.nabble.com/Octave-General-f1599825.html


Reply | Threaded
Open this post in threaded view
|

Re: making a video (animated plot)

Andreas Weber-6
Am 03.10.19 um 22:40 schrieb Pantxo:
> Thanks. Indeed, the VideoWriter works for me too with the synthetic data
> from doit.m, but for some reason I am unable to use data obtained from
> getframe, e.g. the example from movie.m won't produce a readable video:

I'm sorry but I've added fixed width and height in cap_ffmpeg_wrapper.cc
line 286,287 for debugging.


When I've started this branch in march 2019 I didn't know what was the
indended way to set width/height. Ti be compatible with the other
software product I think you can open a video for writing but the first
frame added finally sets width/height.

If I know that you want to help, please give me 1-2days and I'll polish
the code, translate the comments and so on.

Thank you, andy


Reply | Threaded
Open this post in threaded view
|

Re: making a video (animated plot)

Pantxo
Andreas Weber-6 wrote
> Am 03.10.19 um 22:40 schrieb Pantxo:
>
> If I know that you want to help, please give me 1-2days and I'll polish
> the code, translate the comments and so on.
>
> Thank you, andy

Thanks. In the mean time I will open a bug report to track the first obvious
issues in this preliminary implementation of VideoWriter so that the
discussion can take place there until the code is released.

Pantxo



--
Sent from: https://octave.1599824.n4.nabble.com/Octave-General-f1599825.html


Reply | Threaded
Open this post in threaded view
|

Re: making a video (animated plot)

Andreas Weber-6
In reply to this post by Pantxo
Hi Pantxo,

Am 03.10.19 um 22:40 schrieb Pantxo:
> Thanks. Indeed, the VideoWriter works for me too with the synthetic data
> from doit.m, but for some reason I am unable to use data obtained from
> getframe, e.g. the example from movie.m won't produce a readable video:

I removed old cruft and added your example as demo_write_sombrero_video.m

See also https://sourceforge.net/p/octave/video/ci/devel/tree/HACKING
how to get into without the need to make a forge package

Until now there are 2 low-level read/write demos and 2 high-level
classdef read/write examples

I want to keep the original OpenCV code as original as possible to make
merges from upstream easier.

-- Andy


Reply | Threaded
Open this post in threaded view
|

Re: making a video (animated plot)

Andreas Weber-6
In reply to this post by Pantxo
Am 04.10.19 um 18:15 schrieb Pantxo:
> Thanks. In the mean time I will open a bug report to track the first obvious
> issues in this preliminary implementation of VideoWriter so that the
> discussion can take place there until the code is released.

Have you seen my email from 4.10.2019 18.25 (GMT+2)?

We can make a roadmap what features should be implemented to make a
first release. Reading/Writing RGB24 frames into various containers with
different codecs would be IMHO the most important parts.

I think a very important part would be testing on different distros with
ffmpeg and libav. The API changes and different makros are a real pain
in the ass. I'm thinking of a docker directory with tests for various
combinations ffmpeg, libav, distros and perhaps also GNU Octave 4.4.1

-- Andy


Reply | Threaded
Open this post in threaded view
|

Re: making a video (animated plot)

Pantxo
Andreas Weber-6 wrote

> Am 04.10.19 um 18:15 schrieb Pantxo:
>> Thanks. In the mean time I will open a bug report to track the first
>> obvious
>> issues in this preliminary implementation of VideoWriter so that the
>> discussion can take place there until the code is released.
>
> Have you seen my email from 4.10.2019 18.25 (GMT+2)?
>
> We can make a roadmap what features should be implemented to make a
> first release. Reading/Writing RGB24 frames into various containers with
> different codecs would be IMHO the most important parts.
>
> I think a very important part would be testing on different distros with
> ffmpeg and libav. The API changes and different makros are a real pain
> in the ass. I'm thinking of a docker directory with tests for various
> combinations ffmpeg, libav, distros and perhaps also GNU Octave 4.4.1
>
> -- Andy

Thanks Andy,

This looks very promising. I tested the updated code, for VideoWriter only,
and it now works well for non synthetic data.
As for the roadmap, here are in IMHO the missing features that should not be
hard to have before a first realase for the VideoWriter:
* most properties should be read-only (SetAccess = "private"): ColorChannels
(codec specific), Duration, FileFormat (codec specific), FileName/Path
(fixed at object instantiation), FrameCount, Height/Width (fixed by the
first provided frame), VideoBitsPerPixel/VideoCompressionMethod/VideoFormat
(codec specific),
* increment FrameCount and Duration after each successful call to
writeVideo,
* allow passing frames or frame arrays  directly to writeVideo, without
having to extract the "cdata" field manually,
* allow passing arbitrary image data types even if we end up converting them
internally to whatever is prefered for the chosen codec, e.g uint8 for RGB
24bits video formats.

As for the available output formats, I am no expert so in this area, I am
generally happy with whatever the default is. So we just need to make a
sensible choice of 1 or 2 widespread formats that can be read with the
default viewer for the main platforms.

I have reproduced this post in bug #57020 so that we can carry on the
discussion in a more suitable place:

https://savannah.gnu.org/bugs/index.php?57020

Many thanks for those updates.

Pantxo



 



--
Sent from: https://octave.1599824.n4.nabble.com/Octave-General-f1599825.html