diff --git a/home/bin/video2gif b/home/bin/video2gif new file mode 100755 index 0000000..829e25f --- /dev/null +++ b/home/bin/video2gif @@ -0,0 +1,128 @@ +#!/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