我有一个可以访问照片/视频库的选择器,但我的问题是当视频是纵向时,视频的宽度和高度会倒置。我写了一个补丁来检查视频的大小,当宽度大于高度时,它会旋转它。但显然它不适用于肖像以外的其他视频。
有没有办法访问视频的方向?或者欢迎任何其他解决此问题的方法。
这是我的 adPicker 方法、imagePicker(didFinishPickingMediaWithInfo:) 委托方法和 getFramesFromVideo(fileUrl:) 方法的代码:
@objc func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
if let image = info[UIImagePickerControllerOriginalImage] as? UIImage{
editableView.drawnImage.image = image
initialVC.updateState(newState: .photoAdded)
initialVC.viewUpdater.updateContainerHeight()
}
else if let videoUrl = info[UIImagePickerControllerMediaURL] as? URL
{
imageManager.getFramesFromVideo(fileURL: videoUrl)
}
initialVC.dismiss(animated: true, completion: nil)
}
func addPicker()->UIAlertController{
let myAlert = UIAlertController()
guard let imagePicker = self.initialVC.imagePicker else {
fatalError()
return myAlert
}
for type in alertTypes{
let alertText = type == .photoGallery ? AlertText.typeGalery : type == .camera ? AlertText.typeCamera : type == .video ? AlertText.typeVideo : AlertText.typeCancel
myAlert.title = AlertText.title
myAlert.message = ""
let cameraAction = UIAlertAction(title : alertText, style : .default) { (action) in
imagePicker.delegate = self
imagePicker.allowsEditing = false
//type photo gallery
if type == .photoGallery && UIImagePickerController.isSourceTypeAvailable(.photoLibrary) {
imagePicker.sourceType = .photoLibrary
self.initialVC.present(imagePicker, animated: true, completion: nil)
}
//type camera
if type == .camera && UIImagePickerController.isSourceTypeAvailable(.camera) {
imagePicker.sourceType = .camera
self.initialVC.present(imagePicker, animated: true, completion: nil)
}
if type == .video {
imagePicker.mediaTypes = [String(kUTTypeMovie)]
imagePicker.videoQuality = .typeHigh
imagePicker.videoMaximumDuration = VideoTime.maxDuration
self.initialVC.present(imagePicker, animated: true, completion: nil)
}
if type == .cancel {
self.initialVC.dismiss(animated: true, completion: nil)
}
}
myAlert.addAction(cameraAction)
}
return myAlert
}
func getFramesFromVideo(fileURL: URL){
let asset = AVURLAsset(url: fileURL, options: nil)
let videoDuration = asset.duration
print(asset.metadata)
let generator = AVAssetImageGenerator(asset: asset)
generator.requestedTimeToleranceAfter = kCMTimeZero
generator.requestedTimeToleranceBefore = kCMTimeZero
var imageError : Error?
frameForTimes = [NSValue]()
let totalTimeLength = Int(videoDuration.seconds * Double(videoDuration.timescale))
let step = totalTimeLength / VideoTime.maxSampleCounts
for i in 0 ..< VideoTime.maxSampleCounts {
let cmTime = CMTimeMake(Int64(i * step), Int32(videoDuration.timescale))
frameForTimes.append(NSValue(time: cmTime))
}
generator.generateCGImagesAsynchronously(forTimes: frameForTimes, completionHandler: {requestedTime, image, actualTime, result, error in
DispatchQueue.main.async {
guard imageError == nil else {return}
if let image = image {
if self.tempImages.count != self.frameForTimes.count //avoid crash
{
self.videoFrameDelegate?.fillFramesFromVideo(frame: UIImage(cgImage: image))
self.tempImages.updateValue(self.frameForTimes[self.tempImages.count] as! CMTime, forKey: UIImage(cgImage: image))
print("image \(actualTime.seconds) loaded")
}
}
else if (error != nil) {
imageError = error
//TODO: Error handler
generator.cancelAllCGImageGeneration()
self.tempImages.removeAll()
self.videoFrameDelegate?.removeFrames()
print(error as Any)
}
// Completion handler
if self.tempImages.count == self.frameForTimes.count
{
print("frames ended loading")
self.tempImages.removeAll()
self.frameForTimes.removeAll()
self.videoFrameDelegate?.loadFrames()
}
}
})
}