AVFoundation AVPlayer rotation

后端 未结 3 1795
独厮守ぢ
独厮守ぢ 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 01:03

    Thank you very much, Oleh Kudinov, You are awesome!

    Following is the swift version if anyone need it.

      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?
    
        // Check if the asset contains video and audio tracks
    
        if asset.tracksWithMediaType(AVMediaTypeVideo).count != 0
        {
            assetVideoTrack = asset.tracksWithMediaType(AVMediaTypeVideo)[0]
        }
    
        if asset.tracksWithMediaType(AVMediaTypeAudio).count != 0
        {
            assetAudioTrack = asset.tracksWithMediaType(AVMediaTypeAudio)[0]
        }
    
        let insertionPoint = kCMTimeInvalid
    
        // Step 1
    
        // Create a new composition
    
        composition = AVMutableComposition()
    
        // Insert a new composition
    
        if assetVideoTrack != nil {
    
            let compositionVideoTrack: AVMutableCompositionTrack = (composition?.addMutableTrackWithMediaType(AVMediaTypeVideo, preferredTrackID: kCMPersistentTrackID_Invalid))!
            let timeRange = CMTimeRangeMake(kCMTimeZero, asset.duration)
    
            try! compositionVideoTrack.insertTimeRange(timeRange, ofTrack: assetVideoTrack!, atTime: insertionPoint)
    
        }
    
        if assetAudioTrack != nil {
    
            let compositionAudioTrack: AVMutableCompositionTrack = (composition?.addMutableTrackWithMediaType(AVMediaTypeAudio, preferredTrackID: kCMPersistentTrackID_Invalid))!
            let timeRange = CMTimeRangeMake(kCMTimeZero, asset.duration)
    
            try! compositionAudioTrack.insertTimeRange(timeRange, ofTrack: assetAudioTrack!, atTime: insertionPoint)
    
        }
    
    
        // Step 2
    
        // Calculate position and size of render video after rotating
    
        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 = CGAffineTransformMakeTranslation(CGFloat(side1), 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 = CGAffineTransformMakeTranslation(CGFloat(side1), 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(degreesabs))
    
            t1 = CGAffineTransformMakeTranslation(CGFloat(side1), 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 = CGAffineTransformMakeTranslation(CGFloat(side1), CGFloat(side2))
        }
    
        // Rotate transformation
    
        t2 = CGAffineTransformRotate(t1!, CGFloat(degreesToRadians(Float(degrees))))
    
        //
        // Step 3
        //
        // Set the appropriate render sizes and rotational transforms
        //
    
        // Create a new video composition
        //        videoComposition = AVMutableComposition
        videoComposition = AVMutableVideoComposition()
        videoComposition?.renderSize = CGSizeMake(CGFloat(finalWidth), CGFloat(finalHeight))
        videoComposition?.frameDuration = CMTimeMake(1, 30)
    
        // The rotate transform is set on a layer instruction
        instruction = AVMutableVideoCompositionInstruction()
    
        instruction?.timeRange = CMTimeRangeMake(kCMTimeZero, composition!.duration)
    
        //
        // + videoCompositionLayerInstructionWithAssetTrack:
        // Returns a new mutable video composition layer instruction for the given track.
        //
        // Swift
        // convenience init(assetTrack track: AVAssetTrack)
        //
        // Objective-C
        // + (instancetype)videoCompositionLayerInstructionWithAssetTrack:(AVAssetTrack *)track
    
    
    
        // objectiv-c:
        //  layerInstruction = [AVMutableVideoCompositionLayerInstruction videoCompositionLayerInstructionWithAssetTrack:[composition.tracks objectAtIndex:0]];
    
        // Swift
        layerInstruction = AVMutableVideoCompositionLayerInstruction(assetTrack: (composition?.tracks[0])!)
    
    
        layerInstruction?.setTransform(t2!, atTime: kCMTimeZero)
    
        //
        // Step 4
        //
    
        // Add the transfor instructions to the video composition
    
        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 = kCMTimeZero
    
        player.replaceCurrentItemWithPlayerItem(playItem_)
    
        player.seekToTime(time, toleranceBefore: kCMTimeZero, toleranceAfter: kCMTimeZero)
    
        // Export rotated video to the file
    
        let exportSession = AVAssetExportSession(asset: composition!, presetName: AVAssetExportPresetMediumQuality)
    
        exportSession?.outputURL = NSURL(string: String(format: "%@_rotated", url))
        exportSession?.outputFileType = AVFileTypeQuickTimeMovie
        exportSession?.videoComposition = videoComposition
        exportSession?.shouldOptimizeForNetworkUse = true
        exportSession?.timeRange = CMTimeRangeMake(kCMTimeZero, asset.duration)
    
        exportSession?.exportAsynchronouslyWithCompletionHandler({ () -> Void in
            print("Video exported")
        })
    
        return player
    
    }
    

提交回复
热议问题