我可以从我的应用程序中获取相机胶卷上视频的绝对URI并对其进行修改吗?

7
我想在iPhone相册中对视频执行操作,由于我将在我的应用程序内部使用本地的ffmpeg,因此需要绝对URI。
是否可以直接对视频进行操作?还是需要将视频复制到临时目录中,进行操作,然后再写回到相册?
3个回答

6

我阅读了一些文档和教程,基于这些研究回答以下问题。

能否直接操作视频文件?

是的(将其复制到临时目录中),不可以(不能在视频实际存储位置上进行操作)

看一下下面的图片和官方文档的引用:

enter image description here

使用 PhotoKit,您可以获取和缓存资产以进行显示和播放,编辑图像和视频内容,或管理包含大量资产的集合,例如相册、时刻和共享相册。

我们没有直接访问图像/视频实际存储位置的权限,而是使用PHAsset获得原始数据或表示形式。Asset对象是不可变的,因此我们无法直接对其执行操作。我们需要PHAssetChangeRequest来创建、删除、更改元数据或编辑照片资产的内容。

我需要将视频复制到临时目录中,进行操作,然后再写回相册吗?

是的,这就是正确的方式。


当然,用户可以直接编辑图像/视频,但是用户将会收到一个提示框来确认更改。请参考PHAsset类。 - Celeste
4
同意。但我的意思是直接到视频实际存储的原始位置。 - Sahil Manchanda
但是,如果我们尝试替换已编辑的视频,在删除未编辑的视频时,它会要求从“照片”中删除的权限,对吧?这可能看起来很奇怪,你不觉得吗? - Nayan Dave
2
@NayanDave 我们不需要删除原始视频。如果您查看 PHAssetChangeRequest 类,它们已经提到“编辑照片资产的内容”,这就是我们的情况:编辑视频。因此,用户只会被提示一次。 - Sahil Manchanda

3

如果您已经获取了资产,并且有PHFetchResult对象,请尝试:

var video = PHAsset() // the video to be edited 

 if video.canPerform(.content) {  // check if the selected PHAsset can be edited

  video.requestContentEditingInput(with: nil, completionHandler: { editingInput, _ in

  let videoAsset = editingInput?.audiovisualAsset // get tracks and metadata of the video and start editing
  let videoURL = (videoAsset as? AVURLAsset)?.url // This might be nil so better use videoAsset

        /*
         Start editing your video here


        */

  guard let input = editingInput else { return }
  let output = PHContentEditingOutput(contentEditingInput: input)
  let outputURL = output.renderedContentURL // URL at which you write/export the edited video, it must be a .mov file
  let editedVideo = NSData()  // suppose your video fileName is editedVideo.mov, I used NSData since I don't know what final edited object will be.
  editedVideo.write(to: outputURL, atomically: false)

  PHPhotoLibrary.shared().performChanges({
  let changeRequest = PHAssetChangeRequest(for: video)
  changeRequest.contentEditingOutput = output
               })
            })

        }

如果您正在使用默认图像选择器,则可以使用以下代码获取临时视频 URL:

 func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {

    let videoURL = info[UIImagePickerController.InfoKey.mediaURL] as! NSURL
    print(videoURL)  // file is already in tmp folder


     let video = info[UIImagePickerController.InfoKey.phAsset] as! PHAsset
        // implement the above code using this PHAsset 

   // your will still need to request photo library changes, and save the edited video and/or delete the older one

    }

0

我在我的项目中实现了类似这样的功能,希望能对你有所帮助。

我会展示所有集合视图中的项目并在选择时执行动作,你也可以获取所选视频的URL。

func getVideoFromCameraRoll() {
    let options = PHFetchOptions()
    options.sortDescriptors = [ NSSortDescriptor(key: "creationDate", ascending: false) ]
    options.predicate = NSPredicate(format: "mediaType = %d", PHAssetMediaType.video.rawValue)
    videos = PHAsset.fetchAssets(with: options)
    videoLibraryCV.reloadData()
}

func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
    return videos.count
}

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath)
    let asset = videos!.object(at: indexPath.row)
    let width: CGFloat = 150
    let height: CGFloat = 150
    let size = CGSize(width:width, height:height)
    cell.layer.borderWidth = 0.5
    cell.layer.borderColor = UIColor.lightGray.cgColor
    PHImageManager.default().requestImage(for: asset, targetSize: size, contentMode: PHImageContentMode.aspectFit, options: nil)
    {   (image, userInfo) -> Void in

        let imageView = cell.viewWithTag(1) as! UIImageView
        imageView.image = image

        let labelView = cell.viewWithTag(2) as! UILabel
        labelView.text = String(format: "%02d:%02d",Int((asset.duration / 60)),Int(asset.duration) % 60)
    }
    return cell
}

func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {
 let asset = photos!.object(at: indexPath.row)
 guard(asset.mediaType == PHAssetMediaType.Video)
 else {
  print("Not a valid video media type")
  return
 }

 PHCachingImageManager().requestAVAssetForVideo(asset, options: nil, resultHandler: {
  (asset: AVAsset ? , audioMix : AVAudioMix ? , info : [NSObject: AnyObject] ? ) in
  let asset = asset as!AVURLAsset
  print(asset.URL) // Here is video URL
 })

}

希望它能对你有用...:)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接