
Pymedia is a python wrapper around the ffmpeg C audio/video library. It is sometimes useful to compose a video from a series of graphic files or to decompose a video into a series of graphic files. Pymedia is one tool to do this.
There is a sample program on the pymedia site that claims to create a video from a series of separate graphic files. However, it contains a bug. Besides, it may not be as clearly written as it could be. Here’s my rewrite of that code.
I have hard-coded in the function getFiles() that is a routine to find all the graphic files I want in the movie as sort them. If you reuse this script, you will need to write your own version of this.
import sys, os, time import pymedia.video.vcodec as vcodec import pygame def makeVideo(files, outFile, outCodec='mpeg1video'): pygame.init() fw = open( outFile, 'wb' ) if (fw == None) : print("Cannot open file " + outFile) return if outCodec == 'mpeg1video' : bitrate= 2700000 else: bitrate= 9800000 start = time.time() enc = None frame = 1 for fpath in files : img = pygame.image.load( fpath ) # Init once, but need details from an image if enc == None : params= { 'type': 0, 'gop_size': 12, 'frame_rate_base': 30, # 125, 'max_b_frames': 0, 'height': img.get_height(), 'width': img.get_width(), 'frame_rate': 90, # 2997, 'deinterlace': 0, 'bitrate': bitrate, 'id': vcodec.getCodecID( outCodec ) } enc = vcodec.Encoder( params ) # Create VFrame bmpFrame= vcodec.VFrame( vcodec.formats.PIX_FMT_RGB24, img.get_size(), # Covert image to 24bit RGB (pygame.image.tostring(img, "RGB"), None, None) ) # Convert to YUV, then codec d = enc.encode(bmpFrame.convert(vcodec.formats.PIX_FMT_YUV420P)) fw.write(d.data) frame += 1 if frame % 10 == 0 : sys.stdout.write("Progress: %05d/%05d\r" % (frame, len(files))) sys.stdout.flush() fw.close() pygame.quit() print '\nDone\n%d frames written in %.2f secs( %.2f fps )' \ % (frame, time.time() - start, float(frame) / (time.time()- start) ) def getFiles () : # Change this function to get files in the order you want them files = [] base_dir = 'M:/backups/hosted_sites/taskboy/public_html/spy' for f in os.listdir(base_dir) : if f.startswith("20") and f.endswith("png") : files.append(os.path.join(base_dir, f)) files.sort() return files if __name__== '__main__': files = getFiles() makeVideo(files, "out.mpg")
The core of this code is in the makeVideo() function. Pygame is used to load the graphic files into a format that pymedia’s VFrame object can accept. That object is converted into a YUV format suitable for MPEG encoding.
You can control the speed of the images by setting the frame_rate in the params dictionary. Lower numbers are slower than bigger numbers. I leave as an exercise for the reader a refinement that allows for more fine-grained control of the MPEG encoding.