Example #1
0
def ffmpeg_write_video(clip, filename, fps, codec="libx264", bitrate=None,
                       preset="medium", withmask=False, write_logfile=False,
                       audiofile=None, verbose=True, threads=None, ffmpeg_params=None):
    """ Write the clip to a videofile. See VideoClip.write_videofile for details
    on the parameters.
    """
    if write_logfile:
        logfile = open(filename + ".log", 'w+')
    else:
        logfile = None

    verbose_print(verbose, "[MoviePy] Writing video %s\n"%filename)
    writer = FFMPEG_VideoWriter(filename, clip.size, fps, codec = codec,
                                preset=preset, bitrate=bitrate, logfile=logfile,
                                audiofile=audiofile, threads=threads,
                                ffmpeg_params=ffmpeg_params)

    nframes = int(clip.duration*fps)

    for t,frame in clip.iter_frames(progress_bar=True, with_times=True,
                                    fps=fps, dtype="uint8"):
        if withmask:
            mask = (255*clip.mask.get_frame(t))
            if mask.dtype != "uint8":
                mask = mask.astype("uint8")
            frame = np.dstack([frame,mask])
        
        writer.write_frame(frame)

    writer.close()

    if write_logfile:
        logfile.close()

    verbose_print(verbose, "[MoviePy] Done.\n")
Example #2
0
def ffmpeg_audiowrite(clip,
                      filename,
                      fps,
                      nbytes,
                      buffersize,
                      codec='libvorbis',
                      bitrate=None,
                      write_logfile=False,
                      verbose=True,
                      ffmpeg_params=None,
                      progress_bar=False):
    """
    A function that wraps the FFMPEG_AudioWriter to write an AudioClip
    to a file.
    """

    if write_logfile:
        logfile = open(filename + ".log", 'w+')
    else:
        logfile = None

    verbose_print(verbose, "[MoviePy] Writing audio in %s\n" % filename)

    writer = FFMPEG_AudioWriter(filename,
                                fps,
                                nbytes,
                                clip.nchannels,
                                codec=codec,
                                bitrate=bitrate,
                                logfile=logfile,
                                ffmpeg_params=ffmpeg_params)

    try:
        for chunk in clip.iter_chunks(chunksize=buffersize,
                                      progress_bar=progress_bar,
                                      quantize=True,
                                      nbytes=nbytes,
                                      fps=fps):
            writer.write_frames(chunk)
        """
        totalsize = int(fps*clip.duration)

        if (totalsize % buffersize == 0):
            nchunks = totalsize // buffersize
        else:
            nchunks = totalsize // buffersize + 1

        pospos = list(range(0, totalsize,  buffersize))+[totalsize]
        for i in tqdm(range(nchunks)):
            tt = (1.0/fps)*np.arange(pospos[i],pospos[i+1])
            sndarray = clip.to_soundarray(tt, nbytes= nbytes)
            writer.write_frames(sndarray)
        """
    finally:
        writer.close()

        if write_logfile:
            logfile.close()

        verbose_print(verbose, "[MoviePy] Done.\n")
Example #3
0
def ffmpeg_write_video(clip, filename, fps, codec="libx264", bitrate=None,
                       preset = "medium", withmask=False, write_logfile=False,
                       audiofile=None, verbose=True):
    
    if write_logfile:
        logfile = open(filename + ".log", 'w+')
    else:
        logfile = None


    verbose_print(verbose, "\nWriting video into %s\n"%filename)
    writer = FFMPEG_VideoWriter(filename, clip.size, fps, codec = codec,
                                preset=preset, bitrate=bitrate, logfile=logfile,
                                audiofile = audiofile)
             
    nframes = int(clip.duration*fps)
    
    for t,frame in clip.iter_frames(progress_bar=True, with_times=True,
                                    fps=fps):
        if withmask:
            mask = 255*clip.mask.get_frame(t)
            frame = np.dstack([frame,mask])
            
        writer.write_frame(frame.astype("uint8"))
    
    writer.close()

    if write_logfile:
      logfile.close()
    
    verbose_print(verbose, "Done writing video in %s !"%filename)
Example #4
0
def ffmpeg_write_video(clip, filename, fps, codec="libx264", bitrate=None,
                       preset="medium", withmask=False, write_logfile=False,
                       audiofile=None, verbose=True, threads=None, ffmpeg_params=None):

    if write_logfile:
        logfile = open(filename + ".log", 'w+')
    else:
        logfile = None

    verbose_print(verbose, "[MoviePy] Writing video %s\n"%filename)
    writer = FFMPEG_VideoWriter(filename, clip.size, fps, codec = codec,
                                preset=preset, bitrate=bitrate, logfile=logfile,
                                audiofile=audiofile, threads=threads,
                                ffmpeg_params=ffmpeg_params)

    nframes = int(clip.duration*fps)

    for t,frame in clip.iter_frames(progress_bar=True, with_times=True,
                                    fps=fps, dtype="uint8"):
        if withmask:
            mask = (255*clip.mask.get_frame(t))
            if mask.dtype != "uint8":
                mask = mask.astype("uint8")
            frame = np.dstack([frame,mask])
        
        writer.write_frame(frame)

    writer.close()

    if write_logfile:
        logfile.close()

    verbose_print(verbose, "[MoviePy] Done.\n")
Example #5
0
def ffmpeg_audiowrite(clip, filename, fps, nbytes, buffersize,
                      codec='libvorbis', bitrate=None,
                      write_logfile = False, verbose=True,
                      ffmpeg_params=None):
    """
    A function that wraps the FFMPEG_AudioWriter to write an AudioClip
    to a file.
    """

    if write_logfile:
        logfile = open(filename + ".log", 'w+')
    else:
        logfile = None

    verbose_print(verbose, "[MoviePy] Writing audio in %s\n"%filename)

    writer = FFMPEG_AudioWriter(filename, fps, nbytes, clip.nchannels,
                                codec=codec, bitrate=bitrate,
                                logfile=logfile,
                                ffmpeg_params=ffmpeg_params)

    
    
    for chunk in clip.iter_chunks(chunksize=buffersize,
                                  progress_bar=verbose, quantize=True,
                                  nbytes= nbytes, fps=fps):
        writer.write_frames(chunk)

    writer.close()

    if write_logfile:
        logfile.close()

    verbose_print(verbose, "[MoviePy] Done.\n")
