locked
Screen Capture -> Save as AVI RRS feed

  • Question

  • Hello,

    I have been hunting around to research how to record the desktop and then save it as something like an AVI. So far this has been the best find - http://www.codeproject.com/KB/directx/directxcapture.aspx but, it does not compile. I have also found other ways of doing this (manually capturing many "screen shots" then attaching them all together. But this seems the best option as it does all that in one go, also compressing it. I know there are many third party software that record the screen but I am making my own as I want to also do other thing with the captured file. I am using the correct dll's too. So this is the code I am using -

    1 using System;  
    2 using System.Collections.Generic;  
    3 using System.ComponentModel;  
    4 using System.Data;  
    5 using System.Drawing;  
    6 using System.Text;  
    7 using System.Windows.Forms;  
    8 using DirectX.Capture;  
    9 using DShowNET;  
    10  
    11 namespace WindowsApplication1  
    12 {  
    13     public partial class Form1 : Form  
    14     {  
    15         public Form1()  
    16         {  
    17             InitializeComponent();  
    18         }  
    19  
    20         private void button1_Click(object sender, EventArgs e)  
    21         {  
    22               
    23 Capture capture = new Capture( Filters.VideoInputDevices[0],  
    24                                Filters.AudioInputDevices[1] );  
    25  
    26 capture.VideoCompressor = Filters.VideoCompressors[0];  
    27 capture.AudioCompressor = Filters.AudioCompressors[0];  
    28  
    29 capture.FrameRate = 29.997;                 // NTSC  
    30 capture.FrameSize = new Size( 640, 480 );   // 640x480  
    31 capture.AudioSamplingRate = 44100;          // 44.1 kHz  
    32 capture.AudioSampleSize = 16;               // 16-bit  
    33 capture.AudioChannels = 1;                  // Mono  
    34  
    35 capture.Filename = "C:\\MyVideo.avi";  
    36  
    37 capture.Start();  
    38         }  
    39  
    40         private void button2_Click(object sender, EventArgs e)  
    41         {  
    42             capture.Stop();  
    43         }  
    44     }  
    45

    It fails to compile on lines 23,24,26,27 all because if the "Filters..."

    Errors  -

    An object reference is required for the nonstatic field, method, or property 'DirectX.Capture.Filters.VideoInputDevices' 
    An object reference is required for the nonstatic field, method, or property 'DirectX.Capture.Filters.AudioInputDevices' 
    An object reference is required for the nonstatic field, method, or property 'DirectX.Capture.Filters.VideoCompressors' 
    An object reference is required for the nonstatic field, method, or property 'DirectX.Capture.Filters.AudioCompressors' 

    Do you have any idea why it doing this? I would really prefer to use this method as it is the simplist.
    Wednesday, August 6, 2008 11:00 AM

Answers

  • To capture the screen, use the ScreenCapture filter.  You need serious DirectShow help.  Try the DirectShow forum. 
    • Marked as answer by jack 321 Monday, August 11, 2008 2:49 AM
    Wednesday, August 6, 2008 3:43 PM
  •  When I added the public Filters class (found in Directx.Capture) see the code at the top of my post. I hit debug and it failed with the following error's -

    The type 'DirectX.Capture.FilterCollection' has no constructors defined 

    You are not supposed to add this class Filters to the code. You are supposed to reference it properly. I think you did it already, since you have a reference to the namespaces. I hope that class is inside of one of them:

    using DShoeNET;
    using DirextX.Capture.

    index out of range is too early to explore now. You must resolve coarser issues first and then perhaps the index will straighten itself out.

    The classes above are all different. The third one represents a collection (inventory) of all codecs on your system. The first one seems to be the one you are supposed to use.


    AlexB
    Thursday, August 7, 2008 12:11 AM

All replies

  • I'm not really familiar with the DirectX framework but the error messages say that you need an instance of class Filters to use the VideoInputDevices etc. properties:

    Filters f = some instance of the Filters class
    Capture capture = new Capture(f.VideoInputDevices[0], f.AudioInputDevices[1]);
    Wednesday, August 6, 2008 11:50 AM
  • I changed your code in the way that it should compile. I also inroduced a bogus class Filters to make it look good with highlights. It did not compile in my code but for a different reason: I don't have references to Directx.Capture and DShowNET. Here is the code:

    using System;     
    using System.Collections.Generic;     
    using System.ComponentModel;     
    using System.Data;     
    using System.Drawing;     
    using System.Text;     
    using System.Windows.Forms;     
    using DirectX.Capture;     
    using DShowNET;  
     
    namespace WindowsApplication1  
    {  
        public partial class Form1 : Form  
        {  
            public Form1 ( )  
            {  
                InitializeComponent ( );  
            }  
     
            private void button1_Click ( object sender, EventArgs e )  
            {  
                Filters filers = new Filters ( );  
                Capture capture = new Capture ( filers.VideoInputDevices[ 0 ],  
                                   filers.AudioInputDevices[ 1 ] );  
     
                capture.VideoCompressor = filers.VideoCompressors[ 0 ];  
                capture.AudioCompressor = filers.AudioCompressors[ 0 ];  
     
                capture.FrameRate = 29.997;                 // NTSC     
                capture.FrameSize = new Size ( 640, 480 );   // 640x480     
                capture.AudioSamplingRate = 44100;          // 44.1 kHz     
                capture.AudioSampleSize = 16;               // 16-bit     
                capture.AudioChannels = 1;                  // Mono     
     
                capture.Filename = "C:\\MyVideo.avi";  
     
                capture.Start ( );  
            }  
     
            private void button2_Click ( object sender, EventArgs e )  
            {  
                capture.Stop ( );  
            }  
        }  
        public class Filters  
        {  
     
        }  
    }    
     

    I just noticed that I misspelled filters as filers. But it is irrelevant for the compilation.

    AlexB
    Wednesday, August 6, 2008 12:23 PM
  • Wednesday, August 6, 2008 12:29 PM
  •  
    1 using System;  
    2 using System.Collections.Generic;  
    3 using System.ComponentModel;  
    4 using System.Data;  
    5 using System.Drawing;  
    6 using System.Text;  
    7 using System.Windows.Forms;  
    8 using DirectX.Capture;  
    9 using DShowNET;  
    10  
    11 namespace WindowsApplication1  
    12 {  
    13       
    14     public partial class Form1 : Form  
    15     {  
    16         public Form1()  
    17         {  
    18             InitializeComponent();  
    19         }  
    20  
    21         private void button1_Click(object sender, EventArgs e)  
    22         {  
    23             Filters filters = new Filters();  
    24  
    25 Capture capture = new Capture( filters.VideoInputDevices[0],  
    26                                filters.AudioInputDevices[1] );  
    27  
    28 capture.VideoCompressor = filters.VideoCompressors[0];  
    29 capture.AudioCompressor = filters.AudioCompressors[0];  
    30  
    31 capture.FrameRate = 29.997;                 // NTSC  
    32 capture.FrameSize = new Size( 640, 480 );   // 640x480  
    33 capture.AudioSamplingRate = 44100;          // 44.1 kHz  
    34 capture.AudioSampleSize = 16;               // 16-bit  
    35 capture.AudioChannels = 1;                  // Mono  
    36  
    37 capture.Filename = "C:\\MyVideo.avi";  
    38  
    39 capture.Start();  
    40 capture.Stop();  
    41         }  
    42  
    43         private void button2_Click(object sender, EventArgs e)  
    44         {  
    45               
    46         }  
    47     }  
    48     public class Filters  
    49     {  
    50         // ------------------ Public Properties --------------------  
    51  
    52         /// <summary> Collection of available video capture devices. </summary>  
    53         public FilterCollection VideoInputDevices = new FilterCollection(FilterCategory.VideoInputDevice);  
    54  
    55         /// <summary> Collection of available audio capture devices. </summary>  
    56         public FilterCollection AudioInputDevices = new FilterCollection(FilterCategory.AudioInputDevice);  
    57  
    58         /// <summary> Collection of available video compressors. </summary>  
    59         public FilterCollection VideoCompressors = new FilterCollection(FilterCategory.VideoCompressorCategory);  
    60  
    61         /// <summary> Collection of available audio compressors. </summary>  
    62         public FilterCollection AudioCompressors = new FilterCollection(FilterCategory.AudioCompressorCategory);  
    63  
    64     }  
    65

    Hello,

    Thanks everyone. Alex, I had added the new filters(); and when I compiled and click button 1. The process stopped with the following error -

    Index was out of range. Must be non-negative and less than the size of the collection.
    Parameter name: index

    at line 4 below.

    1 /// <summary> Get the filter at the specified index. </summary>  
    2         public Filter this[int index]  
    3         {  
    4             get { return( (Filter) InnerList[index] ); }  
    5         } 

    When I added the public Filters class (found in Directx.Capture) see the code at the top of my post. I hit debug and it failed with the following error's -

    The type 'DirectX.Capture.FilterCollection' has no constructors defined 

    The above error was for each of the FilterCollection's in Filter().

    What am I doing wrong?

    Please help,

    Thanks,
    Wednesday, August 6, 2008 12:47 PM
  • You're not supposed to add your own class Filters to the code, use the one defined in DirectX.Capture. The problem is that you first have to find out how to get the correct Filters instance, it probably won't be as easy as

    filters = new Filters();

    You may need to call a different overload of the class constructor or use some function that will give you the correct Filters instance. I have no idea how to do this because I don't know much about the DirectX api, you'll have to consult the documentation on how to get a Filters instance.
    Wednesday, August 6, 2008 12:55 PM
  • Hmm, There are 3 Filter class files in DirectX.Capture - Filter.cs, FilterCollection.cs and Filters.cs

    The explanations in the files are as follows -

    Filter.cs

    1 /// <summary>  
    2     ///  Represents a DirectShow filter (e.g. video capture device,   
    3     ///  compression codec).  
    4     /// </summary>  
    5     /// <remarks>  
    6     ///  To save a chosen filer for later recall  
    7     ///  save the MonikerString property on the filter:   
    8     ///  <code><div style="background-color:whitesmoke;">  
    9     ///   string savedMonikerString = myFilter.MonikerString;  
    10     ///  </div></code>  
    11     ///    
    12     ///  To recall the filter create a new Filter class and pass the   
    13     ///  string to the constructor:   
    14     ///  <code><div style="background-color:whitesmoke;">  
    15     ///   Filter mySelectedFilter = new Filter( savedMonikerString );  
    16     ///  </div></code>  
    17     /// </remarks> 

    FilterCollection.cs

    1 /// <summary>  
    2     ///  A collection of Filter objects (DirectShow filters).  
    3     ///  This is used by the <see cref="Capture"/> class to provide  
    4     ///  lists of capture devices and compression filters. This class  
    5     ///  cannot be created directly.  
    6     /// </summary> 

    Filters.cs

    1     /// <summary>  
    2     ///  Provides collections of devices and compression codecs  
    3     ///  installed on the system.   
    4     /// </summary>  
    5     /// <example>  
    6     ///  Devices and compression codecs are implemented in DirectShow   
    7     ///  as filters, see the <see cref="Filter"/> class for more   
    8     ///  information. To list the available video devices:  
    9     ///  <code><div style="background-color:whitesmoke;">  
    10     ///   Filters filters = new Filters();  
    11     ///   foreach ( Filter f in filters.VideoInputDevices )  
    12     ///   {  
    13     ///     Debug.WriteLine( f.Name );  
    14     ///   }  
    15     ///  </div></code>  
    16     ///  <seealso cref="Filter"/>  
    17     /// </example> 

    I am confused as to which one I am to use.
    In Filters.cs you can see that it is evoked using new Filters();
    In Filter.cs you can see it is evoked using a similar approch but with a "savedMonikerString", what is that?

    If I do -

    foreach ( Filter f in filters.VideoInputDevices )  

     

       {  

     

         MessageBox.Show( f.Name );  

     

      }  

    It lists out all the video devices.

    Please Help,

    Thanks,
    Wednesday, August 6, 2008 1:08 PM
  • Well I actually just discovered that this method of trying to Screen Capture, captures from external devices such as web cams and not the screen
    Wednesday, August 6, 2008 3:39 PM
  • To capture the screen, use the ScreenCapture filter.  You need serious DirectShow help.  Try the DirectShow forum. 
    • Marked as answer by jack 321 Monday, August 11, 2008 2:49 AM
    Wednesday, August 6, 2008 3:43 PM
  • JohnWein said that you need a serious help. Here it is:)

    Find, download and install OleView.exe. Run it. It will show all OLE and DirectX on your computer in a GUI. Find yours which is not easy, examine the class, come back for more questions.

    That GUI is supposed to give you a complete inside view of the internals of the control.
    AlexB
    Wednesday, August 6, 2008 11:56 PM
  •  When I added the public Filters class (found in Directx.Capture) see the code at the top of my post. I hit debug and it failed with the following error's -

    The type 'DirectX.Capture.FilterCollection' has no constructors defined 

    You are not supposed to add this class Filters to the code. You are supposed to reference it properly. I think you did it already, since you have a reference to the namespaces. I hope that class is inside of one of them:

    using DShoeNET;
    using DirextX.Capture.

    index out of range is too early to explore now. You must resolve coarser issues first and then perhaps the index will straighten itself out.

    The classes above are all different. The third one represents a collection (inventory) of all codecs on your system. The first one seems to be the one you are supposed to use.


    AlexB
    Thursday, August 7, 2008 12:11 AM
  • Have there been any recent breakthroughts since 2008? I have the CodeProject sample project complied and running but I'm having trouble finding information about adding a Screen Capture filter to the list of video devices. My overall goal is to be able to capture and save an AVI video of my desktop as I demo some things. 
    Thursday, February 11, 2010 1:52 AM
  • I did not understand your response. Can you elaborate on what ScreenCapture filter are you talking about?

     

    Sunday, May 16, 2010 6:01 AM