Swift WebRTC修改CMSampleBuffer加人脸滤镜后卡顿、方向异常求助
问题1:视频卡顿的优化方案
- 移除不必要的线程切换:当前你把所有图像处理逻辑都放到了
DispatchQueue.main.async里执行,主线程需要响应UI交互,大量帧处理逻辑抢占主线程资源必然导致卡顿。你可以直接在captureOutput默认的串行队列中执行图像处理,仅需要更新UI类操作(比如人脸框展示)时再切主线程。 - 减少不必要的格式转换:当前流程
CMSampleBuffer -> CIImage -> CGImage -> UIImage -> 绘制 -> UIImage -> CVPixelBuffer -> CMSampleBuffer存在多次内存拷贝,你可以全程用Core Image完成操作,跳过UIImage的中间转换,能减少70%以上的处理耗时:全局复用同一个CIContext,把狗鼻子logo提前转成CIImage缓存,检测到人脸后直接用CIImage的composited(over:)方法叠加滤镜,再直接渲染到CVPixelBuffer即可。 - 跳帧执行人脸检测:人脸位置不会在短时间内发生大幅变化,不需要每帧都执行VN检测逻辑,可以设置计数每2-3帧检测一次,其余帧直接沿用上一次的人脸坐标叠加滤镜即可。
- 修复采样时间戳:当前你创建新CMSampleBuffer时用了
.invalid的CMSampleTimingInfo,会导致输出的帧时间戳混乱,播放器会出现跳帧、卡顿的观感,需要从原始的sampleBuffer中复制duration、presentationTimeStamp、decodeTimeStamp三个时间参数,赋值给新的sampleBuffer。 - 缓存常用资源:不要每次调用都执行
UIImage(named: "dog_nose"),提前把logo资源加载好缓存起来,避免重复IO读取。
// 从原始sampleBuffer复制时间信息示例 var timingInfo = CMSampleTimingInfo() CMSampleBufferGetSampleTimingInfo(sampleBuffer, at: 0, timingInfoOut: &timingInfo)
问题2:图像方向错误的修复方案
- 不要写死VNImageRequestHandler的orientation参数:相机采集的帧方向和设备当前朝向强相关,你需要根据
UIDevice.current.orientation或者connection.videoOrientation计算出正确的CGImagePropertyOrientation传入到VNImageRequestHandler初始化方法中,否则人脸检测返回的boundingBox坐标本身就是错的。 - 处理CIImage的方向信息:你当前转换CIImage到UIImage的时候没有携带原始的方向信息,导致生成的UIImage方向错误。可以在初始化UIImage的时候指定正确的orientation参数,或者用Core Image的
oriented(_:)方法先把CIImage转成方向正确的图像再做后续处理。 - 对齐绘制时的坐标翻转逻辑:当前你在
convertImageToBuffer方法里固定做了Y轴翻转,这个翻转逻辑只有当图像方向为up的时候才正确,如果原始帧是其他方向,需要对应调整翻转和偏移逻辑,或者直接用CIContext把CIImage渲染到CVPixelBuffer,不需要自己处理坐标翻转。
// 计算正确的图像方向示例 func imageOrientation(for connection: AVCaptureConnection) -> CGImagePropertyOrientation { switch connection.videoOrientation { case .portrait: return .right case .portraitUpsideDown: return .left case .landscapeLeft: return .up case .landscapeRight: return .down default: return .up } }
内容的提问来源于stack exchange,提问作者famfamfam
相关产品推荐
相关产品推荐