Example #6
0
def write_gif_with_image_io(clip, filename, fps=None, opt="wu", loop=0, colors=None, verbose=True):
    """
    Writes the gif with the Python library ImageIO (calls FreeImage).
    
    For the moment ImageIO is not installed with MoviePy. You need to install
    imageio (pip install imageio) to use this.

    Parameters
    -----------
    opt

    """

    if colors is None:
        colors = 256

    if not IMAGEIO_FOUND:
        raise ImportError("Writing a gif with imageio requires ImageIO installed," " with e.g. 'pip install imageio'")

    if fps is None:
        fps = clip.fps

    quantizer = "wu" if opt != "nq" else "nq"
    writer = imageio.save(filename, duration=1.0 / fps, quantizer=quantizer, palettesize=colors)

    verbose_print(verbose, "\n[MoviePy] Building file %s with imageio\n" % filename)

    for frame in clip.iter_frames(fps=fps, progress_bar=True, dtype="uint8"):

        writer.append_data(frame)
Example #7
0
def ffmpeg_write_video(clip, filename, fps, codec="libx264", bitrate=None,
                  withmask=False, write_logfile=False, verbose=True):
    
    if write_logfile:
        logfile = open(filename + ".log", 'w+')
    else:
        logfile = None


    verbose_print(verbose, "\nWriting video into %s\n"%filename)
    writer = FFMPEG_VideoWriter(filename, clip.size, fps, codec = codec,
             bitrate=bitrate, logfile=logfile)
             
    nframes = int(clip.duration*fps)
    
    for i in tqdm(range(nframes)):
        frame = clip.get_frame(1.0*i/fps)
        if withmask:
            mask = (255*clip.mask.get_frame(1.0*i/fps))
            frame = np.dstack([frame,mask])
            
        writer.write_frame(frame.astype("uint8"))
    
    writer.close()

    if write_logfile:
      logfile.close()
    
    verbose_print(verbose, "Done writing video in %s !"%filename)
Example #8
0
def write_gif_with_image_io(clip, filename, fps=None, opt='wu', loop=0,
                            colors=None, verbose=True):
    """
    Writes the gif with the Python library ImageIO (calls FreeImage).
    
    For the moment ImageIO is not installed with MoviePy. You need to install
    imageio (pip install imageio) to use this.

    Parameters
    -----------
    opt

    """

    if colors is None:
        colors=256

    if not IMAGEIO_FOUND:
      raise ImportError("Writing a gif with imageio requires ImageIO installed,"
                         " with e.g. 'pip install imageio'")

    if fps is None:
        fps = clip.fps

    quantizer = 'wu' if opt!= 'nq' else 'nq' 
    writer = imageio.save(filename, duration=1.0/fps,
                          quantizer=quantizer, palettesize=colors)

    verbose_print(verbose, "\n[MoviePy] Building file %s with imageio\n"%filename)
    
    for frame in clip.iter_frames(fps=fps, progress_bar=True, dtype='uint8'):

        writer.append_data(frame)
Example #9
0
def write_gif_with_image_io(clip, filename, fps=None, opt=0, loop=0,
                            colors=None, verbose=True, progress_bar=True,
                            progress_cb=None):
    """
    Writes the gif with the Python library ImageIO (calls FreeImage).

    Parameters
    -----------
    opt

    progress_bar
      Boolean indicating whether to display a progress bar in the terminal
      while exporting the file.

    progress_cb
      Callback function to call during export. It should accept
      the current frame index being exported and the total number
      of frames. It can be used to update a gui progressbar while
      running in a separate thread.

    """

    if colors is None:
        colors = 256

    if not IMAGEIO_FOUND:
        raise ImportError("Writing a gif with imageio requires ImageIO installed,"
                         " with e.g. 'pip install imageio'")

    if fps is None:
        fps = clip.fps

    quantizer = 0 if opt != 0 else 'nq'

    writer = imageio.save(
        filename,
        duration=1.0/fps,
        quantizer=quantizer,
        palettesize=colors,
        loop=loop
        )

    verbose_print(verbose, "\n[MoviePy] Building file %s with imageio\n" % filename)

    # if progress callback was define, call it
    if callable(progress_cb):
        nframes = int(clip.duration*fps)+1
        count = 1

    for frame in clip.iter_frames(fps=fps, progress_bar=progress_bar, dtype='uint8'):


        writer.append_data(frame)

        # if progress callback was define, call it
        if callable(progress_cb):
            progress_cb(count, nframes)
            count += 1
Example #10
0
    def write_images_sequence(self, nameformat, fps=None, verbose=True):
        """ Writes the videoclip to a sequence of image files.


        Parameters
        -----------

        nameformat
          A filename specifying the numerotation format and extension
          of the pictures. For instance "frame%03d.png" for filenames
          indexed with 3 digits and PNG format. Also possible:
          "some_folder/frame%04d.jpeg", etc.

        fps
          Number of frames per second to consider when writing the
          clip. If not specified, the clip's ``fps`` attribute will
          be used if it has one.

        verbose
          Verbose output ?


        Returns
        --------

        names_list
          A list of all the files generated.

        Notes
        ------

        The resulting image sequence can be read using e.g. the class
        ``DirectoryClip``.

        """

        verbose_print(verbose, "MoviePy: Writing frames %s."%(nameformat))

        if fps is None:
            fps = self.fps

        tt = np.arange(0, self.duration, 1.0/fps)

        filenames = []
        total = int(self.duration/fps)+1
        for i, t in tqdm(enumerate(tt), total=total):
            name = nameformat%(i+1)
            filenames.append(name)
            self.save_frame(name, t, savemask=True)

        verbose_print(verbose, "MoviePy: Done writing frames %s."%(nameformat))

        return filenames
Example #11
0
def ffmpeg_audiowrite(clip,
                      filename,
                      fps,
                      nbytes,
                      buffersize,
                      codec='libvorbis',
                      bitrate=None,
                      write_logfile=False,
                      verbose=True):
    """
    A function that wraps the FFMPEG_AudioWriter to write an AudioClip
    to a file.
    """

    if write_logfile:
        logfile = open(filename + ".log", 'w+')
    else:
        logfile = None

    verbose_print(verbose, "Writing audio in %s\n" % filename)

    writer = FFMPEG_AudioWriter(filename,
                                fps,
                                nbytes,
                                clip.nchannels,
                                codec=codec,
                                bitrate=bitrate,
                                logfile=logfile)

    totalsize = int(fps * clip.duration)

    if (totalsize % buffersize == 0):
        nchunks = totalsize // buffersize
    else:
        nchunks = totalsize // buffersize + 1

    pospos = list(range(0, totalsize, buffersize)) + [totalsize]

    for i in tqdm(range(nchunks)):
        tt = (1.0 / fps) * np.arange(pospos[i], pospos[i + 1])
        sndarray = clip.to_soundarray(tt, nbytes=nbytes)
        writer.write_frames(sndarray)

    writer.close()

    if write_logfile:
        logfile.close()

    verbose_print(verbose, "Done writing Audio in %s !\n" % filename)
