Previous | EuroHacker Magazine, issue #1 | Next |
Written by: guess who?
A while ago I needed to sample a pretty vast file collection, belonging to a dude I know on the Net. The files were large movie files and so I would have to download all of them just to check out if I liked 'em. This annoyed me so I thought about what to do. The idea I came up with was using mplayer to rip stills out of each file, so I could easily check out if it was worth downloading. In hindsight I could have downloaded chunks of each file using HTTP's Range header and then done mplayer -idx on them but I don't know if that would work plus that's an unnecessary waste of bandwidth. This solution only requires me to run the script on the dude's box.
It's worked so far, but it wouldn't surprise me if it craps out. YMMV. Also, this is my first and only Python script at this point, so don't harass me.
#!/usr/bin/python import os, sys, commands, re, string, glob def usage(): print 'pr0ngallery - A movie still gallery generator' print 'Usage: pr0ngallery <files>' def make_stills(filename, dir, interval, num_stills): os.chdir(dir) i=1 while i <= num_stills: # grab a few frames # I've found that to avoid black frames, cluttered frames and other crap, generally you need to grab the fourth frame # -ss seek to second # -frames number of frames to grab (you need to increment the desired number by one, oddly enough) # -vo video out # -ao audio out # -z png compression level os.system('mplayer -ss %d -frames 5 -vo png -z 1 -ao null "%s" 2>/dev/null >/dev/null' % (i*interval, filename)) #print "num_stills: %d" % num_stills print 'Creating still %d for "%s"' % (i, filename) try: try: os.rename('00000004.png', 'still_%06d.png' % i) # may fail, I've found except OSError: print 'Error, skipping' continue finally: # delete all the crap d=glob.glob('*.png') for curr in d: if not re.compile('^still.+$').match(curr): os.unlink(curr) i+=1 os.chdir('..') def get_movie_info(filename): buffer=commands.getoutput('mplayer -vo null -ao null -frames 0 -identify "%s"' % filename) m=re.compile(r'.*?ID_VIDEO_FORMAT=([^\n]+).*?ID_VIDEO_BITRATE=([^\n]+).*?ID_VIDEO_WIDTH=([^\n]+).*?ID_VIDEO_HEIGHT=([^\n]+).*?ID_VIDEO_FPS=([^\n]+).*?ID_VIDEO_ASPECT=([^\n]+).*?ID_AUDIO_CODEC=([^\n]+).*?ID_AUDIO_FORMAT=([^\n]+).*?ID_AUDIO_BITRATE=([^\n]+).*?ID_AUDIO_RATE=([^\n]+).*?ID_AUDIO_NCH=([^\n]+).*?ID_LENGTH=([^\n]+)', re.S).match(buffer) if not m: print 'Unexpected error!' sys.exit(-1) t=m.groups() info={'vformat': t[0], 'vbitrate': int(t[1]), 'vwidth': int(t[2]), 'vheight': int(t[3]), 'vfps': float(t[4]), 'vaspect': float(t[5]), 'acodec': t[6], 'aformat': int(t[7]), 'abitrate': int(t[8]), 'arate': int(t[9]), 'anch': int(t[10]), 'length': int(t[11])} return info if __name__ == '__main__': # TODO: this shouldn't be hardcoded base_dir='gallery' if len(sys.argv) < 2: usage() sys.exit(-1) # get curr dir launch_dir=os.getcwd() # make the dir where the galleries will be made # abort if it already exists if (os.access(base_dir, os.F_OK)): print '"%s" already exists, aborting' % base_dir sys.exit(-1) # make the dir os.mkdir(base_dir) # change into it os.chdir(base_dir) i=1 # loop thru all the filenames given to us for filename in sys.argv[1:]: if not os.path.isabs(filename): filename='%s/%s' % (launch_dir, filename) num_stills=200 # TODO: shouldn't be hardcoded movie_info=get_movie_info(filename) #print movie_info if movie_info['length'] == 0: print 'Zero-length movie, skipping...' continue elif movie_info['length'] <= 10: num_stills=1 # determine number of stills we need # there should be at least 10 seconds between stills elif float(movie_info['length'])/float(num_stills) < 10: num_stills=int(float(movie_info['length'])/10) interval=int(float(movie_info['length'])/num_stills) print 'Making %d stills for movie "%s"' % (num_stills, filename) print 'Using an interval of %d seconds for the stills' % interval print 'Length of movie: %d seconds' % movie_info['length'] dir="stills_%09d" % i os.mkdir('%s' % dir) make_stills(filename, dir, interval, num_stills) i+=1