97 lines
3.0 KiB
Python
Executable File
97 lines
3.0 KiB
Python
Executable File
#!/usr/bin/env python
|
|
|
|
"""Video Thumbnail Generator
|
|
|
|
Usage:
|
|
./generator <video> <interval> <width> <height> <columns> <output>
|
|
./generator (-h | --help)
|
|
./generator --version
|
|
|
|
Options:
|
|
-h --help Show this screen.
|
|
--version Show version.
|
|
<video> Video filepath.
|
|
<interval> Interval em seconds between frames.
|
|
<width> Width of each thumbnail.
|
|
<height> Height of each thumbnail.
|
|
<columns> Total number of thumbnails per line.
|
|
<output> Output.
|
|
"""
|
|
|
|
from docopt import docopt
|
|
from moviepy.editor import VideoFileClip
|
|
from PIL import Image
|
|
from click import progressbar
|
|
import glob, os, random, shutil, math, tempfile
|
|
|
|
|
|
TMP_FRAMES_PATH = tempfile.mkstemp()[1]
|
|
|
|
def generate_video_thumbnail(args):
|
|
videoFileClip = VideoFileClip(args['<video>'])
|
|
interval = int(args['<interval>'])
|
|
size = (int(args['<width>']), int(args['<height>']))
|
|
outputPrefix = get_output_prefix()
|
|
generate_frames(videoFileClip, interval, outputPrefix, size)
|
|
|
|
columns = int(args['<columns>'])
|
|
output = args['<output>']
|
|
generate_sprite_from_frames(outputPrefix, columns, size, output)
|
|
|
|
def generate_frames(videoFileClip, interval, outputPrefix, size):
|
|
print "Extracting", int(videoFileClip.duration / interval), "frames"
|
|
frameCount = 0
|
|
with progressbar(range(0, int(videoFileClip.duration), interval)) as items:
|
|
for i in items:
|
|
extract_frame(videoFileClip, i, outputPrefix, size, frameCount)
|
|
frameCount += 1
|
|
print "Frames extracted."
|
|
|
|
def extract_frame(videoFileClip, moment, outputPrefix, size, frameCount):
|
|
output = outputPrefix + ("%05d.png" % frameCount)
|
|
videoFileClip.save_frame(output, t=int(moment))
|
|
resize_frame(output, size)
|
|
|
|
def resize_frame(filename, size):
|
|
image = Image.open(filename)
|
|
image = image.resize(size, Image.ANTIALIAS)
|
|
image.save(filename)
|
|
|
|
def generate_sprite_from_frames(framesPath, columns, size, output):
|
|
framesMap = sorted(glob.glob(framesPath + "*.png"))
|
|
|
|
masterWidth = size[0] * columns
|
|
masterHeight = size[1] * int(math.ceil(float(len(framesMap)) / columns))
|
|
|
|
line, column = 0, 0
|
|
|
|
finalImage = Image.new(mode='RGBA', size=(masterWidth, masterHeight), color=(0,0,0,0))
|
|
|
|
for filename in framesMap:
|
|
with Image.open(filename) as image:
|
|
|
|
locationX = size[0] * column
|
|
locationY = size[1] * line
|
|
|
|
finalImage.paste(image, (locationX, locationY))
|
|
|
|
column += 1
|
|
|
|
if column == columns:
|
|
line += 1
|
|
column = 0
|
|
|
|
finalImage.save(output, transparency=0)
|
|
shutil.rmtree(TMP_FRAMES_PATH, ignore_errors=True)
|
|
print "Saved!"
|
|
|
|
def get_output_prefix():
|
|
if not os.path.exists(TMP_FRAMES_PATH):
|
|
os.makedirs(TMP_FRAMES_PATH)
|
|
return TMP_FRAMES_PATH + ("%032x_" % random.getrandbits(128))
|
|
|
|
if __name__ == "__main__":
|
|
arguments = docopt(__doc__, version='0.0.2')
|
|
generate_video_thumbnail(arguments)
|
|
|