共计 1859 个字符,预计需要花费 5 分钟才能阅读完成。
背景痛点
在 C# 开发中实现桌面录制功能时,开发者常遇到以下问题:

- 音视频同步困难:手动管理音频和视频的时间戳容易导致不同步
- 性能瓶颈:高分辨率录制时 CPU 占用率飙升
- 兼容性问题:不同硬件和系统版本的编解码器支持差异大
- 文件格式限制:难以直接生成主流视频格式
技术选型
对比几种常见方案:
- DirectX:性能好但开发复杂度高,需要处理大量底层 API
- Windows API:依赖系统版本,功能有限
- FFmpeg:
- 开源且跨平台
- 支持几乎所有音视频格式
- 命令行调用简单
- 成熟的编解码解决方案
核心实现
环境准备
- 下载 FFmpeg 静态编译版本
- 解压到项目目录或系统 PATH 路径
关键代码实现
public class ScreenRecorder
{
private Process ffmpegProcess;
public void StartRecording(string outputPath)
{
var screenBounds = Screen.PrimaryScreen.Bounds;
var args = $"-y -f gdigrab -framerate 30 -offset_x {screenBounds.X} -offset_y {screenBounds.Y}" +
$"-video_size {screenBounds.Width}x{screenBounds.Height} -i desktop -f dshow -i audio=\" 麦克风 \" " +
$"-c:v libx264 -preset ultrafast -pix_fmt yuv420p -c:a aac" +
$"-map 0:v -map 1:a {outputPath}";
ffmpegProcess = new Process
{
StartInfo = new ProcessStartInfo
{
FileName = "ffmpeg.exe",
Arguments = args,
UseShellExecute = false,
CreateNoWindow = true,
RedirectStandardError = true
}
};
ffmpegProcess.ErrorDataReceived += (sender, e) =>
{if(!string.IsNullOrEmpty(e.Data))
Console.WriteLine($"FFmpeg: {e.Data}");
};
ffmpegProcess.Start();
ffmpegProcess.BeginErrorReadLine();}
public void StopRecording()
{if(ffmpegProcess != null && !ffmpegProcess.HasExited)
{
// 发送 q 命令正常退出
ffmpegProcess.StandardInput.WriteLine("q");
ffmpegProcess.WaitForExit(2000);
if(!ffmpegProcess.HasExited)
ffmpegProcess.Kill();
ffmpegProcess.Dispose();}
}
}
参数详解
- 视频采集:
-f gdigrab:使用 Windows GDI 抓屏-framerate 30:设置帧率为 30fps-
-video_size:指定录制区域大小 -
音频采集:
-f dshow:使用 DirectShow 采集音频-
audio="麦克风":指定音频输入设备 -
编码参数:
-c:v libx264:使用 H.264 视频编码-preset ultrafast:最快编码预设-c:a aac:使用 AAC 音频编码
性能优化
- 降低分辨率:适当减少视频尺寸
- 调整帧率:根据需求降低帧率
- 使用硬件加速 :添加
-hwaccel参数 - 优化编码参数:
-crf 28:平衡质量和文件大小-threads 4:使用多线程编码
避坑指南
- FFmpeg 路径问题:
- 将 ffmpeg.exe 放在程序目录
-
或指定完整路径
-
权限问题:
- 确保对输出目录有写入权限
-
管理员权限运行程序
-
音频设备不可用:
- 先通过
ffmpeg -list_devices true -f dshow -i dummy列出设备 -
确保设备名称正确
-
文件锁定:
- 确保录制完成后再操作文件
- 使用
.mp4等支持流式写入的格式
总结与扩展
基础功能实现后,可以考虑:
- 添加水印:通过
-vf "movie=watermark.png [wm]; [in][wm] overlay=10:10 [out]" - 直播推流:修改输出为 RTMP 地址
- 多显示器支持 :通过
-i desktop:n选择显示器 - 录制区域选择:添加 GUI 让用户选择区域
完整项目示例已上传 GitHub,包含更多高级功能和错误处理。
正文完
