【问题标题】:Use avfoundation to recrod video and save it to photo gallery ~ Swift5使用 avfoundation 录制视频并将其保存到照片库 ~ Swift 5
【发布时间】:2020-01-22 03:09:40
【问题描述】:

我下面的 swift 代码使用 avfoundation 拍摄照片并将其放在一个类中的 imageview 上。我想将此代码用作基础,并且仅当用户调用 func startVideo 进行录制时,然后当用户调用 saveVideo func 时,它会停止录制并将其保存到 imageivew 中。

import UIKit
import AVFoundation

class ViewController: UIViewController {

var captureSession = AVCaptureSession()
var backCamera: AVCaptureDevice?
var frontCamera: AVCaptureDevice?
var currentCamera: AVCaptureDevice?
var photoOutput: AVCapturePhotoOutput?

var cameraPreviewLayer: AVCaptureVideoPreviewLayer?
var image: UIImage?

override func viewDidLoad() {
    super.viewDidLoad()

    setupCaptureSession()
    setupDevice()
    setupInputOutput()
    setupPreviewLayer()
    startRunningCaptureSession()

    // Do any additional setup after loading the view, typically from a nib.
}

func setupCaptureSession () {
    captureSession.sessionPreset = AVCaptureSession.Preset.photo
}

 func setupDevice() {
    let deviceDiscoverySession = AVCaptureDevice.DiscoverySession(deviceTypes: [AVCaptureDevice.DeviceType.builtInWideAngleCamera], mediaType: AVMediaType.video, position: AVCaptureDevice.Position.unspecified)

    let devices = deviceDiscoverySession.devices

    for device in devices {
        if device.position == AVCaptureDevice.Position.back {
            backCamera = device
        } else if device.position == AVCaptureDevice.Position.front {
            frontCamera = device

        }
    }

    currentCamera = backCamera


}

func setupInputOutput() {
    do {
        let captureDeviceInput = try AVCaptureDeviceInput(device: currentCamera!)
        captureSession.addInput(captureDeviceInput)
        photoOutput = AVCapturePhotoOutput()
        photoOutput?.setPreparedPhotoSettingsArray([AVCapturePhotoSettings(format: [AVVideoCodecKey: AVVideoCodecType.jpeg])], completionHandler: nil)

        captureSession.addOutput(photoOutput!)

    } catch {
        print(error)
    }


}

func setupPreviewLayer () {

    cameraPreviewLayer = AVCaptureVideoPreviewLayer(session: captureSession)
    cameraPreviewLayer?.videoGravity = AVLayerVideoGravity.resizeAspectFill
    cameraPreviewLayer?.connection?.videoOrientation = AVCaptureVideoOrientation.portrait
    cameraPreviewLayer?.frame = self.view.frame
    self.view.layer.insertSublayer(cameraPreviewLayer!, at: 0)





}
func startRunningCaptureSession () {
    captureSession.startRunning()
}





@IBAction func startVideo(_ sender: Any) {

}


    @IBOutlet weak var photo: UIImageView!




    @IBAction func saveVideo(_ sender: Any) {


    }}

     extension ViewController: AVCapturePhotoCaptureDelegate {
 func photoOutput(_ output: AVCapturePhotoOutput, didFinishProcessingPhoto photo: AVCapturePhoto, error: Error?) {
    //contains the photo variable
    if let imageData = photo.fileDataRepresentation() {
        print(imageData)
        image = UIImage(data: imageData)



    }

}}

【问题讨论】:

  • 在 func cameraButton 中,我想在调用时开始录制视频。然后当调用 SaveButton 时,我希望视频停止录制,然后保存到 iPhone 的照片库中。
  • 我不知道如何 1 拍摄视频和 2 如何将其保存在图库中。我更改了我的功能名称
  • 它确实完成了一些任务,它在视图控制器上显示实时摄像机视图。这对我的要求很重要。

标签: swift video avfoundation avcapturevideodataoutput


【解决方案1】:

您可以通过创建AVCaptureMovieFileOutput 并将其添加到您的捕获会话,并使您的ViewController 符合AVCaptureFileOutputRecordingDelegate 来将录制的视频保存到文件中。

