1. macOS屏幕录制开发概述在当今远程协作和内容创作日益普及的环境下屏幕录制功能已成为各类应用的核心需求。macOS平台上的ScreenCaptureKit框架为开发者提供了高性能、低延迟的屏幕捕获解决方案相比传统的CGDisplayStream和CGWindowList API它在性能、隐私保护和功能灵活性方面都有显著提升。ScreenCaptureKit支持捕获屏幕显示、应用程序窗口以及音频内容能够以高达屏幕原生分辨率和60fps的帧率进行录制同时支持48kHz立体声音频采集。这个框架特别适合用于开发视频会议应用、远程协作工具、游戏直播软件以及教育类应用。重要提示从macOS 13开始Apple已明确表示将逐步弃用旧的屏幕捕获API因此新项目应优先考虑使用ScreenCaptureKit。2. ScreenCaptureKit核心组件解析2.1 SCShareableContent可共享内容管理SCShareableContent是ScreenCaptureKit中用于管理可捕获内容的中心类。它提供了当前系统中所有可共享的显示、应用程序和窗口的详细信息// 获取当前可共享内容 let content try await SCShareableContent.excludingDesktopWindows( false, onScreenWindowsOnly: true )这个方法返回的对象包含三个主要属性displays: 当前连接的物理显示器列表(SCDisplay)applications: 正在运行的应用程序列表(SCRunningApplication)windows: 所有可见窗口列表(SCWindow)每个SCDisplay对象包含显示器的唯一标识符、尺寸和缩放比例等信息这对于多显示器环境下的屏幕捕获尤为重要。2.2 SCContentFilter内容过滤配置SCContentFilter决定了实际捕获哪些内容它支持两种主要过滤模式显示器无关的窗口过滤捕获特定窗口即使窗口在不同显示器间移动显示器相关的过滤捕获特定显示器上的内容可选择包含或排除某些窗口/应用// 创建内容过滤器排除当前应用 let excludedApps content.applications.filter { app in Bundle.main.bundleIdentifier app.bundleIdentifier } let filter SCContentFilter(display: display, excludingApplications: excludedApps, exceptingWindows: [])这种过滤机制可以有效避免镜厅效应(即捕获到自己的捕获界面)同时保护敏感信息不被意外录制。2.3 SCStreamConfiguration流媒体参数设置SCStreamConfiguration对象控制捕获流的各项参数包括let streamConfig SCStreamConfiguration() // 视频参数 streamConfig.width 1920 // 输出宽度 streamConfig.height 1080 // 输出高度 streamConfig.minimumFrameInterval CMTime(value: 1, timescale: 60) // 60fps streamConfig.showsCursor false // 是否显示鼠标光标 // 音频参数 streamConfig.capturesAudio true // 启用音频捕获 streamConfig.sampleRate 48000 // 48kHz采样率 streamConfig.channelCount 2 // 立体声开发者可以根据应用场景灵活调整这些参数。例如文档共享应用可能更注重分辨率而非帧率而游戏直播则需要更高的帧率保证流畅性。3. 屏幕与音频捕获实战实现3.1 创建和启动捕获流配置好内容和参数后就可以创建SCStream实例并开始捕获// 创建流实例 stream SCStream(filter: filter, configuration: streamConfig, delegate: self) // 添加输出处理器 try stream?.addStreamOutput(self, type: .screen, sampleHandlerQueue: screenQueue) try stream?.addStreamOutput(self, type: .audio, sampleHandlerQueue: audioQueue) // 开始捕获 try await stream?.startCapture()3.2 处理视频和音频样本ScreenCaptureKit通过SCStreamOutput协议回调传递捕获的媒体数据func stream(_ stream: SCStream, didOutputSampleBuffer sampleBuffer: CMSampleBuffer, of type: SCStreamOutputType) { switch type { case .screen: processVideoSample(sampleBuffer) case .audio: processAudioSample(sampleBuffer) } } private func processVideoSample(_ sampleBuffer: CMSampleBuffer) { guard let attachments CMSampleBufferGetSampleAttachmentsArray(sampleBuffer, createIfNecessary: false) as? [[SCStreamFrameInfo: Any]], let info attachments.first?[.status] as? SCStreamFrameInfo else { return } if info .complete, let pixelBuffer CMSampleBufferGetImageBuffer(sampleBuffer) { // 处理完整的视频帧 } }视频样本以CVPixelBuffer形式提供可以直接用于显示、编码或进一步处理。每个样本都附带帧状态信息(.complete或.idle)帮助开发者优化处理逻辑。3.3 音频采集的特殊处理音频采集需要特别注意以下几点音频格式ScreenCaptureKit输出的音频样本格式为LPCM采样率和通道数由SCStreamConfiguration决定音频同步视频和音频样本可能在不同时间到达需要实现自己的同步机制音频混合当捕获多个应用的音频时框架会自动混合无法单独控制每个应用的音量private func processAudioSample(_ sampleBuffer: CMSampleBuffer) { guard let blockBuffer CMSampleBufferGetDataBuffer(sampleBuffer) else { return } var audioBufferList AudioBufferList() var length 0 CMBlockBufferGetDataPointer(blockBuffer, atOffset: 0, lengthAtOffsetOut: length, totalLengthOut: nil, dataPointerOut: audioBufferList.mBuffers.mData) // 处理音频数据... }4. 高级功能与性能优化4.1 动态调整捕获参数ScreenCaptureKit支持实时更新捕获参数无需重新创建流// 动态调整分辨率 streamConfig.width 1280 streamConfig.height 720 try await stream?.updateConfiguration(streamConfig) // 动态切换捕获内容 let newFilter SCContentFilter(display: anotherDisplay) try await stream?.updateContentFilter(newFilter)这一特性特别适合需要根据网络状况动态调整质量的远程协作应用。4.2 多流管理一个应用可以同时创建多个SCStream实例分别捕获不同的内容// 主显示器捕获流 let mainStream SCStream(filter: mainFilter, configuration: mainConfig, delegate: self) // 第二显示器捕获流 let secondStream SCStream(filter: secondFilter, configuration: secondConfig, delegate: self) // 分别启动 try await mainStream.startCapture() try await secondStream.startCapture()每个流可以独立配置和管理但需要注意系统资源消耗。4.3 性能优化技巧帧率与分辨率平衡高分辨率(如4K)下适当降低帧率(如15-30fps)像素格式选择BGRA格式处理效率最高适合直接显示如需编码考虑使用NV12队列管理为视频和音频处理使用不同的DispatchQueue避免相互阻塞内存优化及时释放不再需要的CMSampleBuffer和CVPixelBuffer5. 常见问题与解决方案5.1 权限问题处理ScreenCaptureKit需要用户授权屏幕录制权限应用应妥善处理权限相关错误func stream(_ stream: SCStream, didStopWithError error: Error) { if let scError error as? SCStreamError, scError.code .userDeclined { // 引导用户前往系统设置开启权限 showPermissionAlert() } }5.2 音频捕获失败排查如果音频无法正常捕获检查以下方面确保streamConfig.capturesAudio true确认应用有麦克风使用权限检查系统音频设置确保没有静音或音量过低5.3 性能问题诊断当遇到高CPU使用率或帧率不稳定时使用Instruments工具分析性能瓶颈考虑降低输出分辨率或帧率检查是否有不必要的样本拷贝操作5.4 多显示器环境下的特殊考虑在多显示器环境下每个显示器可能有不同的缩放比例需要手动调整输出分辨率窗口跨显示器移动时显示器无关的窗口过滤器能保持捕获连续性不同显示器可能支持不同的最大刷新率6. 实际应用场景扩展6.1 视频会议应用集成在视频会议应用中ScreenCaptureKit可用于共享特定应用窗口而非整个屏幕动态切换共享内容实现标注、高亮等协作功能// 会议应用中动态切换共享窗口 func switchToSharedWindow(_ window: SCWindow) { let newFilter SCContentFilter(desktopIndependentWindow: window) Task { try await stream?.updateContentFilter(newFilter) } }6.2 教育类应用开发教育类应用可以利用ScreenCaptureKit实现课件录制与直播学生屏幕监控互动教学工具6.3 游戏直播实现对于游戏直播场景优先保证高帧率(60fps)使用硬件编码器减少CPU负载实现低延迟的音频视频同步// 游戏直播专用配置 let gameConfig SCStreamConfiguration() gameConfig.width 1920 gameConfig.height 1080 gameConfig.minimumFrameInterval CMTime(value: 1, timescale: 60) gameConfig.capturesAudio true gameConfig.sampleRate 48000 gameConfig.channelCount 2ScreenCaptureKit为macOS屏幕录制开发提供了强大而灵活的工具集。通过合理配置和优化开发者可以构建出满足各种场景需求的高性能屏幕录制功能。在实际开发中建议从简单配置开始逐步添加复杂功能并始终关注性能和用户体验的平衡。
阅读完成 · 觉得有帮助?