VideoFrameReader
I'm enamored with the movie capabilities of my Canon Digital Elph. While I love taking pictures, sometimes I don't just want stills from an event, but would prefer to capture the whole thing in the form of a movie. As a result, I take short movies with it all the time.
Recently, I wanted to extract some frames from one of these .avi movies. Sure, there are a plethora of tools I could download that would do this for me, but what fun is that when I could write one myself? :)
So, I wrote a small app called ExtractFrames that extracts all the frames from a video into individual .jpg files, and I've made the source available for download (standard disclaimers apply). To use the tool, simply drag-and-drop the video(s) you want to process onto the app in Explorer, or from the command line specify the video(s) you want processed as separate arguments.
The Main method of ExtractFrames is a short wrapper around a class I wrote called VideoFrameReader:
using (VideoFrameReader reader = new VideoFrameReader(path))
{
Console.WriteLine("Processing " + path + "...");
// Create a directory to store the frames
string dirPath = path + "_frames\\";
Directory.CreateDirectory(dirPath);
// Read each frame and save it into the directory
for (int frameNumber = 0; frameNumber < reader.NumberOfFrames; frameNumber++)
{
using (Bitmap frame = reader.GetFrame(frameNumber))
{
const long quality = 100;
Console.WriteLine("\tSaving frame {0}/{1}", frameNumber, reader.NumberOfFrames);
ImageUtilities.SaveImage(frame, dirPath + frameNumber + ".jpg", quality);
}
}
}
VideoFrameReader is, in turn, a wrapper around the MediaDet COM object, accessed through COM interop (if you want to use VideoFrameReader in your own apps, make sure to add a COM reference to the Dexter 1.0 type library, or just use the existing Interop.DexterLib.dll included in the download).
MediaDet works with most .avi and .wmv files, and I believe some .mpg files, which means VideoFrameReader will do the same. Unfortunately, it doesn't currently work with .dvr-ms files, so this class can't be used to extract stills from recorded television unless you first transcode the .dvr-ms to another supported format.
Enjoy!
Comments
Anonymous
May 03, 2006
PingBack from http://blog.dotmark.net/?p=431Anonymous
December 15, 2007
Hey, Stephen, I am working on a video add-in for Media Center and hit a snag with Dexterlib; could you lend a hand? How do I give it a strong name so I can use it with my addin? My add-in is going into the GAC. Thanks! PS. Love your in-depth (and cool!) articlesAnonymous
December 16, 2007
The comment has been removedAnonymous
December 20, 2007
Stephen- There appears to be a bug under Vista using Dexterlib. Your sample VideoFrameReader suffers from the same issue that my own code does namely that the 1st image from an avi file is always returned regardless of the requested time. Any help would be greatly appreciated. jeremywise@readingsuccesslab.comAnonymous
March 13, 2008
Is there anyway to make this work for dvr-ms files? Thanks.Anonymous
April 27, 2008
Stephen, I have been using code very similar to yours found in the VideoFrameReader.CS GetFrameSize function. This has worked fine under XP but now under Vista & Visual Studio 2008 (.NET 2.0 still) I am getting an exception when the following executes: VIDEOINFOHEADER videoInfo = (VIDEOINFOHEADER)Marshal.PtrToStructure( mediaType.pbFormat, typeof(VIDEOINFOHEADER)); The exception is: "Attempted to read or write protected memory. This is often an indication that other memory is corrupt." System.Exception {System.AccessViolationException} Any idea what may be causing this and how this can be resolved? Thanks.Anonymous
September 28, 2008
It's really helpful.... Thanks