Use Python To Create A '.Gif' From Any Video

Animated images are really popular on the web right now, especially on sites like Tumblr and Reddit. So now and then you may see something in a tv show or movie you are watching and want to create a gif from it. Using python and 'images2gif' this is very easy and this is how.

Requirements:

This isn't needed, but I am going to assume you are running on Windows.

The Plan

The plan is very simple. We are going to use FFMpeg to generate a series of screenshots from the video and then we are going resize them and stitch them together using "images2gif".

Setup the batch file to grab screenshots

FFMpeg is what we will be using to grab the screenshots and that can be called with a few command line instructions to get what we want out of it. 

ffmpeg -i "Video.wmv" -ss 200 -f image2 -vframes 100 "Images//Frame%%03d.png"
  • -i : The video file we want to use
  • -ss : The start time we want to begin.
  • -f : Output type.
  • -vframes: The number of frames we want to grab
  • The last argument is the output directory and file name. The %%03d will be replace by the frame number so we have a sequential list.

Have a little play with this to get a feel for how it works and then put it into a batch file.

Calling the batch file from Python

Starting with a blank python file you will want to add code like this:

import os

#Create the screengrabs
os.system("GrabScreenshots.bat ")

So that will write out the screenshots into a folder you have set in step one.

 Using the images in python

Once the images are created you will want to load them like this

from PIL import Image

#Get the file names
file_names = sorted((fn for fn in os.listdir('./Images') if fn.endswith('.png')))
print file_names

#Open the files
print 'Opening the images'
images = [Image.open('Images/' + fn) for fn in file_names]

Resizing the images

This can be done using standard PIL functions like so:

#Resize
baseSize = images[0].size
minheight = 192
height = baseSize[1]
scale = float(height)/float(minheight)
print "Scale: " + str(scale)

print "Old Size: " + str(baseSize)
baseSize = ( int(baseSize[0] /scale) , int(baseSize[1] /scale) ) 

print 'Resizing'
size = baseSize;
for im in images:
    im.thumbnail(size, Image.ANTIALIAS)

Writing out the .gif file

This is where we use the "images2gif" to create a gif from our resized images.

from images2gif import writeGif
from time import time

#Set to 24FPS
runningtime = 0.0416
print runningtime

print 'Saving'
filename = "Gif/Gif" 
writeGif(filename   + str(int(time())) + ".gif", images, duration=runningtime, dither=1, nq = 1)

I have set 0.0416 as the frame time as that is the time of one frame at 24fps. A lot of this could be controlled on input, or through a simple interface but that is a task for the reader.

This last bit of code will write out the .gif file for you to use. I would recommend playing with the settings and the size of the output image to find the desired quality and file size.

FINAL CODE

Here is all that code together with some input controls to make it easier to hook up and some cleanup at the end.

Python:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
from images2gif import writeGif
from PIL import Image
from time import time
import os
import sys

#Part 1 -------------------------------

#Create the screengrabs
BatFileString = "GS.bat"

#Set Filename
BatFileString += " AD5.wmv"

#Set Start frame
BatFileString += " 75"

#Set Desired Number of Frames
BatFileString += " 10"

print BatFileString
os.system(BatFileString)

# Part 2 -------------------------------

#Get the file names
file_names = sorted((fn for fn in os.listdir('./Images') if fn.endswith('.png')))
print file_names

#Open the files
print 'Opening the images'
images    = [Image.open('Images/' + fn) for fn in file_names]

#Resize
baseSize  = images[0].size
minheight = 192
height    = baseSize[1]
scale     = float(height)/float(minheight)
print "Scale: " + str(scale)

print "Old Size: " + str(baseSize)
baseSize  = ( int(baseSize[0] /scale) , int(baseSize[1] /scale) ) 

print 'Resizing'
size = baseSize;
for im in images:
	im.thumbnail(size, Image.ANTIALIAS)

#Part 3-------------------------------
	
#Set to 24FPS
runningtime = 0.0416
print runningtime
	
print 'Saving'
filename = "Gif/Gif" 
writeGif(filename + str(int(time())) + ".gif", images, duration=runningtime, dither=1, nq = 1)

#Clean Up -----------------------------

#Remove generated images
filelist = [ f for f in os.listdir('./Images') if f.endswith(".png") ]
for f in filelist:
    os.remove('./Images/' + f)

Bat File:

ffmpeg -i %1 -ss %2 -f image2 -vframes %3 "Images//outd%%03d.png"

 

And here is a link of it all together: DOWNLOAD.

Next time I look at python I will show you how this can be combined to make easily make a .gif from Youtube and other web video sites and automatically upload them to Twitter or Tumblr.