Introduction
This article presents a class library for capturing audio and video to AVI files in .NET. Some of the features of this library:
- List and select hardware devices
- Access to common audio and video settings (e.g. frame rate, size)
- Support audio and video compression codecs
- Support video preview
- Support TV tuners
- Support crossbars and audio mixers
- Retrieve device capabilities
- Show property pages exposed by drivers
- MSDN-style documentation included
Using the Code
The Capture class is the core of this library. Here is a simple example:
using DirectX.Capture
Capture capture = new Capture( Filters.VideoInputDevices[0],
Filters.AudioInputDevices[0] );
capture.Start();
capture.Stop();
Remember to add a reference in your project to DirectX.Capture.dll. This DLL requires DShowNET.dll, so make sure they are both in the same directory. Once you add the reference, Visual Studio .NET should take care of the copying for you.
This example will capture video and audio using the first video and audio devices installed on the system. To capture video only, pass a null as the second parameter to the constructor.
The class is initialized to a valid temporary file in the Windows temp folder. To capture to a different file, set the Capture.Filename property before you begin capturing.
A Second Example
This next example shows how to change video and audio settings. Properties such as Capture.FrameRate and Capture.AudioSampleSize allow you to programmatically adjust the capture. Use Capture.VideoCaps and Capture.AudioCaps to determine valid values for these properties.
Capture capture = new Capture( Filters.VideoInputDevices[0],
Filters.AudioInputDevices[1] );
capture.VideoCompressor = Filters.VideoCompressors[0];
capture.AudioCompressor = Filters.AudioCompressors[0];
capture.FrameRate = 29.997;
capture.FrameSize = new Size( 640, 480 );
capture.AudioSamplingRate = 44100;
capture.AudioSampleSize = 16;
capture.AudioChannels = 1;
capture.Filename = "C:\MyVideo.avi";
capture.Start();
...
capture.Stop();
The example above also shows the use of video and audio compressors. In most cases, you will want to use compressors. Uncompressed video can easily consume over 1GB of disk space per minute. Whenever possible, set the Capture.VideoCompressor and Capture.AudioCompressor properties as early as possible. Changing them requires the internal filter graph to be rebuilt which often causes most of the other properties to be reset to default values.
Behind the Scenes
This project uses 100% DirectShow to capture video. Once a capture is started, DirectShow spawns another thread and handles retrieving/moving all the video and audio data itself. That means you should be able to capture at the same speed and quality as an application written in C.
DirectShow is implemented as a set of COM components and we use .NET Interop to access them. The pioneering work on this was done by NETMaster with the DShowNET project. This Capture library uses DShowNET for the interop layer with only a few extensions. This is the DShowNET.dll mentioned earlier.
Sitting on top of all of this is the Capture class library. The center of any DirectShow app is the filter graph and the filter graph manager. For a good overview, see The Filter Graph and Its Components from the MSDN.
The Least Work Possible
The library tries at all times to do the least amount of work possible. The problem is: DirectShow is very flexible, but has few firm standards for driver developers and I have limited hardware to test with. As a result, the class tries to avoid doing any work that may not be necessary, hopefully avoiding potential incompatibilities in the process.
One example is video preview. You can start and stop preview with:
capture.PreviewWindow = myPanelControl;
capture.PreviewWindow = null;
Hopefully this is simple to use. Internally, DirectShow does a lot of work: add required upstream filters for WDM devices, search for preview pins, use the Overlay Manager for video ports (hardware overlays), insert SmartTee filters when a separate preview pin is not available and more. Instead of rendering the preview stream as soon as the class is created, the class waits until the PreviewWindow property is set.
For developers who don't need preview, none of this work will ever be done. That means your application is more likely to work on a wider range of hardware. For developers that do need preview, this makes it easier to locate the cause of the problem and fix it or handle it gracefully.
Performance Tips
Many of the properties on the Capture class are retrieved directly from the underlying DirectShow COM components. If you need to refer to the property repeatedly in a block of code, take a copy of the value and use your copy.
for ( int c = 0; c < 32; c++ )
{
if ( c == capture.AudioSampleSize )
MessageBox.Show( "Found!" );
}
int x = capture.AudioSampleSize;
for ( int c = 0; c < 32; c++ )
{
if ( c == x )
MessageBox.Show( "Found!" );
}
Why doesn't the class simply cache the value internally? We don't know when the filter (device driver) will change this value, so we have to retrieve the value every time. This means you will always get the real value of the property.
Credits
The DirectShow interop layer was developed by NETMaster in the DShowNET project. The MDSN-style documentation was generated from the source code using nDoc.
Troubleshooting
I have tested this with an Asus v7700 (NVidia GeForce2, reference drivers) and my onboard sound card. I can't guarantee any other hardware will work. However, I expect most video capture cards and sound cards will work. You may have trouble with TV Tuner cards and DV devices (Firewire camcorders) though they should be solvable.
Try the AMCap sample from the DirectX SDK (DX9\Samples\C++\DirectShow\Bin\AMCap.exe) or Virtual VCR, a free DirectShow capture application.
This class library uses COM Interop to access the full capabilities of DirectShow, so if there is another application that can successfully use a hardware device then it should be possible to modify this class library to use the device. Please post your experiences, good or bad, in the forum below.
User Enhancements
The following enhancements have been posted to the discussion board:
Thanks to fdaupias and dauboro for their submissions. I have not had time to post a tested, updated version with these enhancements. If anyone wants to make an updated download zip, mail it to me and I will added it to this page. Keep the enhancements coming.
DirectX.Capture Wiki
A Wiki for this project is available here. This Wiki can be edited by anyone, no registration is required. I hope this Wiki will allow interested users to more easily collaborate on this project. New versions, enhancements, tips and tricks can be posted on the Wiki.
|
|
 |
 | Is there any simple i can modify your code so i can capture just one frame? [modified] koziel.przemyslaw | 10:38 6 Feb '10 |
