当我在 buttonTapped 函数或 AV fileOutput 中使用它上传视频时,函数的不同行为
Different behavior in a function when I use it in a buttonTapped function or in AV fileOutput to upload a video
我要上传一个视频,是AV录制的。
当我在 func fileOutput() 中使用我的 API 函数时它有效。
var urlToUpload: URL?
/// - Tag: DidFinishRecording
func fileOutput(_ output: AVCaptureFileOutput,
didFinishRecordingTo outputFileURL: URL,
from connections: [AVCaptureConnection],
error: Error?) {
urlToUpload = outputFileURL
PostApi.shared.uploadTOFireBaseVideo(url: urlToUpload!, userUid: "huhu", success: {
}) {
}
然而,当我这样称呼它时:
// Upload a post to Firestore
@IBAction func buttonSendPostTapped(_ sender: RoundedButton) {
print(urlToUpload!)
-> (Optional(file:///private/var/mobile/Containers/Data/Application/60C494F1-2C08-476A-81C2-052A51987682/tmp/517523BC-B84B-460D-81C9-2D8FDB4051BA.mov))
PostApi.shared.uploadTOFireBaseVideo(url: urlToUpload!, userUid: "huhu", success: {
}) {
}
}
它不会工作。
我如何上传数据:
let data = NSData(contentsOf: ur as URL) <- "data" 为零,当我从 buttonTapped 调用它并正常工作时,如果我从 fileOutput() 调用它.
为什么我的数据是零,当我从按钮点击时调用它?
// Upload media to firestore
func uploadTOFireBaseVideo(url: URL, userUid: String, success : @escaping () -> Void, failure : @escaping () -> Void) {
let db = Firestore.firestore()
let name = "\(Int(Date().timeIntervalSince1970)).mp4"
let dispatchgroup = DispatchGroup()
dispatchgroup.enter()
let documentsURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
let outputurl = documentsURL.appendingPathComponent(name)
var ur = outputurl
print(ur)
self.convertVideo(toMPEG4FormatForVideo: url as URL, outputURL: outputurl) { (session) in
ur = session.outputURL!
dispatchgroup.leave()
}
dispatchgroup.wait()
let data = NSData(contentsOf: ur as URL)
let storageRef = Storage.storage().reference().child("Media").child(name)
if let uploadData = data as Data? {
print("if let uploaded data")
storageRef.putData(uploadData, metadata: nil) { (metadata, error) in
if error != nil {
print(error!)
return
}
storageRef.downloadURL(completion: { (url, error) in
if error != nil {
print(error!)
return
}
let mediaUrl = url?.absoluteString
let dic = ["userUid" : userUid, "postMediaUrl" : mediaUrl ?? "No Media"] as [String : Any]
db.collection("posts-media").document(userUid).setData(dic)
{ err in
if let err = err {
print("Error adding document: \(err)")
failure()
return
} else {
print("Document added")
success()
}
}
})
}
}
}
// Additional function to convert a video to mp4
func convertVideo(toMPEG4FormatForVideo inputURL: URL, outputURL: URL, handler: @escaping (AVAssetExportSession) -> Void) {
let asset = AVURLAsset(url: inputURL as URL, options: nil)
let exportSession = AVAssetExportSession(asset: asset, presetName: AVAssetExportPresetHighestQuality)!
exportSession.outputURL = outputURL
exportSession.outputFileType = .mp4
exportSession.exportAsynchronously(completionHandler: {
handler(exportSession)
})
}
file:///private/var/mobile/Containers/Data/Application/60C494F1-2C08-476A-81C2-052A51987682/tmp/517523BC-B84B-460D-81C9-2D8FDB4051BA.mov
Optional(file:///private/var/mobile/Containers/Data/Application/60C494F1-2C08-476A-81C2-052A51987682/tmp/517523BC-B84B-460D-81C9-2D8FDB4051BA.mov)
进一步检查 fileOutput(...)
方法的实现。它的内部 cleanup()
例程在控制流离开删除临时视频文件的方法时被调用。这意味着在您的 buttonSendPostTapped
方法中,视频文件可能不再存在。
您需要确保 fileOutput(...)
将文件存储在一个保存位置,并在您完成后自行删除。
我要上传一个视频,是AV录制的。
当我在 func fileOutput() 中使用我的 API 函数时它有效。
var urlToUpload: URL?
/// - Tag: DidFinishRecording
func fileOutput(_ output: AVCaptureFileOutput,
didFinishRecordingTo outputFileURL: URL,
from connections: [AVCaptureConnection],
error: Error?) {
urlToUpload = outputFileURL
PostApi.shared.uploadTOFireBaseVideo(url: urlToUpload!, userUid: "huhu", success: {
}) {
}
然而,当我这样称呼它时:
// Upload a post to Firestore
@IBAction func buttonSendPostTapped(_ sender: RoundedButton) {
print(urlToUpload!)
-> (Optional(file:///private/var/mobile/Containers/Data/Application/60C494F1-2C08-476A-81C2-052A51987682/tmp/517523BC-B84B-460D-81C9-2D8FDB4051BA.mov))
PostApi.shared.uploadTOFireBaseVideo(url: urlToUpload!, userUid: "huhu", success: {
}) {
}
}
它不会工作。
我如何上传数据:
let data = NSData(contentsOf: ur as URL) <- "data" 为零,当我从 buttonTapped 调用它并正常工作时,如果我从 fileOutput() 调用它.
为什么我的数据是零,当我从按钮点击时调用它?
// Upload media to firestore
func uploadTOFireBaseVideo(url: URL, userUid: String, success : @escaping () -> Void, failure : @escaping () -> Void) {
let db = Firestore.firestore()
let name = "\(Int(Date().timeIntervalSince1970)).mp4"
let dispatchgroup = DispatchGroup()
dispatchgroup.enter()
let documentsURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
let outputurl = documentsURL.appendingPathComponent(name)
var ur = outputurl
print(ur)
self.convertVideo(toMPEG4FormatForVideo: url as URL, outputURL: outputurl) { (session) in
ur = session.outputURL!
dispatchgroup.leave()
}
dispatchgroup.wait()
let data = NSData(contentsOf: ur as URL)
let storageRef = Storage.storage().reference().child("Media").child(name)
if let uploadData = data as Data? {
print("if let uploaded data")
storageRef.putData(uploadData, metadata: nil) { (metadata, error) in
if error != nil {
print(error!)
return
}
storageRef.downloadURL(completion: { (url, error) in
if error != nil {
print(error!)
return
}
let mediaUrl = url?.absoluteString
let dic = ["userUid" : userUid, "postMediaUrl" : mediaUrl ?? "No Media"] as [String : Any]
db.collection("posts-media").document(userUid).setData(dic)
{ err in
if let err = err {
print("Error adding document: \(err)")
failure()
return
} else {
print("Document added")
success()
}
}
})
}
}
}
// Additional function to convert a video to mp4
func convertVideo(toMPEG4FormatForVideo inputURL: URL, outputURL: URL, handler: @escaping (AVAssetExportSession) -> Void) {
let asset = AVURLAsset(url: inputURL as URL, options: nil)
let exportSession = AVAssetExportSession(asset: asset, presetName: AVAssetExportPresetHighestQuality)!
exportSession.outputURL = outputURL
exportSession.outputFileType = .mp4
exportSession.exportAsynchronously(completionHandler: {
handler(exportSession)
})
}
file:///private/var/mobile/Containers/Data/Application/60C494F1-2C08-476A-81C2-052A51987682/tmp/517523BC-B84B-460D-81C9-2D8FDB4051BA.mov
Optional(file:///private/var/mobile/Containers/Data/Application/60C494F1-2C08-476A-81C2-052A51987682/tmp/517523BC-B84B-460D-81C9-2D8FDB4051BA.mov)
进一步检查 fileOutput(...)
方法的实现。它的内部 cleanup()
例程在控制流离开删除临时视频文件的方法时被调用。这意味着在您的 buttonSendPostTapped
方法中,视频文件可能不再存在。
您需要确保 fileOutput(...)
将文件存储在一个保存位置,并在您完成后自行删除。