Here it is. I didn't spend any time making this code nice, but you can just rip out the parts you need.
2008/5/8 Alistair Buxton <[EMAIL PROTECTED]>: > I have a full example of doing exactly this task using python to > render to a series of png images (which you can load into something > like adobe premier), or a raw RV24 file (which you can transcode under > linux using... transcode). Will post it as soon as I've dug it out and > tested it still works. Includes examples of using transcode too. > > 2008/5/8 Ian Mallett <[EMAIL PROTECTED]>: > > > > I figured out a way to do it in my program--Animation Shop Pro. It would > > still be cool to have examples of how to do this without Animation Shop. I > > was thinking ffmpeg or pil for doing so. I looked around, but couldn't > find > > anything. > > Thanks everyone, > > Ian > > > > > > -- > Alistair Buxton > [EMAIL PROTECTED] > -- Alistair Buxton [EMAIL PROTECTED]
#!/usr/bin/env python # Python OpenGL -> Video file # (c) 2008 Alistair Buxton <[EMAIL PROTECTED]> # Handy for doing procedural animations for compositing with other # videos in <your favourite video editing package.> import os, random, math from OpenGL.GL import * from OpenGL.GLU import * import pygame, pygame.image, pygame.key from pygame.locals import * from PIL import Image ###################################################################################### # render settings # 1 = best QUALITY = 16 # whether to actually write output files or just preview render_on = True # If you don't want to write separate png files, you can just dump the output # from glReadPixels() into one huge file and encode it with transcode: # transcode --use_rgb -i whatever.rv24 -x raw=RGB,null -y xvid4 -o output.xvid.avi -k -z -f 25 # (for xvid) # But beware that whatever.rv24 will be HUGE as it is uncompressed (not even RLE). # the size will be width*height*numframes*3 bytes, that's 31mb/sec for standard PAL video. # Also worth mentioning: RV24 export is RGB, but png export is RGBA - thus if you use # RV24 method, you will loose the alpha channel of your video. # render type # if true, write one big RV24 raw video file # if false, write a png sequence render_rv24 = False if render_on: # size of final render w = 720 h = 576 else: # size for preview w = 720 h = 576 # how many frames to render before exiting max_frames = 25 # framerate of rendered video fps = 25.0 if render_rv24: framefile = file("whatever.rv24", "wb") ###################################################################################### # the snowflake animation stuff flakes = [] class SnowFlake(object): def __init__(self): self.x = random.randrange(0,720) self.y = random.randrange(0,576) self.z = 3 + (random.randrange(3,20) / random.randrange(3,25)) self.dy = random.randrange(1,10) self.drift = random.randrange(1,100)/1000.0 self.rad = random.randrange(1,100)/100.0 def draw(self): glColor4f(1.0,1.0,1.0,1.0) if self.z < 0: return glBegin(GL_POLYGON) r = math.floor(self.z * 4) for i in range(int(r)): glVertex2f( self.x+(self.z*math.sin(2*math.pi*(i/r))), self.y+(self.z*math.cos(2*math.pi*(i/r))) ) glVertex2f( self.x, self.y+self.z ) glEnd() def update(self, ftime): self.rad += ((ftime*0.5)+self.drift) self.x += math.sin(self.rad) self.y -= 0.7*ftime*(40.0+self.dy)*self.z; if (self.y < -10): self.y = 586 if (self.x < -10): self.x = 730 if (self.x > 730): self.x = -10 # standard opengl stuff init/draw/update/resize def resize((width, height)): if height==0: height=1.0 glViewport(0, 0, width, height) glMatrixMode(GL_PROJECTION) glLoadIdentity() gluOrtho2D(0, 720, 0, 576) # gluOrtho2D(-(width/(2*height)), width/(2*height), 0, 1) glMatrixMode(GL_MODELVIEW) glLoadIdentity() def init(): glShadeModel(GL_SMOOTH) glClearColor(0.3,0.5,0.7,0.0) glClearDepth(1.0) glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ) glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST) glDisable(GL_DEPTH_TEST) for i in range(100): flakes.append(SnowFlake()) def update(ftime): for f in flakes: f.update(ftime) def draw(): glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ) glMatrixMode(GL_MODELVIEW) glLoadIdentity() glDisable(GL_TEXTURE_2D) for f in flakes: f.draw() ####################################################################################### # write a png file from GL framebuffer data def png_file_write(name, number, data): im = Image.frombuffer("RGBA", (720,576), data, "raw", "RGBA", 0, 0) fnumber = "%05d" % number im.save(name + fnumber + ".png") ###################################################################################### # main def main(): video_flags = OPENGL|DOUBLEBUF#|FULLSCREEN pygame.init() surface = pygame.display.set_mode((w,h), video_flags) pygame.key.set_repeat(100,30) resize((w,h)) init() frames = 0 done = 0 ftime = 0 oldticks = newticks = ticks = pygame.time.get_ticks() while not done: while 1: event = pygame.event.poll() if event.type == NOEVENT: break if event.type == KEYDOWN: if event.key == K_ESCAPE: done = 1 if event.type == QUIT: done = 1 draw() ########### This is where the output gets written ########### # NOTE: the GL_RGB / GL_RGBA difference if render_on == 1: if render_rv24: framefile.write(glReadPixels(0,0, w, h, GL_RGB, GL_UNSIGNED_BYTE)) else: png_file_write("snow", frames, glReadPixels( 0,0, w, h, GL_RGBA, GL_UNSIGNED_BYTE)) pygame.display.flip() newticks = pygame.time.get_ticks() # if rendering then set the frame time to fixed amount if render_on == 1: thistime = 1.0 / fps # change this to the desired framerate of your video! # else if previewing, use varying frame length to approximate actual output else: thistime = (newticks - oldticks) / 1000.0 oldticks = newticks ftime += thistime frames += 1 update(thistime) print "frame %d : ftime %f" % (frames,ftime) if (frames) > max_frames: if render_on == 1: break else: pass if __name__ == '__main__': main()