I've made CustomCamera which records video into full screen (by setting AVCaptureVideoPreviewLayer's videoGravity to resizeAspectFill) and saving the recording using AVCaptureMovieFileOutput. The recording works perfect but when I save the recorded video into Gallery it is not played in full screen. It has black bar at top and bottom. So, while recording it is shown in full screen due to resizeAspectFill but after exporting the video is exported without any transformation so it is played in the ratio it was recorded (I'm guessing). The code that I've tried to make the video export full screen is below but it is not working.
func fileOutput(_ output: AVCaptureFileOutput, didFinishRecordingTo outputFileURL: URL, from connections: [AVCaptureConnection], error: Error?) {
if let err = error as NSError?, err.code != -11810 { //-11810 = recording stopped when timelimit reached
print("Error recording movie: \(err)")
} else {
let videoAsset: AVAsset = AVAsset( url: outputFileURL )
guard let clipVideoTrack = videoAsset.tracks( withMediaType: AVMediaType.video ).first as AVAssetTrack? else {
return
}
let videoComposition = AVMutableVideoComposition(propertiesOf: videoAsset)
let instruction = AVMutableVideoCompositionInstruction()
instruction.timeRange = clipVideoTrack.timeRange
let transformer = AVMutableVideoCompositionLayerInstruction( assetTrack: clipVideoTrack)
transformer.setTransform(videoPreviewLayer.affineTransform(), at: .zero) // This is the transform value of AVCaptureVideoPreviewLayer
print("clipVideoTrack size: \(clipVideoTrack.naturalSize)")
instruction.layerInstructions = [transformer]
videoComposition.instructions = [instruction]
let outputPath = "\(NSTemporaryDirectory())\(UUID().uuidString).mov"
let croppedOutputFileUrl = URL(fileURLWithPath: outputPath)
let exporter = AVAssetExportSession(asset: videoAsset, presetName: AVAssetExportPresetHighestQuality)!
exporter.videoComposition = videoComposition
exporter.outputURL = croppedOutputFileUrl
exporter.outputFileType = .mov
exporter.shouldOptimizeForNetworkUse = true
exporter.canPerformMultiplePassesOverSourceMediaData = true
exporter.exportAsynchronously( completionHandler: { () -> Void in
if let error = exporter.error {
print("Error in exporting: \(error)")
}
if exporter.status == .completed {
print("exported successfully")
}
DispatchQueue.main.async(execute: {
if let url = exporter.outputURL {
print("exported file url: \(url)")
} else {
}
})
})
}
}
I found out that using the AVCaptureMovieFileOutput it is hard to change the resolution of the recorded video and cropping comes with alot of challenges. So, finally I decided to give AVCaptureVideoDataOutput a try and it worked like a charm. I'm able to record the video in fullscreen as well as when the AVCaptureVideoDataOutput produces the final video it looks exactly same while video recording is going on.