首页 > 解决方案 > 修剪的快速视频仅保存未修剪的视频 Xcode 12 Swift 5

问题描述

根据本教程,我设置了一个简单的“录制”UIButton,我被带到相机,只能录制视频,拍摄视频后,我会被带到我可以修剪的视频编辑器屏幕。修剪后,我点击保存,视频成功保存到我的相机胶卷。但是,它只是保存未修剪的视频。(下面更新,使用 UIVideoEditorController,我现在在保存时得到 2 个未编辑的视频)。

代码如下:

VideoHelper.swift

import MobileCoreServices
import UIKit
import AVFoundation

enum VideoHelper {
  static func startMediaBrowser(
    delegate: UIViewController & UINavigationControllerDelegate & UIImagePickerControllerDelegate,
    sourceType: UIImagePickerController.SourceType
  ) {
    guard UIImagePickerController.isSourceTypeAvailable(sourceType)
      else { return }

    let mediaUI = UIImagePickerController()
    mediaUI.sourceType = sourceType //checks to see if a movie exists on the camera roll, the camera itself, and the photo library
    mediaUI.mediaTypes = [kUTTypeMovie as String] //allows only movies to be selected
    mediaUI.allowsEditing = true
    mediaUI.delegate = delegate
    delegate.present(mediaUI, animated: true, completion: nil)
  }
}

RecordVideoViewController.swift

import UIKit
import MobileCoreServices //contain predefined constants such as kUTTypeMovie which lets you select only video
import Photos
import AVFoundation

class RecordVideoViewController: UIViewController {
  @IBAction func record(_ sender: AnyObject) {
    VideoHelper.startMediaBrowser(delegate: self, sourceType: .camera) //opens the image picker and chooses the camera itself
    
  
  
  }
}
//MARK: - UIImagePickerControllerDelegate
extension RecordVideoViewController: UIImagePickerControllerDelegate {
  func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey: Any]) {
  dismiss(animated: true, completion: nil)
  
    guard
      let mediaType = info[UIImagePickerController.InfoKey.mediaType] as? String,
      mediaType == (kUTTypeMovie as String),
      
      //1 gives you the URL pointing to the video
      let url = info[UIImagePickerController.InfoKey.mediaURL] as? URL,
      
      //2 verify the app can save the file to the device's photo album
      UIVideoAtPathIsCompatibleWithSavedPhotosAlbum(url.path)
      else { return }
    
    //launches video editor
    guard UIVideoEditorController.canEditVideo(atPath: url.path) else { return }
    
    let editor = UIVideoEditorController()
    
    editor.videoPath = url.path
    editor.videoMaximumDuration = 10.0
    editor.videoQuality = .typeIFrame1280x720
    
    present(editor, animated: true, completion: nil)
    
      
    //3 if it can, save it
    UISaveVideoAtPathToSavedPhotosAlbum(
      url.path,
      self,
      #selector(video(_:didFinishSavingWithError:contextInfo:)),
      nil)
    
    }
    //Displays an alert announcing whether the video file was saved or not, based on the error status
    @objc func video(
      _ videoPath: String,
      didFinishSavingWithError error: Error?,
      contextInfo info: AnyObject
    ) {
        
      let title = (error == nil) ? "Success" : "Error"
      let message = (error == nil) ? "Video was saved" : "Video failed to save"
        
      let alert = UIAlertController(
        title: title,
        message: message,
        preferredStyle: .alert)
      alert.addAction(UIAlertAction(
        title: "OK",
        style: UIAlertAction.Style.cancel,
        handler: nil))
      present(alert, animated: true, completion: nil)
    }
  
 
  
}
//MARK: - UINavigationControllerDelegate
extension RecordVideoViewController: UINavigationControllerDelegate {
  
}

//MARK: - UIVideoEditorControllerDelegate
extension RecordVideoViewController: UIVideoEditorControllerDelegate {
  
}

我必须接近,因为我有一个成功的视频,只是我只想要修剪的版本。

更新到 RecordVideoViewController.swift

我现在添加了 UIVideoEditorDelegate,并实例化了委托,并设置了委托并实现了委托方法。它现在会生成两个保存的视频,其中没有一个是经过编辑的。

import UIKit
import MobileCoreServices //contain predefined constants such as kUTTypeMovie which lets you select only video
import Photos
import AVFoundation

