Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Video Output Size Not Adjusted #3

Open
Appswage opened this issue Mar 25, 2018 · 4 comments
Open

Video Output Size Not Adjusted #3

Appswage opened this issue Mar 25, 2018 · 4 comments

Comments

@Appswage
Copy link

Great job on incorporating video orientation! However, the output is not correctly adjusted when merging multiple videos. So when one video is portrait the size is adjusted, but the output is never adjusted again when the video is landscape. The result is correct orientation but the width is cut-off for landscape videos.

My change was simply to set outputSize equal to videoSize when the video is not portrait.

 if assetInfo.isPortrait == true {
                videoSize.width = videoTrack.naturalSize.height
                videoSize.height = videoTrack.naturalSize.width
            }
            else
            {
                outputSize = videoSize
            }
@khoavd-dev
Copy link
Owner

khoavd-dev commented May 16, 2018

@Appswage
Nah, there is no problem here. If you assign outputSize = videoSize for landscape video, then you compare their height together, it makes no sense. Like

var videoSize = videoTrack.naturalSize
if assetInfo.isPortrait == true {
        videoSize.width = videoTrack.naturalSize.height
        videoSize.height = videoTrack.naturalSize.width
}
else
{
        outputSize = videoSize
}
            
if videoSize.height > outputSize.height {
        outputSize = videoSize
 }

In my sample, I merged videos with aspect fill mode, which means there is no black space (when you merge a portrait video and a landscape video) in the output video.

You could change the aspect fill to aspect fit (no cut-off for landscape videos) by changing the formula in this function
videoCompositionInstructionForTrack(track: AVCompositionTrack, asset: AVAsset, standardSize:CGSize, atTime: CMTime)

@Appswage
Copy link
Author

@khoavd-dev - Apologies, I had discovered the same shortly after writing the above and forgot to come back to this thread to update. Below are the edits I wound up making as I also noticed that portrait only video was cut-off at the top. There is probably a cleaner way to write this, but it worked well for me. Also, I notice that orientation is not always identified correctly which is why you see additional width and height checking to more directly ascertain orientation.

fileprivate func videoCompositionInstructionForTrack(track: AVCompositionTrack, asset: AVAsset, standardSize:CGSize, atTime: CMTime) -> AVMutableVideoCompositionLayerInstruction {
        let instruction = AVMutableVideoCompositionLayerInstruction(assetTrack: track)
        let assetTrack = asset.tracks(withMediaType: AVMediaType.video)[0]

        let transform = assetTrack.preferredTransform
        let assetInfo = orientationFromTransform(transform: transform)

        var aspectFillRatio:CGFloat = 1
        if assetTrack.naturalSize.height < assetTrack.naturalSize.width {
            aspectFillRatio = standardSize.height / assetTrack.naturalSize.height
        }
        else {
            aspectFillRatio = standardSize.width / assetTrack.naturalSize.width
        }

        if assetInfo.isPortrait || assetTrack.naturalSize.width < assetTrack.naturalSize.height{

            let naturalWidth = fabs(assetTrack.naturalSize.applying(assetTrack.preferredTransform).width)
            let naturalHeight = fabs(assetTrack.naturalSize.applying(assetTrack.preferredTransform).height)

            let heightDiff = naturalHeight - standardSize.height
            let percentDiffHeight = heightDiff / naturalHeight
            let percentHeightMultiplyer = 1 - percentDiffHeight

            let aspectNativeX:CGFloat = naturalWidth / naturalHeight
            let aspectY:CGFloat = standardSize.height / naturalHeight
            let aspectX = aspectNativeX * aspectY

            let scaleFactor = CGAffineTransform(scaleX: percentHeightMultiplyer, y: percentHeightMultiplyer)

            let posX = fabs(standardSize.width/2 - (naturalHeight * aspectX)/2)
            let posY = fabs(standardSize.height/2 - (naturalHeight * aspectY)/2)
            let moveFactor = CGAffineTransform(translationX: posX, y: posY)

            instruction.setTransform(assetTrack.preferredTransform.concatenating(scaleFactor).concatenating(moveFactor), at: atTime)

        } else {
            let scaleFactor = CGAffineTransform(scaleX: aspectFillRatio, y: aspectFillRatio)

            let posX = standardSize.width/2 - (assetTrack.naturalSize.width * aspectFillRatio)/2
            let posY = standardSize.height/2 - (assetTrack.naturalSize.height * aspectFillRatio)/2
            let moveFactor = CGAffineTransform(translationX: posX, y: posY)

            var concat = assetTrack.preferredTransform.concatenating(scaleFactor).concatenating(moveFactor)

            if assetInfo.orientation == .down {
                let fixUpsideDown = CGAffineTransform(rotationAngle: CGFloat(Double.pi))
                concat = fixUpsideDown.concatenating(scaleFactor).concatenating(moveFactor)
            }

            instruction.setTransform(concat, at: atTime)
        }
        return instruction
    }

@swami303
Copy link

swami303 commented Jun 9, 2018

In your sample when merging two videos with one is landscape and one is portrait(Captured from camera) leave black space in video.

@khoavd-dev
Copy link
Owner

@swami303 I just updated the code, might solve this issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants