UISaveVideoAtPathToSavedPhotosAlbum无法将视频保存到相册

3
我正在尝试使用glimpse来记录UIView。它成功地将其保存到应用程序的文档文件夹中,但我还需要将其保存到用户的相机胶卷中。它没有保存到相机胶卷中,虽然我被提示允许应用程序访问我的相机胶卷,但它没有保存在任何相册中。
我尝试过很多代码,包括这个:
[self.glimpse startRecordingView:self.view onCompletion:^(NSURL *fileOuputURL) {
        NSLog(@"DONE WITH OUTPUT: %@", fileOuputURL.absoluteString);


      UISaveVideoAtPathToSavedPhotosAlbum(fileOuputURL.absoluteString,nil,nil,nil);





    }];

变成这样:

 ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
        [library writeVideoAtPathToSavedPhotosAlbum:fileOuputURL
                                    completionBlock:^(NSURL *assetURL, NSError *error){NSLog(@"hello");}];

日志已经打印,但视频并没有保存到相机胶卷中。 如果有人知道为什么不起作用,请告诉我!谢谢!

检查是否可以保存该视频,if ([library videoAtPathIsCompatibleWithSavedPhotosAlbum:contentURL]) {} - Thilina Chamath Hewagama
@ThilinaCháminHewagama 看起来视频不兼容,我收到了这个 NSLocalizedDescription=在此服务器上未找到请求的网址。} 有什么方法可以解决吗? - Jack
3个回答

22

问题在于提供的视频路径。请提供相对于URL的路径。

if UIVideoAtPathIsCompatibleWithSavedPhotosAlbum(fileUrl.relativePath) {
    UISaveVideoAtPathToSavedPhotosAlbum(fileUrl.relativePath, nil, nil, nil)
}

如果您添加了这个UIVideoAtPathIsCompatibleWithSavedPhotosAlbum检查,编译器将会显示文件的问题。


我可以说,当使用absoluteString时,UIVideoAtPathIsCompatibleWithSavedPhotosAlbum不会报告文件问题。只有在UISaveVideoAtPathToSavedPhotosAlbum失败时才会注意到问题。但是传递relativePath可以解决它。日志中的错误是“源文件:X不在/var/mobile/Media、/var/mobile/Library/ReplayKit或/var/mobile/Library/SMS/Attachments中,客户端没有访问权限”。 - Robin Daugherty

4
问题是您提供的视频路径为URL地址,因此您需要检查您的URL路径是否与视频保存兼容。如果您想将视频保存到相机胶卷中,只需传递URL并按照以下代码操作:
-(void)saveVideo:(NSString *)videoData withCallBack:(void(^)(id))callBack{
library = [[ALAssetsLibrary alloc] init];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

    NSData *yourVideoData=[NSData dataWithContentsOfURL:[NSURL URLWithString:videoData]];
    if (yourVideoData) {
        NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
        NSString *documentsDirectory = [paths objectAtIndex:0];

        NSString  *filePath = [NSString stringWithFormat:@"%@/%@", documentsDirectory,@"video.mp4"];


                 if([yourVideoData writeToFile:filePath atomically:YES])
                 {
                     NSURL *capturedVideoURL = [NSURL URLWithString:filePath];
                    //Here you can check video is compactible to store in gallary or not
                     if ([library videoAtPathIsCompatibleWithSavedPhotosAlbum:capturedVideoURL]) {
                         // request to save video in photo roll.
                         [library writeVideoAtPathToSavedPhotosAlbum:capturedVideoURL completionBlock:^(NSURL *assetURL, NSError *error) {
                             if (error) {
                                 callBack(@"error while saving video");
                                 NSLog(@"error while saving video");
                             } else{

                                     callBack(@"Video has been saved in to album successfully !!!");

                    }
                         }];
                     }
                }

    }
});


}

0

我在使用UISaveVideoAtPathToSavedPhotosAlbum时遇到了一个问题,那就是视频路径的扩展名。如果从应用程序中下载并保存到照片中的视频是"quicktime"格式,则会出现错误ALAssetsLibraryErrorDomain / PHPhotosErrorDomain。 以下方法解决了我的问题。 将视频路径扩展名更改为".mp4"即可解决问题。

public func download(url: URL, completion: @escaping ((URL?, Error?) -> Void)) {
    let cachesDirectoryUrl = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask).first!
    let pathExtension = url.pathExtension == "quicktime" ? "mp4" : url.pathExtension
    var lastPathComponent = url.lastPathComponent.components(separatedBy: ".").first
        lastPathComponent = lastPathComponent?.appending(".\(pathExtension)")
   let destinationUrl = cachesDirectoryUrl.appendingPathComponent(lastPathComponent ?? "")
   
    if url.isFileURL {
        completion(nil, nil)
    } else if FileManager.default.fileExists(atPath: destinationUrl.path) {
        completion(destinationUrl, nil)
    } else {
        URLSession.shared.downloadTask(with: url) { (location, response, error) in
            guard let tempLocation = location, error == nil else {
                completion(nil, error)
                return
            }

            try? FileManager.default.removeItem(at: destinationUrl)
            do {
                try FileManager.default.moveItem(at: tempLocation, to: destinationUrl)
                completion(destinationUrl, nil)
            } catch let error as NSError {
                completion(nil, error)
            }
        }.resume()
    }
}

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