I'm new to swift and I make Live camera feed and hand track with vision
This is my code
import SwiftUI
import AVFoundation
import Vision
@MainActor
class Camera: NSObject, ObservableObject {
// MARK: - Properties
private var captureSession: AVCaptureSession?
private let videoOutput = AVCaptureVideoDataOutput()
@Published var previewLayer: AVCaptureVideoPreviewLayer?
private let sessionQueue = DispatchQueue(label: "CameraSessionQueue")
private let handPoseRequest: VNDetectHumanHandPoseRequest = {
let request = VNDetectHumanHandPoseRequest()
request.maximumHandCount = 1
return request
}()
override init() {
super.init()
Task {
await configureCaptureSession()
}
}
// MARK: - Capture Session Configuration
private func configureCaptureSession() async {
// Local capture session to avoid cross-thread isolation issues
let localCaptureSession = AVCaptureSession()
localCaptureSession.sessionPreset = .high
// Configure video input
guard let videoDevice = AVCaptureDevice.default(.builtInWideAngleCamera, for: .video, position: .back) else {
print("Error: Unable to access the camera")
return
}
do {
let videoInput = try AVCaptureDeviceInput(device: videoDevice)
guard localCaptureSession.canAddInput(videoInput) else {
print("Error: Unable to add video input")
return
}
localCaptureSession.addInput(videoInput)
} catch {
print("Error: \(error.localizedDescription)")
return
}
// Configure video output
videoOutput.setSampleBufferDelegate(self, queue: DispatchQueue(label: "VideoOutputQueue"))
guard localCaptureSession.canAddOutput(videoOutput) else {
print("Error: Unable to add video output")
return
}
localCaptureSession.addOutput(videoOutput)
// Assign the configured session to the main actor property
await MainActor.run {
self.captureSession = localCaptureSession
self.previewLayer = AVCaptureVideoPreviewLayer(session: localCaptureSession)
self.previewLayer?.videoGravity = .resizeAspectFill
}
}
// MARK: - Public Methods
func startSession() {
sessionQueue.async { [weak self] in
Task {
await self?.startCaptureSession()
}
}
}
func stopSession() {
sessionQueue.async { [weak self] in
Task {
await self?.stopCaptureSession()
}
}
}
private func startCaptureSession() async {
await MainActor.run {
captureSession?.startRunning()
}
}
private func stopCaptureSession() async {
await MainActor.run {
captureSession?.stopRunning()
}
}
var pointsProcessorHandler: (([CGPoint]) -> Void)?
func processPoints(_ fingerTips: [CGPoint]) {
guard let previewLayer = previewLayer else { return }
let convertedPoints = fingerTips.map {
previewLayer.layerPointConverted(fromCaptureDevicePoint: $0)
}
pointsProcessorHandler?(convertedPoints)
}
}
// MARK: - AVCaptureVideoDataOutputSampleBufferDelegate
extension Camera: AVCaptureVideoDataOutputSampleBufferDelegate {
nonisolated func captureOutput(_ output: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection) {
guard let pixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer) else { return }
let requestHandler = VNImageRequestHandler(cvPixelBuffer: pixelBuffer, options: [:])
do {
try requestHandler.perform([handPoseRequest])
if let results = handPoseRequest.results?.first {
let handLandmarks = try results.recognizedPoints(.all)
let fingerTipKeys: [VNHumanHandPoseObservation.JointName] = [
.thumbTip, .indexTip, .middleTip, .ringTip, .littleTip
]
// Map the detected points to an array of CGPoints
let fingerTips = fingerTipKeys.compactMap { handLandmarks[$0]?.location }
Task { @MainActor in
self.processPoints(fingerTips)
}
}
} catch {
print("Error performing hand pose request: \(error.localizedDescription)")
}
}
}
and error is
Main actor-isolated property 'handPoseRequest' can not be referenced from a nonisolated context
Is there any solution to fix it?
Thank you.