|
 |
Id like to be able to capture frame after frame every 10 seconds and write them as jpg files to disc. Thanks a lot for great job!modified on Saturday, February 6, 2010 4:54 PM
|
|
|
|
 |
 | Poor preview quality Horacio Prada | 4:54 31 Jan '10 |
|
 |
The video quality of the recorded .avi file is good but the preview is, like, low-resolution. Is there any way to improve it ? Is it because of limitations on the preview pin ?
|
|
|
|
 |
 | Access denied on Vista Horacio Prada | 4:49 31 Jan '10 |
|
 |
When start button (or cue button) is clicked an error message "Access is denied" appears, on Vista. Works OK on XP. How to fix ?
|
|
|
|
 |
 | Nice Article. Destiny777 | 16:40 22 Jan '10 |
|
 |
Only one small adjustment would make it better: - On the Preview, if a Video Codec Filter has been chosen, attach it when rendering the Video.
The Recorded Video Looks correct when using a Video Codec.
Thanks!
|
|
|
|
 |
 | Multiple Cams Causing Error robin24 | 5:45 21 Jan '10 |
|
 |
Hello,
I just use this Lib two years along with no problems.
I coded a Single Cam Program wich is able to do his work perfectly. I can start this program twice and it supports two devices with each property pages separatly.
Now I wanted to merge this in one application, so i can view multiple cams (2-3) in a overview. I use three Aver Media TV Cards and a single USB Card.
I instanciated 3 different capture devices like
capture1 = New Capture(TV_Filters.VideoInputDevices(0), Nothing) capture2 = New Capture(TV_Filters.VideoInputDevices(1), Nothing) capture3 = New Capture(TV_Filters.VideoInputDevices(2), Nothing) When I start rendering, all cams will show a correct preview, but the first two Cams Causing Error while setting up Video Input Source (TV Tuner, Composite, S-Video)in a combobox after that, for Each Capture1 and capture2 separatly.
Its a memory error?! ('Attempted to read or write protected memory' error)
If i want to select video input source with video crossbar, an error with crossbar property page is caused.
The settings for the last instanciated Device capture3 can be set up correctly without trouble.
Anyone can help me find out whats the problem?
I think there is a problem with the crossbars, wich will not release some memory????
Robin
|
|
|
|
 |
 | Preview Interlace hareshet | 12:23 20 Jan '10 |
|
 |
Hello all I need to use the preview window as a .net panel. First I had very bad resolution, but after retrieving the stream control interface for the preview window as suggested by another thread here, I managed to increase the resolution. The problem now is that my preview window has a very bad case of interlacing(video shows lines when the picture is moving fast). I understood from a different thread (by Almere109) that I need to use VMR9 instead of the default video renderer, and I do not know how to do this. Is this solution OK and if so - can someone please help me on howto do this or a hint for where to start from
Thanks
Itai Shmida
|
|
|
|
 |
 | Fantastic work essyvossy | 18:06 8 Jan '10 |
|
 |
Thank you very much for the work you have put into this. Is there any way to run the code on a web server, or remote IP, to display a web cam from a remote location not attached to the PC where this code is running from?
|
|
|
|
 |
 | Thanks! loyal ginger | 8:56 6 Jan '10 |
|
 |
I used the code in my projects. Saved me lots of time. Thanks!
|
|
|
|
 |
 | how to capture or record every camera Member 2166827 | 22:09 4 Jan '10 |
|
 |
I have tested this application with card video and it works great. When i use many camera for card video (Card Camera Video 4 channel), i dont know how to capture or recording with every camera. Help me?
Thanks
|
|
|
|
 |
 | Is it recommendable to update this dll to the last version? boscor | 18:24 27 Dec '09 |
|
|
 |
 | Overlay video with text/Image anki123 | 0:58 18 Dec '09 |
|
 |
Hi
I m using Directx.Capture library for video recording.
Now I want to record a video file with text/Image watermark.
How to overlay a video file at the time of recording using Directx.Capture library?
Thanks in Advance
|
|
|
|
 |
|
 |
I too would like to overlay the date and time, so basically, once a frame is captured, write text over the top before compression, is this possible?
Thanks
|
|
|
|
 |
|
 |
