播放通过CloudKit下载的视频作为CKAsset - iOS

时间:2015-10-01 02:03:56

标签: ios swift icloud avplayer cloudkit

我正在创建一个记录视频的应用程序,使用带有CKAsset的CloudKit将其上传到iCloud,然后下载该文件并在AVPlayer中播放。这都是用Swift 2.0编写的

我已经下载了数据,我想我已经能够引用它,但我不确定。当我将URL转换为NSData对象并将其打印到控制台时,数据/垃圾会打印。然而,视频文件作为二进制文件下载。我能够访问CloudKit仪表板并下载该文件并附加' .mov'对它来说,它在Quicktime中打开没问题。

所以我认为我的主要问题是我无法弄清楚如何让视频文件真正播放,因为该文件没有扩展名。我试过追加' .mov'最后用URLByAppendingPathExtension()无济于事。让我知道任何想法!

上传视频

func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : AnyObject]) {
    let tempURL = info[UIImagePickerControllerMediaURL] as! NSURL

    dismissViewControllerAnimated(true) { () -> Void in
        self.uploadVideoToiCloud(tempURL)
        print("\n     Before Upload: \(tempURL)\n")
    }
}

func uploadVideoToiCloud(url: NSURL) {
    let videoRecord = CKRecord(recordType: "video", recordID: id)

    videoRecord["title"] = "This is the title"

    let videoAsset = CKAsset(fileURL: url)
    videoRecord["video"] = videoAsset

    CKContainer.defaultContainer().privateCloudDatabase.saveRecord(videoRecord) { (record, error) -> Void in
        dispatch_async(dispatch_get_main_queue(), { () -> Void in
            if error == nil {
                print("upload successful")

            } else {
                print(error!)
            }
        })
    }
}

下载视频

func downloadVideo(id: CKRecordID) {

    privateDatabase.fetchRecordWithID(id) { (results, error) -> Void in

        dispatch_async(dispatch_get_main_queue()) { () -> Void in
            if error != nil {

                    print(" Error Fetching Record  " + error!.localizedDescription)
            } else {
                if results != nil {
                    print("pulled record")

                    let record = results!
                    let videoFile = record.objectForKey("video") as! CKAsset

                    self.videoURL = videoFile.fileURL

                    print("     After Download: \(self.videoURL!)")

                    self.videoAsset = AVAsset(URL: self.videoURL!)
                    self.playVideo()

                } else {
                    print("results Empty")
                }
            }
        }
    }
}

2 个答案:

答案 0 :(得分:2)

根本问题是AVPlayer需要文件扩展名,例如.mov,但CKAsset的{​​{1}}属性指向缺少扩展名的文件。最干净的解决方案是创建一个硬链接,避免混乱数兆字节的数据并且不需要磁盘空间:

fileURL

然后在视图控制器中,将- (NSURL *)videoURL { return [self createHardLinkToVideoFile]; } - (NSURL *)createHardLinkToVideoFile { NSError *err; if (![self.hardURL checkResourceIsReachableAndReturnError:nil]) { if (![[NSFileManager defaultManager] linkItemAtURL:self.asset.fileURL toURL:self.hardURL error:&err]) { // if creating hard link failed it is still possible to create a copy of self.asset.fileURL and return the URL of the copy } } return self.hardURL; } - (void)removeHardLinkToVideoFile { NSError *err; if ([self.hardURL checkResourceIsReachableAndReturnError:nil]) { if (![[NSFileManager defaultManager] removeItemAtURL:self.hardURL error:&err]) { } } } - (NSURL *)hardURL { return [self.asset.fileURL URLByAppendingPathExtension:@"mov"]; } 指向AVPlayer而不是videoURL

答案 1 :(得分:1)

解决方案最终是我在向其写入数据之前忘记指定文件名。我正在使用URLByAppendingPathExtension,它搞砸了URL,最后使用了URLByAppendingPathComponent并在那里添加了一个文件名。这是适合我的解决方案!感谢你们的评论。

func downloadVideo(id: CKRecordID) {

    privateDatabase.fetchRecordWithID(id) { (results, error) -> Void in

        dispatch_async(dispatch_get_main_queue()) { () -> Void in
            if error != nil {

                    print(" Error Fetching Record  " + error!.localizedDescription)
            } else {
                if results != nil {
                    print("pulled record")

                    let record = results as CKRecord!
                    let videoFile = record.objectForKey("video") as! CKAsset

                    self.videoURL = videoFile.fileURL as NSURL!
                    let videoData = NSData(contentsOfURL: self.videoURL!)

                    let documentsPath = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0]
                    let destinationPath = NSURL(fileURLWithPath: documentsPath).URLByAppendingPathComponent("filename.mov", isDirectory: false) //This is where I messed up.

                    NSFileManager.defaultManager().createFileAtPath(destinationPath.path!, contents:videoData, attributes:nil)

                    self.videoURL = destinationPath

                    self.videoAsset = AVURLAsset(URL: self.videoURL!)
                    self.playVideo()

                } else {
                    print("results Empty")
                }
            }
        }
    }
}