Example #12
0
def ffmpeg_audiowrite(clip, filename, fps, nbytes, buffersize,
                      codec='libvorbis', bitrate=None,
                      write_logfile = False, verbose=True,
                      ffmpeg_params=None):
    """
    A function that wraps the FFMPEG_AudioWriter to write an AudioClip
    to a file.
    """

    if write_logfile:
        logfile = open(filename + ".log", 'w+')
    else:
        logfile = None

    verbose_print(verbose, "[MoviePy] Writing audio in %s\n"%filename)

    writer = FFMPEG_AudioWriter(filename, fps, nbytes, clip.nchannels,
                                codec=codec, bitrate=bitrate,
                                logfile=logfile,
                                ffmpeg_params=ffmpeg_params)

    
    
    for chunk in clip.iter_chunks(chunksize=buffersize,
                                  progress_bar=True, quantize=True,
                                  nbytes= nbytes, fps=fps):
        writer.write_frames(chunk)

    """
    totalsize = int(fps*clip.duration)

    if (totalsize % buffersize == 0):
        nchunks = totalsize // buffersize
    else:
        nchunks = totalsize // buffersize + 1

    pospos = list(range(0, totalsize,  buffersize))+[totalsize]
    for i in tqdm(range(nchunks)):
        tt = (1.0/fps)*np.arange(pospos[i],pospos[i+1])
        sndarray = clip.to_soundarray(tt, nbytes= nbytes)
        writer.write_frames(sndarray)
    """

    writer.close()

    if write_logfile:
        logfile.close()

    verbose_print(verbose, "[MoviePy] Done.\n")
Example #13
0
def write_gif(clip,
              filename,
              fps=None,
              program='ImageMagick',
              opt="OptimizeTransparency",
              fuzz=1,
              verbose=True,
              loop=0,
              dispose=False,
              colors=None):
    """ Write the VideoClip to a GIF file, without temporary files.

    Converts a VideoClip into an animated GIF using ImageMagick
    or ffmpeg.


    Parameters
    -----------

    filename
      Name of the resulting gif file.

    fps
      Number of frames per second (see note below). If it
        isn't provided, then the function will look for the clip's
        ``fps`` attribute (VideoFileClip, for instance, have one).

    program
      Software to use for the conversion, either 'ImageMagick' or
      'ffmpeg'.

    opt
      (ImageMagick only) optimalization to apply, either
      'optimizeplus' or 'OptimizeTransparency'.

    fuzz
      (ImageMagick only) Compresses the GIF by considering that
      the colors that are less than fuzz% different are in fact
      the same.


    Notes
    -----

    The gif will be playing the clip in real time (you can
    only change the frame rate). If you want the gif to be played
    slower than the clip you will use ::

        >>> # slow down clip 50% and make it a gif
        >>> myClip.speedx(0.5).write_gif('myClip.gif')

    """

    #
    # We use processes chained with pipes.
    #
    # if program == 'ffmpeg'
    # frames --ffmpeg--> gif
    #
    # if program == 'ImageMagick' and optimize == (None, False)
    # frames --ffmpeg--> bmp frames --ImageMagick--> gif
    #
    #
    # if program == 'ImageMagick' and optimize != (None, False)
    # frames -ffmpeg-> bmp frames -ImagMag-> gif -ImagMag-> better gif
    #

    delay = 100.0 / fps

    cmd1 = [
        get_setting("FFMPEG_BINARY"), '-y', '-loglevel', 'error', '-f',
        'rawvideo', '-vcodec', 'rawvideo', '-r',
        "%.02f" % fps, '-s',
        "%dx%d" % (clip.w, clip.h), '-pix_fmt', 'rgb24', '-i', '-'
    ]

    popen_params = {"stdout": DEVNULL, "stderr": DEVNULL, "stdin": DEVNULL}

    if os.name == "nt":
        popen_params["creationflags"] = 0x08000000

    if program == "ffmpeg":
        popen_params["stdin"] = sp.PIPE
        popen_params["stdout"] = DEVNULL

        proc1 = sp.Popen(cmd1 + ['-r', "%.02f" % fps, filename],
                         **popen_params)
    else:

        popen_params["stdin"] = sp.PIPE
        popen_params["stdout"] = sp.PIPE

        proc1 = sp.Popen(cmd1 + ['-f', 'image2pipe', '-vcodec', 'bmp', '-'],
                         **popen_params)

    if program == 'ImageMagick':

        cmd2 = [
            get_setting("IMAGEMAGICK_BINARY"), '-delay',
            "%.02f" % (delay), "-dispose",
            "%d" % (2 if dispose else 1), '-loop',
            '%d' % loop, '-', '-coalesce'
        ]

        if (opt in [False, None]):
            popen_params["stdin"] = proc1.stdout
            popen_params["stdout"] = DEVNULL
            proc2 = sp.Popen(cmd2 + [filename], **popen_params)

        else:
            popen_params["stdin"] = proc1.stdout
            popen_params["stdout"] = sp.PIPE
            proc2 = sp.Popen(cmd2 + ['gif:-'], **popen_params)

        if opt:

            cmd3 = [
                get_setting("IMAGEMAGICK_BINARY"), '-', '-layers', opt,
                '-fuzz',
                '%d' % fuzz + '%'
            ] + (["-colors", "%d" %
                  colors] if colors is not None else []) + [filename]

            popen_params["stdin"] = proc2.stdout
            popen_params["stdout"] = DEVNULL
            proc3 = sp.Popen(cmd3, **popen_params)

    # We send all the frames to the first process
    verbose_print(
        verbose,
        "\nMoviePy: building GIF file %s\n" % filename + 40 * "-" + "\n")
    verbose_print(verbose, "Generating GIF frames...\n")

    try:

        for frame in clip.iter_frames(fps=fps, progress_bar=True):
            proc1.stdin.write(frame.tostring())
        verbose_print(verbose, "Done.\n")

    except IOError as err:

        error = ("MoviePy Error: creation of %s failed because "
                 "of the following error:\n\n%s.\n\n." % (filename, str(err)))

        if program == "ImageMagick":
            error = error + (
                "This can be due to the fact that "
                "ImageMagick is not installed on your computer, or "
                "(for Windows users) that you didn't specify the "
                "path to the ImageMagick binary in file conf.py.")

        raise IOError(error)
    verbose_print(verbose, "Writing GIF... ")
    proc1.stdin.close()
    proc1.wait()
    if program == 'ImageMagick':
        proc2.wait()
        if opt:
            proc3.wait()
    verbose_print(verbose, 'Done. Your GIF is ready !')
