简体   繁体   English

使用相同的按钮/avfoundation swift 拍照和录制视频

[英]Taking photo & record video with same button / avfoundation swift

Currently when I tap capture photo button it takes a photo and the preview pops up and I can save the photo to my camera roll.目前,当我点击拍摄照片按钮时,它会拍照并弹出预览,我可以将照片保存到我的相机胶卷中。

I want to do the same thing with video, but I am having trouble getting video to record or even know how to get started.我想对视频做同样的事情,但我无法录制视频,甚至不知道如何开始。

I have used button.addTarget(self, action: #selector(handleCaptureVideo), for: .touchDown) and it prints "Video is recording..." so I see it working but I don't know what to put in there to get video to actually start recording.我使用过button.addTarget(self, action: #selector(handleCaptureVideo), for: .touchDown)并打印“视频正在录制......”所以我看到它工作但我不知道在那里放什么获取视频以实际开始录制。

import UIKit
import AVFoundation

class cameraController: UIViewController, AVCapturePhotoCaptureDelegate {

let capturePhotoButton: UIButton = {
    let button = UIButton(type: .system)
    button.setImage(#imageLiteral(resourceName: "capture_photo"), for: .normal)
    button.addTarget(self, action: #selector(handleCapturePhoto), for: .touchUpInside)
    button.addTarget(self, action: #selector(handleCaptureVideo), for: .touchDown)
    return button
}()

let settingsButton: UIButton = {
    let button = UIButton(type: .system)
    button.setImage(#imageLiteral(resourceName: "gear"), for: .normal)
    button.addTarget(self, action: #selector(handleSettings), for: .touchUpInside)
    return button
}()

let cameraFlipButton: UIButton = {
    let button = UIButton(type: .system)
    button.setImage(#imageLiteral(resourceName: "right_arrow_shadow"), for: .normal)
    button.addTarget(self, action: #selector(handleReversingCamera), for: .touchUpInside)
    return button
}()

override func viewDidLoad() {
    super.viewDidLoad()

    setupCameraSession()
    setupHUD()
    handleSettings()
    handleReversingCamera()

}

override var prefersStatusBarHidden: Bool {
    return true
}

fileprivate func setupHUD() {
    view.addSubview(capturePhotoButton)
    capturePhotoButton.anchor(top: nil, left: nil, bottom: view.bottomAnchor, right: nil, paddingTop: 0, paddingLeft: 0, paddingBottom: 24, paddingRight: 0, width: 80, height: 80)
    capturePhotoButton.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
}

@objc func handleCaptureVideo() {
    print("Video is recording...")

}

@objc func handleCapturePhoto() {
    print("Capturing Photo...")

    let settings = AVCapturePhotoSettings()
    guard let previewFormatType = settings.availablePreviewPhotoPixelFormatTypes.first else { return }
    settings.previewPhotoFormat = [kCVPixelBufferPixelFormatTypeKey as String: previewFormatType]

    output.capturePhoto(with: settings, delegate: self)

}

@objc func handleReversingCamera() {
    view.addSubview(cameraFlipButton)
    cameraFlipButton.anchor(top: nil, left: nil, bottom: view.bottomAnchor, right: view.rightAnchor, paddingTop: 0, paddingLeft: 0, paddingBottom: 48, paddingRight: 24, width: 50, height: 50)
    print("Camera just flipped...")

}

@objc func handleSettings() {
    view.addSubview(settingsButton)
    settingsButton.anchor(top: view.topAnchor, left: view.leftAnchor, bottom: nil, right: nil, paddingTop: 12, paddingLeft: 12, paddingBottom: 0, paddingRight: 0, width: 50, height: 50)
    let goToSettings = settingsViewController()
    let settingsController = UINavigationController(rootViewController: goToSettings)
    present(settingsController, animated: true, completion: nil)
    print("Settings Opened Up...")

}


func photoOutput(_ captureOutput: AVCapturePhotoOutput, didFinishProcessingPhoto photoSampleBuffer:
    CMSampleBuffer?, previewPhoto previewPhotoSampleBuffer: CMSampleBuffer?, resolvedSettings: AVCaptureResolvedPhotoSettings, bracketSettings: AVCaptureBracketedStillImageSettings?, error: Error?) {

    let imageData = AVCapturePhotoOutput.jpegPhotoDataRepresentation(forJPEGSampleBuffer: photoSampleBuffer!, previewPhotoSampleBuffer: previewPhotoSampleBuffer!)

    let previewImage = UIImage(data: imageData!)

    let containerView = PreviewPhotoContainerView()
    containerView.previewImageView.image = previewImage
    view.addSubview(containerView)
    containerView.anchor(top: view.topAnchor, left: view.leftAnchor, bottom: view.bottomAnchor, right: view.rightAnchor, paddingTop: 0, paddingLeft: 0, paddingBottom: 0, paddingRight: 0, width: 0, height: 0)

   /* let previewImageView = UIImageView(image: previewImage)
    view.addSubview(previewImageView)
    previewImageView.anchor(top: view.topAnchor, left: view.leftAnchor, bottom: view.bottomAnchor, right: view.rightAnchor, paddingTop: 0, paddingLeft: 0, paddingBottom: 0, paddingRight: 0, width: 0, height: 0)


    print("Did finish processing sample image buffer") */
}



// Capture Photo
let output = AVCapturePhotoOutput()
fileprivate func setupCameraSession() {
    let captureSession = AVCaptureSession()

    // 1. Setup Inputs

    let captureDevice = AVCaptureDevice.default(for: AVMediaType.video)

    do {
      let input = try AVCaptureDeviceInput(device: captureDevice!)
        if captureSession.canAddInput(input) {
        captureSession.addInput(input)
        }
    } catch let err {
        print("Could not print camera input:", err)
    }

    // 2. Setup Output
    if captureSession.canAddOutput(output) {
          captureSession.addOutput(output)
    }
    // 3. Setup Output Preview
    let previewLayer = AVCaptureVideoPreviewLayer(session: captureSession)
    previewLayer.frame = view.frame
    view.layer.addSublayer(previewLayer)
    previewLayer.videoGravity = .resizeAspectFill

    captureSession.startRunning()




}

You need to use AVCaptureMovieFileOutput and add it to your capture session.您需要使用AVCaptureMovieFileOutput并将其添加到您的捕获会话中。 To use the same button - you could have a long tap gesture recognizer on the button and start recording when long tap and stop recording when releasing the long tap.要使用相同的按钮 - 您可以在按钮上安装一个长按手势识别器,并在长按时开始录制并在松开长按时停止录制。 Something like Instagram stories.类似于 Instagram 故事。

Step 1第 1 步

Add movie file output添加电影文件输出

var movieFileOutput = AVCaptureMovieFileOutput()
captureSession?.addOutput(movieFileOutput)

Step 2第 2 步

Add long press gesture to your button为您的按钮添加长按手势

let longPressGesture = UILongPressGestureRecognizer.init(target: self, action: #selector(handleLongPress))
self.capturePhotoButton.addGestureRecognizer(longPressGesture);

Step 3第 3 步

Start and stop recording video on long tap长按开始和停止录制视频

func handleLongPress(gestureRecognizer: UILongPressGestureRecognizer) {

        if gestureRecognizer.state == UIGestureRecognizerState.began {
            debugPrint("long press started")
            let documentsURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0] as URL
            let filePath = documentsURL.appendingPathComponent("tempMovie.mp4")
            if FileManager.default.fileExists(atPath: filePath.absoluteString) {
                do {
                    try FileManager.default.removeItem(at: filePath)
                }
                catch {
                    // exception while deleting old cached file
                    // ignore error if any
                }
            }
            movieFileOutput?.startRecording(toOutputFileURL: filePath, recordingDelegate: self)
        }
        else if gestureRecognizer.state == UIGestureRecognizerState.ended {
            debugPrint("longpress ended")
            movieFileOutput?.stopRecording()
        }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM