C#wpf使用ffmpeg命令行实现录屏的示例代码

 

前言

上一章我们实现了截屏界面与功能,接下来可以在此基础上实现录屏功能,录屏采用ffmpeg命令行实现会方便一些,效果也是不错的,当然前提是要对Windows子进程的控制比较熟悉,做出来之后完全可以满足项目使用。

 

一、主要步骤

1、使用 AllowsTransparency实现穿透框

录屏需要使用AllowsTransparency来实现透明背景,因为录屏时框选区域需要能够点击穿透到桌面,使用WindowChome则不行。

在这里插入图片描述

2、获取音频设备名称

因为不依赖第三方工具(比如:screen capture recorder),只要我们能够获取音频设备名称就可以使用ffmpeg的dshow录制声音。我们通过调用Com的方式就可以获取到设备名称,在《C# 使用com获取Windows摄像头列表》的基础上添加一个属性获取音频设备列表:

static readonly Guid AudioInputDevice = new Guid(0x33d9a762, 0x90c8, 0x11d0, 0xbd, 0x43, 0x0, 0xa0, 0xc9, 0x11, 0xce, 0x86);
/// <summary>
/// 枚举录音设备
/// </summary>
public static IEnumerable<string> AudioInputDevices
{
  get
  {
      IMoniker[] monikers = new IMoniker[5];
      var devEnum = Activator.CreateInstance(Type.GetTypeFromCLSID(SystemDeviceEnum)) as ICreateDevEnum;
      IEnumMoniker moniker;
      if (devEnum.CreateClassEnumerator(AudioInputDevice, out moniker, 0) == 0)
      {
          while (true)
          {
              int hr = moniker.Next(1, monikers, IntPtr.Zero);
              if (hr != 0 || monikers[0] == null)
                  break;
              yield return GetName(monikers[0]);
              foreach (var i in monikers)
              {
                  if (i != null)
                      Marshal.ReleaseComObject(i);
              }
          }
          Marshal.ReleaseComObject(moniker);
      }
      Marshal.ReleaseComObject(devEnum);
  }
}

获取音频设备名称

string audio = null;
//获取音频采集设备名称
foreach (var i in EnumDevices.AudioInputDevices)
{
  audio = i;
  break;
}

3、命令行启动ffmpeg

得到了音频设备名称之后,我们就可以使用下面的命令行是实现录屏了。
录屏命令行,-i audio=上一步获取的音频设备名称。

ffmpeg -y -f dshow -sample_rate 44100 -sample_size 16 -channels 2 -i audio="麦克风 (Realtek High Definition Audio)" -f gdigrab -offset_x 10 -offset_y 20 -video_size 640x480 -i desktop -preset:v ultrafast -tune:v zerolatency -r 30 screen.mp4 

启动ffmpeg(示例)

var process = new Process();
process.StartInfo.FileName = "ffmpeg";
process.StartInfo.Arguments ="-y -f dshow -sample_rate 44100 -sample_size 16 -channels 2 -i audio=\"麦克风 (Realtek High Definition Audio)\"  -f gdigrab  -offset_x 10 -offset_y 20 -video_size 640x480  -i desktop  -preset:v ultrafast -tune:v zerolatency  -r 30     screen.mp4 "
process.Start()

4、使用JobObject管理子进程

启动ffmpeg作为子进程,需要对其进行一定的管理,要保证主进程任何情况的退出子进程跟随退出,我们可以使用Windows的JobObject实现这一功能。C#需要使用dllimport包装Job Object的WinApi。
下面是部分示例代码:创建了作业对象,并设置为对象销毁后,加入的进程全部退出。

handle = CreateJobObject(IntPtr.Zero, null);
var info = new JOBOBJECT_BASIC_LIMIT_INFORMATION
{
  LimitFlags = 0x2000
};

var extendedInfo = new JOBOBJECT_EXTENDED_LIMIT_INFORMATION
{
  BasicLimitInformation = info
};

int length = Marshal.SizeOf(typeof(JOBOBJECT_EXTENDED_LIMIT_INFORMATION));
IntPtr extendedInfoPtr = Marshal.AllocHGlobal(length);
Marshal.StructureToPtr(extendedInfo, extendedInfoPtr, false);

if (!SetInformationJobObject(handle, JobObjectInfoType.ExtendedLimitInformation, extendedInfoPtr, (uint)length))
  throw new Exception(string.Format("Unable to set information.  Error: {0}", Marshal.GetLastWin32Error()));

 

二、完整代码

实现了录屏功能,包括画面和声音的录制,只依赖ffmpeg.exe。

之后上传

 

三、效果预览

1、录制中

在这里插入图片描述

2、录制动态流程

在这里插入图片描述

 

总结

以上就是今天要讲的内容了,因为使用了命令行所以录屏逻辑不用自己实现,但是要控制ffmpeg子进程还是有不少细节需要处理的,比如进程自动退出、信息反馈、停止录屏、异常提示等。另外一方面在界面上也有需要处理的东西,比如可控的点击穿透、控制窗口置顶等等。总的来说,实现这一一个功能模块还是需要一定的时间和精力,以及一些相关的知识。

关于C# wpf使用ffmpeg命令行实现录屏的示例代码的文章就介绍至此,更多相关C# wpf ffmpeg命令行录屏内容请搜索编程宝库以前的文章,希望以后支持编程宝库

 投篮小游戏规则,点击投篮目标点,就会有一个球沿着相关抛物线,然后,判断是否进入篮子里,其实就是一个矩形,直接是按照碰撞检测来的,碰到就算进去了,对其增加了一个分数统计等功能。Wpf ...