如何在 CVImageBuffer 中实时叠加每个捕获帧的视图,而不是 post 过程
How to superimpose views over each captured frame inside CVImageBuffer, realtime not post process
我已经成功设置了一个基本的 AVCaptureSession
,它可以使用 AVCaptureFileOutputRecordingDelegate
录制视频并将其保存在设备上。我一直在搜索文档以了解我们如何在正在录制的视频之上添加统计叠加层。
即
如上图所示。我在视频预览层之上有多个叠加层。现在,当我保存我的视频输出时,我也想将这些视图合成到视频中。
到目前为止我尝试了什么?
- 老实说,我只是在互联网上四处游荡,寻找一个解释如何做到这一点的知名博客。但是没找到。
- 我读过一些地方可以通过创建
CALayer
并将其添加为子层来渲染文本层覆盖,如 following post 中所述。
- 但是,如果我想在正在录制的视频之上渲染
MapView
怎么办?另外,我不是在寻找屏幕截图。屏幕上的某些内容不会成为最终录制的一部分,因此我希望能够挑选将要组成的视图。
我在寻找什么?
- 方向。
- 没有直接的解决方案
- 文档 link 和 class 名称我应该阅读更多关于创建它的内容。
到目前为止的进度:
我已经明白我需要从 CMSampleBuffer
获取 CVImageBuffer
并在其上绘制文本。我仍然不清楚是否有可能以某种方式将 MapView 覆盖在正在录制的视频上。
帮助您实现目标的最佳方式是使用 Metal
框架。使用 Metal
摄像头有助于最大限度地减少对设备有限计算资源的影响。如果您正在尝试实现对相机传感器的最低开销访问,使用 AVCaptureSession
将是一个非常好的开始。
您需要从 CMSampleBuffer
中获取每一帧数据(您是对的),然后将一帧转换为 MTLTexture
。 AVCaptureSession
将通过委托回调从设备的相机不断向我们发送帧。
所有可用的叠加层也必须转换为 MTLTextures
。然后你可以用over
操作合成所有MTLTextures
层。
因此,在这里您可以找到 四部分 Metal Camera 系列.[=23= 中的所有必要信息]
这里是 link 到 博客:About Compositing in Metal。
此外,我想发布代码摘录(在 Metal 中使用 AVCaptureSession):
import Metal
guard let imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer) else {
// Handle an error here.
}
// Texture cache for converting frame images to textures
var textureCache: CVMetalTextureCache?
// `MTLDevice` for initializing texture cache
var metalDevice = MTLCreateSystemDefaultDevice()
guard
let metalDevice = metalDevice
where CVMetalTextureCacheCreate(kCFAllocatorDefault, nil, metalDevice, nil, &textureCache) == kCVReturnSuccess
else {
// Handle an error (failed to create texture cache)
}
let width = CVPixelBufferGetWidth(imageBuffer)
let height = CVPixelBufferGetHeight(imageBuffer)
var imageTexture: CVMetalTexture?
let result = CVMetalTextureCacheCreateTextureFromImage(kCFAllocatorDefault, textureCache.takeUnretainedValue(), imageBuffer, nil, pixelFormat, width, height, planeIndex, &imageTexture)
// `MTLTexture` is in the `texture` variable now.
guard
let unwrappedImageTexture = imageTexture,
let texture = CVMetalTextureGetTexture(unwrappedImageTexture),
result == kCVReturnSuccess
else {
throw MetalCameraSessionError.failedToCreateTextureFromImage
}
And here you can find a final project on a GitHub: MetalRenderCamera
我已经成功设置了一个基本的 AVCaptureSession
,它可以使用 AVCaptureFileOutputRecordingDelegate
录制视频并将其保存在设备上。我一直在搜索文档以了解我们如何在正在录制的视频之上添加统计叠加层。
即
如上图所示。我在视频预览层之上有多个叠加层。现在,当我保存我的视频输出时,我也想将这些视图合成到视频中。
到目前为止我尝试了什么?
- 老实说,我只是在互联网上四处游荡,寻找一个解释如何做到这一点的知名博客。但是没找到。
- 我读过一些地方可以通过创建
CALayer
并将其添加为子层来渲染文本层覆盖,如 following post 中所述。 - 但是,如果我想在正在录制的视频之上渲染
MapView
怎么办?另外,我不是在寻找屏幕截图。屏幕上的某些内容不会成为最终录制的一部分,因此我希望能够挑选将要组成的视图。
我在寻找什么?
- 方向。
- 没有直接的解决方案
- 文档 link 和 class 名称我应该阅读更多关于创建它的内容。
到目前为止的进度:
我已经明白我需要从 CMSampleBuffer
获取 CVImageBuffer
并在其上绘制文本。我仍然不清楚是否有可能以某种方式将 MapView 覆盖在正在录制的视频上。
帮助您实现目标的最佳方式是使用 Metal
框架。使用 Metal
摄像头有助于最大限度地减少对设备有限计算资源的影响。如果您正在尝试实现对相机传感器的最低开销访问,使用 AVCaptureSession
将是一个非常好的开始。
您需要从 CMSampleBuffer
中获取每一帧数据(您是对的),然后将一帧转换为 MTLTexture
。 AVCaptureSession
将通过委托回调从设备的相机不断向我们发送帧。
所有可用的叠加层也必须转换为 MTLTextures
。然后你可以用over
操作合成所有MTLTextures
层。
因此,在这里您可以找到 四部分 Metal Camera 系列.[=23= 中的所有必要信息]
这里是 link 到 博客:About Compositing in Metal。
此外,我想发布代码摘录(在 Metal 中使用 AVCaptureSession):
import Metal
guard let imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer) else {
// Handle an error here.
}
// Texture cache for converting frame images to textures
var textureCache: CVMetalTextureCache?
// `MTLDevice` for initializing texture cache
var metalDevice = MTLCreateSystemDefaultDevice()
guard
let metalDevice = metalDevice
where CVMetalTextureCacheCreate(kCFAllocatorDefault, nil, metalDevice, nil, &textureCache) == kCVReturnSuccess
else {
// Handle an error (failed to create texture cache)
}
let width = CVPixelBufferGetWidth(imageBuffer)
let height = CVPixelBufferGetHeight(imageBuffer)
var imageTexture: CVMetalTexture?
let result = CVMetalTextureCacheCreateTextureFromImage(kCFAllocatorDefault, textureCache.takeUnretainedValue(), imageBuffer, nil, pixelFormat, width, height, planeIndex, &imageTexture)
// `MTLTexture` is in the `texture` variable now.
guard
let unwrappedImageTexture = imageTexture,
let texture = CVMetalTextureGetTexture(unwrappedImageTexture),
result == kCVReturnSuccess
else {
throw MetalCameraSessionError.failedToCreateTextureFromImage
}
And here you can find a final project on a GitHub: MetalRenderCamera