Example #14
0
def write_gif_with_tempfiles(clip,
                             filename,
                             fps=None,
                             program='ImageMagick',
                             opt="OptimizeTransparency",
                             fuzz=1,
                             verbose=True,
                             loop=0,
                             dispose=False,
                             colors=None,
                             tempfiles=False):
    """ Write the VideoClip to a GIF file.


    Converts a VideoClip into an animated GIF using ImageMagick
    or ffmpeg. Does the same as write_gif (see this one for more
    docstring), but writes every frame to a file instead of passing
    them in the RAM. Useful on computers with little RAM.

    """

    fileName, fileExtension = os.path.splitext(filename)
    tt = np.arange(0, clip.duration, 1.0 / fps)

    tempfiles = []

    verbose_print(
        verbose,
        "\nMoviePy: building GIF file %s\n" % filename + 40 * "-" + "\n")

    verbose_print(verbose, "Generating GIF frames.\n")

    total = int(clip.duration * fps) + 1
    for i, t in tqdm(enumerate(tt), total=total):

        name = "%s_GIFTEMP%04d.png" % (fileName, i + 1)
        tempfiles.append(name)
        clip.save_frame(name, t, savemask=True)

    verbose_print(verbose, "Done generating GIF frames.\n")

    delay = int(100.0 / fps)

    if program == "ImageMagick":

        cmd = [
            get_setting("IMAGEMAGICK_BINARY"),
            '-delay',
            '%d' % delay,
            "-dispose",
            "%d" % (2 if dispose else 1),
            "-loop",
            "%d" % loop,
            "%s_GIFTEMP*.png" % fileName,
            "-coalesce",
            "-layers",
            "%s" % opt,
            "-fuzz",
            "%02d" % fuzz + "%",
        ] + (["-colors", "%d" %
              colors] if colors is not None else []) + [filename]

    elif program == "ffmpeg":

        cmd = [
            get_setting("FFMPEG_BINARY"), '-y', '-f', 'image2', '-r',
            str(fps), '-i', fileName + '_GIFTEMP%04d.png', '-r',
            str(fps), filename
        ]

    try:
        subprocess_call(cmd, verbose=verbose)

    except (IOError, OSError) as err:

        error = ("MoviePy Error: creation of %s failed because "
                 "of the following error:\n\n%s.\n\n." % (filename, str(err)))

        if program == "ImageMagick":
            error = error + (
                "This error can be due to the fact that "
                "ImageMagick is not installed on your computer, or "
                "(for Windows users) that you didn't specify the "
                "path to the ImageMagick binary in file conf.py.")

        raise IOError(error)

    for f in tempfiles:
        os.remove(f)
Example #15
0
    def write_gif(self, filename, fps=None, program= 'ImageMagick',
               opt="OptimizeTransparency", fuzz=1, verbose=True,
               loop=0, dispose=False):
        """ Write the VideoClip to a GIF file.

        Converts a VideoClip into an animated GIF using ImageMagick
        or ffmpeg.


        Parameters
        -----------

        filename
          Name of the resulting gif file.

        fps
          Number of frames per second (see note below). If it
            isn't provided, then the function will look for the clip's
            ``fps`` attribute (VideoFileClip, for instance, have one).

        program
          Software to use for the conversion, either 'ImageMagick' or
          'ffmpeg'.

        opt
          (ImageMagick only) optimalization to apply, either
          'optimizeplus' or 'OptimizeTransparency'.

        fuzz
          (ImageMagick only) Compresses the GIF by considering that
          the colors that are less than fuzz% different are in fact
          the same.


        Notes
        -----

        The gif will be playing the clip in real time (you can
        only change the frame rate). If you want the gif to be played
        slower than the clip you will use ::

            >>> # slow down clip 50% and make it a gif
            >>> myClip.speedx(0.5).to_gif('myClip.gif')

        """

        if fps is None:
            fps = self.fps

        fileName, fileExtension = os.path.splitext(filename)
        tt = np.arange(0,self.duration, 1.0/fps)

        tempfiles = []

        verbose_print(verbose, "\nMoviePy: building GIF file %s\n"%filename
                      +40*"-"+"\n")

        verbose_print(verbose, "Generating GIF frames.\n")

        total = int(self.duration*fps)+1
        for i, t in tqdm(enumerate(tt), total=total):

            name = "%s_GIFTEMP%04d.png"%(fileName, i+1)
            tempfiles.append(name)
            self.save_frame(name, t, savemask=True)

        verbose_print(verbose, "Done generating GIF frames.\n")

        delay = int(100.0/fps)

        if program == "ImageMagick":

            cmd = [IMAGEMAGICK_BINARY,
                  '-delay' , '%d'%delay,
                  "-dispose" ,"%d"%(2 if dispose else 1),
                  "-loop" , "%d"%loop,
                  "%s_GIFTEMP*.png"%fileName,
                  "-coalesce",
                  "-fuzz", "%02d"%fuzz + "%",
                  "-layers", "%s"%opt,
                  filename]

        elif program == "ffmpeg":

            cmd = [FFMPEG_BINARY, '-y',
                   '-f', 'image2', '-r',str(fps),
                   '-i', fileName+'_GIFTEMP%04d.bmp',
                   '-r',str(fps),
                   filename]

        try:
            subprocess_call( cmd, verbose = verbose )
        
        except IOError as err:

            error = ("MoviePy Error: creation of %s failed because "
              "of the following error:\n\n%s.\n\n."%(filename, str(err)))
            
            if program == "ImageMagick":
                error = error + ("This can be due to the fact that "
                    "ImageMagick is not installed on your computer, or "
                    "(for Windows users) that you didn't specify the "
                    "path to the ImageMagick binary in file conf.py." )
            
            raise IOError(error)

        for f in tempfiles:
            os.remove(f)
