1

I'm working on adding video recording to an app using AVFoundation. I managed to record the video and then display it, but then I realized that (unlike in the preview) front-camera videos aren't mirrored along the vertical axis. It seems like this is the standard behavior but I would like the video to look like the preview. I believe that CGAffineTransform can do this but I'm not sure how to apply it to the video.

This is what I had so far:

extension CameraViewController: AVCaptureFileOutputRecordingDelegate {
    func fileOutput(_ output: AVCaptureFileOutput, didFinishRecordingTo outputFileURL: URL, from connections: [AVCaptureConnection], error: Error?) {
        guard error != nil else {
            print("Error recording movie: \(error!.localizedDescription)")
            return
        }

        if self.currentCameraPosition == .front {
            mirrorVideo(outputFileURL)
        }
        performSegue(withIdentifier: "ShowVideo", sender: outputFileURL)
    }

    func mirrorVideo(_ outputFileURL: URL){
        var transform: CGAffineTransform = CGAffineTransform(scaleX: -1.0, y: 1.0)
        transform = transform.rotated(by: CGFloat(Double.pi/2))
        // Apply transform
    }
}
wizplum
  • 427
  • 5
  • 17
  • 1
    Take a look at accepted answer, its objective C, if you cant convert it and apply, tell me I will try to write for you: https://stackoverflow.com/questions/12136841/avmutablevideocomposition-rotated-video-captured-in-portrait-mode – emrepun Dec 16 '18 at 10:06
  • 1
    Great, that had enough information to get me to an answer! – wizplum Dec 16 '18 at 11:52

2 Answers2

3

Use this Method after add Input & Output to your AVCaptureSession

    private func adjustVideoMirror(){

        guard let currentCameraInput: AVCaptureDeviceInput = captureSession.inputs.first as? AVCaptureDeviceInput else {
            return
        }

        if let conn = movieOutput.connection(with: .video){
            conn.isVideoMirrored = currentCameraInput.device.position == .front
        }

    }

The key is isVideoMirrored property

MJ Studio
  • 3,947
  • 1
  • 26
  • 37
1

Based on the response I got and some playing around I arrived at an answer:

extension CameraViewController: AVCaptureFileOutputRecordingDelegate {
    func fileOutput(_ output: AVCaptureFileOutput, didFinishRecordingTo outputFileURL: URL, from connections: [AVCaptureConnection], error: Error?) {
        if error != nil {
            print("Error recording movie: \(error!.localizedDescription)")
        } else {
            processMovie()
        }
    }

    func processMovie() {
        let asset = AVAsset(url: CameraViewController.movieURL)
        let composition = AVMutableComposition()
        let assetVideoTrack = asset.tracks(withMediaType: .video).last!
        let compositionVideoTrack = composition.addMutableTrack(withMediaType: AVMediaType.video,
                                                                preferredTrackID: CMPersistentTrackID(kCMPersistentTrackID_Invalid))
        try? compositionVideoTrack?.insertTimeRange(CMTimeRangeMake(start: CMTime.zero, duration: asset.duration),
                                                    of: assetVideoTrack,
                                                    at: CMTime.zero)
        if self.currentCameraPosition == .rear {
            compositionVideoTrack?.preferredTransform = assetVideoTrack.preferredTransform
        }
        if self.currentCameraPosition == .front {
            compositionVideoTrack?.preferredTransform = CGAffineTransform(scaleX: -1.0, y: 1.0).rotated(by: CGFloat(Double.pi/2))
        }

        if let exporter = AVAssetExportSession(asset: composition,
                                               presetName: AVAssetExportPresetHighestQuality) {
            exporter.outputURL = CameraViewController.exportMovieURL
            exporter.outputFileType = AVFileType.mov
            exporter.shouldOptimizeForNetworkUse = true
            exporter.exportAsynchronously() {
                DispatchQueue.main.async {
                    self.performSegue(withIdentifier: "ShowVideo", sender: nil)
                }
            }
        }
    }
}
wizplum
  • 427
  • 5
  • 17