关于NextLevel慢动作模式下Custom Buffer Rendering支持的技术咨询
Hey there, let's dig into this frustrating issue with NextLevel's custom buffer rendering failing in slow-motion recording mode! It’s so annoying when a feature works perfectly in standard mode but breaks when you switch to slow-mo, so let’s walk through the most likely oversights step by step:
Check pixel format & video setting compatibility
Slow-motion recording often uses different resolutions, frame rates, or pixel formats compared to standard recording. Your custom renderer might not be handling these variations. For example, some devices default tokCVPixelFormatType_420YpCbCr8BiPlanarFullRangefor slow-mo, while standard mode uses a different format. Make sure yourrenderPixelBuffermethod can handle the pixel format active in slow-mo mode—you might need to add format conversion logic if your watermark drawing relies on a specific color space.Re-enable custom rendering after switching modes
When you toggle to slow-motion, you probably reconfigure theAVCaptureSession(adjusting frame rates, resolutions, etc.). It’s easy to accidentally reset the custom buffer settings during this process. Double-check that after updating your session configuration for slow-mo, you explicitly set:nextLevel.isCustomBufferRenderingEnabled = true nextLevel.customBufferDelegate = selfThese settings can get wiped when you call
session.beginConfiguration()/commitConfiguration(), so re-applying them post-config is critical.Verify coordinate & size scaling for slow-mo resolutions
Slow-mo videos often use different dimensions (e.g., 1080p instead of 4K on some devices). If your watermark’s position/size is hardcoded for standard resolution, it might be drawn outside the frame or too small to see in slow-mo. UsenextLevel.videoDimensionsto get the real-time recording resolution, then calculate your watermark’s frame dynamically:let videoSize = nextLevel.videoDimensions let watermarkSize = CGSize(width: videoSize.width * 0.15, height: videoSize.height * 0.1) let watermarkRect = CGRect(x: videoSize.width - watermarkSize.width - 20, y: videoSize.height - watermarkSize.height - 20, width: watermarkSize.width, height: watermarkSize.height)Ensure thread-safe rendering
Slow-mo recording processes frames at a much higher rate (e.g., 120/240fps), which can expose thread conflicts if your rendering code isn’t properly queued. NextLevel uses a dedicatedrenderQueuefor custom buffer work—make sure all your drawing logic runs on this queue (or a serial queue you control) to avoid race conditions that might silently fail in high-frame-rate scenarios.Check for hardware acceleration conflicts
Some slow-mo recording configurations leverage specialized hardware encoding, which might clash with custom buffer rendering. Try disabling hardware acceleration temporarily in your video settings to test:nextLevel.videoSettings[AVVideoAllowHardwareAcceleratedVideoEncoderKey] = falseIf this fixes the issue, you’ll need to adjust your settings to balance hardware efficiency with custom rendering support.
Here’s a quick example of a robust renderPixelBuffer implementation that handles dynamic sizing and format compatibility:
extension YourViewController: NextLevelCustomBufferDelegate { func nextLevel(_ nextLevel: NextLevel, renderPixelBuffer pixelBuffer: CVPixelBuffer, for connection: AVCaptureConnection) -> CVPixelBuffer? { CVPixelBufferLockBaseAddress(pixelBuffer, .readOnly) defer { CVPixelBufferUnlockBaseAddress(pixelBuffer, .readOnly) } let width = CVPixelBufferGetWidth(pixelBuffer) let height = CVPixelBufferGetHeight(pixelBuffer) guard let context = CGContext(data: CVPixelBufferGetBaseAddress(pixelBuffer), width: width, height: height, bitsPerComponent: 8, bytesPerRow: CVPixelBufferGetBytesPerRow(pixelBuffer), space: CGColorSpaceCreateDeviceRGB(), bitmapInfo: CGImageAlphaInfo.premultipliedFirst.rawValue) else { return pixelBuffer } // Draw your watermark if let watermark = UIImage(named: "your_logo") { let watermarkSize = CGSize(width: width * 0.15, height: height * 0.1) let watermarkRect = CGRect(x: width - watermarkSize.width - 20, y: height - watermarkSize.height - 20, width: watermarkSize.width, height: watermarkSize.height) watermark.draw(in: watermarkRect) } return pixelBuffer } }
Start by checking if you’re re-enabling the custom buffer delegate after switching to slow-mo mode—that’s the most common culprit here. If that doesn’t fix it, move on to verifying the pixel format and dynamic sizing.
内容的提问来源于stack exchange,提问作者SharpAffair

