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
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
}