【问题标题】:my portraits videos gets rotated after load from url (AVURLAsset)从 url (AVURLAsset) 加载后,我的肖像视频会旋转
【发布时间】:2018-08-05 21:08:17
【问题描述】:

我有一个可以访问照片/视频库的选择器,但我的问题是当视频是纵向时,视频的宽度和高度会反转。 我写了一个补丁来检查视频的大小,当宽度大于高度时,它会旋转它。但显然它不适用于肖像以外的其他视频。

有没有办法访问视频的方向?或者欢迎任何其他解决此问题的方法。

这是我的 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()
            }
        }
    })
}

【问题讨论】:

    标签: ios swift swift3 avurlasset


    【解决方案1】:

    找到具有此属性的解决方案:videoTrack.preferredTransform

     ▿ CGAffineTransform
     - a : 0.0
     - b : 1.0
     - c : -1.0
     - d : 0.0
     - tx : 360.0
     - ty : 0.0
    

    当 tx 带有一个值时,表示视频已经旋转。使用简单的if else 旋转视频的图像,如果它已被旋转,将解决问题:

    extension UIImage {
        func imageRotatedByDegrees(oldImage: UIImage, deg degrees: CGFloat) -> UIImage {
            //Calculate the size of the rotated view's containing box for our drawing space
            let rotatedViewBox: UIView = UIView(frame: CGRect(x: 0, y: 0, width: oldImage.size.width, height: oldImage.size.height))
            let t: CGAffineTransform = CGAffineTransform(rotationAngle: degrees * CGFloat.pi / 180)
            rotatedViewBox.transform = t
            let rotatedSize: CGSize = rotatedViewBox.frame.size
            //Create the bitmap context
            UIGraphicsBeginImageContext(rotatedSize)
            let bitmap: CGContext = UIGraphicsGetCurrentContext()!
            //Move the origin to the middle of the image so we will rotate and scale around the center.
            bitmap.translateBy(x: rotatedSize.width / 2, y: rotatedSize.height / 2)
            //Rotate the image context
            bitmap.rotate(by: (degrees * CGFloat.pi / 180))
            //Now, draw the rotated/scaled image into the context
            bitmap.scaleBy(x: 1.0, y: -1.0)
            bitmap.draw(oldImage.cgImage!, in: CGRect(x: -oldImage.size.width / 2, y: -oldImage.size.height / 2, width: oldImage.size.width, height: oldImage.size.height))
            let newImage: UIImage = UIGraphicsGetImageFromCurrentImageContext()!
            UIGraphicsEndImageContext()
            return newImage
        }
    }
    

    希望对某人有所帮助

    【讨论】:

      猜你喜欢
      • 2011-05-05
      • 1970-01-01
      • 1970-01-01
      • 2021-11-02
      • 2017-11-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多