From: Jim T. <jt...@mi...> - 2009-10-19 15:23:17
|
Here is a pretty workable solution under Linux. I had found some information that made me think I could get this to work on Windows (see the comments below) but I never got around to finishing and releasing this. It is supposed to be part of the next release of this: http://www.missioncognition.net/wp-content/uploads/2009/06/VisualPyODE_v0.1_src.tar.gz and you can get copies of the license files there. In short you can either let the user select the window, or you can pass the name of the window. I could not find any saved code that worked using the window name but I'm sure that I was able to get this to work using whatever name the visual window defaults to. I think I was also able to change the title of the visual window and use that as well. Right now my system is broken for running Visual so I can't verify anything at the moment. But if you are interested, go to http://www.missioncognition.net/visualpyode/ to see a video I made using the code below (or something very closely resembling it). You will notice the scene is panning, I also have code which captures the user view actions and then can restore them later as a playback. That way I could create a real-time pan despite the fact that the screen capturing is a much slower process. If anybody is interested in that, holler and I'll post it here as well. One of these days I might get around to doing an update of visualPyODE and these will be included. Unfortunately I have very little feedback on that project so I don't know if there is anybody using it and it is on my back burner as well -- so obviously it is not my top priority. JT Python code below: """ videograb.py A module to perform video capture of an x-windows window. Written By: James Thomas Email: jt...@mi... Web: http://missioncognition.net/ Copyright 2009 This library is free software; you can redistribute it and/or modify it under the terms of EITHER: (1) The GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. The text of the GNU Lesser General Public License is included with this library in the file LICENSE. (2) The BSD-style license that is included with this library in the file LICENSE-BSD. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files LICENSE and LICENSE-BSD for more details. """ import subprocess import re import tempfile import shutil # Note for possible MS Windows implementation. Apparently the window can be obtained as follows: # import win32gui # window = win32gui.FindWindow ( None, WindowTitle ) class VideoCaptureXWindows: """Capture a mpeg video from an X-Windows display. Requires xwininfo, import, and convert utilities and the mpeg generation library to be installed.""" def __init__(self, WindowTitle=None): """Setup for recording an mpeg video. The window title is not specified then the user will be prompted to click the desired window.""" # Initialize variables self._windowID = None self._frameCounter = 0 # Generate unique temporary directory to store the captures self._fileLocation = tempfile.mkdtemp() # Setup window ID determination based on whether a window title was specified or not if WindowTitle is None: # Get the x-windows information without parameters so the user will have to select a window. command = ['xwininfo'] # Print a message telling the user to click a window # It would be cool if we could come up with a better way to notify the user # Perhaps some text overlay over the entire desktop. print 'Click the window you want to record' # Set the regular expression string for extracting the window ID from the results reString = 'xwininfo: Window id: ([0-9x]*)' else: # Get the x-windows information about the window that has the specified title command = ['xwininfo', '-tree', '-root', '| grep', WindowTitle] # Set the regular expression string for extracting the window ID from the results reString = '([0-9x]*) "%s"' % title # Run the command proc = subprocess.Popen(command, stdout=subprocess.PIPE) # Get the results. Blocks until the results are ready. (resultsText, errText) = proc.communicate() # Check for error status if proc.returncode: raise subprocess.CalledProcessError(proc.returncode, cmdText) # Extract the window id from the results string. result = re.findall('xwininfo: Window id: ([0-9x]*)', resultsText) if result: self._windowID = result[0] def CaptureFrame(self): """Capture a still image of the current display in the temp directory.""" if self._windowID: command = ['import', '-window', self._windowID, '%s/capture-%06d.miff' % (self._fileLocation, self._frameCounter)] subprocess.check_call(command) # Increment the frame counter self._frameCounter += 1 def EncodeMovie(self, FrameTiming, Filename): """Generate an mpeg movie from the sequence of frames captured. FrameTiming is the time spacing between frames specified in seconds as a floating point number. Due to the limitation of the convert utility the timing resolution is limited to 10 milliseconds. Unfortunately that means typical video frame rates are limited to 25, 33 1/3, or 50 frames per second. If you want real-time to be preserved make sure you animation frame spacing matches.""" if self._frameCounter > 0: delay = int(100 * FrameTiming) # Add the .mpg extension if it was not provided. if Filename.find('.mpg') < 0: Filename += '.mpg' # Use convert to make the movie. command = ['convert', '-delay', '%d' % delay, '%s/*.miff' % self._fileLocation, Filename] subprocess.check_call(command) def DeleteCapturedFrames(self): """Delete the temp directory holding the sequence of captured frames.""" shutil.rmtree(self._fileLocation) |