Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to capture screen to be video using C# .Net?

Do you have some library to capture a screen to be a compressed video file or some solution that can do it?

like image 305
Gramero Avatar asked Nov 01 '10 11:11

Gramero


People also ask

How do you take a screenshot in C?

Win + Print Screen: Captures the entire screen. The difference here is that Windows saves the image as a file. By default, it's sent to C:Users Pictures>Screenshots or C:Users OneDrive>Pictures>Screenshots on your PC. Win + Shift + S: Captures a screenshot using the built-in screenshot tool called Snip & Sketch.

Can Capture be used for video?

A capture card is a device that's used in conjunction with a computer to capture on-screen content and encode it for playback in either a livestream or a high-quality video file. Capture cards can be used with video game consoles new and old, as well as computers and cameras.


1 Answers

This code uses SharpAvi available on NuGet.

using System; using System.Drawing; using System.Drawing.Imaging; using System.Runtime.InteropServices; using System.Threading; using System.Threading.Tasks; using SharpAvi; using SharpAvi.Codecs; using SharpAvi.Output; using System.Windows.Forms;  namespace Captura {     // Used to Configure the Recorder     public class RecorderParams     {         public RecorderParams(string filename, int FrameRate, FourCC Encoder, int Quality)         {             FileName = filename;             FramesPerSecond = FrameRate;             Codec = Encoder;             this.Quality = Quality;              Height = Screen.PrimaryScreen.Bounds.Height;             Width = Screen.PrimaryScreen.Bounds.Width;         }          string FileName;         public int FramesPerSecond, Quality;         FourCC Codec;          public int Height { get; private set; }         public int Width { get; private set; }          public AviWriter CreateAviWriter()         {             return new AviWriter(FileName)             {                 FramesPerSecond = FramesPerSecond,                 EmitIndex1 = true,             };         }          public IAviVideoStream CreateVideoStream(AviWriter writer)         {             // Select encoder type based on FOURCC of codec             if (Codec == KnownFourCCs.Codecs.Uncompressed)                 return writer.AddUncompressedVideoStream(Width, Height);             else if (Codec == KnownFourCCs.Codecs.MotionJpeg)                 return writer.AddMotionJpegVideoStream(Width, Height, Quality);             else             {                 return writer.AddMpeg4VideoStream(Width, Height, (double)writer.FramesPerSecond,                     // It seems that all tested MPEG-4 VfW codecs ignore the quality affecting parameters passed through VfW API                     // They only respect the settings from their own configuration dialogs, and Mpeg4VideoEncoder currently has no support for this                     quality: Quality,                     codec: Codec,                     // Most of VfW codecs expect single-threaded use, so we wrap this encoder to special wrapper                     // Thus all calls to the encoder (including its instantiation) will be invoked on a single thread although encoding (and writing) is performed asynchronously                     forceSingleThreadedAccess: true);             }         }     }      public class Recorder : IDisposable     {         #region Fields         AviWriter writer;         RecorderParams Params;         IAviVideoStream videoStream;         Thread screenThread;         ManualResetEvent stopThread = new ManualResetEvent(false);         #endregion          public Recorder(RecorderParams Params)         {             this.Params = Params;              // Create AVI writer and specify FPS             writer = Params.CreateAviWriter();              // Create video stream             videoStream = Params.CreateVideoStream(writer);             // Set only name. Other properties were when creating stream,              // either explicitly by arguments or implicitly by the encoder used             videoStream.Name = "Captura";              screenThread = new Thread(RecordScreen)             {                 Name = typeof(Recorder).Name + ".RecordScreen",                 IsBackground = true             };              screenThread.Start();         }          public void Dispose()         {             stopThread.Set();             screenThread.Join();              // Close writer: the remaining data is written to a file and file is closed             writer.Close();              stopThread.Dispose();         }          void RecordScreen()         {             var frameInterval = TimeSpan.FromSeconds(1 / (double)writer.FramesPerSecond);             var buffer = new byte[Params.Width * Params.Height * 4];             Task videoWriteTask = null;             var timeTillNextFrame = TimeSpan.Zero;              while (!stopThread.WaitOne(timeTillNextFrame))             {                 var timestamp = DateTime.Now;                  Screenshot(buffer);                  // Wait for the previous frame is written                 videoWriteTask?.Wait();                  // Start asynchronous (encoding and) writing of the new frame                 videoWriteTask = videoStream.WriteFrameAsync(true, buffer, 0, buffer.Length);                  timeTillNextFrame = timestamp + frameInterval - DateTime.Now;                 if (timeTillNextFrame < TimeSpan.Zero)                     timeTillNextFrame = TimeSpan.Zero;             }              // Wait for the last frame is written             videoWriteTask?.Wait();         }          public void Screenshot(byte[] Buffer)         {             using (var BMP = new Bitmap(Params.Width, Params.Height))             {                 using (var g = Graphics.FromImage(BMP))                 {                     g.CopyFromScreen(Point.Empty, Point.Empty, new Size(Params.Width, Params.Height), CopyPixelOperation.SourceCopy);                      g.Flush();                      var bits = BMP.LockBits(new Rectangle(0, 0, Params.Width, Params.Height), ImageLockMode.ReadOnly, PixelFormat.Format32bppRgb);                     Marshal.Copy(bits.Scan0, Buffer, 0, Buffer.Length);                     BMP.UnlockBits(bits);                 }             }         }     } } 

Example Usage

  1. Create a console application.
  2. Add Reference to System.Drawing and System.Windows.Forms. (The usage of System.Windows.Forms can be avoided if you modify the code).
  3. Install SharpAvi from NuGet.

Code:

using Captura; using System;  namespace ConsoleApp {     class Program     {         static void Main(string[] args)         {             // Using MotionJpeg as Avi encoder,             // output to 'out.avi' at 10 Frames per second, 70% quality             var rec = new Recorder(new RecorderParams("out.avi", 10, SharpAvi.KnownFourCCs.Codecs.MotionJpeg, 70));              Console.WriteLine("Press any key to Stop...");             Console.ReadKey();              // Finish Writing             rec.Dispose();         }     } } 
like image 96
Mathew Sachin Avatar answered Sep 17 '22 16:09

Mathew Sachin