在 Swift 中正确移除 AVCaptureSession 和 PreviewLayer
Remove AVCaptureSession and PreviewLayer Properly in Swift
使用 iOS Swift 从 App 捕获视频源,并希望正确停止它。
现在,我创建了一个启动 AVCaptureSession 的按钮,并希望允许同一个按钮在用户喜欢时正确停止 AVCapture 会话。这将允许用户轻松开始和结束相机捕获。
我在使用时收到错误消息:
captureSession.stopRunning()
代码如下:
import UIKit
import AVFoundation
import Vision
class ViewController: UIViewController, AVCaptureVideoDataOutputSampleBufferDelegate {
// creates a new capture session
let captureSession = AVCaptureSession()
override func viewDidLoad() {
super.viewDidLoad()
setupLabel()
createButton()
}
func setupCaptureSession() {
// search for available capture devices
let availableDevices = AVCaptureDevice.DiscoverySession(deviceTypes: [.builtInWideAngleCamera], mediaType: AVMediaType.video, position: .back).devices
// get capture device, add device input to capture session
do {
if let captureDevice = availableDevices.first {
captureSession.addInput(try AVCaptureDeviceInput(device: captureDevice))
}
} catch {
print(error.localizedDescription)
}
// setup output for Model 1, add output to capture session
let captureOutput = AVCaptureVideoDataOutput()
captureSession.addOutput(captureOutput)
captureOutput.setSampleBufferDelegate(self, queue: DispatchQueue(label: "videoQueue"))
let previewLayer = AVCaptureVideoPreviewLayer(session: captureSession)
previewLayer.frame = view.frame
view.layer.addSublayer(previewLayer)
captureSession.startRunning()
}
// called everytime a frame is captured
func captureOutput(_ output: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection) {
guard let model_one = try? VNCoreMLModel(for: imagenet_ut().model) else { return }
let request = VNCoreMLRequest(model: model_one) { (finishedRequest, error) in
guard let results = finishedRequest.results as? [VNClassificationObservation] else { return }
guard let Observation = results.first else { return }
DispatchQueue.main.async(execute: {
// use model here
})
}
guard let pixelBuffer: CVPixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer) else { return }
// executes request
try? VNImageRequestHandler(cvPixelBuffer: pixelBuffer, options: [:]).perform([request])
self.label.text = "label text"
}
func setupLabel() {
let label: UILabel = {
let label = UILabel()
label.textColor = .white
label.translatesAutoresizingMaskIntoConstraints = false
label.text = "Label"
label.font = label.font.withSize(30)
return label
}90
view.addSubview(label)
label.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
label.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: -50).isActive = true
}
func createButton () {
let button = UIButton();
button.setTitle("Start Camera", for: .normal)
button.setTitleColor(UIColor.white, for: .normal)
button.frame = CGRect(x: 5, y: 710, width: 200, height: 100)
button.addTarget(self, action: #selector(ViewController.buttonPressed(_:)), for: .touchUpInside)
self.view.addSubview(button)
}
@objc func buttonPressed(_ sender: UIButton!) {
setupCaptureSession()
if let buttonTitle = sender.title(for: .normal) {
print(buttonTitle)
if buttonTitle == "Stop Camera" {
print("was stopped")
}
}
sender.setTitle("Stop Camera", for: .normal)
}
func stopCamera() {
captureSession.stopRunning() // error occurs here
}
}
停止捕获会话:)
func stopSession() {
if captureSession.isRunning {
DispatchQueue.global().async {
self.captureSession.stopRunning()
}
}
}
使用 iOS Swift 从 App 捕获视频源,并希望正确停止它。
现在,我创建了一个启动 AVCaptureSession 的按钮,并希望允许同一个按钮在用户喜欢时正确停止 AVCapture 会话。这将允许用户轻松开始和结束相机捕获。
我在使用时收到错误消息:
captureSession.stopRunning()
代码如下:
import UIKit
import AVFoundation
import Vision
class ViewController: UIViewController, AVCaptureVideoDataOutputSampleBufferDelegate {
// creates a new capture session
let captureSession = AVCaptureSession()
override func viewDidLoad() {
super.viewDidLoad()
setupLabel()
createButton()
}
func setupCaptureSession() {
// search for available capture devices
let availableDevices = AVCaptureDevice.DiscoverySession(deviceTypes: [.builtInWideAngleCamera], mediaType: AVMediaType.video, position: .back).devices
// get capture device, add device input to capture session
do {
if let captureDevice = availableDevices.first {
captureSession.addInput(try AVCaptureDeviceInput(device: captureDevice))
}
} catch {
print(error.localizedDescription)
}
// setup output for Model 1, add output to capture session
let captureOutput = AVCaptureVideoDataOutput()
captureSession.addOutput(captureOutput)
captureOutput.setSampleBufferDelegate(self, queue: DispatchQueue(label: "videoQueue"))
let previewLayer = AVCaptureVideoPreviewLayer(session: captureSession)
previewLayer.frame = view.frame
view.layer.addSublayer(previewLayer)
captureSession.startRunning()
}
// called everytime a frame is captured
func captureOutput(_ output: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection) {
guard let model_one = try? VNCoreMLModel(for: imagenet_ut().model) else { return }
let request = VNCoreMLRequest(model: model_one) { (finishedRequest, error) in
guard let results = finishedRequest.results as? [VNClassificationObservation] else { return }
guard let Observation = results.first else { return }
DispatchQueue.main.async(execute: {
// use model here
})
}
guard let pixelBuffer: CVPixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer) else { return }
// executes request
try? VNImageRequestHandler(cvPixelBuffer: pixelBuffer, options: [:]).perform([request])
self.label.text = "label text"
}
func setupLabel() {
let label: UILabel = {
let label = UILabel()
label.textColor = .white
label.translatesAutoresizingMaskIntoConstraints = false
label.text = "Label"
label.font = label.font.withSize(30)
return label
}90
view.addSubview(label)
label.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
label.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: -50).isActive = true
}
func createButton () {
let button = UIButton();
button.setTitle("Start Camera", for: .normal)
button.setTitleColor(UIColor.white, for: .normal)
button.frame = CGRect(x: 5, y: 710, width: 200, height: 100)
button.addTarget(self, action: #selector(ViewController.buttonPressed(_:)), for: .touchUpInside)
self.view.addSubview(button)
}
@objc func buttonPressed(_ sender: UIButton!) {
setupCaptureSession()
if let buttonTitle = sender.title(for: .normal) {
print(buttonTitle)
if buttonTitle == "Stop Camera" {
print("was stopped")
}
}
sender.setTitle("Stop Camera", for: .normal)
}
func stopCamera() {
captureSession.stopRunning() // error occurs here
}
}
停止捕获会话:)
func stopSession() {
if captureSession.isRunning {
DispatchQueue.global().async {
self.captureSession.stopRunning()
}
}
}