将视频保存到相册并获取其在相册中的路径

6
我希望能将从UIImagePickerController选择的视频保存到照片相册中,并获取保存路径的URL。我看到一些现有的问题,回答使用了已经过时的ALAssetsLibrary。例如:Save video on the gallery and store the path to the video 请问有人能指导我如何使用Photo's framework来实现上述所需结果吗?如果我有任何错误,请指正。
谢谢!

1
请参考此链接,你将了解如何处理 PHAsset:https://github.com/SanjeetVerma/UIImagePicker-PHAsset-swift/blob/master/PhotoGalleryDemo/ViewController.swift - Bhupat Bheda
兄弟,你的例子很好。 但我仍然无法获取存储在相册中的视频路径。 - Ankit Kumar Gupta
1
在该示例中,您可以像这样获取视频路径:let videoPath = info[UIImagePickerControllerMediaURL] as!NSURL,只需在该示例中检查。 - Bhupat Bheda
1
这是指向临时目录的链接。我想要存储在画廊中的资产的 url。 - Ankit Kumar Gupta
1
让我们在聊天中继续这个讨论 - Bhupat Bheda
显示剩余2条评论
6个回答

18

这对我完美地起作用了。

Swift 3.1 ->

PHPhotoLibrary.shared().performChanges({
            PHAssetChangeRequest.creationRequestForAssetFromVideo(atFileURL: url!)
}) { saved, error in
            if saved {
                let fetchOptions = PHFetchOptions()
                fetchOptions.sortDescriptors = [NSSortDescriptor(key: "creationDate", ascending: true)]

                // After uploading we fetch the PHAsset for most recent video and then get its current location url

                let fetchResult = PHAsset.fetchAssets(with: .video, options: fetchOptions).lastObject 
                PHImageManager().requestAVAsset(forVideo: fetchResult!, options: nil, resultHandler: { (avurlAsset, audioMix, dict) in
                    let newObj = avurlAsset as! AVURLAsset
                    print(newObj.url) 
                    // This is the URL we need now to access the video from gallery directly.
                    })
            }
}

7

首先,在应用的plist文件中设置以下权限:

隐私 - 照片库使用说明

提供一个字符串,向用户解释您为什么要请求该权限。

接下来,

import photos

然后使用此代码存储视频。

    PHPhotoLibrary.shared().performChanges({
        PHAssetChangeRequest.creationRequestForAssetFromVideo(atFileURL: fileURL)
    }) { saved, error in
        if saved {
            let fetchOptions = PHFetchOptions()
            fetchOptions.sortDescriptors = [NSSortDescriptor(key: "creationDate", ascending: false)]

            let fetchResult = PHAsset.fetchAssets(with: .video, options: fetchOptions).firstObject
            // fetchResult is your latest video PHAsset
            // To fetch latest image  replace .video with .image
        }
    }

要从PHAsset获取url,请参考这个问题的答案

要从PHAsset中获取URL,请参考上述链接中的答案。

兄弟,我们从哪里获取保存视频到图库的链接? - Ankit Kumar Gupta
它可以工作了,兄弟!虽然需要进行一些编辑才能将URL提取出来 :) 我很快就会发布它。非常感谢你的努力。还有一个点赞。 - Ankit Kumar Gupta
尽管我有点混乱,但我们需要将升序设置为真,以便使用lastObject。 - Ankit Kumar Gupta
1
告诉我是很好的,我会更新我的答案给其他人看。我之前用过这个来获取图片,但是使用了其他一些过滤器。根据您的需求,我进行了更新。 - Surjeet Singh
1
没问题。好的,我已经更新了我的答案,从lastObject改为firstObject以获取最新的资产。 - Surjeet Singh
显示剩余2条评论

3

如果您想获取已保存的元素(没有使用日期排序描述符),可以按照以下方式进行:

var changeRequest: PHAssetChangeRequest?
var blockPlaceholder: PHObjectPlaceholder?

PHPhotoLibrary.shared().performChanges({
            changeRequest = PHAssetChangeRequest.creationRequestForAssetFromVideo(atFileURL: url!)
            blockPlaceholder = changeRequest?.placeholderForCreatedAsset
}) { saved, error in
            if saved {
                guard let placeholder = blockPlaceholder else {
                    return
                }
                let fetchOptions = PHFetchOptions()
                let fetchResult:PHFetchResult = PHAsset.fetchAssets(withLocalIdentifiers: [placeholder.localIdentifier], options: fetchOptions)
                if let asset = fetchResult.firstObject {
                    //here you have the PHAsset
                } 
            }
}

