AVMutableVideoComposition fails to rotate video recorded using iOS Camera in Swift 5

A downloaded video chosen from the Photos App seems to rotate fine but when it is a video that has been taken using the iPhone's native Camera app, the rotation keeps its original portrait position instead of rotating to landscape which the downloaded videos do successfully. It seems that for recorded videos, AVMutableVideoComposition does not seem to transform the video for some reason. The following is my code in Swift 5.

func rotateVideo(completion: @escaping (_ outputURL: URL?) -> Void) {
        let asset = AVAsset(url: videoURL)
        let track = asset.tracks(withMediaType: AVMediaType.video).first! as AVAssetTrack
        let size = track.naturalSize
        var transform = track.preferredTransform
        transform = transform.translatedBy(x: size.height, y: 0)
        transform = transform.rotated(by: .pi / 2)
        let transformer = AVMutableVideoCompositionLayerInstruction(assetTrack: track)
        transformer.setTransform(transform, at: .zero)
        let instruction = AVMutableVideoCompositionInstruction()
        instruction.timeRange = CMTimeRange(start: .zero, duration: .positiveInfinity)
        instruction.layerInstructions = [transformer]
        let composition = AVMutableVideoComposition()
        composition.frameDuration = CMTime(value: 1, timescale: 30)
        var newWidth = Int(size.height)
        var newHeight = Int(size.width)
        if (newWidth % 2 != 0) {
            newWidth = newWidth + 1
        }
        if (newHeight % 2 != 0) {
            newHeight = newHeight + 1
        }
        composition.renderSize = CGSize(width: newWidth, height: newHeight)
        composition.instructions = [instruction]
        
        exportAsset(asset: asset, videoComposition: composition, filename: "rotate", completion: completion)
    }

    func exportAsset(asset: AVAsset, videoComposition: AVVideoComposition, filename: String, completion: @escaping (_ outputURL: URL) -> Void) {
        let outputURL = URL(fileURLWithPath: NSHomeDirectory() + "/Documents/\(filename).mp4")
        let exporter = AVAssetExportSession(asset: asset, presetName: AVAssetExportPresetHighestQuality)!
        exporter.videoComposition = videoComposition
        exporter.outputFileType = AVFileType.mov
        exporter.outputURL = outputURL
        do {
            try FileManager.default.removeItem(at: outputURL)
        } catch {
            print("Failed to delete file at \(outputURL)")
        }
        exporter.exportAsynchronously(completionHandler: { () -> Void in
            DispatchQueue.main.async(execute: {
                completion(outputURL)
            })
        })
    }


Read more here: https://stackoverflow.com/questions/66271754/avmutablevideocomposition-fails-to-rotate-video-recorded-using-ios-camera-in-swi

Content Attribution

This content was originally published by Purple Lights at Recent Questions - Stack Overflow, and is syndicated here via their RSS feed. You can read the original post over there.

%d bloggers like this: