基于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. 内存管理
- 对象池:重用
Texture2D和MemoryStream对象
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录屏的资料请关注脚本之家其它相关文章!
相关文章
asp.net(c#)编程实现将彩色图片变灰阶图片的方法示例
这篇文章主要介绍了asp.net(c#)编程实现将彩色图片变灰阶图片的方法,结合实例形式分析了C#图片读取及属性操作相关技巧,需要的朋友可以参考下2017-07-07


最新评论