ios - 显示和关闭 AVPlayer 控制器的问题
问题描述
所以我有一个应用程序可以拍摄和记录要发送到服务器并稍后查看的视频。
事件顺序如下 1. 录制视频 2. 添加过滤器或文本 3. 发送到服务器 4. 关闭 avplayer 并返回摄像头
一切正常,但在第四步,avplayer 永远不会完全解雇,我所看到的就是这个。
这是 avplayer 控制器上所有 UI 组件的图像减去实际视频。
我确保我调用了present 和dismiss,因此不存在我使用错误的视图控制器演示和dismissal 方法组合的问题。当我到达这个屏幕时,我必须再次按下 X 才能回到相机,这不应该是这种情况。
/// Add the story to firebase
func handleAddToStory() {
print("Attempting to add to story")
self.dismiss(animated: true, completion: nil)
// hide the color slider so we can return the image of the tapView that contains the text field if they added one
colorSlider.isHidden = true
colorSlider.isHidden = false
DispatchQueue.global(qos: .background).async {
print("This is run on the background queue")
let videoImage = self.imageWithView(inView: self.tapView)
// Export the video
self.video?.exportFilterVideo(videoComposition: self.avVideoComposition , completion: { (url) in
if let videoImage = videoImage {
let filterVideoAsset = AVAsset(url: url! as URL)
// Now merge the filtered video with tapView image which will contain the textfield if the user added one
Merge(config: .standard).overlayVideo(video: filterVideoAsset, overlayImage: videoImage, completion: { (finalVideoUrl) in
// Upload to firebase storage
let dateFormatter = ISO8601DateFormatter()
let timeStamp = dateFormatter.string(from: Date())
let uid = User.current.uid
let storageRef = Storage.storage().reference().child("event_stories").child(self.eventKey).child(uid).child(timeStamp + ".mp4")
StorageService.uploadVideo(finalVideoUrl! as URL, at: storageRef) { (downloadUrl) in
guard let downloadUrl = downloadUrl else {
return
}
let videoUrlString = downloadUrl.absoluteString
print(videoUrlString)
// Post to firebase
PostService.create(for: self.eventKey, for: videoUrlString)
}
}, progressHandler: { _ in })
} else {
let dateFormatter = ISO8601DateFormatter()
let timeStamp = dateFormatter.string(from: Date())
let uid = User.current.uid
let storageRef = Storage.storage().reference().child("event_stories").child(self.eventKey).child(uid).child(timeStamp + ".mp4")
StorageService.uploadVideo(url! as URL, at: storageRef) { (downloadUrl) in
guard let downloadUrl = downloadUrl else {
return
}
let videoUrlString = downloadUrl.absoluteString
print(videoUrlString)
PostService.create(for: self.eventKey, for: videoUrlString)
}
//svprogresshud insert here
}
})
DispatchQueue.main.async {
print("This is run on the main queue, after the previous code in outer block")
self.dismiss(animated: true, completion: nil)
self.videoPlayer?.replaceCurrentItem(with: nil)
}
}
}
这是处理添加到服务器的函数。有一些异步任务正在进行,但不应该篡改控制器的解雇,这可以在底部看到。有谁知道为什么视图控制器仍然存在?
下面是呈现上述视图控制器的代码片段。
if let event = self.event {
let video = AVURLAsset(url: videoURL)
let videoViewController = FilterVideoViewController(video: video)
videoViewController.event = event
SVProgressHUD.dismiss(completion: {
self.present(videoViewController, animated: false, completion: nil)
})
}
解决方案
These parts
video?.exportFilterVideo(videoComposition: avVideoComposition , completion: { (url) in
Merge(config: .standard).overlayVideo(video: filterVideoAsset, overlayImage: videoImage, completion: { (finalVideoUrl) in
are making the main thread very busy . so you need a background queue like
func handleAddToStory() {
print("Attempting to add to story")
// hide the color slider so we can return the image of the tapView that contains the text field if they added one
colorSlider.isHidden = true
let videoImage = self.imageWithView(inView: self.tapView)
colorSlider.isHidden = false
self.dismiss(animated:false, completion: nil)
self.videoPlayer?.replaceCurrentItem(with: nil)
DispatchQueue.main.asyncAfter(deadline: .now() + 0.7 ) {
video?.exportFilterVideo(videoComposition: avVideoComposition , completion: { (url) in
if let videoImage = videoImage {
let filterVideoAsset = AVAsset(url: url! as URL)
// Now merge the filtered video with tapView image which will contain the textfield if the user added one
Merge(config: .standard).overlayVideo(video: filterVideoAsset, overlayImage: videoImage, completion: { (finalVideoUrl) in
upload(finalVideoUrl! as URL)
}, progressHandler: { _ in })
} else {
upload(url! as URL)
}
})
}
}
func upload(_ url:URL) {
DispatchQueue.global().async {
let dateFormatter = ISO8601DateFormatter()
let timeStamp = dateFormatter.string(from: Date())
let uid = User.current.uid
let storageRef = Storage.storage().reference().child("event_stories").child(self.eventKey).child(uid).child(timeStamp + ".mp4")
StorageService.uploadVideo(url, at: storageRef) { (downloadUrl) in
guard let downloadUrl = downloadUrl else {
return
}
let videoUrlString = downloadUrl.absoluteString
print(videoUrlString)
PostService.create(for: self.eventKey, for: videoUrlString)
}
}
}
推荐阅读
- linux-kernel - USB:为什么USB设备模块会自动加载
- datetime - 为什么从 EST 到 UTC 的转换是 +5 小时而不是 +4?
- javascript - 在选择更改时重置容器中的内容
- sql - Postgres 表选择多列并将结果(列)动态转换为行 - 将列转置为行
- php - Laravel Api 请求在生产服务器上触发两次
- postgresql - Go SQL map 1:M 关系 json 数组切片
- android - 将 android 项目从 pc 移动到另一个,Firebase Auth 问题?
- tensorflow - 在 Pycharm 中同时运行两个 .py 文件时,GPU 同步失败
- laravel - 返回 0 作为没有数据的月份的数据
- excel - 如何使用 PhpSpreadsheet 隐藏列