#!/usr/bin/env python # # Ffmpeg video thumbnailer # generates a thumbnail from a video file # # requires ffmpeg, imagemagick and filmholes.png from totem # # Use: # ffmpeg-video-thumbnailer [-s geometry] input output # # geometry = thumbnail geometry, eg. "128" or "128x96" # input = video file name # output = thumbnail file name # # Author: JM. Philippe - http://philipjm.free.fr/blog/ # Public domain import sys, os, re, commands, urllib # the ffmpeg command to be executed (extracts 1st video image) FfmpegCmd = "ffmpeg -i '%s' -vcodec png -vframes 1 -s %s -f rawvideo -y '%s'" # the imagemagick command (composes images) MagickCmd = "composite -compose atop -geometry %s %s %s %s" # film holes to be overlaid (from totem install) FilmHoles = '/usr/share/totem/filmholes.png' HoleHeight = 35 # film holes image dimensions #HoleWidth = 9 # log file for debugging LogFile = os.path.expanduser('~/ffmpeg-thumbnailer.log') WriteLog = False # True to write log file ################## ################## def log(Text): """ writes a log file for debugging """ if WriteLog: FileId = open(LogFile, 'a') FileId.write(str(Text) + '\n') FileId.close() ################## ################## def dims(FileName): """ gets video dimensions """ Result = commands.getoutput("ffmpeg -i '%s'" % FileName) #log(Result) Orient = re.findall(r'(\d+)x(\d+)', Result) #log(Orient) if len(Orient): return map(int, Orient[0]) else: return 0, 0 ################## ################## def film_holes(FileName, Height): """ adds film holes on the left side """ Start = 0 while Start < Height: # repeat pattern vertically Position = '+%d+%d' % (0, Start) commands.getoutput(MagickCmd % (Position, FilmHoles, FileName, FileName)) Start += HoleHeight ################## # get parameters if sys.argv[1] == "-s": ThumbSize, Input, Output = sys.argv[2:5] else: ThumbSize = "128" Input, Output = sys.argv[1:3] log('********') log(str(sys.argv)) ################## # URL's to pathnames Input = urllib.url2pathname(Input.replace('file://', '')) Output = urllib.url2pathname(Output.replace('file://', '')) ################## # thumbnail size if 'x' not in ThumbSize: ImgWidth, ImgHeight = dims(Input) ThumbWidth = int(ThumbSize) if ImgWidth >= ImgHeight: ThumbHeight = ThumbWidth * ImgHeight / ImgWidth else: ThumbHeight = ThumbWidth ThumbWidth = ThumbHeight * ImgWidth / ImgHeight ThumbSize = '%dx%d' % (ThumbWidth, ThumbHeight) ################## # make thumbnail Result = commands.getoutput(FfmpegCmd % (Input, ThumbSize, Output)) film_holes(Output, ThumbHeight) commands.getoutput("mogrify -flop " + Output) # flip left to right film_holes(Output, ThumbHeight) commands.getoutput("mogrify -flop " + Output) ################## # write log (continued) log(Input) log('%dx%d' % (ImgWidth, ImgHeight)) log(Output) log(FfmpegCmd % (Input, ThumbSize, Output)) log(Result) log('')