#!/usr/bin/env python3

"""video2gif: convert a video into a GIF image using ffmpeg.

Usage: video2gif input_video.mp4
       # produces video2gif.gif output of the first 5 seconds from the video

Command line options and their defaults:

    --time, -t = 00:00:00
        The time offset to seek into the video before starting the GIF,
        default is "00:00:00", this value can be an integer number of seconds too
        like "190"

    --length, -l = 5
        The number of seconds to convert into a GIF, default is 5, usually 10
        or fewer is a good length for a GIF.

    --width, -w = 480
        The max width for the output GIF to be scaled down to. 480 is a good
        default, smaller or bigger and you'll trade off file size for resolution.

    --fps = 10
        Set the FPS setting in ffmpeg for the GIF, 10 is a good default.

    --output, -o = video2gif.gif
        Name a different output file for the GIF image.

--Kirsle
https://www.kirsle.net/
"""

import argparse
import sys
import os
import os.path
import subprocess
import tempfile

# Test for required programs.
if subprocess.call("which ffmpeg >/dev/null 2>&1", shell=True) != 0:
    print("You require ffmpeg to use this script, install the ffmpeg package and try again")
    sys.exit(1)

def main():
    # Command line options for this script. Run `video2gif --help` for automatic
    # documentation.
    parser = argparse.ArgumentParser(description="video2gif: convert a video into a GIF image")
    parser.add_argument("--time", "-t",
        help="Time skip in the video, in 00:00:00 format or as an integer number of seconds, default is 0.",
        type=str,
        default="00:00:00",
    )
    parser.add_argument("--length", "-l",
        help="Number of seconds of video to go into the GIF, beginning at the --time option."
            "Usually use a value <= 10 seconds. Default is 5.",
        type=str,
        default="5",
    )
    parser.add_argument("--fps",
        help="Set a custom FPS value for the output GIF, default is 10",
        type=str,
        default="10",
    )
    parser.add_argument("--width", "-w",
        help="Set a target width for the output GIF image, default is 480",
        type=str,
        default="480",
    )
    parser.add_argument("--output", "-o",
        help="Output file name, default is video2gif.gif",
        type=str,
        default="video2gif.gif",
    )
    parser.add_argument("input",
        help="Input file, a video to convert into a GIF",
    )

    # Parse the command line arguments.
    args = parser.parse_args()

    # We need a temporary file to hold the video palette.
    palette_fh = tempfile.NamedTemporaryFile(
        suffix=".png",
        delete=False,
    )
    palette_file = palette_fh.name  # file path like "/tmp/tmpabccdd.png"
    palette_fh.close()  # we're not the ones writing to it so close the file

    print("Temporary palette file is:", palette_file)

    # 1. create the palette from the original video file
    subprocess.call([
        "ffmpeg",
        "-y",  # yes, force overwrite the named temporary file
        "-ss", args.time,
        "-t", args.length,
        "-i", args.input,
        "-vf", "fps={fps},scale={width}:-1:flags=lanczos,palettegen".format(
            fps=args.fps,
            width=args.width,
        ),
        palette_file,
    ])

    # 2. create the GIF from the original video file and the temp palette.
    subprocess.call([
        "ffmpeg",
        "-ss", args.time,
        "-t", args.length,
        "-i", args.input,
        "-i", palette_file,
        "-filter_complex", "fps={fps},scale={width}:-1:flags=lanczos[x];[x][1:v]paletteuse".format(
            fps=args.fps,
            width=args.width,
        ),
        args.output,
    ])

    # clean up the temporary palette file
    os.unlink(palette_file)

# the following condition is only true when this python script is being run
# as a script directly (not when imported as a module in another program)
if __name__ == "__main__":
    main()

# vim:expandtab