IOS的Firebase存储无法从相机胶卷上传.MOV

时间:2017-12-06 19:38:50

标签: ios swift firebase firebase-storage phasset

我正在从PHAsset对象中检索URL(文件:///var/mobile/Media/DCIM/100APPLE/IMG_0840.MOV),并且能够在设备上重播视频。但是,当需要在Firebase存储上传/ putfile时,我甚至都没有得到我的completionHandler。

    //requesting url from asset
    PHImageManager.default().requestAVAsset(forVideo: asset, options: options, resultHandler: { (videoAsset, audioMix, info) in

            if let assetURL = videoAsset as? AVURLAsset {

               let url = assetURL.url

               //upload from url
            let storageRef = Storage.storage().reference().child("videos").child("\(memory.ID!)")
            let uploadMetaData = StorageMetadata()
            uploadMetaData.contentType = "video/quicktime" 
               self.storageRef.putFile(from: url, metadata: uploadMetaData) { (metaData, error) in

                if error != nil {
                    print(error!.localizedDescription)
                } 
            }

如果我使用这样的本地网址从AVFoundation捕获上传.mp4文件,(file:/// var / mobile / Containers / Data / Application / 209BB017-13C7-4432-AFE4-EC3A13469900 / Documents / ff49bbc9ac794ed28d6f25944f128933.mp4),它运行正常。

我还尝试在Firebase存储控制台上上传.MOV文件,这也有效。

由于

1 个答案:

答案 0 :(得分:1)

有时PHAssets不会返回我们的URLAsset,所以我们必须检查给定的资产是否是AVURLAsset,如果不是,我们必须将此资产保存在我们的文档目录中,然后从文档目录中获取URL。

func uploadVideoToFirebase(content: PHAsset) {
    let options = PHVideoRequestOptions()
    options.isNetworkAccessAllowed = true
    PHImageManager.default().requestAVAsset(forVideo: content, options: options) { (asset, mix, args) in
        if let asset = asset as? AVURLAsset {
            let url = asset.url
            // URL OF THE VIDEO IS GOT HERE
        } else {
            guard let asset = asset else {return}
            self.startAnimating(message: "Processing.")
            self.saveVideoInDocumentsDirectory(withAsset: asset, completion: { (url, error) in
                if let error = error {
                    print(error.localizedDescription)
                }
                if let url = url {
                    // SAVED IN DOCUMENTS DIRECTORY AND URL IS GOT HERE
                }
            })
        }
    }
}

保存到文档目录:

func saveVideoInDocumentsDirectory(withAsset asset: AVAsset, completion: @escaping (_ url: URL?,_ error: Error?) -> Void) {
    let manager = FileManager.default
    guard let documentDirectory = try? manager.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true) else {return}
    var outputURL = documentDirectory.appendingPathComponent("output")
    do {
        try manager.createDirectory(at: outputURL, withIntermediateDirectories: true, attributes: nil)
        let name = NSUUID().uuidString
        outputURL = outputURL.appendingPathComponent("\(name).mp4")
    }catch let error {
        print(error.localizedDescription)
    }
    //Remove existing file
    _ = try? manager.removeItem(at: outputURL)
    guard let exportSession = AVAssetExportSession(asset: asset, presetName: AVAssetExportPresetMediumQuality) else {return}
    exportSession.outputURL = outputURL
    exportSession.outputFileType = AVFileTypeMPEG4
    exportSession.exportAsynchronously {
        switch exportSession.status {
        case .completed:
            print("exported at \(outputURL)")
            completion(outputURL, exportSession.error)
        case .failed:
            print("failed \(exportSession.error?.localizedDescription ?? "")")
            completion(nil, exportSession.error)
        case .cancelled:
            print("cancelled \(exportSession.error?.localizedDescription ?? "")")
            completion(nil, exportSession.error)
        default: break
        }
    }
}

我们必须在成功上传后清除此不需要的视频,或在下次应用启动时将其清除。我在下一个应用程序启动时使用此方法清除它。

func clearDocumentsDirectory() {
    let manager = FileManager.default
    guard let documentDirectory = try? manager.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true) else {return}
    let outputURL = documentDirectory.appendingPathComponent("output")
    //Remove existing file
    _ = try? manager.removeItem(at: outputURL)
}

希望这有帮助。