SCStreamUpdateFrameContentRect X coordinate always returns 48 instead of expected 0

SCStreamUpdateFrameContentRect X coordinate always returns 48 instead of expected 0

Environment

  • Device: MacBook Pro 13-inch
  • macOS: Sequoia 15.6.1
  • Xcode: 16.4
  • Framework: Screen Capture Kit

Issue Description

I'm experiencing an unexpected behavior with Screen Capture Kit where the SCStreamUpdateFrameContentRect X coordinate consistently returns 48 instead of the expected 0.

Code Context

I'm using SCContentSharingPicker to capture screen content and implementing the SCStreamOutput protocol to receive frame data. In my stream(_:didOutputSampleBuffer:of:) method, I'm extracting the content rect information from the sample buffer attachments:

func stream(_ stream: SCStream, didOutputSampleBuffer sampleBuffer: CMSampleBuffer, of type: SCStreamOutputType) {
    switch type {
    case .screen:
        guard let attachmentsArray = CMSampleBufferGetSampleAttachmentsArray(sampleBuffer, createIfNecessary: false) as? [[SCStreamFrameInfo: Any]] else {
            return
        }
        
        guard let attachments = attachmentsArray.first else { return }
        
        if !attachments.keys.contains(.contentRect) {
            return
        }
        
        print(attachments) // X coordinate always shows 48
/*
, __C.SCStreamFrameInfo(_rawValue: SCStreamUpdateFrameContentRect): {
    Height = 540;
    Width = 864;
    X = 48; <<-- unexpected offset
    Y = 0;
}]
*/
        return
    // ... other cases
    }
}

Expected vs Actual Behavior

  • Expected: X coordinate should be 0 (indicating the content starts at the left edge of the screen)
  • Actual: X coordinate is consistently 48
  • Visual verification: When I display the captured screen content, it appears correctly without any offset, suggesting the actual content should indeed start at X=0

Additional Information

  • The picker is configured with .singleDisplay mode
  • I'm excluding the current app's bundle ID from capture
  • The captured content visually appears correct, only the reported coordinates seem off

Main ViewModel Class


import Foundation
import ScreenCaptureKit
import SwiftUICore

class VM: NSObject, ObservableObject, SCContentSharingPickerObserver, SCStreamDelegate, SCStreamOutput {
    @State var isRecording = false

    // Error handling delegate
    func stream(_ stream: SCStream, didStopWithError error: Error) {
        DispatchQueue.main.async {
            self.isRecording = false
       }
    }
    
    var picker: SCContentSharingPicker?
    func createPicker() -> SCContentSharingPicker {
        if let p = picker {
            return p
        }

        let picker = SCContentSharingPicker.shared
        
        picker.add(self)
        picker.isActive = true
        
        SCContentSharingPicker.shared.present(using: .display)
        
        return picker
    }

    var stream: SCStream?
    
    let videoSampleBufferQueue = DispatchQueue(label: "com.example.apple-samplecode.VideoSampleBufferQueue")
    
    // observer call back for picker
    func contentSharingPicker(_ picker: SCContentSharingPicker, didUpdateWith filter:
    SCContentFilter, for stream: SCStream?) {
       if let stream = stream {
            stream.updateContentFilter(filter)
        } else {

            
            let config = SCStreamConfiguration()
            config.capturesAudio = false
            config.captureMicrophone = false
            config.captureResolution = .automatic
            config.captureDynamicRange = .SDR
            config.showMouseClicks = false
            config.showsCursor = false

            // Set the frame rate for screen capture
            config.minimumFrameInterval = CMTime(value: 1, timescale: 5) // 10 FPS
            
            self.stream = SCStream(filter: filter, configuration: config, delegate: self)
            
            do {
                try self.stream?.addStreamOutput(self, type: .screen, sampleHandlerQueue: self.videoSampleBufferQueue)
            } catch {
                print("\(error)")
            }
            
            self.stream?.updateContentFilter(filter)
            
            DispatchQueue.main.async {
                self.stream?.startCapture()
            }
        }
    }
    
    func contentSharingPicker(_ picker: SCContentSharingPicker, didCancelFor stream: SCStream?) {}
    
    func contentSharingPickerStartDidFailWithError(_ error: any Error) {
        print(error)
    }

    func stream(_ stream: SCStream, didOutputSampleBuffer sampleBuffer: CMSampleBuffer, of type: SCStreamOutputType) {
        
        switch type {
        case .screen:
            
            guard let attachmentsArray = CMSampleBufferGetSampleAttachmentsArray(sampleBuffer,
                                                                                 createIfNecessary: false) as? [[SCStreamFrameInfo: Any]] else {
                return
            }


            guard let attachments = attachmentsArray.first else { return }
        
            if !attachments.keys.contains(.contentRect) {
                return
            }
            print(attachments)
            return
        case .audio:
            return
        case .microphone:
            return
        @unknown default:
            return
        }
    }
    
    func outputVideoEffectDidStart(for stream: SCStream) {
        print("outputVideoEffectDidStart")
    }

    func outputVideoEffectDidStop(for stream: SCStream) {
        print("outputVideoEffectDidStop")
    }

    func streamDidBecomeActive(_ stream: SCStream) {
        print("streamDidBecomeActive")
    }

    func streamDidBecomeInactive(_ stream: SCStream) {
        print("streamDidBecomeInactive")
    }
}
SCStreamUpdateFrameContentRect X coordinate always returns 48 instead of expected 0
 
 
Q