我正在从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文件,这也有效。
由于
答案 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)
}
希望这有帮助。