此示例将 5 秒的视频录制到应用程序的 Documents 目录中名为“output.mov”的文件中。

class ViewController: UIViewController, AVCaptureFileOutputRecordingDelegate {

    var captureSession = AVCaptureSession()
    var sessionOutput = AVCaptureStillImageOutput()
    var movieOutput = AVCaptureMovieFileOutput()
    var previewLayer = AVCaptureVideoPreviewLayer()

    @IBOutlet var cameraView: UIView!

    override func viewWillAppear(animated: Bool) {
        self.cameraView = self.view

        let devices = AVCaptureDevice.devicesWithMediaType(AVMediaTypeVideo)
        for device in devices {
            if device.position == AVCaptureDevicePosition.Front{


                do{

                    let input = try AVCaptureDeviceInput(device: device as! AVCaptureDevice)

                    if captureSession.canAddInput(input){

                        captureSession.addInput(input)
                        sessionOutput.outputSettings = [AVVideoCodecKey : AVVideoCodecJPEG]

                        if captureSession.canAddOutput(sessionOutput){

                            captureSession.addOutput(sessionOutput)

                            previewLayer = AVCaptureVideoPreviewLayer(session: captureSession)
                            previewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill
                            previewLayer.connection.videoOrientation = AVCaptureVideoOrientation.Portrait
                            cameraView.layer.addSublayer(previewLayer)

                            previewLayer.position = CGPoint(x: self.cameraView.frame.width / 2, y: self.cameraView.frame.height / 2)
                            previewLayer.bounds = cameraView.frame


                        }

                        captureSession.addOutput(movieOutput)

                        captureSession.startRunning()

                        let paths = NSFileManager.defaultManager().URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask)
                        let fileUrl = paths[0].URLByAppendingPathComponent("output.mov")
                        try? NSFileManager.defaultManager().removeItemAtURL(fileUrl)
                        movieOutput.startRecordingToOutputFileURL(fileUrl, recordingDelegate: self)

                        let delayTime = dispatch_time(DISPATCH_TIME_NOW, Int64(5 * Double(NSEC_PER_SEC)))
                        dispatch_after(delayTime, dispatch_get_main_queue()) {
                            print("stopping")
                            self.movieOutput.stopRecording()
                        }
                    }

                }
                catch{

                    print("Error")
                }

            }
        }

    }

    func captureOutput(captureOutput: AVCaptureFileOutput!, didFinishRecordingToOutputFileAtURL outputFileURL: NSURL!, fromConnections connections: [AnyObject]!, error: NSError!) {
        print("FINISHED \(error)")
        // save video to camera roll
        if error == nil {
            UISaveVideoAtPathToSavedPhotosAlbum(outputFileURL.path!, nil, nil, nil)
        }
    }

}

【讨论】:

  • 这在 swift 3、4.2 或 5 中是什么构建版本?
  • @YaoSmith 这在 2 中,但您可以在 Xcode > Devices > iPhone > app name > Download Container 中从设备下载 Documents 目录。您可以通过从 didFinishRecordingToOutputFileAtURL 委托方法调用 UISaveVideoAtPathToSavedPhotosAlbum() 将视频保存到相机胶卷。
  • 我能够将大部分代码转换为没有错误。但是,我在上面添加了一张带有错误的图片。如果你能告诉我要写什么,这样我就不会出错。我会给你赏金。
  • @YaoSmith 有一个“URL”类型的“appendingPathComponent”方法,方法是确保它是 URL 类型的变量let documentURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first! let fileURL = documentURL.appendingPathComponent("tempImage.jpg") 第二个错误您正在使用字符串参数调用该函数,但是该函数不带字符串参数。
  • 第二个错误我该怎么写? dispatch_time_t(DispatchTime.now()), Int64(5 * Double(NSEC_PER_SEC)))。 Dispatch_Time 导致错误。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-05-15
  • 2014-12-14
  • 1970-01-01
  • 2012-01-13
  • 1970-01-01
  • 2018-02-04
相关资源
最近更新 更多