Example #16
0
    def write_gif2(self, filename, fps=None, program= 'ImageMagick',
                   opt="OptimizeTransparency", fuzz=1, verbose=True,
                   loop=0, dispose=False):
        """ Write the VideoClip to a GIF file, without temporary files.

        Converts a VideoClip into an animated GIF using ImageMagick
        or ffmpeg.


        Parameters
        -----------

        filename
          Name of the resulting gif file.

        fps
          Number of frames per second (see note below). If it
            isn't provided, then the function will look for the clip's
            ``fps`` attribute (VideoFileClip, for instance, have one).

        program
          Software to use for the conversion, either 'ImageMagick' or
          'ffmpeg'.

        opt
          (ImageMagick only) optimalization to apply, either
          'optimizeplus' or 'OptimizeTransparency'.

        fuzz
          (ImageMagick only) Compresses the GIF by considering that
          the colors that are less than fuzz% different are in fact
          the same.


        Notes
        -----

        The gif will be playing the clip in real time (you can
        only change the frame rate). If you want the gif to be played
        slower than the clip you will use ::

            >>> # slow down clip 50% and make it a gif
            >>> myClip.speedx(0.5).write_gif('myClip.gif')

        """
        
        #
        # We use processes chained with pipes.
        #
        # if program == 'ffmpeg'
        # frames --ffmpeg--> gif
        #
        # if program == 'ImageMagick' and optimize == (None, False)
        # frames --ffmpeg--> bmp frames --ImageMagick--> gif
        #
        # 
        # if program == 'ImageMagick' and optimize != (None, False)
        # frames -ffmpeg-> bmp frames -ImagMag-> gif -ImagMag-> better gif
        #
    
        if fps is None:
            fps=self.fps
        
        cmd1 = [FFMPEG_BINARY, '-y', '-loglevel', 'error',
                '-f', 'rawvideo',
                '-vcodec','rawvideo', '-r', "%.02f"%fps,
                '-s', "%dx%d"%(self.w, self.h), '-pix_fmt', 'rgb24',
                '-i', '-']
        cmd1a = cmd1+['-r', "%.02f"%fps, filename]
        cmd1b = cmd1+['-f', 'image2pipe','-vcodec', 'bmp', '-']
        
        cmd2 = [IMAGEMAGICK_BINARY, '-', '-delay', "%d"%int(100.0/fps),
                '-loop', '%d'%loop]
        cmd2a = cmd2+[filename]
        cmd2b = cmd2+['gif:-'] 
        
        proc1 = (sp.Popen(cmd1a, stdin=sp.PIPE, stdout=DEVNULL) if (program =='ffmpeg')
                 else sp.Popen(cmd1b, stdin=sp.PIPE, stdout=sp.PIPE))
        
        if program == 'ImageMagick':
            proc2 = (sp.Popen(cmd2a, stdin=proc1.stdout) if (opt in [False, None])
                     else sp.Popen(cmd2b, stdin=proc1.stdout, stdout=sp.PIPE))
            if opt:
                cmd3 = [IMAGEMAGICK_BINARY, '-', '-layers', opt,
                        '-fuzz', '%d'%fuzz+'%',filename]
                proc3 = sp.Popen(cmd3, stdin=proc2.stdout)
        
        # We send all the frames to the first process
        verbose_print(verbose, "\nMoviePy: building GIF file %s\n"%filename
                                +40*"-"+"\n")
        verbose_print(verbose, "Generating GIF frames...\n")
        nframes = int(self.duration*fps)+1
        
        try:

            for frame in tqdm(self.iter_frames(fps=fps), total=nframes):
                proc1.stdin.write(frame.tostring())
            verbose_print(verbose, "Done.\n")

        except IOError as err:

            error = ("MoviePy Error: creation of %s failed because "
              "of the following error:\n\n%s.\n\n."%(filename, str(err)))
            
            if program == "ImageMagick":
                error = error + ("This can be due to the fact that "
                    "ImageMagick is not installed on your computer, or "
                    "(for Windows users) that you didn't specify the "
                    "path to the ImageMagick binary in file conf.py." )
            
            raise IOError(error)
        verbose_print(verbose, "Writing GIF... ")
        proc1.stdin.close()
        proc1.wait()
        if program == 'ImageMagick':
            proc2.wait()
            if opt:
                proc3.wait()
        verbose_print(verbose, 'Done. Your GIF is ready !')
Example #17
0
def write_gif(clip, filename, fps=None, program= 'ImageMagick',
           opt="OptimizeTransparency", fuzz=1, verbose=True, withmask=True,
           loop=0, dispose=True, colors=None, progress_bar=True,
           progress_cb=None):
    """ Write the VideoClip to a GIF file, without temporary files.

    Converts a VideoClip into an animated GIF using ImageMagick
    or ffmpeg.


    Parameters
    -----------

    filename
      Name of the resulting gif file.

    fps
      Number of frames per second (see note below). If it
        isn't provided, then the function will look for the clip's
        ``fps`` attribute (VideoFileClip, for instance, have one).

    program
      Software to use for the conversion, either 'ImageMagick' or
      'ffmpeg'.

    opt
      (ImageMagick only) optimalization to apply, either
      'optimizeplus' or 'OptimizeTransparency'.

    fuzz
      (ImageMagick only) Compresses the GIF by considering that
      the colors that are less than fuzz% different are in fact
      the same.

    progress_bar
      Determines whether to display a progress bar in the terminal
      while exporting the file.

    progress_cb
      Callback function to call during export. It should accept
      the current frame index being exported and the total number
      of frames. It can be used to update a gui progressbar while
      running in a separate thread.


    Notes
    -----

    The gif will be playing the clip in real time (you can
    only change the frame rate). If you want the gif to be played
    slower than the clip you will use ::

        >>> # slow down clip 50% and make it a gif
        >>> myClip.speedx(0.5).write_gif('myClip.gif')

    """

    #
    # We use processes chained with pipes.
    #
    # if program == 'ffmpeg'
    # frames --ffmpeg--> gif
    #
    # if program == 'ImageMagick' and optimize == (None, False)
    # frames --ffmpeg--> bmp frames --ImageMagick--> gif
    #
    #
    # if program == 'ImageMagick' and optimize != (None, False)
    # frames -ffmpeg-> bmp frames -ImagMag-> gif -ImagMag-> better gif
    #

    delay= 100.0/fps

    if clip.mask is None:
        withmask = False

    cmd1 = [get_setting("FFMPEG_BINARY"), '-y', '-loglevel', 'error',
            '-f', 'rawvideo',
            '-vcodec','rawvideo', '-r', "%.02f"%fps,
            '-s', "%dx%d"%(clip.w, clip.h),
            '-pix_fmt', ('rgba' if withmask else 'rgb24'),
            '-i', '-']

    popen_params = {"stdout": DEVNULL,
                    "stderr": DEVNULL,
                    "stdin": DEVNULL}

    if os.name == "nt":
        popen_params["creationflags"] = 0x08000000

    if program == "ffmpeg":
        popen_params["stdin"] = sp.PIPE
        popen_params["stdout"] = DEVNULL

        proc1 = sp.Popen(cmd1+[ '-pix_fmt', ('rgba' if withmask else 'rgb24'),
                                '-r', "%.02f"%fps, filename], **popen_params)
    else:

        popen_params["stdin"] = sp.PIPE
        popen_params["stdout"] = sp.PIPE

        proc1 = sp.Popen(cmd1+ ['-f', 'image2pipe', '-vcodec', 'bmp', '-'],
                         **popen_params)

    if program == 'ImageMagick':

        cmd2 = [get_setting("IMAGEMAGICK_BINARY"), '-delay', "%.02f"%(delay),
                "-dispose" ,"%d"%(2 if dispose else 1),
                '-loop', '%d'%loop, '-', '-coalesce']

        if (opt in [False, None]):
            popen_params["stdin"] = proc1.stdout
            popen_params["stdout"] = DEVNULL
            proc2 = sp.Popen(cmd2+[filename], **popen_params)

        else:
            popen_params["stdin"] = proc1.stdout
            popen_params["stdout"] = sp.PIPE
            proc2 = sp.Popen(cmd2+['gif:-'], **popen_params)

        if opt:

            cmd3 = [get_setting("IMAGEMAGICK_BINARY"), '-', '-layers', opt,
                    '-fuzz', '%d'%fuzz+'%'
                   ]+(["-colors", "%d"%colors] if colors is not None else [])+[
                   filename]

            popen_params["stdin"] = proc2.stdout
            popen_params["stdout"] = DEVNULL
            proc3 = sp.Popen(cmd3, **popen_params)

    # We send all the frames to the first process
    verbose_print(verbose, "\n[MoviePy] >>>> Building file %s\n"%filename)
    verbose_print(verbose, "[MoviePy] Generating GIF frames...\n")

    try:
        # if progress callback was define, call it
        if callable(progress_cb):
            nframes = int(clip.duration*fps)+1
            count = 1

        for t,frame in clip.iter_frames(fps=fps, progress_bar=progress_bar,
                                        with_times=True,  dtype="uint8"):
            if withmask:
                mask = 255 * clip.mask.get_frame(t)
                frame = np.dstack([frame, mask]).astype('uint8')
            proc1.stdin.write(frame.tostring())

            # if progress callback was define, call it
            if callable(progress_cb):
                progress_cb(count, nframes)
                count += 1

    except IOError as err:

        error = ("[MoviePy] Error: creation of %s failed because "
          "of the following error:\n\n%s.\n\n."%(filename, str(err)))

        if program == "ImageMagick":
            error = error + ("This can be due to the fact that "
                "ImageMagick is not installed on your computer, or "
                "(for Windows users) that you didn't specify the "
                "path to the ImageMagick binary in file conf.py." )

        raise IOError(error)
    if program == 'ImageMagick':
        verbose_print(verbose, "[MoviePy] Optimizing the GIF with ImageMagick...\n")
    proc1.stdin.close()
    proc1.wait()
    if program == 'ImageMagick':
        proc2.wait()
        if opt:
            proc3.wait()
    verbose_print(verbose, "[MoviePy] >>>> File %s is ready!"%filename)
