如何使用 C# .Net 将屏幕捕获为视频?
Posted
技术标签:
【中文标题】如何使用 C# .Net 将屏幕捕获为视频?【英文标题】:How to capture screen to be video using C# .Net? 【发布时间】:2011-05-03 09:01:59 【问题描述】:您是否有一些库可以将屏幕捕获为压缩视频文件或一些可以做到这一点的解决方案?
【问题讨论】:
【参考方案1】:此代码使用 NuGet 上提供的 SharpAvi。
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);
示例用法
-
创建控制台应用程序。
添加对
System.Drawing
和System.Windows.Forms
的引用。 (修改代码可以避免使用System.Windows.Forms
)。
从 NuGet 安装 SharpAvi。
代码:
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();
【讨论】:
你能在这里多描述一下吗? 该应用程序使用 user32.dll 和 gdi32.dll 捕获屏幕截图并将它们与使用 WaveIn api 捕获的音频一起写入 AviWriter 为我工作!感谢马修分享! 为什么捕获的视频速度是 x2 甚至 x3? 这个 SharpAvi 正在加速视频,不管我给他的位图有多慢,即使我添加了阻塞队列。不要浪费时间在上面的代码上。【参考方案2】:您最好的选择似乎是 Windows Media Encoder。
这里有一些链接:
http://www.c-sharpcorner.com/UploadFile/armoghanasif/CaptureDesktopActivities11122005013755AM/CaptureDesktopActivities.aspx
http://www.codeproject.com/KB/audio-video/CaptureScreenAsVideo.aspx
http://mycomponent.blogspot.com/2009/04/capture-screen-activitiesvideo-using.html
【讨论】:
我正在寻找 DirectshowNet,但我不知道应该使用什么输入过滤器进行屏幕捕获。以上是关于如何使用 C# .Net 将屏幕捕获为视频?的主要内容,如果未能解决你的问题,请参考以下文章
视频捕获 + 上传 + 处理 + 流回 - .NET & C#