video2gif

Solapas principales

Nombre: video2gif
Autor: Point_to_null (Carlos Marcelo Cabrera)
Origen: Propio
Lenguaje: python
Dependencias: python, mplayer, imagemagick
Licencia: GPL
Propósito: Convierte un video (de cualquier tipo (avi, mpeg, vob, wmv, mov, flv, mp4, ect)) en un gif animado

Código:

#!/usr/bin/env python
#-*- coding: UTF-8 -*-
import commands
import re
import tempfile
import shutil
from optparse import OptionParser, OptionValueError

def identify(filename):
    """Return a dict with the video file details."""
    output = commands.getoutput("""mplayer -slave -identify -frames 0 \
        -vc null -vo null -ao null '%s'""" % filename)
    out = dict(re.findall(r"""(?m).*?ID_(?P<item>.*?)=(?P<value>.*)""", output))
    for key in out:
        try:
            out[key] = float(out[key])
        except ValueError:
            pass
    return out

def execute(command, verbose=0):
    if verbose > 0: print("    " + command)
    stdout = commands.getoutput(command)
    if verbose > 1: print(stdout)

def main():
    # Instance the parser and define the usage message
    parser = OptionParser(usage="""
    %prog [-rsdo] file""", version="%prog 2")

    # Define the options and the actions of each one
    parser.add_option("-o", "--output-file", action="store", dest="output",
        metavar="filename")
    parser.add_option("-r", "--resize", help="Use NxN to do the best fit; " +
        "NxN! to ignore aspect ratio; " +
        "NxN> to only shrink larger; " +
        "NxN< to only enlarge smaller; " +
        "Scale% to scale; " +
        "Pixels@ to fit the area limit",
        metavar="size", action="store", type="string", dest="resize")
    parser.add_option("-s", "--start", action="store", dest="start",
        metavar="TIME")
    parser.add_option("-d", "--duration", action="store", dest="duration",
        metavar="TIME", help="TIME must be in seconds or h:m:s")
    parser.add_option("-S", "--speed", action="store", dest="speed",
        metavar="FPS")
    parser.add_option("-v", "--verbose", action="count", dest="verbose")

#    # Define the default options
    parser.set_defaults(verbose=0)

    # Process the options
    options, args = parser.parse_args()

    # Process the args
    filename = shutil.abspath(args[0])
    assert shutil.os.stat(filename)

    if options.output:
        output = shutil.abspath(options.output)
    else:
        output =  ".".join(filename.split(".")[:-1]) + ".gif"

    # Create tempdir
    tempdir = tempfile.mkdtemp()
    shutil.os.chdir(tempdir)

    # Set speed
    if options.speed:
        fps = float(options.speed)
    else:
        fps = identify(filename).get('VIDEO_FPS', 25.)

    delay = 100 / fps

    # Print info
    print("Input: %s" % filename)
    print("Output: %s" % output)
    print("Tempdir: %s" % tempdir)
    print("Speed: %.2ffps == %.5fms per frame" % (fps, delay * 10))

    # Decompressing video
    print("Decompressing video...")
    command = """mplayer -slave -vo jpeg -ao null"""
    if options.start:
        command += " -ss '%s'" % options.start
    if options.duration:
        command += " -endpos '%s'" % options.duration

    command += """ '%s'""" % filename
    execute(command, options.verbose)

    # Composing animated gif
    print("Composing animated gif...")
    command = """convert -delay %f""" % delay
    if options.resize:
        command += """ -resize '%s'""" % options.resize

    command += """ *.jpg '%s'""" % output
    execute(command, options.verbose)

    # Cleaning tempdir
    print("Cleaning up tempdir...")
    shutil.rmtree(tempdir)
    print("Done :)")

if __name__ == "__main__":
    exit(main())

Ejemplos de uso:
video2gif -s 35:15 -d 20 -r 50% -o ~/descargas/montypython.gif Monty\ Python\ -\ Se\ Armo\ la\ Gorda\[Spanish.DvdRip\]\[Divx.Mp3\].avi

Changelog:

  • Versión 3 (en desarrollo)
    • Se agregó la posibilidad de usar filtros de pre y post-procesamiento
    • Se implementó el primer filtro: "dropframes" (el nombre puede variar en la versión final). Que permite modificar el FPS final para lograr ficheros finales más pequeños y mejorar la compatibilidad con navegadores web y otros reproductores que restringen la velocidad de reproducción.
  • Versión 2-2 (actual)
    • Arreglado un bug que, por falta de comprobación, asumía las rutas del fichero de destino como absolutas produciendo resultados impredecibles al usarse rutas relativas.
    • Arreglado un bug reportado por jjgomera por el que se mostraba incorrectamente la información del archivo gif a generar a pesar de que era bien calculada.
  • Versión 2
    • Arreglado un bug en el calculo de fps
    • Arreglado un bug de falta de escape de entrada del usuario
    • Arreglado un error que causaba la reproducción del audio del video a convertir
    • Agregadas las opciones:
      • --version Una trivialidad
      • -h, --help No sea tímido, usela
      • -o filename, --output-file=filename Permite especificar la ruta del fichero de salida
      • -r size, --resize=size Permite especificar el tamaño de la imagen final
      • -s TIME, --start=TIME Establece el inicio del rango a convertir
      • -d TIME, --duration=TIME Estable la duración del rango a convertir
      • -S FPS, --speed=FPS Modifica la velocidad de la animación final
      • -v, --verbose Queda bonito
  • Versión 1
    • Versión inicial. Solo permite especificar como argumento inicial el nombre del fichero de entrada.

Bugs conocidos:

  • No saca provecho de PIL
  • Si existe un archivo en la ruta de destino lo sobreescribe sin contemplaciones