Py淡

Python, Python, Python! In the spirit of "import antigravity"

How to record the panda3d app screen as avi file using ffmpeg

# It's better to use base.movie() instead of this code. see below

Here is an example script I wrote today. To run this on your PC, at least the model in the script needs to be replaced with your egg file.

Panda3d has a nice facility to save the screenshot of the app provided by base.win.saveScreenshot() but that gives us an image file not a video. I noticed that there is also getScreenshot method in the ShowBase class which turned out to be quite useful for getting the texture buffer for ffmpeg. Because Panda3d actually comes with ffmpeg which is used for movie texure loading (Playing MPG and AVI files - Panda3D Manual), there might be a better way to do the same but I could not figure out (yes, use base.movie below...).

tex.getRamImage() seems to give me a pointer to the memory of this texture. So, I had to call getData() to get the actual buffer strings. The buffer seems up-side down and with these parameters to ffmpeg, the video created was not so good. I will have to tweek parameters more...


PS

I found someone mentioning on base.movie() on the forum (Panda3D • View topic - Using Panda3d To render output to video). This is probably a better way to do this. The API for base.movie is found at Panda3D API Reference.

just call self.movie() within ShowBase class to start recording. e.g., self.accept("r", self.OnRec) and in the OnRec, self.movie(duration=10) for 10 s video.

movie(self, namePrefix = 'movie', duration = 1.0, fps = 30,
format = 'png', sd = 4, source = None)

Spawn a task to capture a movie using the screenshot function.

  • namePrefix will be used to form output file names (can include

path information (e.g. '/i/beta/frames/myMovie')

  • duration is the length of the movie in seconds
  • fps is the frame rate of the resulting movie
  • format specifies output file format (e.g. png, bmp)
  • sd specifies number of significant digits for frame count in the

output file name (e.g. if sd = 4, movie_0001.png)

  • source is the Window, Buffer, DisplayRegion, or Texture from which

to save the resulting images. The default is the main window.

base.movie creates an image sequence, one image per frame (at fps you specify). default is 1 s video at 30.0 fps with file name like movie_0001.png etc. They can be put together as avi using ffmpeg later like this.

ffmpeg -y -framerate 30 -f image2 -i movie_%04d.png -q:a 2 -q:v 4 -vcodec wmv2 -acodec wmav2 out.avi

Above command will produce powerpoint friendly avi file. I modified from FFMPEG settings for PowerPoint Video Playback - esonderegger.


Although calling movie() slows down the app while recording, the resulting video is actually fine (smooth and nice).