17.3MB7Z
录屏采用ffmpeg命令行实现会方便一些,效果也是不错的,当然前提是要对Windows子进程的控制比较熟悉,做出来之后完全可以满足项目使用。
前言
上一章我们实现了截屏界面与功能,接下来可以在此基础上实现录屏功能,录屏采用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);
///
/// 枚举录音设备
///
public static IEnumerable 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 640×480 -i desktop -preset:v ultrafast -tune:v zerolatency -r 30 screen.mp4
1
启动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 640×480 -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子进程还是有不少细节需要处理的,比如进程自动退出、信息反馈、停止录屏、异常提示等。另外一方面在界面上也有需要处理的东西,比如可控的点击穿透、控制窗口置顶等等。总的来说,实现这一一个功能模块还是需要一定的时间和精力,以及一些相关的知识。
资源声明(购买视为同意此声明): 1.在网站平台的任何操作视为已阅读和同意网站底部的注册协议及免责声明,本站资源已是超低价,且不提供技术支持 2.部分网络用户分享网盘地址有可能会失效,如发生失效情况请发邮件给客服code711cn#qq.com (把#换成@)会进行补发 3.本站站内提供的所有可下载资源(软件等等)本站保证未做任何负面改动;但本网站不能保证资源的准确性、安全性和完整性,用户下载后自行斟酌,我们以交流学习为目的,并不是所有的源码都不是100%无错或无bug;需要您有一定的基础能够看懂代码,能够自行调试修改代码并解决报错。同时本站用户必须明白,源码便利店对提供下载的软件等不拥有任何权利,其版权归该资源的合法拥有者所有。 4.本站所有资源仅用于学习及研究使用,请必须在24小时内删除所下载资源,切勿用于商业用途,否则由此引发的法律纠纷及连带责任本站和发布者概不承担 5.因资源可复制性,一旦购买均不退款,充值余额也不退款