hello i'm combining two videos with AVMutableVideoComposition() and it works good with landscape videos and portrait videos downloaded from youtube but when try portrait video recorded in iPhone or android the exported video comes as landscape/horizontal instead of original portrait/ vertical.
if researched lot on stack overflow and google but couldn't find any working solution.
this raywenderlich's article explains very well why video is in landscape mode and provides solution mathod in Orienting Video section of article, that first checks if video is portrait and then sets it's height width and preferredOrientation. but it doesn't work anymore.
i tried manually setting AVAssetTrack's .preferredTransform to CGAffineTransform(a: 0.0, b: 1.0, c: -1.0, d: 0.0, tx: 0.0, ty: 0.0) but doesn't work.
many old answer suggest setting AVAssetTrack's .preferredTransform to AvAsset's preferredTransform but it doesn't work.
from AVAssetTrack's .preferredTransform i'm able to know if video is portrait or not but not able to change it, any help will be really appreciated, thank you.
After searching and trying many things i did this to solve the problem, first i check orientation with this function from raywenderlich article.
func orientationFromTransform(
_ transform: CGAffineTransform
) -> (orientation: UIImage.Orientation, isPortrait: Bool) {
var assetOrientation = UIImage.Orientation.up
var isPortrait = false
let tfA = transform.a
let tfB = transform.b
let tfC = transform.c
let tfD = transform.d
if tfA == 0 && tfB == 1.0 && tfC == -1.0 && tfD == 0 {
assetOrientation = .right
isPortrait = true
} else if tfA == 0 && tfB == -1.0 && tfC == 1.0 && tfD == 0 {
assetOrientation = .left
isPortrait = true
} else if tfA == 1.0 && tfB == 0 && tfC == 0 && tfD == 1.0 {
assetOrientation = .up
} else if tfA == -1.0 && tfB == 0 && tfC == 0 && tfD == -1.0 {
assetOrientation = .down
}
return (assetOrientation, isPortrait)
}
and store it
let firstAssetInfo = orientationFromTransform(firstVideoTrack!.preferredTransform)
then before adding transform instructions i check if it is portrait then transform it to portrait manually and set it's scaling according to and use it's width as height and height as width, and if it's not portrait then do what i was doing before.
let firstLayerInstruction = AVMutableVideoCompositionLayerInstruction(assetTrack: firstTrack!)
if firstAssetInfo.isPortrait {
let rotate = __CGAffineTransformMake(0.0, 1.0, -1.0, 0.0, 0.0, 0.0)
let scale = CGAffineTransform(scaleX: firstPosScale.videoScale.x, y: firstPosScale.videoScale.y)
let move = CGAffineTransform(translationX: firstPosScale.videoLocation.x, y: firstPosScale.videoLocation.y)
let transform = rotate.concatenating(scale).concatenating(move)
firstLayerInstruction.setTransform(transform, at: .zero)
} else {
let scale = CGAffineTransform(scaleX: firstPosScale.videoScale.x, y: firstPosScale.videoScale.y)
let move = CGAffineTransform(translationX: firstPosScale.videoLocation.x, y: firstPosScale.videoLocation.y)
let transform = scale.concatenating(move)
firstLayerInstruction.setTransform(transform, at: .zero)
}