Still working on it....
Download DirectShowSamples from the link given below
http://sourceforge.net/projects/directshownet/files/DirectShowSamples/
It contains number of sample applications. DxLogo is one of the sample application which record video with Overlay.
Hope it will help you..
|
|
|
|
 |
 | Nicely done... However Minor issue on disconnecting / connecting Video Devices... Destiny777 | 11:20 16 Dec '09 |
|
 |
Brian,
The program works pretty well.
However, unlike AMCAP that senses when a device is connected or disconnected - Your Demo Program does not update the Devices Lists for Video and Audio.
There are a few minor inconveniences but this is very close to what I needed in regards to connecting to and using Video Codecs and Audio Codecs.
Thanks for your hard work on this project.
Bill New
|
|
|
|
 |
 | Losing conection to capture device bigal_ | 0:39 30 Nov '09 |
|
 |
Hi
My software is recording sequences, starting...stopping...new filename and start again. Often , very frequent for some hardware, is that it loses the connection to the interface when trying to set a new filename. I have a preview right before the error and i'm able to stop it from previewing, so it has some kind of connection just before.
The error message: "Unable to cast COM object of type 'System.__ComObject' to interface type 'DShowNET.IFileSinkFilter'." "No such interface supported (Exception from HRESULT: 0x80004002 (E_NOINTERFACE))."
How do i avoid this error? Different devices cause it more or less frequencly.
I have tried to restart the device but i dont know if I do it or can do it when this error occurs.
Cheers!
|
|
|
|
 |
 | Selecting Video Input Source aebarredo | 16:03 17 Nov '09 |
|
 |
I have tested this application with a UVC device and it works great! Is there a way to change video input source? My UVC device has two video inputs.
Thanks
|
|
|
|
 |
 | Changing video output booyeeka | 8:15 31 Oct '09 |
|
 |
Hi all!
Can you help me how can I change video output (from tv card's default, to ie. 800x600)? I'm trying to do next...
In file VideoCapabilities.cs, I have added next few lines in constructor VideoCapabilities:
int hr; VideoInfoHeader v = new VideoInfoHeader(); Marshal.PtrToStructure(mediaType.formatPtr, v); v.BmiHeader.Width = 800; v.BmiHeader.Height = 600; Marshal.StructureToPtr(v, mediaType.formatPtr, false); hr = videoStreamConfig.SetFormat(mediaType);
But no luck with that... Can you help me where I'm doing wrong?
|
|
|
|
 |
 | Can I Capture a stream to transfer it ? jimnox | 20:29 27 Oct '09 |
|
 |
I want to capture a video+audio stream to transfer it through the net. Can I create and transfer (maybe even encode) this stream on-the-fly?
Thank you ahead!
|
|
|
|
 |
 | Thank you guys! Todd Chen | 17:29 24 Sep '09 |
|
 |
Your source code is really helpful to me for reference, thank you
|
|
|
|
 |
 | Regarding Firewire device detection binnibinni | 19:37 17 Sep '09 |
|
 |
Hi, I have samsung DV camera. When I plugged this camera using firewire, It shows me video device as Microsoft DV camera and VCR but it is not showing me audio device of samsung camera. Please help me to solve this problem. This is very urgent....
Thanks...
|
|
|
|
 |
|
 |
noone help us. a few years ago some people have helped but now noone it's interesting..
anyway binnibinni maybe this answer may help you.. DirectX.Capture Class Library[^]
A.C
|
|
|
|
 |
 | In video compressors only with DMO rescuer85 | 22:52 16 Sep '09 |
|
 |
Hi All,
excellent article thank you, but i have a question, in my computer, there are only 4 compressors (WMVideo 8 Encoder DMO, ......) in video compressors. this computer have a camera with capture card. but another computer and camera there are more than 20 video compressors...
can i solve this problem with same camera?? thanks for answers..
A.C.
|
|
|
|
 |
 | Threading Geoffreyasdf | 13:50 16 Sep '09 |
|
 |
I am running a pretty cpu intesive control with a webcam. Is there any way (in wpf) to push the webcam onto a seperate thread?
|
|
|
|
 |
 | Recording Speaker Sound Under Vista usacoder | 8:15 31 Aug '09 |
|
 |
I would like to be able to record the sound coming out of my speakers under Vista. The only audio devices shown in the sample application running on my Dell laptop are:
Microphone (2- C-Media USB Head Microphone (High Definition Aud
Neither provides any audio from the speakers when I record. I believe that the speaker audio source is not being displayed in the drop-down. Any ideas regarding how to do this?
|
|
|
|
 |
 | Video Playback too fast Will Siu | 0:39 27 Aug '09 |
|
 |
I have two video capture devices on my machine...1)a built-in webcam on the laptop screen 2) a USB web cam. For some reason, when I record video with the USB web cam, the playback on the video file is incredibly fast. I am not sure why the DirectX.Capture is not recording correctly with that particular webcam, because the built-in webcam works just fine.
A big difference is that I am using drivers from the manufacturer for the built-in webcam, whereas for the USB webcam, I am using the generic Microsoft USB2 webcam drivers.
Any ideas what is going on here?
|
|
|
|
 |
|
|