
在实时音视频应用中macOS 过去更多被视为“观看端”或“管理端”用于查看摄像头画面、导播预览、监控墙展示、设备管理和流媒体调试。但随着远程办公、在线教育、工业视觉、无人机图传、设备远程运维和软件操作演示等场景不断增加Mac 正在从单纯的播放终端逐渐变成实时音视频链路中的采集端、编码端和分发端。这意味着Mac 不仅需要播放 RTSP、RTMP 等实时流还需要完成摄像头和麦克风采集屏幕或指定窗口采集系统声音采集H.264/H.265 视频编码AAC 音频编码RTMP 低延迟推流局域网 RTSP 实时分发本地录像、快照和事件状态管理。这正是大牛直播SDKSmartMediaKit推出 macOS 版推流能力和轻量级 RTSP 服务的核心背景。本文结合SmartMacPublisher示例工程从代码和工程设计角度分析 macOS 为什么需要专业的低延迟 RTMP 推流与轻量级 RTSP 服务以及这一方案适合哪些业务场景。一、为什么 macOS 也需要专业推流SDK很多人提到推流首先想到的是手机直播、摄像头推流或者 Windows 桌面采集。但在大量专业场景中Mac 已经不只是一个内容消费设备。例如老师使用 Mac 播放课件并把屏幕和讲解声音推送到教学平台工程师采集工业控制软件窗口供远程专家实时查看售后人员将 Mac 上的软件操作过程推送给客户导播人员把 Mac 上的画面作为一路信号源接入直播系统开发者使用 Mac 快速产生 RTMP、RTSP 测试流局域网内临时将 Mac 摄像头或屏幕共享给多个播放终端会议、培训和产品发布过程中同时推流并进行本地录像。这些需求看似不同底层却都离不开同一套实时音视频能力采集、格式处理、编码、封装、推送、分发、录像、状态回调和异常恢复。如果从零开始开发需要处理的问题非常多摄像头、麦克风设备枚举与权限申请屏幕、窗口和系统声音采集BGRA、NV12、PCM 等媒体格式转换VideoToolbox 编码器配置RTMP 连接、发送、断线和重连RTSP 服务端口、流名称和客户端会话管理动态分辨率和窗口尺寸变化音视频时间戳和同步推流、录像、RTSP 发布之间的状态组合App 退出时的线程、采集设备和 SDK 资源释放。任何一个环节处理不当都可能带来黑屏、花屏、无声音、延迟堆积、摄像头无法释放或者应用退出崩溃等问题。SmartMediaKit macOS 版的价值并不只是“增加一个平台”而是把这些复杂、容易踩坑的底层能力沉淀到 SDK 中让上层应用更专注于采集源选择、业务流程、用户界面和产品体验。二、SmartMacPublisher的总体设计上层采集SDK负责媒体处理与输出SmartMacPublisher 没有简单照搬移动端“SDK 内置采集”的模式而是采用了更适合 macOS 桌面应用的架构上层应用负责采集SmartPublisherSDK 负责编码、封装、推流、RTSP 发布、录像和快照。整个链路可以概括为这种“外部采集 SDK 投递”模式非常适合 macOS。因为桌面端的采集方式更加多样可以采集整个显示器可以只采集某个窗口可以采集内置或外接摄像头可以使用 Continuity Camera可以采集麦克风可以采集系统播放声音可以在运行中调整窗口大小可以根据业务切换音频来源。让上层掌握采集源能够保留桌面应用所需要的灵活性SDK 则专注于编码和协议链路避免每个项目重复实现复杂的音视频基础设施。三、摄像头采集尽量直接输出编码器友好的NV12SmartMacPublisher 的摄像头采集基于 AVFoundation。Demo 会先检查摄像头和麦克风权限然后创建AVCaptureSession添加视频输入、音频输入以及对应的数据输出。在视频输出配置中Demo 主动要求 AVFoundation 输出 NV12AVCaptureVideoDataOutput *videoOutput [[AVCaptureVideoDataOutput alloc] init]; videoOutput.videoSettings { (__bridge NSString *)kCVPixelBufferPixelFormatTypeKey: (kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange) }; videoOutput.alwaysDiscardsLateVideoFrames YES; [videoOutput setSampleBufferDelegate:self queue:self.captureQueue];这里有两个值得关注的细节。1. 摄像头直接输出NV12NV12 是 VideoToolbox 编码链路中非常常见的输入格式。摄像头直接输出 NV12可以避免先得到 BGRA再通过 CPU 做一次颜色空间转换从而减少CPU 占用内存带宽消耗视频帧拷贝格式转换引入的排队延迟。对于摄像头推流来说如果不需要复杂美颜、叠加和图像处理尽量保持CVPixelBuffer → VideoToolbox的短链路是降低端侧延迟和功耗的重要方式。2. 丢弃处理不及时的旧帧videoOutput.alwaysDiscardsLateVideoFrames YES;实时推流和离线视频处理的目标不同。离线任务更关注“每一帧都不能丢”而实时直播更关注“当前看到的是最新画面”。如果应用来不及处理某些帧继续缓存旧帧只会导致延迟越来越大。因此在实时采集场景下及时丢弃已经过期的帧通常比积压帧队列更合理。四、摄像头分辨率与帧率不能只依赖SessionPresetmacOS 摄像头的设备类型比较复杂可能包括MacBook 内置摄像头USB 摄像头采集卡虚拟摄像头Continuity Camera第三方 DAL 驱动设备。不同设备支持的分辨率和帧率组合并不完全一致。SmartMacPublisher 会枚举AVCaptureDeviceFormat按照宽高对 Format 进行归类再根据目标帧率选择合适的 Format。AVCaptureDeviceFormat *targetFormat [selectedResolution bestFormatForFPS:selectedFPS]; if ([videoDevice lockForConfiguration:error]) { videoDevice.activeFormat targetFormat; [videoDevice unlockForConfiguration]; }Demo 没有完全依赖sessionPreset还会在AVCaptureVideoDataOutput中明确设置目标宽高videoOutput.videoSettings { (__bridge NSString *)kCVPixelBufferPixelFormatTypeKey: (kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange), (__bridge NSString *)kCVPixelBufferWidthKey: (selectedResolution.width), (__bridge NSString *)kCVPixelBufferHeightKey: (selectedResolution.height) };这是一个很实际的工程处理。部分 Continuity Camera 或外接设备即使已经设置了activeFormat仍可能按照硬件原生分辨率输出。明确指定输出宽高可以让采集管线对输出帧进行统一约束避免UI 中选择的是 1280×720实际送给编码器的却是 1920×1080SDK 外部分辨率配置与真实帧尺寸不一致。五、屏幕和窗口采集基于ScreenCaptureKit实现SmartMacPublisher 的屏幕和窗口采集基于 ScreenCaptureKit。代码中针对不同 macOS 版本采用了不同处理方式macOS 12.3 及以上支持 ScreenCaptureKitmacOS 13.0 及以上支持通过 SCStream 采集系统声音macOS 14.0 及以上优先使用系统SCContentSharingPickermacOS 14.0 及以上支持监听窗口内容尺寸变化并动态更新采集配置。在 macOS 14 及以上版本Demo 直接调用系统内容选择器SCContentSharingPickerConfiguration *config [[SCContentSharingPickerConfiguration alloc] init]; config.allowedPickerModes SCContentSharingPickerModeSingleDisplay | SCContentSharingPickerModeSingleWindow; SCContentSharingPicker *picker [SCContentSharingPicker sharedPicker]; picker.defaultConfiguration config; picker.active YES; [picker present];用户可以使用系统界面选择整个显示器或某个具体窗口。相较于自行枚举窗口系统选择器在权限、安全性和用户体验方面更符合 macOS 的设计逻辑也可以减少重复触发授权流程带来的困扰。对于 macOS 12.3 至 13.xDemo 则通过SCShareableContent获取可共享的显示器和窗口再使用自定义窗口完成选择。六、为什么屏幕采集需要BGRA转NV12ScreenCaptureKit 在当前 Demo 中配置为输出 BGRASCStreamConfiguration *config [[SCStreamConfiguration alloc] init]; config.pixelFormat kCVPixelFormatType_32BGRA; config.showsCursor self.showCursor; config.minimumFrameInterval CMTimeMake(1, MAX(1, self.fps));之所以不直接要求 ScreenCaptureKit 输出 NV12是因为在部分较早的 macOS 12.x 版本中NV12 并不是所有采集路径都能稳定支持的输出格式可能导致SCStream启动失败。因此SmartMacPublisher 选择了一条兼容性更好的路径ScreenCaptureKit 稳定输出 BGRA应用层使用VTPixelTransferSession转换为 NV12将转换后的CMSampleBufferRef投递给 SDKSDK 再交给 VideoToolbox 编码。核心代码如下if (!_pixelTransferSession) { VTPixelTransferSessionCreate( kCFAllocatorDefault, _pixelTransferSession); } CVPixelBufferRef dstPixelBuffer NULL; CVPixelBufferPoolCreatePixelBuffer( kCFAllocatorDefault, _nv12Pool, dstPixelBuffer); VTPixelTransferSessionTransferImage( _pixelTransferSession, srcPixelBuffer, dstPixelBuffer);这里没有使用 CPU 逐像素转换而是使用 VideoToolbox 提供的 Pixel Transfer 能力。同时Demo 根据采集分辨率创建并复用CVPixelBufferPool只有尺寸发生变化时才重建 Buffer Pool从而降低频繁分配内存带来的开销。转换完成后Demo 会保留原始视频帧的时间信息重新构造CMSampleBufferRefCMSampleTimingInfo timing kCMTimingInfoInvalid; CMSampleBufferGetSampleTimingInfo( sourceSampleBuffer, 0, timing); CMSampleBufferCreateForImageBuffer( kCFAllocatorDefault, dstPixelBuffer, YES, NULL, NULL, formatDescription, timing, result);这保证了视频格式发生变化但时间戳语义仍然保持一致。七、窗口尺寸变化固定分辨率还是动态跟随窗口采集有一个摄像头采集通常不会遇到的问题被采集窗口可能在推流过程中被用户拖动和缩放。SmartMacPublisher 提供了两种策略。固定推流分辨率窗口尺寸发生变化时仍然保持原来的编码分辨率对窗口内容进行居中或缩放适配。这种方式的优点是编码器参数稳定服务端和播放端不需要处理分辨率变化更适合持续直播和多终端观看不容易引发播放器重新建解码器。跟随窗口分辨率在 macOS 14 及以上版本Demo 可以监听SCStreamConfiguration更新并调用[stream updateConfiguration:newConfiguration completionHandler:^(NSError *error) { // 更新成功 }];为了避免用户连续拖动窗口时频繁更新代码增加了约 500ms 的防抖逻辑。当新的分辨率真正生效后Demo 还会通知 SDK[self.publisherSDK SmartPublisherSetExternalResolution:newWidth height:newHeight];动态跟随更适合开发调试工具单窗口远程预览分辨率变化必须完整保留的工业软件接收端能够正确处理编码参数变化的私有链路。而在面向公网直播或大量播放端时通常更建议保持固定编码分辨率。八、第一帧到达后再启动推流一个容易忽略的关键细节SmartMacPublisher 没有在用户点击按钮后立刻调用 RTMP、RTSP 或录像启动接口。它首先判断是否已经收到有效视频帧if (self.lastVideoWidth 0 || self.lastVideoHeight 0) { self.pendingStartPublishing YES; [self appendLog: 等待第一帧视频到达后再启动 RTMP 推流…]; return; }当第一帧到达时Demo 从CVPixelBuffer中读取实际宽高NSInteger width CVPixelBufferGetWidth(pixelBuffer); NSInteger height CVPixelBufferGetHeight(pixelBuffer); self.lastVideoWidth width; self.lastVideoHeight height; [self.publisherSDK SmartPublisherSetExternalResolution:width height:height];然后统一处理之前挂起的操作- (void)_flushPendingStarts { BOOL startRTMP self.pendingStartPublishing; BOOL startRecord self.pendingStartRecording; BOOL startRTSP self.pendingStartRtspStream; self.pendingStartPublishing NO; self.pendingStartRecording NO; self.pendingStartRtspStream NO; if (startRTMP) [self startPublishing]; if (startRecord) [self startRecording]; if (startRTSP) [self startRtspStream]; }这看似只是一个启动顺序问题实际上会直接影响首屏和编码稳定性。如果视频宽高尚未确定就启动编码器可能出现编码器初始化参数不完整第一段视频数据尺寸错误推流已连接但长时间没有有效视频录像文件头信息与实际视频不一致屏幕采集尺寸变化后参数未同步。因此“先采集、等首帧、确认分辨率、再启动输出”是外部视频数据投递模式中非常重要的工程策略。九、SDK初始化外部CMSampleBuffer投递模式SmartMacPublisher 初始化 SmartPublisherSDK 时将音频和视频模式都设置为3static const NSInteger kExternalAudio 3; static const NSInteger kExternalVideo 3; [self.publisherSDK SmartPublisherInit:kExternalAudio video_opt:kExternalVideo];这里的含义是音频由上层采集以编码前CMSampleBufferRef投递视频由上层采集以编码前CMSampleBufferRef投递SDK 不负责选择具体摄像头、屏幕或窗口SDK 负责后续编码、封装和协议输出。初始化完成后Demo 配置编码参数[self.publisherSDK SmartPublisherSetVideoEncoderType: NT_MEDIA_CODEC_ID_H264 isHwEncoder:YES]; [self.publisherSDK SmartPublisherSetAudioEncoderType:1 isHwEncoder:NO]; [self.publisherSDK SmartPublisherSetFPS:fps]; [self.publisherSDK SmartPublisherSetGopInterval:gop]; [self.publisherSDK SmartPublisherSetVideoBitRate:bitrate maxBitRate:bitrate];当前 SmartMacPublisher Demo 默认采用H.264 视频编码VideoToolbox 硬件编码AAC 音频编码可配置 FPS、GOP 和视频码率。SmartPublisherSDK 的视频编码接口也支持选择 H.265但在实际 RTMP 推流项目中是否采用 H.265还需要结合服务器、封装格式和播放端兼容性综合判断。对于通用 RTMP 直播链路H.264 仍然是兼容性更稳妥的选择对于私有 RTSP、局域网或明确支持 HEVC 的系统则可以评估 H.265。十、RTMP推流面向云端、中心服务器和业务平台RTMP 仍然是直播采集端最常见的上行协议之一。它的优势主要体现在流媒体服务器支持广泛CDN 和私有直播平台接入成熟推流端实现和部署相对简单适合从边缘采集端向中心服务器汇聚便于后续转码、录制、分发和内容审核。SmartMacPublisher 启动 RTMP 推流的代码很简洁NSString *url self.urlTextField.stringValue; NSInteger ret [self.publisherSDK SmartPublisherStartPublisher:url]; if (ret 0) { self.isRtmpPublishing YES; }真实项目中上层可以将地址替换为rtmp://server-address/live/stream-name摄像头模式适合企业活动直播在线面试会议转播客服讲解远程医疗咨询主播工具。屏幕或窗口模式则适合PPT 课件直播软件操作演示编程和技术培训工业控制界面共享远程售后支持金融行情和数据分析展示产品发布会和导播信号接入。需要说明的是低延迟不是单个推流接口决定的。最终端到端延迟还会受到以下因素影响采集帧率视频编码参数GOP 长度上行网络RTMP 服务器缓存转码和分发链路播放器缓冲策略。SmartMacPublisher 的目标是尽可能压缩采集端和编码端的排队与转换开销为后续低延迟链路提供基础。十一、轻量级RTSP服务让Mac直接成为局域网视频源RTMP 更适合将流推送到云端或中心服务器而 RTSP 更适合安防监控工业设备摄像机和 NVR局域网预览实验室联调边缘侧视频分发。SmartMacPublisher 内置了轻量级 RTSP 服务。Demo 默认使用static const NSInteger kRtspPort 8554; static NSString * const kRtspStreamName stream1;启动 RTSP 服务分为三个步骤self.rtspServerSDK [[SmartRTSPServerSDK alloc] init]; self.rtspServerHandle [self.rtspServerSDK OpenRtspServer:0]; [self.rtspServerSDK SetRtspServerPort:self.rtspServerHandle port:8554]; [self.rtspServerSDK StartRtspServer:self.rtspServerHandle reserve:0];随后把当前 SmartPublisherSDK 产生的媒体流绑定到该 RTSP Server[self.publisherSDK SetRtspStreamName:stream1]; [self.publisherSDK ClearRtspStreamServer]; [self.publisherSDK AddRtspStreamServer:self.rtspServerHandle reserve:0]; [self.publisherSDK StartRtspStream:0];局域网内的客户端即可通过类似地址播放rtsp://Mac的局域网IP:8554/stream1例如rtsp://192.168.1.100:8554/stream1这种模式不需要单独部署流媒体服务器Mac 本身就可以成为一个临时 RTSP 视频源。十二、轻量级RTSP服务适合哪些场景1. 局域网临时视频分发在展会、实验室或设备联调现场可以直接把 Mac 的摄像头或屏幕发布成 RTSP 流。其他电脑、移动终端或测试设备只需要知道 RTSP 地址就可以直接拉流。2. 工业现场预览工业软件、检测系统和控制界面经常运行在桌面端。将指定窗口采集后通过 RTSP 发布可以让局域网内的监控终端或远程操作站实时查看。3. 安防系统临时接入部分安防平台习惯以 RTSP 地址接入视频源。通过轻量级 RTSP 服务可以把 Mac 屏幕、USB 摄像头或采集卡包装成标准 RTSP 视频源降低现有系统的接入成本。4. 播放器和服务端测试开发低延迟播放器、录像系统、转发网关或视频分析程序时需要一个可控的视频源。相比依赖外部网络摄像机使用 Mac 直接生成 RTSP 流更容易切换不同分辨率调整码率和帧率产生屏幕动态内容复现特定问题对比不同播放器的延迟和稳定性。5. 无需中心服务器的小型系统对于只在局域网使用的小型项目单独部署大型流媒体服务器可能并不划算。轻量级 RTSP 服务可以直接嵌入业务程序减少安装、配置和运维成本。十三、RTMP与RTSP不是替代关系而是互补关系RTMP 和轻量级 RTSP 服务面向的链路并不相同。对比维度RTMP推流轻量级RTSP服务典型网络公网、专网、中心化网络局域网、设备网、边缘网络主要方向Mac主动推向服务器客户端主动从Mac拉流典型场景直播平台、云端汇聚、CDN安防、工业、本地预览、设备联调是否需要外部服务器通常需要不需要部署复杂度需要准备RTMP服务地址应用内启动即可链路特点适合中心化分发链路短、依赖少SmartMacPublisher 同时支持两种输出方式意味着一份采集数据可以服务多条业务链路摄像头 / 屏幕 / 窗口 │ ▼ SmartPublisherSDK │ ├── RTMP推送到中心服务器 ├── 发布到本地RTSP服务 ├── 本地MP4录像 └── 实时快照例如现场画面可以一路通过 RTMP 推送给远程平台同时通过 RTSP 提供给局域网监视器并在 Mac 本地完成录像留档。十四、音频采集麦克风与系统声音如何统一处理macOS 屏幕推流如果只有视频往往无法满足真实业务需求。常见音频需求包括老师讲课时采集麦克风播放课件视频时采集系统声音软件演示时采集讲解声音会议转播时采集会议音频游戏和多媒体内容采集应用声音。SmartMacPublisher 支持AVFoundation 麦克风采集ScreenCaptureKit 系统声音采集麦克风和系统声音之间的实时选择。麦克风音频格式macOS 麦克风默认可能输出 Float32、Non-Interleaved 的 PCM 数据而 SDK 的 AAC 编码链路需要规范的 PCM 输入。因此 Demo 在AVCaptureAudioDataOutput中明确要求audioOutput.audioSettings { AVFormatIDKey: (kAudioFormatLinearPCM), AVNumberOfChannelsKey: 1, AVLinearPCMBitDepthKey: 16, AVLinearPCMIsFloatKey: NO, AVLinearPCMIsBigEndianKey: NO, AVLinearPCMIsNonInterleaved: NO };也就是16-bitSigned Integer单声道Interleaved PCM。系统声音格式转换ScreenCaptureKit 输出的系统声音通常是 Float32 PCM。Demo 使用 Accelerate 框架中的 vDSP 将 Float32 转换为 Int16float scale 32767.0f; vDSP_vsmul(floatSamples, 1, scale, tempSamples, 1, sampleCount); vDSP_vclip(tempSamples, 1, low, high, tempSamples, 1, sampleCount); vDSP_vfixr16(tempSamples, 1, int16Samples, 1, sampleCount);与逐样本手工循环相比vDSP 更适合持续实时音频处理。推流中切换音频来源在屏幕采集模式下Demo 可以同时保持麦克风和系统声音采集再根据用户当前选择决定投递哪一路if (self.audioSourcePreferMic) { // 投递麦克风忽略系统声音 } else { // 投递系统声音忽略麦克风 }这样切换音频源时不必重新创建整个视频编码和推流链路。十五、录像与快照不仅要实时传输还要形成业务闭环真实项目中的推流工具通常不能只解决“把视频发出去”这一件事。很多场景还需要本地留档培训课程录像设备异常过程记录工业巡检取证软件操作回放直播问题复现监控画面抓拍远程协助操作记录。SmartMacPublisher 支持本地 MP4 录像。SDK 初始化时设置录像目录[self.publisherSDK SmartPublisherSetRecorderDirectory:recordDirectory]; [self.publisherSDK SmartPublisherSetRecorderFileMaxSize:200]; [self.publisherSDK SmartPublisherSetRecorderAudio:1]; [self.publisherSDK SmartPublisherSetRecorderVideo:1];Demo 默认将录像保存到~/Movies/SmartMacPublisher单个录像文件最大设置为 200MB达到上限后可自动切换到新文件。启动录像[self.publisherSDK SmartPublisherStartRecorder];停止录像[self.publisherSDK SmartPublisherStopRecorder];快照保存目录为~/Pictures/SmartMacPublisher保存当前帧[self.publisherSDK SmartPublisherSaveCurImage:imagePath];这些能力可以与 RTMP 和 RTSP 组合使用只录像只 RTMP 推流只发布 RTSPRTMP 推流同时录像RTSP 发布同时录像RTMP、RTSP、录像同时运行。这种多输出组合在工业、教育、安防和企业直播项目中非常实用。十六、事件回调上层必须知道链路正在发生什么推流不是一次普通的网络请求而是一个持续运行的状态机。上层应用必须知道是否开始连接是否连接成功是否连接失败是否发生断线SDK 是否准备重连当前发送是否出现延迟是否创建了新录像文件一个录像文件是否已经写入完成快照是否保存成功RTSP 地址是否生成RTSP 服务是否返回异常状态。SmartMacPublisher 通过SmartPublisherDelegate接收事件。例如case EVENT_DANIULIVE_ERC_PUBLISHER_CONNECTED: status RTMP推流中已连接; break; case EVENT_DANIULIVE_ERC_PUBLISHER_CONNECTION_FAILED: case EVENT_DANIULIVE_ERC_PUBLISHER_DISCONNECTED: status RTMP推流中重连中; break; case EVENT_DANIULIVE_ERC_PUBLISHER_SEND_DELAY: log [NSString stringWithFormat: 发送延迟%llu毫秒, param1]; break;录像和快照也会产生独立事件新录制文件创建 单个录像文件完成 快照保存成功 RTSP地址生成 RTSP服务器状态码没有事件回调时应用通常只能显示一个模糊的“推流中”。有了完整事件上层才能真正实现状态栏日志面板失败提示自动恢复提示运行健康监控业务统计和异常上报。十七、RTSP会话数查询服务启动不等于真的有人观看轻量级 RTSP 服务启动成功只能说明端口已经开始监听并不能说明已经有客户端连接。SmartMacPublisher 提供了会话数查询NSInteger sessionCount 0; [self.rtspServerSDK GetRtspServerClientSessionNumbers: self.rtspServerHandle session_numbers:sessionCount];这一能力可以用于UI 显示当前观看人数判断是否存在活跃客户端无客户端时降低采集频率无人观看时延迟启动某些业务设备运行状态监控限制最大客户端数量。对于嵌入式 RTSP 服务而言“可查询会话状态”比单纯提供一个启动接口更有工程价值。十八、资源释放与状态组合真正容易出问题的地方音视频应用中启动接口通常不难难的是正确停止。SmartMacPublisher 明确限制RTMP 推流、RTSP 流和录像没有停止之前不能直接停止采集。代码中会先检查if (self.isRtmpPublishing || self.isRecording || self.isRtspPublishing) { [self appendLog: 请先停止推流、RTSP流和录制再停止采集。]; return; }SDK 也只有在所有输出都停止后才会反初始化- (void)tryUninitSDK { if (self.isRtmpPublishing || self.isRecording || self.isRtspPublishing || !self.sdkInitialized) { return; } self.publisherSDK.delegate nil; [self.publisherSDK SmartPublisherUnInit]; self.publisherSDK nil; self.sdkInitialized NO; }这样的生命周期设计可以避免录像仍在写文件时释放 SDKRTSP 客户端仍在拉流时关闭编码器视频回调仍在执行时销毁对象摄像头指示灯无法关闭CoreAudio 回调未退出应用关闭时发生野指针访问。在停止采集时Demo 还会在对应串行队列中同步等待stopRunning完成确保回调真正结束后再释放相关对象。这些代码不一定是 Demo 中最“显眼”的部分却往往决定了产品是否能够长期稳定运行。十九、典型应用场景1. macOS同屏直播老师、培训师和工程师可以将整个屏幕或指定窗口推送到 RTMP 服务器。适用于在线教学技术培训软件演示产品发布金融投研设计协作远程售后支持。相比浏览器屏幕共享SDK 方案更适合需要私有化部署自定义 UI自定义推流协议本地录像低延迟播放与现有业务系统深度集成。2. 摄像头直播采集端使用 Mac 内置摄像头、USB 摄像头、采集卡或者 Continuity Camera可以快速构建 macOS 直播采集工具。适用于企业直播会议转播在线面试客服讲解医疗咨询远程培训。3. 工业视觉与远程巡检工业软件、检测界面和设备控制程序通常运行在桌面系统中。通过窗口采集可以只传输目标软件画面而不暴露整个桌面。视频既可以通过 RTMP 推送到远程调度中心也可以通过 RTSP 提供给局域网监控终端。4. 局域网轻量视频分发一台 Mac 可以临时充当视频源局域网内多个终端直接通过 RTSP 地址观看。适用于展会演示实验室测试设备联调会议室视频分发安防系统临时接入。5. 流媒体开发与测试SmartMacPublisher 可以快速产生可控的 RTMP 或 RTSP 测试流用于验证低延迟播放器RTMP服务器RTSP客户端转码服务录像服务视频分析程序弱网重连策略动态分辨率兼容性。相比使用固定网络摄像机Mac 屏幕和摄像头更容易制造不同的动态画面和测试条件。二十、SmartMediaKit macOS方案的技术优势结合 SmartMacPublisher 的实现这套方案的优势主要体现在以下几个方面。1. 采集源覆盖完整支持摄像头、麦克风、屏幕、窗口和系统声音覆盖 macOS 常见实时采集需求。2. 上层采集模型开放应用层通过 AVFoundation 和 ScreenCaptureKit 自主控制采集SDK 不限制业务如何选择和组合采集源。3. CMSampleBuffer接口边界清晰上层只需要投递编码前音视频数据编码、封装、推流、RTSP、录像和事件处理由 SDK 完成。4. 充分利用macOS硬件媒体能力摄像头 NV12 直通、VTPixelTransferSession 格式转换和 VideoToolbox 硬件编码有利于降低 CPU 占用与端侧延迟。5. 同时覆盖公网和局域网链路RTMP 适合云端与中心服务器轻量级 RTSP 服务适合局域网和边缘侧实时分发。6. 输出能力可以组合RTMP、RTSP、录像和快照可以围绕同一份采集数据协同运行。7. 工程细节相对完整Demo 不只是简单调用几个接口还处理了权限申请系统内容选择器摄像头设备枚举分辨率与帧率匹配首帧等待动态分辨率BGRA 转 NV12Float32 音频转 Int16音频源切换RTSP 会话查询事件状态更新SDK 生命周期安全停止和资源释放。这些内容正是从 Demo 走向真实产品时最容易踩坑的部分。二十一、为什么SmartMediaKit要补齐macOS推流能力从产品战略看macOS 推流并不是简单的平台补齐而是 SmartMediaKit 实时音视频链路向桌面端采集与边缘分发的一次延伸。过去的跨平台直播 SDK往往将 Mac 定位为播放器、监控端或调试端。但现在Mac 越来越多地参与实时内容生产作为课件和软件画面的采集端作为摄像头直播终端作为远程技术支持工具作为工业现场的视频采集节点作为局域网 RTSP 视频源作为直播和流媒体系统的测试信号发生器。因此一个完整的 macOS 实时音视频方案不能只有“播放”还需要同时具备采集 编码 推流 本地分发 录像 快照 状态管理SmartMacPublisher 展示的正是这样一条完整链路。二十二、总结大牛直播SDKSmartMediaKit推出 macOS 版低延迟 RTMP 推流和轻量级 RTSP 服务并不是简单地把其他平台接口移植到 Mac而是结合 macOS 桌面采集特点重新设计了一套更加开放的实时音视频架构。在这套架构中AVFoundation 负责摄像头和麦克风采集ScreenCaptureKit 负责屏幕、窗口和系统声音采集摄像头尽量直接输出 NV12屏幕 BGRA 通过 VTPixelTransferSession 转为 NV12系统声音通过 Accelerate/vDSP 转为 Int16 PCM音视频以CMSampleBufferRef投递给 SmartPublisherSDKSDK 负责 VideoToolbox 视频编码、AAC 音频编码、RTMP 推流、轻量级 RTSP 发布、MP4 录像、快照和事件回调。SmartMacPublisher 还重点处理了第一帧等待、真实分辨率获取、窗口尺寸变化、音频源切换、多输出状态组合以及安全资源释放等实际工程问题。对于正在开发以下产品的团队macOS 同屏直播摄像头直播采集端在线教学和远程培训工业视觉远程预览局域网 RTSP 分发企业私有化直播流媒体开发测试工具边推边录与视频留档系统SmartMediaKit macOS 推流方案可以减少重复开发底层音视频模块的成本让团队更快完成从采集、编码到分发和留档的完整业务闭环。从更长远的角度看macOS 已经不再只是实时视频的观看终端也正在成为桌面端内容生产、边缘采集和本地视频分发的重要节点。 CSDN官方博客音视频牛哥-CSDN博客