Take the 2-minute tour ×

I have a .Net application which renders graphics using GDI+ and/or XNA and I want to record the frames directly into a video (preferably an AVI, where I can include a codec like xvid etc). I've tried many of the solutions out there, and run into show stoppers with all of them.

All of the FFMPeg based libs seem to be dedicated to transcoding an existing stream, not so much generating a new one from frames.

There is a .Net lib called Splicer on codeplex, but from what I can tell it is more geared towards building a "slideshow" because it takes each frame and stores it on the HD. The directshow solutions behave the same way.

Then there is the AVIFile wrapper, which is almost exactly what I need. The only problem is that when you start a new encoding it pops up (and sometimes UNDER!?) a dialog box. The dialog isn't a problem for normal use, but I also need this to run as a service, so mandatory UI is obviously a show stopper.

Anyone know of another option that is relatively .Net friendly, or am I just asking too much?

share|improve this question
add comment

4 Answers

up vote 1 down vote accepted

I don't know which AVIFile wrapper you're using, but I believe AviFile is probably calling AVISaveOptions to get an initialized AVICOMPRESSOPTIONS struct. You can just initialize AVICOMPRESSOPTIONS yourself. Most members in AVICOMPRESSOPTIONS are pretty easy. lpParms and cbParms contain a block (cbParms = length of block) of binary codec configuration data. You can get this data calling ICGetState.

It should be a fairly simple change to your native AVIFile and your wrapper should still work.

Have a look at this sample for how to init AVICOMPRESSOPTIONS.

share|improve this answer
add comment

Check out this question on the XNA forums for some insight and considerations if you want to do this in XNA. In particular, this answer by the ZMan:

"There's nothing in XNA to help you here - you need to be looking at other windows APIs. You would use XNA to capture the back buffer and then save each frame out but there's many things to be concerned about. Pulling each frame from the back buffer instantly creates some latency, compressing the images (if you choose to compress on the fly) is CPU heavy, saving to a file adds latency.

DirectShow is one API you can use to do the compression - there's many others. Off/MP4 etc. SOund recording has DSound and I think DShow can use DSound to grab the audio output too. They are fairly specialist APIs so you might want to seek out other forums."

share|improve this answer
I already have the capture from XNA(framebuffer) working, I just need something to encode the video. I think I'll end up sticking with AVIFile but making the Changes that Ben Schwehn suggested above. –  Brook Jun 11 '09 at 19:51
add comment

Actually, Splicer can produce smooth videos from multiple still frames, you just need to ensure that you set the apropriate clip offset and clip end parameters when you call ITrack.AddFrame. In my program I use:

videoTrack.AddImage(buffer, 0, 1f / FramesPerSecond);

where videoTrack comes from:

timeline = new DefaultTimeline(framesPerSecond);
videoGroup = timeline.AddVideoGroup("main", framesPerSecond, 24, width, height);
videoTrack = videoGroup.AddTrack();

in the constructor of my video exporter for a simulation program I'm working on.

share|improve this answer
Thanks for the reference... For unknown reasons, I had no success getting AVIFile to work at all; whereas Splicer (and in turn DirectShow) look like they will do the trick. –  harpo Jan 21 '11 at 21:16
add comment

If you still want to use ffmpeg, then write the frames to disk and use something like

ffmpeg -f image2 -i foo-%03d.jpeg -r 12 -s WxH foo.avi

The syntax foo-%03d.jpeg specifies to use a decimal number composed of three digits padded with zeroes to express the sequence number. It is the same syntax supported by the C printf function, but only formats accepting a normal integer are suitable.

-r 12 specifies 12 frames per second

-s WxH should specify width & height

This is from the ffmpeg documentation.

share|improve this answer
add comment

Your Answer


