一、屏幕录制权限 应用首次创建屏幕截图或者窗口截图时(以下任一接口都可以),就会显示系统的权限申请弹窗,通过选中Screen Recording里面的相关应用,重启应用后即可开启权限。
CGDisplayCreateImage() CGDisplayCreateImageForRect() CGWindowListCreateImage() CGWindowListCreateImageFromArray() 二、获取screenId 通过AppKit的NSScreen.screens或者通过CoreGraphics的CGGetActiveDisplayList()都可以获取当前的所有显示器信息,下面用NSScreen.screens举例子:
[NSScreen.screens enumerateObjectsUsingBlock:^(NSScreen * _Nonnull screen, NSUInteger idx, BOOL * _Nonnull stop) { NSNumber *screenNumber = screen.deviceDescription[@"NSScreenNumber"]; if (screenNumber) { CGDirectDisplayID displayId = screenNumber.unsignedIntValue; NSLog(@"displayId: %d", displayId); } }]; 注意:如果是镜像显示,则只会打印一个显示器信息。
三、获取windowId 1、获取windowId列表 通过接口CGWindowListCopyWindowInfo()可以获取windowId列表。
其中kCGWindowListExcludeDesktopElements参数表示从列表中排除所有属于桌面元素的窗口。
CGWindowListCopyWindowInfo()返回的是一个CFArrayRef,使用完后需要主动release。 这里有一个技巧,利用CFBridgingRelease()函数,可以把CFArrayRef桥接到NSArray,并且会把内存管理转移到ARC,就是说我们不需要再去主动release了。
NSArray *windowDictArr = CFBridgingRelease(CGWindowListCopyWindowInfo(kCGWindowListOptionAll | kCGWindowListExcludeDesktopElements, 0)); 2、过滤无用windowId 通过以上接口获取到的windowId列表可能会包含很多我们不关心的windowId:
1. 没显示出来的window 通过kCGWindowLayer跟kCGWindowAlpha两个key,可以获取到当前window是否有layer以及是否透明,我们需要过滤掉不可见的window。
2. 过滤信息不全的window kCGWindowNumberkey可以从字典里获取到windowId,需要过滤没有windowId的字典信息。
3. 过滤无法获取截图的window 通过CGWindowListCreateImage()接口,传入对应windowId,可获取到window的截图,如果无法获取到截图,可能没有录屏权限、不是window主体、window不可见。
3、获取window frame 通过CGRectMakeWithDictionaryRepresentation()可获取窗口的frame,某些业务可能需要用到frame。
四、屏幕共享 屏幕共享的视频输入总体来说跟摄像头的视频输入相当类似,可以理解成视频流从摄像头改成了屏幕输入(AVCaptureDeviceInput->AVCaptureScreenInput),视频输出的处理则跟摄像头的输出处理完全一样。
1、关键代码: - (void)startCapture { self....