基于C#实现的高性能实时MP4录屏方案

 更新时间:2026年02月13日 08:50:00   作者:hoiii187  
这篇文章主要介绍了基于C#实现的高性能实时MP4录屏方案,文中通过代码示例介绍的非常详细,具有一定的参考价值,需要的朋友可以参考下

一、技术选型对比

方案优点缺点适用场景
GDI截图+FFmpeg实现简单,兼容性强CPU占用高(约30%-50%)低分辨率/非实时场景
DXGI捕获+MediaFoundation高性能(GPU加速),低CPU占用开发复杂度高,需处理帧同步问题高帧率(60fps)/4K录制
SharpDX/D3D11支持DirectX加速,画质最佳需要DirectX开发经验游戏直播/专业视频制作

二、推荐实现方案(DXGI + MediaFoundation)

1. 核心代码结构

// 初始化捕获设备
var factory = new SharpDX.Direct3D11.DeviceFactory();
var adapter = factory.GetAdapter1(0);
var device = new SharpDX.Direct3D11.Device(adapter);

// 创建DXGI输出
var output = adapter.GetOutput(0);
var output1 = output.QueryInterface<SharpDX.DXGI.Output1>();
var duplication = output1.DuplicateOutput(device);

// 配置视频编码参数
var mediaType = new MediaFoundationEncoder.VideoMediaType(
    width: 1920,
    height: 1080,
    frameRate: 30,
    pixelFormat: SharpDX.WIC.PixelFormat.Format32bppBGRA,
    codec: MediaFoundationEncoder.Codec.H264,
    bitrate: 5000000 // 5Mbps
);

// 创建编码器
var encoder = new MediaFoundationEncoder(mediaType);
encoder.StartEncoding("output.mp4");

// 录制循环
while (isRecording)
{
    var frame = duplication.AcquireNextFrame(1000);
    var texture = frame.DesktopImage;
    
    // 转换为MediaFoundation可处理格式
    using (var stream = new MemoryStream())
    {
        texture.CopyTo(stream);
        encoder.EncodeFrame(stream.ToArray());
    }
    
    frame.Release();
}

2. 关键优化点

  • GPU加速编码:使用MediaFoundation的硬件编码(如NVIDIA NVENC),CPU占用可降低至5%以下
  • 内存映射文件:通过MemoryMappedFile实现零拷贝写入,提升IO性能
  • 帧率控制:动态调整捕获间隔,避免丢帧或卡顿
// 自适应帧率控制
var targetFrameTime = 1000 / targetFPS;
var lastFrameTime = Stopwatch.StartNew();

while (isRecording)
{
    var frameTime = lastFrameTime.ElapsedMilliseconds;
    if (frameTime >= targetFrameTime)
    {
        // 捕获并编码帧
        lastFrameTime.Restart();
    }
    else
    {
        Thread.Sleep(targetFrameTime - (int)frameTime);
    }
}

三、分段保存实现

// 自动分段保存逻辑
private void CheckSegment()
{
    if (encoder.TotalDuration >= _segmentDuration)
    {
        encoder.StopEncoding();
        string newPath = GenerateSegmentPath();
        encoder.StartEncoding(newPath);
    }
}

// 文件名生成策略
private string GenerateSegmentPath()
{
    var now = DateTime.Now;
    return $"recording_{now:yyyyMMdd_HHmmss}_{Guid.NewGuid():N}.mp4";
}

四、完整实现步骤

1. 环境配置

<!-- NuGet依赖 -->
<PackageReference Include="SharpDX" Version="4.3.0" />
<PackageReference Include="MediaFoundationEncoder" Version="1.2.0" />

2. 界面设计(WinForm)

<!-- 主窗体布局 -->
<DockPanel>
    <StatusBar DockPanel.Dock="Bottom">
        <TextBlock Text="{Binding Status}"/>
        <TextBlock Text="{Binding FPS} FPS"/>
    </StatusBar>
    
    <Button Content="开始录制" Command="{Binding StartCommand}"/>
    <Button Content="停止录制" Command="{Binding StopCommand}"/>
    
    <Slider Minimum="1" Maximum="60" Value="{Binding FrameRate}" Width="200"/>
</DockPanel>

3. ViewModel实现

