My app recognises an event using Vision and uses CMSampleBuffer to do so. After the event I am recording the video already using AVWriter successfully.
Now I want to record the full motion and thus record 1-2 seconds before the event occurred.
I tried pushing the CMSampleBuffer
into a ring buffer, but that starves the camera of buffers.
func captureOutput(_ output: AVCaptureOutput,
didOutput sampleBuffer: CMSampleBuffer,
from connection: AVCaptureConnection) {
// sends that to detectBall
/// Gets called by the camera every time there is a new buffer available
func detectBall(inBuffer buffer: CMSampleBuffer,
ballDetectionRequest: VNCoreMLRequest,
orientation: CGImagePropertyOrientation,
frame: NormalizedPoint,
updatingRingBuffer: PassthroughSubject<AppEnvironment.AVState.RingBufferItem, Never>
) throws {
// I tried to convert it into a CVPixelBuffer but its a shallow copy as well so it also starves the camera
let imageBuffer: CVPixelBuffer = CMSampleBufferGetImageBuffer(buffer)!
/// rotated 90 because of the cameras native landscape orientation
let visionHandler = VNImageRequestHandler(ciImage: croppedImage, options: [:])
try visionHandler.perform([ballDetectionRequest])
if let results = ballDetectionRequest as? [VNClassificationObservation] {
// Filter out classification results with low confidence
let filteredResults = results.filter { $0.confidence > 0.9 }
guard let topResult = results.first,
topResult.confidence > 0.9 else { return }
// print(" its a: \(topResult.identifier)")
// print("copy buffer")
updatingRingBuffer.send(AppEnvironment.AVState.RingBufferItem(
/// HERE IS THE PROBLEM: AS SOON AS I SEND IT SOMEWHERE ELSE THE CAMERA IS STARVED
buffer: imageBuffer,
ball: topResult.identifier == "ball")
How can I achieve to store these 1-2 seconds of video continuously without writing it to disk and then prepending it to the video file?
Thanks!