Example #18
0
    def write_videofile(self, filename, fps=24, codec='libx264',
                 bitrate=None, audio=True, audio_fps=44100,
                 audio_nbytes = 4, audio_codec= 'libmp3lame',
                 audio_bitrate = None, audio_bufsize = 2000,
                 temp_audiofile=None,
                 rewrite_audio = True, remove_temp = True,
                 write_logfile=False,
                 para = False, verbose = True):
        """Write the clip to a videofile.

        Parameters
        -----------

        filename
          Name of the video file. The extension must correspond to the
          codec used (see below), ar simply be '.avi'.

        fps
          Number of frames per second in the resulting video file.

        codec
          Codec to use for image encoding. Can be any codec supported
          by ffmpeg, but the extension of the output filename must be
          set accordingly.

          Some examples of codecs are:

          ``'libx264'`` (default codec, use file extension ``.mp4``)
          makes well-compressed videos (quality tunable using 'bitrate').


          ``'mpeg4'`` (use file extension ``.mp4``) can be an alternative
          to ``'libx264'``, and produces higher quality videos by default.


          ``'rawvideo'`` (use file extension ``.avi``) will produce 
          a video of perfect quality, of possibly very huge size.

          ``png`` (use file extension ``.avi``) will produce a video
          of perfect quality, of smaller size than with ``rawvideo``

          ``'libvorbis'`` (use file extension ``.ogv``) is a nice video
          format, which is completely free/ open source. However not
          everyone has the codecs installed by default on their machine.

          ``'libvpx'`` (use file extension ``.webm``) is tiny a video
          format well indicated for web videos (with HTML5). Open source.


        audio
          Either ``True``, ``False``, or a file name.
          If ``True`` and the clip has an audio clip attached, this
          audio clip will be incorporated as a soundtrack in the movie.
          If ``audio`` is the name of an audio file, this audio file
          will be incorporated as a soundtrack in the movie.

        audiofps
          frame rate to use when generating the sound.

        temp_audiofile
          the name of the temporary audiofile to be generated and
          incorporated in the the movie, if any.

        audio_codec
          Which audio codec should be used. Examples are 'libmp3lame'
          for '.mp3', 'libvorbis' for 'ogg', 'libfdk_aac':'m4a',
          'pcm_s16le' for 16-bit wav and 'pcm_s32le' for 32-bit wav.

        audio_bitrate
          Audio bitrate, given as a string like '50k', '500k', '3000k'.
          Will determine the size/quality of audio in the output file.
          Note that it mainly an indicative goal, the bitrate won't
          necessarily be the this in the final file.

        write_logfile
          If true, will write log files for the audio and the video.
          These will be files ending with '.log' with the name of the
          output file in them.

        """

        name, ext = os.path.splitext(os.path.basename(filename))

        if audio_codec == 'raw16':
            audio_codec = 'pcm_s16le'
        elif audio_codec == 'raw32':
            audio_codec = 'pcm_s32le'

        if isinstance(audio, str):
            # audio is some audiofile it is maybe not a wav file. It is
            # NOT temporary file, it will NOT be removed at the end.
            temp_audiofile = audio
            make_audio = False
            merge_audio = True

        elif self.audio is None:
            # audio not provided as a file and no clip.audio
            make_audio = merge_audio =  False

        elif audio:
            # The audio will be the clip's audio
            if temp_audiofile is None:

                # make a name for the temporary audio file

                D_ext = {'libmp3lame': 'mp3',
                       'libvorbis':'ogg',
                       'libfdk_aac':'m4a',
                       'aac':'m4a',
                       'pcm_s16le':'wav',
                       'pcm_s32le': 'wav'}

                if audio_codec in D_ext.values():
                    audio_ext = audio_codec
                else:
                    if audio_codec in D_ext.keys():
                        audio_ext = D_ext[audio_codec]
                    else:
                        raise ValueError('audio_codec for file'
                                          '%s unkown !'%filename)

                temp_audiofile = (name+Clip._TEMP_FILES_PREFIX +
                            "write_videofile_SOUND.%s"%audio_ext)

            make_audio = ( (not os.path.exists(temp_audiofile))
                            or rewrite_audio)
            merge_audio = True

        else:

            make_audio = False
            merge_audio = False

        if merge_audio:

            # make a name for the temporary video file
            videofile = (name + Clip._TEMP_FILES_PREFIX +
                         "write_videofile%s"%ext)

        else:

            videofile = filename

        # enough cpu for multiprocessing ?
        enough_cpu = (multiprocessing.cpu_count() > 2)

        verbose_print(verbose, "\nMoviePy: building video file %s\n"%filename
                                +40*"-"+"\n")

        if para and make_audio and  enough_cpu:

            # Parallelize
            verbose_print(verbose, "Writing audio/video in parrallel.\n")
            audioproc = multiprocessing.Process(
                    target=self.audio.write_audiofile,
                    args=(temp_audiofile,audio_fps,audio_nbytes,
                          audio_bufsize,audio_codec,
                          audio_bitrate,
                          verbose))

            audioproc.start()
            
            ffmpeg_write_video(self, 
                               videofile, fps, codec,
                               bitrate=bitrate,
                               write_logfile=write_logfile,
                               verbose=verbose)
            audioproc.join()
            if audioproc.exitcode:
                print ("WARNING: something went wrong with the audio"+
                       " writing, Exit code %d"%audioproc.exitcode)
        else:

            # Don't parallelize
            if make_audio:
                self.audio.write_audiofile(temp_audiofile,audio_fps,
                                        audio_nbytes, audio_bufsize,
                                        audio_codec, bitrate=audio_bitrate,
                                        write_logfile=write_logfile,
                                        verbose=verbose)

            ffmpeg_write_video(self,
                               videofile, fps, codec,
                               bitrate=bitrate,
                               write_logfile=write_logfile,
                               verbose=verbose)

        # Merge with audio if any and trash temporary files.
        if merge_audio:

            verbose_print(verbose, "\n\nNow merging video and audio:\n")
            ffmpeg_merge_video_audio(videofile,temp_audiofile,
                                  filename, ffmpeg_output=True)

            if remove_temp:
                os.remove(videofile)
                if not isinstance(audio,str):
                    os.remove(temp_audiofile)
            verbose_print(verbose, "\nYour video is ready !\n")
