如何使用 C# .NET 将屏幕捕获为视频?

2023-12-14

是否有一些库可以将屏幕捕获为压缩视频文件或可以执行此操作的某种解决方案?


此代码使用 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);
                }
            }
        }
    }
}

用法示例

  1. 创建一个控制台应用程序。
  2. 添加参考System.Drawing and System.Windows.Forms。 (使用System.Windows.Forms如果修改代码就可以避免)。
  3. 从 NuGet 安装 SharpAvi。

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();
        }
    }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何使用 C# .NET 将屏幕捕获为视频? 的相关文章

随机推荐

  • PHP四舍五入,圆/天花板/地板?

    假设我有以下两个数字 a 77 5 b 74 5 我如何得到以下内容 a 80 b 70 我看过圆形 天花板和地板 但我不知道该怎么做 谢谢 PHP 支持负精度round功能 a round a 1 这与写作几乎相同 a round a 1
  • 如何在 python 中编写自定义编码来清理数据?

    我知道我以前在另一份工作中做过这样的事 但我不记得我做了什么 我有一个数据库 里面充满了 varchar 和 memo 字段 这些字段是从 Office 网页以及谁知道其他地方剪切和粘贴的 这开始给我带来编码错误 由于 Python 有一个
  • IntersectionObserver 和位置:绝对

    当观察到的元素有时 IntersectionObserver 似乎不起作用position absolute并且根不是 视口 我在这里错过了什么吗 尝试删除position absolute查看预期结果 let intersectionRo
  • python 可以处理未计算的表达式参数吗?

    我想将一条语句传递给 python 函数 该语句只应在我在函数中执行其他操作后执行 默认情况下 python 计算语句 然后将其结果作为参数传递 有什么办法可以改变这种行为吗 我发现的唯一方法是将语句包装在函数中 然后传递该函数 大多数 P
  • 如何将 LinearGradient 添加到垂直 SVG 线[重复]

    这个问题在这里已经有答案了 我正在尝试为线条的笔划添加渐变 该线条在顶部淡出 但没有运气 实际上 我的工作原理是这样的 但即使在 Chrome 中 某些 SVG 尺寸也会出现浏览器问题 其中渐变会中断并且是固定的
  • MacOS X 10.6.2 上的 Perl:GDBM_File 丢失,如何安装或解决?

    当我需要 Perl 模块时 我通常使用 CPAN 效果很好 但这次不是 我想使用MARC Charset 但是这个使用GDBM File 而且我似乎无法从CPAN安装GDBM File CPAN 发现一切正常 但尝试安装它时 它开始安装完整
  • 为什么 useState 会让组件渲染两次?

    也许你们中的一些人可以让我睁开眼睛 我不明白为什么在这段代码中 https codesandbox io s use state renders twice 6r1xl组件 App 在安装并单击按钮时渲染两次 console log 被调用
  • Qt 中的自定义圆形进度条[关闭]

    Closed 这个问题需要多问focused 目前不接受答案 我可以在覆盖时在 qt 中执行循环进度条paintEvent小部件并绘制圆形进度条 但在主圆形进度条后面的第二个圆形进度条 无法像这样绘制 有困难 有人可以指导我吗 预先感谢 我
  • 如何使用R中的“bootstrap函数”计算置信区间

    我正在尝试计算R中的置信区间 由于一些特殊原因 我必须使用 bootstrap 包中的函数来计算 这意味着我不能使用 boot 包中的函数 这是我的代码 我正在做的是尝试计算 Pearson 相关系数 然后应用 Bootstrap 方法 B
  • awk 不匹配所有匹配我的所有条目

    我正在尝试制作 脚本 本质上是一个 awk 命令 来提取 c 文件中 C 代码函数的原型 以自动生成标头 h 我是 awk 的新手 所以我不了解所有细节 这是源 c 的示例 dict t dictup dict t d const char
  • Jetty:如何在 Jetty 客户端使用 SSL

    我正在使用 Jetty 开发我的客户端应用程序端 我没有在服务器部分使用 Jetty 我需要在客户端配置什么才能使用 Jetty 客户端发送 https 请求 这就是我对 HTTP 客户端所做的事情 httpClient new HttpC
  • JsonConvert.DeserializeObject 特殊字符 未终止的字符串。预期分隔符:

    由于某种原因 当我的淘汰模型中有一个特殊字符并将其转换为 json 对象时 字符串在特殊字符应该在的位置结束 并且在反序列化时出现错误 ajax url Admin Forms Convert type post contentType a
  • Retrofit 2 的定制转换器

    我必须处理动态 JSON 响应 之前 我使用类和注释如下 public class ChatResponse SerializedName status private int status SerializedName error pri
  • 在哪里删除 Swift 中 NSNotification 的观察者?

    我应该在哪里删除观察者NSNotification在斯威夫特 因为viewDidUnload and dealloc 不可用 As of iOS 9 和 OS X 10 11 你不需要移除观察者你自己 如果你不使用基于块的观察者的话 系统会
  • 为什么 IIS Express 在加载 javascript 和 CSS 时返回 HTTP 500 错误?

    我正在尝试使用 IIS Express 开发 ASP NET MVC5 解决方案进行本地调试 通常 Chrome 在尝试加载某些 JS 和 CSS 文件时会报告 HTTP500 错误 有些使用 MVC 的内置捆绑和缩小功能 有些则使用自己的
  • 错误:使用 wikixmlj 解析 xml 文件时出现 xml.sax.SAXParseException

    我正在使用解析维基百科 xml 转储wikixmlj并收到以下错误 org xml sax SAXParseException lineNumber 64243259 columnNumber 371 JAXP00010004 The ac
  • Nodejs FS 模块返回 no such file or dir 错误

    Code fs readdir commands err files gt Do something Error ENOENT 没有这样的文件或目录 scandir commands 文件夹 commands does存在 这个文件是src
  • MapKit 中的 MapTypeStyle

    我想知道是否有任何方法可以配置我们的 MapKit 地图 就像我们在 Google 地图 API 中使用 MapTypeStyle 对象一样 如果我参考Apple文档 MKMapView有一个mapType选项 它需要MKMapType常量
  • MySQL删除语句优化

    我有一些删除查询要针对一些相当大的表 100 GB 运行 并且我想尽可能地优化它们 delete from table1 where column1 lt date sub now interval 100 hour 第 1 列是datet
  • 如何使用 C# .NET 将屏幕捕获为视频?

    是否有一些库可以将屏幕捕获为压缩视频文件或可以执行此操作的某种解决方案 此代码使用 NuGet 上提供的 SharpAvi using System using System Drawing using System Drawing Ima