Share via


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!

 

ExtractFrames.zip

Comments

  • Anonymous
    May 03, 2006
    PingBack from http://blog.dotmark.net/?p=431

  • Anonymous
    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!) articles

  • Anonymous
    December 16, 2007
    The comment has been removed

  • Anonymous
    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.com

  • Anonymous
    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