AVFoundation AVPlayer rotation

后端 未结 3 1805
独厮守ぢ
独厮守ぢ 2020-12-09 00:17

I am trying to rotate avplayer but when i rotate it ,it is rotated from the beginning,i want to rotate while i am playing it at any time and it should rotate from there.I am

3条回答
  •  忘掉有多难
    2020-12-09 00:50

    Swift 5 Version

    func rotateVideoPlayer(player: AVPlayer, degrees: CGFloat) -> AVPlayer? {
    
        let urlAsset = player.currentItem?.asset as! AVURLAsset
        let url = urlAsset.url
    
        var composition: AVMutableComposition?
        var videoComposition: AVMutableVideoComposition?
        var instruction: AVMutableVideoCompositionInstruction?
    
        let asset = AVURLAsset(url: url)
    
        var layerInstruction: AVMutableVideoCompositionLayerInstruction?
        var t1: CGAffineTransform?
        var t2: CGAffineTransform?
    
        var assetVideoTrack: AVAssetTrack?
        var assetAudioTrack: AVAssetTrack?
    
        if asset.tracks(withMediaType: AVMediaType.video).count != 0 {
            assetVideoTrack = asset.tracks(withMediaType: AVMediaType.video)[0]
        }
    
        if asset.tracks(withMediaType: AVMediaType.audio).count != 0 {
            assetAudioTrack = asset.tracks(withMediaType: AVMediaType.audio)[0]
        }
    
        let insertionPoint = CMTime.invalid
    
        composition = AVMutableComposition()
    
        if assetVideoTrack != nil {
    
            let compositionVideoTrack: AVMutableCompositionTrack = (composition?.addMutableTrack(withMediaType: AVMediaType.video, preferredTrackID: kCMPersistentTrackID_Invalid))!
            let timeRange = CMTimeRangeMake(start: CMTime.zero, duration: asset.duration)
    
            try! compositionVideoTrack.insertTimeRange(timeRange, of: assetVideoTrack!, at: insertionPoint)
    
        }
    
        if assetAudioTrack != nil {
    
            let compositionAudioTrack: AVMutableCompositionTrack = (composition?.addMutableTrack(withMediaType: AVMediaType.audio, preferredTrackID: kCMPersistentTrackID_Invalid))!
            let timeRange = CMTimeRangeMake(start: CMTime.zero, duration: asset.duration)
            try! compositionAudioTrack.insertTimeRange(timeRange, of: assetAudioTrack!, at: insertionPoint)
    
        }
    
        let width = Float((assetVideoTrack?.naturalSize.width)!)
        let height = Float((assetVideoTrack?.naturalSize.height)!)
        let toDiagonal = Float(sqrt(width * width + height * height))
        let toDiagonalAngle = Float(radiansToDegrees(acosf(width/toDiagonal)))
        let toDiagonalAngle2 = Float(90 - radiansToDegrees(acosf(width/toDiagonal)))
    
        var toDiagonalAngleComple: Float
        var toDiagonalAngleComple2: Float
        var finalHeight: Float = 0
        var finalWidth: Float = 0
    
        if degrees >= 0 && degrees <= 90 {
    
            toDiagonalAngleComple = toDiagonalAngle + Float(degrees)
            toDiagonalAngleComple2 = toDiagonalAngle2 + Float(degrees)
    
            let sinfValue = sinf(degreesToRadians(toDiagonalAngleComple))
            let sinfValue2 = sinf(degreesToRadians(toDiagonalAngleComple2))
    
            finalHeight = abs(toDiagonal * sinfValue)
            finalWidth = abs(toDiagonal * sinfValue2)
    
            let side1 = height * sinf(degreesToRadians(Float(degrees)))
            let side2 = 0.0
    
            t1 = CGAffineTransform(translationX: CGFloat(side1), y: CGFloat(side2))
    
        } else if degrees > 90 && degrees <= 180 {
    
            let degrees2 = Float(degrees - 90)
    
            toDiagonalAngleComple = toDiagonalAngle + degrees2
            toDiagonalAngleComple2 = toDiagonalAngle2 + degrees2
    
            let sinfValue = sinf(degreesToRadians(toDiagonalAngleComple2))
            let sinfValue2 = sinf(degreesToRadians(toDiagonalAngleComple))
    
            finalHeight = abs(toDiagonal * sinfValue)
            finalWidth = abs(toDiagonal * sinfValue2)
    
            let side1 = width * sinf(degreesToRadians(degrees2)) + height * cosf(degreesToRadians(degrees2))
            let side2 = height * sinf(degreesToRadians(degrees2))
    
            t1 = CGAffineTransform(translationX: CGFloat(side1), y: CGFloat(side2))
    
        } else if degrees >= -90 && degrees < 0 {
    
            let degrees2 = Float(degrees - 90)
            let degrees2abs = Float(abs(degrees))
    
            toDiagonalAngleComple = toDiagonalAngle + degrees2
            toDiagonalAngleComple2 = toDiagonalAngle2 + degrees2
    
            let sinfValue = sinf(degreesToRadians(toDiagonalAngleComple2))
            let sinfValue2 = sinf(degreesToRadians(toDiagonalAngleComple))
    
            finalHeight = abs(toDiagonal * sinfValue)
            finalWidth = abs(toDiagonal * sinfValue2)
    
            let side1 = 0
            let side2 = width * sinf(degreesToRadians(degrees2abs))
    
            t1 = CGAffineTransform(translationX: CGFloat(side1), y: CGFloat(side2))
    
        } else if degrees >= -180 && degrees < -90 {
    
            let degreesabs = Float(abs(degrees))
            let degreesPlus = degreesabs - 90
    
            toDiagonalAngleComple = toDiagonalAngle + Float(degrees)
            toDiagonalAngleComple2 = toDiagonalAngle2 + Float(degrees)
    
            let sinfValue = sinf(degreesToRadians(toDiagonalAngleComple))
            let sinfValue2 = sinf(degreesToRadians(toDiagonalAngleComple2))
    
            finalHeight = abs(toDiagonal * sinfValue)
            finalWidth = abs(toDiagonal * sinfValue2)
    
            let side1 = width * sinf(degreesToRadians(degreesPlus))
            let side2 = height * sinf(degreesToRadians(degreesPlus)) + width * cosf(degreesToRadians(degreesPlus))
    
            t1 = CGAffineTransform(translationX: CGFloat(side1), y: CGFloat(side2))
        }
    
        t2 = t1!.rotated(by: CGFloat(degreesToRadians(Float(degrees))))
    
        videoComposition = AVMutableVideoComposition()
        videoComposition?.renderSize = CGSize(width: CGFloat(finalWidth), height: CGFloat(finalHeight))
        videoComposition?.frameDuration = CMTimeMake(value: 1, timescale: 30)
    
        instruction = AVMutableVideoCompositionInstruction()
    
        instruction?.timeRange = CMTimeRangeMake(start: CMTime.zero, duration: composition!.duration)
    
        layerInstruction = AVMutableVideoCompositionLayerInstruction(assetTrack: (composition?.tracks[0])!)
    
    
        layerInstruction?.setTransform(t2!, at: CMTime.zero)
    
        instruction?.layerInstructions = NSArray(object: layerInstruction!) as! [AVVideoCompositionLayerInstruction]
        videoComposition?.instructions = NSArray(object: instruction!) as! [AVVideoCompositionInstructionProtocol]
    
        let playItem_ = AVPlayerItem(asset: composition!)
    
        playItem_.videoComposition = videoComposition
    
        var time: CMTime!
    
        time = CMTime.zero
    
        player.replaceCurrentItem(with: playItem_)
    
        player.seek(to: time, toleranceBefore: CMTime.zero, toleranceAfter: CMTime.zero)
    
        let exportSession = AVAssetExportSession(asset: composition!, presetName: AVAssetExportPresetMediumQuality)
    
        exportSession?.outputURL = URL(string: String(format: "%@_rotated", url as CVarArg))
        exportSession?.outputFileType = AVFileType.mov
        exportSession?.videoComposition = videoComposition
        exportSession?.shouldOptimizeForNetworkUse = true
        exportSession?.timeRange = CMTimeRangeMake(start: CMTime.zero, duration: asset.duration)
    
        exportSession?.exportAsynchronously(completionHandler: { () -> Void in
            print("Video exported")
        })
    
        return player
    
    }
    
    func degreesToRadians(_ input: Float) -> Float {
        let float: Float = 180
        return Float(input) * .pi / float
    }
    
    func radiansToDegrees(_ input: Float) -> Float {
        return Float(input) * 180 / .pi
    }
    

提交回复
热议问题