octave

How to create a mp4 video out of Octave/via plot


This is a follow up to question 54847941. I make videos from sequences of images created by Octave using the print command, for example:

clear;
for kt=1:100
  t(kt)=0.1*kt;
  clf,plot(t,sin(t),'linewidth',1);axis([0,10,-1,1]);
  fname=strcat('img',num2str(kt,"%0.2i"),'.png');
  eval(['print -dpng ' fname ' -r100']);
endfor

##use ffmpeg to make mp4 with:
##ffmpeg -framerate 20 -i img%02d.png -vf scale=1080:-1 Example1.mp4

This works when the imgaes are small, but if they are large, the print operations takes a very long time. What is an alternative to my method, using functions like getframe and imwrite?


Solution

  • Your initial code took 15.5s on my machine. The first optimization step is to keep the plot and update xdata and y data:

    t = linspace (0, 10, 100);
    for k = 1:numel(t) 
    
      y = sin (t(1:k));
    
      if (k == 1)
        p = plot (t(1:k), y, 'linewidth', 1);
        axis ([0, 10, -1, 1]);
      else
        set (p, "xdata", t(1:k));
        set (p, "ydata", y);
      endif
      fname = sprintf ("img%03i.png", k);
      print ("-dpng", "-r100", fname);
    endfor
    

    This takes 13.1s on my machine. Next we can use getframe:

    out_dir = "temp_img";
    mkdir (out_dir);
    t = linspace (0, 10, 100);
    for k = 1:numel(t) 
      y = sin (t(1:k));
      if (k == 1)
        p = plot (t(1:k), y, 'linewidth', 1);
        axis ([0, 10, -1, 1]);
      else
        set (p, "xdata", t(1:k));
        set (p, "ydata", y);
      endif
      fname = fullfile (out_dir, sprintf ("img%03i.png", k));
      imwrite (getframe (gcf).cdata, fname);
    endfor
    cmd = sprintf ("ffmpeg -framerate 20 -i ./%s/img%%03i.png -vf scale=1080:-1 Example1.mp4", out_dir)
    system (cmd)
    

    This takes 3.7s even with running ffmpeg .

    Keep in mind that if you're creating images (I guess like your vortex videos) you haven't go though plot