swift camera swift-playground

No se puede capturar datos de video en Swift Playgrounds, no se llama al método delegado captureOutput AVCaptureVideoDataOutputSampleBufferDelegate



camera swift-playground (2)

Quiero acceder a la cámara del iPad en la aplicación Swift Playgrounds iPad. Descubrí que no es posible capturar datos de video, aunque mi área de juegos funciona bien.

captureOutput(_ captureOutput: AVCaptureOutput!, didOutputSampleBuffer sampleBuffer: CMSampleBuffer!, from connection: AVCaptureConnection!) , un método delegado del protocolo AVCaptureVideoDataOutputSampleBufferDelegate , no se llama. la aplicación

La vista en mi área de juegos se supone que muestra la vista de la cámara FaceTime. ¿Por qué no puedo mostrar la salida de la cámara a pesar de que Apple explícitamente dice que está permitido hacerlo ? Además, la aplicación Playground me pide permisos de cámara tan pronto como abra mi área de juegos, por lo que debería permitirse de alguna manera.

import UIKit import CoreImage import AVFoundation import ImageIO import PlaygroundSupport class Visage: NSObject, AVCaptureVideoDataOutputSampleBufferDelegate { var visageCameraView : UIView = UIView() fileprivate var faceDetector : CIDetector? fileprivate var videoDataOutput : AVCaptureVideoDataOutput? fileprivate var videoDataOutputQueue : DispatchQueue? fileprivate var cameraPreviewLayer : AVCaptureVideoPreviewLayer? fileprivate var captureSession : AVCaptureSession = AVCaptureSession() fileprivate let notificationCenter : NotificationCenter = NotificationCenter.default override init() { super.init() self.captureSetup(AVCaptureDevicePosition.front) var faceDetectorOptions : [String : AnyObject]? faceDetectorOptions = [CIDetectorAccuracy : CIDetectorAccuracyHigh as AnyObject] self.faceDetector = CIDetector(ofType: CIDetectorTypeFace, context: nil, options: faceDetectorOptions) } func beginFaceDetection() { self.captureSession.startRunning() } func endFaceDetection() { self.captureSession.stopRunning() } fileprivate func captureSetup (_ position : AVCaptureDevicePosition) { var captureError : NSError? var captureDevice : AVCaptureDevice! for testedDevice in AVCaptureDevice.devices(withMediaType: AVMediaTypeVideo){ if ((testedDevice as AnyObject).position == position) { captureDevice = testedDevice as! AVCaptureDevice } } if (captureDevice == nil) { captureDevice = AVCaptureDevice.defaultDevice(withMediaType: AVMediaTypeVideo) } var deviceInput : AVCaptureDeviceInput? do { deviceInput = try AVCaptureDeviceInput(device: captureDevice) } catch let error as NSError { captureError = error deviceInput = nil } captureSession.sessionPreset = AVCaptureSessionPresetHigh if (captureError == nil) { if (captureSession.canAddInput(deviceInput)) { captureSession.addInput(deviceInput) } self.videoDataOutput = AVCaptureVideoDataOutput() self.videoDataOutput!.videoSettings = [kCVPixelBufferPixelFormatTypeKey as AnyHashable: Int(kCVPixelFormatType_32BGRA)] self.videoDataOutput!.alwaysDiscardsLateVideoFrames = true self.videoDataOutputQueue = DispatchQueue(label: "VideoDataOutputQueue", attributes: []) self.videoDataOutput!.setSampleBufferDelegate(self, queue: self.videoDataOutputQueue!) if (captureSession.canAddOutput(self.videoDataOutput)) { captureSession.addOutput(self.videoDataOutput) } } visageCameraView.frame = UIScreen.main.bounds let previewLayer = AVCaptureVideoPreviewLayer(session: captureSession) previewLayer?.frame = UIScreen.main.bounds previewLayer?.videoGravity = AVLayerVideoGravityResizeAspectFill visageCameraView.layer.addSublayer(previewLayer!) } // NOT CALLED func captureOutput(_ captureOutput: AVCaptureOutput!, didOutputSampleBuffer sampleBuffer: CMSampleBuffer!, from connection: AVCaptureConnection!) { print("delegate method called!") } } class SmileView: UIView { let smileView = UIView() var smileRec: Visage! override init(frame: CGRect) { super.init(frame: frame) self.addSubview(smileView) self.translatesAutoresizingMaskIntoConstraints = false smileRec = Visage() smileRec.beginFaceDetection() let cameraView = smileRec.visageCameraView self.addSubview(cameraView) } required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } } let frame = CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height) let sView = SmileView(frame: frame) PlaygroundPage.current.liveView = sView


Creo que necesitas establecer la propiedad needsIndefiniteExecution para que la ejecución no se detenga una vez que se complete tu código. De manzana

De forma predeterminada, se ejecuta todo el código de nivel superior y, a continuación, se termina la ejecución. Al trabajar con código asíncrono, habilite la ejecución indefinida para permitir que la ejecución continúe después de que se alcance el final del código de nivel superior del patio de recreo. Esto, a su vez, le da tiempo a los subprocesos y devoluciones de llamada para ejecutar.

La edición del campo de juego detiene automáticamente la ejecución, incluso cuando la ejecución indefinida está habilitada.

Establezca needsIndefiniteExecution en true para continuar la ejecución después del final del código de nivel superior. configúrelo en falso para detener la ejecución en ese punto.

Así que el código posible al final será:

let frame = CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height) let sView = SmileView(frame: frame) PlaygroundPage.current.needsIndefiniteExecution = true PlaygroundPage.current.liveView = sView


Edición: esto debería haber sido arreglado :)

-

Edición: esto fue confirmado como un error por Apple.

He presentado un informe de error y actualizaré esta respuesta cuando llegue nueva información oficial.