class RecordVideoViewController: UIViewController {
  @IBAction func record(_ sender: AnyObject) {
    VideoHelper.startMediaBrowser(delegate: self, sourceType: .camera) //opens the image picker and chooses the camera itself
    
  
  
  }
}
//MARK: - UIImagePickerControllerDelegate
extension RecordVideoViewController: UIImagePickerControllerDelegate {
  func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey: Any]) {
  dismiss(animated: true, completion: nil)
  
    guard
      let mediaType = info[UIImagePickerController.InfoKey.mediaType] as? String,
      mediaType == (kUTTypeMovie as String),
      
      //1 gives you the URL pointing to the video
      let url = info[UIImagePickerController.InfoKey.mediaURL] as? URL,
      
      //2 verify the app can save the file to the device's photo album
      UIVideoAtPathIsCompatibleWithSavedPhotosAlbum(url.path),
    
     //****2.5?  Totally of the rails fromt he tutorial on this one:*****
      UIVideoEditorController.canEditVideo(atPath:url.path)
      else { return }
    
  
  
    //Must instantiate the UIVideoEditorController with "let editor = UIVideoEditorController()" and set the instance's delegate via self as well as show the file path

      let editor = UIVideoEditorController()
      editor.delegate = self

      editor.videoPath = url.path
  
      //presents the UIVideoEditorController
      self.present(editor, animated: true)
      print(editor.modalPresentationStyle.rawValue)
}
      // The UIVideoController's interface on the phone shows cancel and save buttons, which "do not" dismiss the presented view.  Must do that in the implementation of the delegate methods, of which there are 3.  And all 3 methods must be told to dismiss the presented view.
      // Delegate Method #1 (didSaveEditedVideoToPath): Called when the system has finished saving an edited movie.  At this point, the the trimmed video has already been saved to a file in app's temporary directory
  func videoEditorController(_ editor: UIVideoEditorController, didSaveEditedVideoToPath path: String) {
  self.dismiss(animated:true)
  
}
  

  //Delegate Method #2 (videoEditorControllerDidCancel): Called when the user has cancelled a movie editing operation
  func videoEditorControllerDidCancel(_ editor: UIVideoEditorController) {
  self.dismiss(animated:true)
}

  //Delegate Method #3 (didFailWithError): Called when the video editor is unable to load or save a movie.  Important as things "can" fail at this point.  MMhmmm
  func videoEditorController(_ editor: UIVideoEditorController, didFailWithError error: Error) {
  self.dismiss(animated:true)

    
    //***back on the rails with the tutorial, hope this works***
    
  //3 if it can, save it
  UISaveVideoAtPathToSavedPhotosAlbum(
    editor.videoPath,
    self,
    #selector(video(_:didFinishSavingWithError:contextInfo:)),
    nil)
    
    }
  //Displays an alert announcing whether the video file was saved or not, based on the error status
  @objc func video(
    _ videoPath: String,
    didFinishSavingWithError error: Error?,
    contextInfo info: AnyObject
    ) {
        
    let title = (error == nil) ? "Success" : "Error"
    let message = (error == nil) ? "Video was saved" : "Video failed to save"
        
    let alert = UIAlertController(
      title: title,
      message: message,
      preferredStyle: .alert)
    alert.addAction(UIAlertAction(
      title: "OK",
      style: UIAlertAction.Style.cancel,
      handler: nil))
    present(alert, animated: true, completion: nil)
    }
  
 
  
}
//MARK: - UINavigationControllerDelegate
extension RecordVideoViewController: UINavigationControllerDelegate {
  
}

//MARK: - UIVideoEditorControllerDelegate
extension RecordVideoViewController: UIVideoEditorControllerDelegate {
  
}

标签: iosswift

解决方案


iOS 中的代码不会神奇地“等待”某事发生。所以,当你这样说时:

let editor = UIVideoEditorController()
// ...
present(editor, animated: true, completion: nil)
UISaveVideoAtPathToSavedPhotosAlbum(

...您展示了编辑器,但您无需等待用户查看编辑器并进行修剪,而是立即继续保存原始视频。

那你怎么等?好吧,看看UIVideoEditorController 文档。它有一个委托。您必须设置该委托(没有一个您不能使用视频编辑器控制器),并且您必须在您的委托中实现委托方法。结果,该方法将被调用——在用户编辑之后!当它被调用时,它会被交给编辑过的视频!这就是您进行保存的地方。


推荐阅读