Example #19
0
def write_gif_with_tempfiles(clip, filename, fps=None, program= 'ImageMagick',
       opt="OptimizeTransparency", fuzz=1, verbose=True,
       loop=0, dispose=True, colors=None, tempfiles=False, progress_bar=True,
       progress_cb=None):

    """ Write the VideoClip to a GIF file.


    Converts a VideoClip into an animated GIF using ImageMagick
    or ffmpeg. Does the same as write_gif (see this one for more
    docstring), but writes every frame to a file instead of passing
    them in the RAM. Useful on computers with little RAM.

    Parameters
    -----------

    filename
      Name of the resulting gif file.

    fps
      Number of frames per second (see note below). If it
        isn't provided, then the function will look for the clip's
        ``fps`` attribute (VideoFileClip, for instance, have one).

    program
      Software to use for the conversion, either 'ImageMagick' or
      'ffmpeg'.

    opt
      (ImageMagick only) optimalization to apply, either
      'optimizeplus' or 'OptimizeTransparency'.

    fuzz
      (ImageMagick only) Compresses the GIF by considering that
      the colors that are less than fuzz% different are in fact
      the same.

    progress_bar
      Boolean indicating whether to display a progress bar in the terminal
      while exporting the file.

    progress_cb
      Callback function to call during export. It should accept
      the current frame index being exported and the total number
      of frames. It can be used to update a gui progressbar while
      running in a separate thread.

    """

    fileName, fileExtension = os.path.splitext(filename)
    tt = np.arange(0,clip.duration, 1.0/fps)

    tempfiles = []

    verbose_print(verbose, "\n[MoviePy] Building file %s\n"%filename
                  +40*"-"+"\n")

    verbose_print(verbose, "[MoviePy] Generating GIF frames...\n")

    total = int(clip.duration*fps)+1

    if progress_bar:
        # Show a terminal-based progress bar while exporting
        iterator = tqdm(enumerate(tt), total=total)
    else:
        iterator = enumerate(tt)

    for i, t in iterator:
        name = "%s_GIFTEMP%04d.png"%(fileName, i+1)
        tempfiles.append(name)
        clip.save_frame(name, t, withmask=True)

        # if progress callback was define, call it
        if callable(progress_cb):
            progress_cb(i+1, total)

    delay = int(100.0/fps)

    if program == "ImageMagick":
        verbose_print(verbose, "[MoviePy] Optimizing GIF with ImageMagick... ")
        cmd = [get_setting("IMAGEMAGICK_BINARY"),
              '-delay' , '%d'%delay,
              "-dispose" ,"%d"%(2 if dispose else 1),
              "-loop" , "%d"%loop,
              "%s_GIFTEMP*.png"%fileName,
              "-coalesce",
              "-layers", "%s"%opt,
              "-fuzz", "%02d"%fuzz + "%",
              ]+(["-colors", "%d"%colors] if colors is not None else [])+[
              filename]

    elif program == "ffmpeg":

        cmd = [get_setting("FFMPEG_BINARY"), '-y',
               '-f', 'image2', '-r',str(fps),
               '-i', fileName+'_GIFTEMP%04d.png',
               '-r',str(fps),
               filename]

    try:
        subprocess_call( cmd, verbose = verbose )
        verbose_print(verbose, "[MoviePy] GIF %s is ready."%filename)

    except (IOError,OSError) as err:

        error = ("MoviePy Error: creation of %s failed because "
          "of the following error:\n\n%s.\n\n."%(filename, str(err)))

        if program == "ImageMagick":
            error = error + ("This error can be due to the fact that "
                "ImageMagick is not installed on your computer, or "
                "(for Windows users) that you didn't specify the "
                "path to the ImageMagick binary in file conf.py." )

        raise IOError(error)

    for f in tempfiles:
        os.remove(f)