public class MainViewModel : INotifyPropertyChanged
{
    private bool _isRecording;
    private int _frameRate = 30;
    private long _totalFrames;
    
    public ICommand StartCommand => new RelayCommand(StartRecording);
    public ICommand StopCommand => new RelayCommand(StopRecording);
    
    public string Status => _isRecording ? "录制中..." : "空闲";
    public int FPS => (int)(_totalFrames / (Stopwatch.GetTimestamp() / 1e7));
    
    private void StartRecording()
    {
        _isRecording = true;
        _totalFrames = 0;
        
        Task.Run(() => 
        {
            using (var recorder = new MediaRecorder())
            {
                recorder.Start(_frameRate);
                while (_isRecording)
                {
                    var frame = CaptureFrame();
                    recorder.Encode(frame);
                    _totalFrames++;
                }
                recorder.Stop();
            }
        });
    }
    
    private void StopRecording()
    {
        _isRecording = false;
    }
}

五、性能优化方案

1. 内存管理

  • 对象池:重用Texture2DMemoryStream对象
public class FramePool
{
    private readonly Queue<Texture2D> _pool = new();
    
    public Texture2D GetFrame(int width, int height)
    {
        return _pool.Count > 0 ? _pool.Dequeue() : new Texture2D(device, width, height);
    }
    
    public void ReturnFrame(Texture2D frame)
    {
        frame.Dispose();
    }
}

2. 多线程处理

// 生产者-消费者模型
BlockingCollection<Bitmap> _frameQueue = new();
Task.Run(() => EncodeWorker());

void EncodeWorker()
{
    foreach (var frame in _frameQueue.GetConsumingEnumerable())
    {
        // 编码处理
    }
}

3. GPU内存优化

// 使用DX12的显存直接访问
var commandAllocator = new CommandAllocator(device, CommandListType.Copy);
var commandList = new CommandList(device, commandAllocator);
commandList.CopyBufferRegion(stagingBuffer, 0, gpuBuffer, 0, dataSize);
commandAllocator.Reset();
commandList.Reset(commandAllocator, null);

六、扩展功能实现

1. 鼠标点击高亮

// 在捕获帧时叠加点击标记
void DrawClickMarker(Graphics g, Point position)
{
    using (var pen = new Pen(Color.Red, 2))
    {
        g.DrawEllipse(pen, position.X - 5, position.Y - 5, 10, 10);
    }
}

2. 音频同步录制

// 使用NAudio捕获系统音频
using (var waveIn = new WaveInEvent())
{
    waveIn.DataAvailable += (s, e) => 
    {
        audioBuffer.Write(e.Buffer, 0, e.BytesRecorded);
    };
    waveIn.StartRecording();
}

七、测试与调试

1. 性能监控

// 实时显示资源占用
public class PerformanceMonitor
{
    private readonly PerformanceCounter _cpuCounter = new("Processor", "% Processor Time", "_Total");
    private readonly PerformanceCounter _ramCounter = new("Memory", "Available MBytes");
    
    public string GetStatus()
    {
        return $"CPU: {_cpuCounter.NextValue()}%  内存: {_ramCounter.NextValue()}MB";
    }
}

2. 日志系统

public static class Logger
{
    private static readonly RollingFileAppender _appender = new();
    
    static Logger()
    {
        _appender.File = "log.txt";
        _appender.Layout = new PatternLayout("%date [%thread] %-5level %logger - %message%newline");
        _appender.ActivateOptions();
    }
    
    public static void Log(string message)
    {
        _appender.DoAppend(new LoggingEvent(new LoggingEventData {
            Message = message,
            TimeStamp = DateTime.Now
        }));
    }
}

八、部署建议

安装依赖

  • 安装Microsoft Visual C++ 2015-2022 Redistributable
  • 部署FFmpeg动态库(ffmpeg.dll, avcodec-58.dll等)

代码签名

# 使用signtool进行数字签名
signtool sign /fd SHA256 /tr http://timestamp.digicert.com /td SHA256 MyApp.exe

安装包制作

<!-- WiX安装配置 -->
<Component Id="MainComponent" Guid="*">
    <File Id="MainExe" Name="MyApp.exe" Source="..\bin\Release\MyApp.exe"/>
    <RegistryValue Root="HKLM" Key="Software\MyCompany\MyApp" 
                   Name="InstallDir" Value="[INSTALLDIR]" Type="string"/>
