将视频保存到图库并获取存储到图库的视频的路径

Posted

技术标签:

【中文标题】将视频保存到图库并获取存储到图库的视频的路径【英文标题】:Save video to the gallery and get the path for the video stored to Gallery 【发布时间】:2017-04-25 10:40:17 【问题描述】:

我想将从UIImagePickerController 中选择的视频保存到相册。 之后,我需要获取保存路径的 URL。我看到了一些预先存在的问题,这些问题使用 ALAssetsLibrary 来回答,现在已弃用。 喜欢:Save video on the gallery and store the path to the video

有人可以指导我使用Photo's framework 并达到上述预期结果。如果我在任何地方错了,请纠正我。

谢谢!!

【问题讨论】:

请参考这个你会知道如何处理 PHAsset github.com/SanjeetVerma/UIImagePicker-PHAsset-swift/blob/master/… 兄弟你的例子很好。但我仍然无法获取存储到图库的视频的路径。 您可以在该示例中获取视频的路径,例如 let videoPath = info[UIImagePickerControllerMediaURL] ! NSURL 只需签入该示例 是临时目录的链接。我想要存储在 Gallery 中的资产的 url。 让我们continue this discussion in chat. 【参考方案1】:

这对我来说非常有效。

斯威夫特 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.
                    )
            

【讨论】:

【参考方案2】:

首先,您需要在应用的 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,请参考 question's answer

【讨论】:

兄弟,我们从哪里获得保存的视频到图库的链接? 谢谢兄弟!将检查并回复您 它有效,兄弟!虽然有一些编辑让你从中提取 URL :) 我很快就会发布它。非常感谢您的努力。也是一个赞成票。 很高兴通知我,我会为其他人更新我的答案。我之前使用它获取了图像,但使用了其他一些过滤器。我根据你的要求更新了。 没关系。好吧,我也将我的答案从 lastObject 更新为 firstObject 以获取最新资产。【参考方案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
                 
            

【讨论】:

也会看看这个,如果它的行为更合适会更新。 在我们的例子中,它在 ios 13 中失败了,其他人确实面临同样的问题吗?它给出了 PHAssetChangeRequest.creationRequestForAssetFromVideo【参考方案4】:

这样试试吧!

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)
            )
      

【讨论】:

【参考方案5】:

这是 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);
                                      
                                  ];

【讨论】:

【参考方案6】:

我通过创建 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 用于通过 AVPlayerViewController 播放视频

导入 PhotosPhotosUI 以使用 PHAsset 保存视频。

希望对你有帮助!

【讨论】:

您首先将视频保存到文档目录,然后创建保存请求到画廊。为了避免应用程序的内存消耗,我只想保存它的画廊,然后从那里参考视频。 好的!!!为此,您可以参考此class 以直接从相册中保存和检索。

以上是关于将视频保存到图库并获取存储到图库的视频的路径的主要内容,如果未能解决你的问题,请参考以下文章

iOS:从网址下载视频并保存在图库中......?

为什么从Android应用程序下载的视频没有显示在图库中?

Android相机意图不应允许将图像保存到图库并将其存储在指定路径中

如何从图库中选择视频并获取其真实路径?

Android - 将图像存储到图库

Flutter 如何将图像文件保存到图库中的新文件夹?