Example #20
0
def write_gif(clip, filename, fps=None, program= 'ImageMagick',
           opt="OptimizeTransparency", fuzz=1, verbose=True, withmask=True,
           loop=0, dispose=True, colors=None):
    """ Write the VideoClip to a GIF file, without temporary files.

    Converts a VideoClip into an animated GIF using ImageMagick
    or ffmpeg.


    Parameters
    -----------

    filename
      Name of the resulting gif file.

    fps
      Number of frames per second (see note below). If it
        isn't provided, then the function will look for the clip's
        ``fps`` attribute (VideoFileClip, for instance, have one).

    program
      Software to use for the conversion, either 'ImageMagick' or
      'ffmpeg'.

    opt
      (ImageMagick only) optimalization to apply, either
      'optimizeplus' or 'OptimizeTransparency'.

    fuzz
      (ImageMagick only) Compresses the GIF by considering that
      the colors that are less than fuzz% different are in fact
      the same.


    Notes
    -----

    The gif will be playing the clip in real time (you can
    only change the frame rate). If you want the gif to be played
    slower than the clip you will use ::

        >>> # slow down clip 50% and make it a gif
        >>> myClip.speedx(0.5).write_gif('myClip.gif')

    """

    #
    # We use processes chained with pipes.
    #
    # if program == 'ffmpeg'
    # frames --ffmpeg--> gif
    #
    # if program == 'ImageMagick' and optimize == (None, False)
    # frames --ffmpeg--> bmp frames --ImageMagick--> gif
    #
    #
    # if program == 'ImageMagick' and optimize != (None, False)
    # frames -ffmpeg-> bmp frames -ImagMag-> gif -ImagMag-> better gif
    #

    delay= 100.0/fps

    if clip.mask is None:
        withmask = False

    cmd1 = [get_setting("FFMPEG_BINARY"), '-y', '-loglevel', 'error',
            '-f', 'rawvideo',
            '-vcodec','rawvideo', '-r', "%.02f"%fps,
            '-s', "%dx%d"%(clip.w, clip.h),
            '-pix_fmt', ('rgba' if withmask else 'rgb24'),
            '-i', '-']

    popen_params = {"stdout": DEVNULL,
                    "stderr": DEVNULL,
                    "stdin": DEVNULL}

    if os.name == "nt":
        popen_params["creationflags"] = 0x08000000

    if program == "ffmpeg":
        popen_params["stdin"] = sp.PIPE
        popen_params["stdout"] = DEVNULL

        proc1 = sp.Popen(cmd1+[ '-pix_fmt', ('rgba' if withmask else 'rgb24'),
                                '-r', "%.02f"%fps, filename], **popen_params)
    else:

        popen_params["stdin"] = sp.PIPE
        popen_params["stdout"] = sp.PIPE

        proc1 = sp.Popen(cmd1+ ['-f', 'image2pipe', '-vcodec', 'bmp', '-'],
                         **popen_params)

    if program == 'ImageMagick':

        cmd2 = [get_setting("IMAGEMAGICK_BINARY"), '-delay', "%.02f"%(delay),
                "-dispose" ,"%d"%(2 if dispose else 1),
                '-loop', '%d'%loop, '-', '-coalesce']

        if (opt in [False, None]):
            popen_params["stdin"] = proc1.stdout
            popen_params["stdout"] = DEVNULL
            proc2 = sp.Popen(cmd2+[filename], **popen_params)

        else:
            popen_params["stdin"] = proc1.stdout
            popen_params["stdout"] = sp.PIPE
            proc2 = sp.Popen(cmd2+['gif:-'], **popen_params)

        if opt:

            cmd3 = [get_setting("IMAGEMAGICK_BINARY"), '-', '-layers', opt,
                    '-fuzz', '%d'%fuzz+'%'
                   ]+(["-colors", "%d"%colors] if colors is not None else [])+[
                   filename]

            popen_params["stdin"] = proc2.stdout
            popen_params["stdout"] = DEVNULL
            proc3 = sp.Popen(cmd3, **popen_params)

    # We send all the frames to the first process
    verbose_print(verbose, "\n[MoviePy] >>>> Building file %s\n"%filename)
    verbose_print(verbose, "[MoviePy] Generating GIF frames...\n")

    try:

        for t,frame in clip.iter_frames(fps=fps, progress_bar=True,
                                        with_times=True,  dtype="uint8"):
            if withmask:
                mask = 255 * clip.mask.get_frame(t)
                frame = np.dstack([frame, mask]).astype('uint8')
            proc1.stdin.write(frame.tostring())

    except IOError as err:

        error = ("[MoviePy] Error: creation of %s failed because "
          "of the following error:\n\n%s.\n\n."%(filename, str(err)))

        if program == "ImageMagick":
            error = error + ("This can be due to the fact that "
                "ImageMagick is not installed on your computer, or "
                "(for Windows users) that you didn't specify the "
                "path to the ImageMagick binary in file conf.py." )

        raise IOError(error)
    if program == 'ImageMagick':
        verbose_print(verbose, "[MoviePy] Optimizing the GIF with ImageMagick...\n")
    proc1.stdin.close()
    proc1.wait()
    if program == 'ImageMagick':
        proc2.wait()
        if opt:
            proc3.wait()
    verbose_print(verbose, "[MoviePy] >>>> File %s is ready!"%filename)
Example #21
0
def write_gif_with_tempfiles(clip, filename, fps=None, program= 'ImageMagick',
       opt="OptimizeTransparency", fuzz=1, verbose=True,
       loop=0, dispose=True, colors=None):
    """ Write the VideoClip to a GIF file.


    Converts a VideoClip into an animated GIF using ImageMagick
    or ffmpeg. Does the same as write_gif (see this one for more
    docstring), but writes every frame to a file instead of passing
    them in the RAM. Useful on computers with little RAM.

    """

    fileName, fileExtension = os.path.splitext(filename)
    tt = np.arange(0,clip.duration, 1.0/fps)

    tempfiles = []

    verbose_print(verbose, "\n[MoviePy] Building file %s\n"%filename
                  +40*"-"+"\n")

    verbose_print(verbose, "[MoviePy] Generating GIF frames...\n")

    total = int(clip.duration*fps)+1
    for i, t in tqdm(enumerate(tt), total=total):

        name = "%s_GIFTEMP%04d.png"%(fileName, i+1)
        tempfiles.append(name)
        clip.save_frame(name, t, withmask=True)

    delay = int(100.0/fps)

    if program == "ImageMagick":
        verbose_print(verbose, "[MoviePy] Optimizing GIF with ImageMagick... ")
        cmd = [get_setting("IMAGEMAGICK_BINARY"),
              '-delay' , '%d'%delay,
              "-dispose" ,"%d"%(2 if dispose else 1),
              "-loop" , "%d"%loop,
              "%s_GIFTEMP*.png"%fileName,
              "-coalesce",
              "-layers", "%s"%opt,
              "-fuzz", "%02d"%fuzz + "%",
              ]+(["-colors", "%d"%colors] if colors is not None else [])+[
              filename]

    elif program == "ffmpeg":

        cmd = [get_setting("FFMPEG_BINARY"), '-y',
               '-f', 'image2', '-r',str(fps),
               '-i', fileName+'_GIFTEMP%04d.png',
               '-r',str(fps),
               filename]

    try:
        subprocess_call( cmd, verbose = verbose )
        verbose_print(verbose, "[MoviePy] GIF %s is ready."%filename)

    except (IOError,OSError) as err:

        error = ("MoviePy Error: creation of %s failed because "
          "of the following error:\n\n%s.\n\n."%(filename, str(err)))

        if program == "ImageMagick":
            error = error + ("This error can be due to the fact that "
                "ImageMagick is not installed on your computer, or "
                "(for Windows users) that you didn't specify the "
                "path to the ImageMagick binary in file conf.py." )

        raise IOError(error)

    for f in tempfiles:
        os.remove(f)