</Component>

参考代码 C#实时录屏软件 MP4格式 www.youwenfan.com/contentcsr/93565.html

九、方案对比与选择

场景推荐方案理由
企业级会议录制MediaFoundation+DXGI低延迟,支持多路流输入
游戏直播SharpDX+NVENC硬件编码最高支持8K 60fps,极致性能
简单录屏工具GDI+FFmpeg命令行开发周期短,维护成本低
跨平台录制AValon+FFmpeg.AutoGen支持Windows/macOS/Linux

十、常见问题解决方案

黑屏问题

  • 检查DXGI输出是否正确初始化
  • 确保以管理员权限运行程序

音频不同步

  • 设置AVSyncMode.AudioMaster同步模式
  • 添加音频缓冲队列(建议500ms)

文件损坏

mediaType.FFmpegOptions.Add("movflags", "faststart");
  • 启用moov atom前置(快速启动)

通过上述方案,可实现专业级的实时MP4录屏软件。开发者可根据具体需求选择基础方案或深度定制,建议优先测试硬件加速编码路径以获得最佳性能。

以上就是基于C#实现的高性能实时MP4录屏方案的详细内容,更多关于C#实时MP4录屏的资料请关注脚本之家其它相关文章!

相关文章

  • C#代码设置开机启动示例

    C#代码设置开机启动示例

    本文介绍了使用C#代码设置开机启动的方法,原理就是在注册表启动项里添加一项
    2014-01-01
  • C#调用执行命令行窗口(CMD)的方法与技巧

    C#调用执行命令行窗口(CMD)的方法与技巧

    在 C# 的编程世界里,我们常常会遇到需要与操作系统底层进行交互的场景,这时,调用命令行窗口(CMD)就成为了一个强大的工具,通过 C# 调用 CMD 都能为我们提供极大的便利,极大地拓展了 C# 应用程序的功能边界,本文介绍了C#中调用执行CMD的方法与技巧
    2025-01-01
  • C#开发中的垃圾回收机制简析

    C#开发中的垃圾回收机制简析

    这篇文章主要为大家详细介绍了C#开发中的垃圾回收机制,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2015-10-10
  • C#中数据类型的转换介绍

    C#中数据类型的转换介绍

    大家好,本篇文章主要讲的是C#中数据类型的转换介绍,感兴趣的同学赶快来看一看吧,对你有帮助的话记得收藏一下,方便下次浏览
    2022-01-01
  • 利用WPF实现Windows屏保的制作

    利用WPF实现Windows屏保的制作

    屏保程序的本质上就是一个Win32 窗口应用程序。本文将利用WPF实现Windows屏保的制作,文中的示例代码简洁易懂,对我们学习WPF有一定帮助,感兴趣的可以了解一下
    2022-07-07
  • asp.net(c#)编程实现将彩色图片变灰阶图片的方法示例

    asp.net(c#)编程实现将彩色图片变灰阶图片的方法示例

    这篇文章主要介绍了asp.net(c#)编程实现将彩色图片变灰阶图片的方法,结合实例形式分析了C#图片读取及属性操作相关技巧,需要的朋友可以参考下
    2017-07-07
  • 对int array进行排序的实例讲解

    对int array进行排序的实例讲解

    下面小编就为大家分享一篇对int array进行排序的实例讲解,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2017-12-12
  • C#内存管理CLR深入讲解(上篇)

    C#内存管理CLR深入讲解(上篇)

    本文详细讲解了C#内存管理CLR的程序集和应用程序域,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-01-01
  • C#实现利用Windows API读写INI文件的方法

    C#实现利用Windows API读写INI文件的方法

    这篇文章主要介绍了C#实现利用Windows API读写INI文件的方法,涉及C#针对ini文件的创建、读取及写入等操作技巧,具有一定参考借鉴价值,需要的朋友可以参考下
    2015-07-07
  • C# 实现绘制PDF嵌套表格案例详解

    C# 实现绘制PDF嵌套表格案例详解

    嵌套表格,顾名思义,就是在一张表格中的特定单元格中再插入一个或者多个表格,本文将为大家介绍C#绘制PDF嵌套表格的代码示例,需要的同学可以参考一下
    2021-11-11

最新评论