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

Bri*_*rie 0 ios avplayer icloud swift cloudkit

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

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

所以我认为我的主要问题是我无法弄清楚如何让视频文件实际播放,因为该文件没有扩展名。我曾尝试使用 URLByAppendingPathExtension() 将 '.mov' 附加到末尾,但无济于事。让我知道任何想法!

上传视频

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!)
            }
        })
    }
}
Run Code Online (Sandbox Code Playgroud)

下载视频

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")
                }
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

Moj*_*o66 5

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

- (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"];
}
Run Code Online (Sandbox Code Playgroud)

然后,在视图控制器,点AVPlayervideoURL代替asset.fileURL