如果它表现得更合适,我会再看一下并进行更新。 - Ankit Kumar Gupta
在我们的情况下,它在iOS 13中失败了,有其他人遇到过同样的问题吗?它会给出PHAssetChangeRequest.creationRequestForAssetFromVideo。 - Andrea Leganza

1
这是关于Objective-C的答案。
代码示例:
 [[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
    [PHAssetChangeRequest creationRequestForAssetFromVideoAtFileURL:[NSURL URLWithString:urlOfFile]];
} completionHandler:^(BOOL success, NSError *error) {
                                      if (success)
                                      {
                                          PHFetchOptions *fetchOptions = [[PHFetchOptions alloc]init];
                                          fetchOptions.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"creationDate" ascending:false]];
                                          PHFetchResult *fetchResult = [PHAsset fetchAssetsWithMediaType:PHAssetMediaTypeVideo options:fetchOptions];
                                          PHAsset *lastAsset = [fetchResult lastObject];
                                          [[PHImageManager defaultManager] requestAVAssetForVideo:lastAsset options:nil resultHandler:^(AVAsset *asset, AVAudioMix *audioMix, NSDictionary *info) {
                                              //here's the url to the file
                                              NSURL *url = (NSURL *)[(AVURLAsset *)asset URL];


                                      }else{
                                          NSLog(@"%@",error.description);
                                      }
                                  }];

1

试试这样做!

func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : AnyObject]){
if mediaType.isEqualToString(kUTTypeMovie as NSString as String) || mediaType.isEqualToString(kUTTypeVideo as NSString as String){
    let videoPath = info[UIImagePickerControllerMediaURL] as! NSURL // Path of video Url
    PHPhotoLibrary.sharedPhotoLibrary().performChanges({
    let createAssetRequest = PHAssetChangeRequest.creationRequestForAssetFromVideoAtFileURL(videoPath)
    let assetPlaceholder = createAssetRequest?.placeholderForCreatedAsset
    let albumChangeRequest = PHAssetCollectionChangeRequest(forAssetCollection: self.assetCollection, assets: self.photosAsset)
            albumChangeRequest!.addAssets([assetPlaceholder!])
       }, completionHandler: { (success, error) in
                    NSLog("Adding video to Library ->%@", (success ? "Success" : "Error"))
                    picker.dismissViewControllerAnimated(true, completion: nil)
            })
      }
}

0

我通过创建URL类的扩展来实现这一点

extension URL {

    func saveVideo( success:@escaping (Bool,URL?)->()){


        URLSession.shared.downloadTask(with: URLRequest(url: self)) { (url, response, error) in

            let mgr = FileManager.default

            let documentsPath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0]


            let destination = URL(fileURLWithPath: String(format: "%@/%@", documentsPath, "video.mp4"))


            try? mgr.moveItem(atPath: /url?.path, toPath: /destination.path)

            PHPhotoLibrary.shared().performChanges({
                PHAssetChangeRequest.creationRequestForAssetFromVideo(atFileURL: destination)
            }) { completed, error in
                if completed {
                    print("Video is saved!")
                    success(true,destination)
                }
                if error != nil{
                    success(false,nil)
                }
            }
        }.resume()
    }
}

当您想要保存和播放时,可以在ViewController中使用以下代码:

guard let urlToDownload = URL(string: videoURLStringToDownload) else { return }

  urlToDownload.saveVideo(success: { (isSaved,url) in           
    guard let videoURL = url, isSaved else { return }

        let player = AVPlayer(url: videoURL)
          let playerViewController = AVPlayerViewController()
           playerViewController.player = player
          self.present(playerViewController, animated: true) {
                            playerViewController.player?.play()
          }
    })

使用 AVKit 播放器控制器播放视频。

使用 PhotosPhotosUI 保存视频到 PHAsset。

希望这能帮到你!


你先将视频保存到文档目录,然后创建保存请求到相册。为了避免应用程序的内存消耗,我只想将其保存到相册,然后从那里引用视频。 - Ankit Kumar Gupta
1
好的!!! 针对此问题,您可以参考此 class 直接从相册中保存和检索。 - Agent Smith

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