title: How to adjust AVCaptureVideoPreview orientation to device current orientation?
body: <p>I am trying to adjust AVCaptureVideoPreview orientation to device current orientation and I tried someways which I found on Stackoverflow but it didn’t work. How can I adjust AVCaptureVideoPreview orientation to device current orientation?</p>
  <p>Here are CameraManager.swift codes:</p>
  <pre><code>// MARK: Camera View Model
  class CameraViewModel: NSObject,ObservableObject,AVCaptureFileOutputRecordingDelegate{
      @Published var session = AVCaptureSession()
      @Published var alert = false
      @Published var output = AVCaptureMovieFileOutput()
      @Published var preview : AVCaptureVideoPreviewLayer!
      
      // MARK: Video Recorder Properties
      @Published var isRecording: Bool = false
      @Published var recordedURLs: [URL] = []
      @Published var previewURL: URL?
      @Published var showPreview: Bool = false
      
      // Top Progress Bar
      @Published var recordedDuration: CGFloat = 0
      // Timing
      @Published var maxDuration: CGFloat = 10
      
      func checkPermission(){
          
          switch AVCaptureDevice.authorizationStatus(for: .video) {
          case .authorized:
              setUp()
              return
          case .notDetermined:
              AVCaptureDevice.requestAccess(for: .video) { (status) in
                  
                  if status{
                      self.setUp()
                  }
              }
          case .denied:
              self.alert.toggle()
              return
          default:
              return
          }
      }
      
      func setUp(){
          
          do{
              self.session.beginConfiguration()
              let cameraDevice = AVCaptureDevice.default(.builtInWideAngleCamera, for: .video, position: .front)
              let videoInput = try AVCaptureDeviceInput(device: cameraDevice!)
              let audioDevice = AVCaptureDevice.default(for: .audio)
              let audioInput = try AVCaptureDeviceInput(device: audioDevice!)
              
              // MARK: Audio Input
              
              if self.session.canAddInput(videoInput) &amp;&amp; self.session.canAddInput(audioInput){
                  self.session.addInput(videoInput)
                  self.session.addInput(audioInput)
              }
              
              if self.session.canAddOutput(self.output){
                  self.session.addOutput(self.output)
              }
              
              self.session.commitConfiguration()
          }
          catch{
              print(error.localizedDescription)
          }
      }
      
      func startRecording(){
          // MARK: Temporary URL for recording Video
          let tempURL = NSTemporaryDirectory() + &quot;\(Date()).mov&quot;
          output.startRecording(to: URL(fileURLWithPath: tempURL), recordingDelegate: self)
          isRecording = true
      }
      
      func stopRecording(){
          output.stopRecording()
          isRecording = false
      }
      
      func fileOutput(_ output: AVCaptureFileOutput, didFinishRecordingTo outputFileURL: URL, from connections: [AVCaptureConnection], error: Error?) {
          if let error = error {
              print(error.localizedDescription)
              return
          }
          
          // CREATED SUCCESSFULLY
          print(outputFileURL)
          self.recordedURLs.append(outputFileURL)
          if self.recordedURLs.count == 1{
              self.previewURL = outputFileURL
              return
          }
          
          // CONVERTING URLs TO ASSETS
          let assets = recordedURLs.compactMap { url -&gt; AVURLAsset in
              return AVURLAsset(url: url)
          }
          
          self.previewURL = nil
          // MERGING VIDEOS
          mergeVideos(assets: assets) { exporter in
              exporter.exportAsynchronously {
                  if exporter.status == .failed{
                      // HANDLE ERROR
                      print(exporter.error!)
                  }
                  else{
                      if let finalURL = exporter.outputURL{
                          print(finalURL)
                          DispatchQueue.main.async {
                              self.previewURL = finalURL
                          }
                      }
                  }
              }
          }
      }
      
      func mergeVideos(assets: [AVURLAsset],completion: @escaping (_ exporter: AVAssetExportSession)-&gt;()){
          
          let compostion = AVMutableComposition()
          var lastTime: CMTime = .zero
          
          guard let videoTrack = compostion.addMutableTrack(withMediaType: .video, preferredTrackID: Int32(kCMPersistentTrackID_Invalid)) else{return}
          guard let audioTrack = compostion.addMutableTrack(withMediaType: .audio, preferredTrackID: Int32(kCMPersistentTrackID_Invalid)) else{return}
          
          for asset in assets {
              // Linking Audio and Video
              do{
                  try videoTrack.insertTimeRange(CMTimeRange(start: .zero, duration: asset.duration), of: asset.tracks(withMediaType: .video)[0], at: lastTime)
                  // Safe Check if Video has Audio
                  if !asset.tracks(withMediaType: .audio).isEmpty{
                      try audioTrack.insertTimeRange(CMTimeRange(start: .zero, duration: asset.duration), of: asset.tracks(withMediaType: .audio)[0], at: lastTime)
                  }
              }
              catch{
                  // HANDLE ERROR
                  print(error.localizedDescription)
              }
              
              // Updating Last Time
              lastTime = CMTimeAdd(lastTime, asset.duration)
          }
          
          // MARK: Temp Output URL
          let tempURL = URL(fileURLWithPath: NSTemporaryDirectory() + &quot;Reel-\(Date()).mp4&quot;)
          
          // VIDEO IS ROTATED
          // BRINGING BACK TO ORIGNINAL TRANSFORM
          
          let layerInstructions = AVMutableVideoCompositionLayerInstruction(assetTrack: videoTrack)
          
          // MARK: Transform
          var transform = CGAffineTransform.identity
          transform = transform.rotated(by: .pi / 0.5)
          transform = transform.translatedBy(x: 0, y: 0)
          layerInstructions.setTransform(transform, at: .zero)
          
          let instructions = AVMutableVideoCompositionInstruction()
          instructions.timeRange = CMTimeRange(start: .zero, duration: lastTime)
          instructions.layerInstructions = [layerInstructions]
          
          let videoComposition = AVMutableVideoComposition()
          videoComposition.renderSize = CGSize(width: videoTrack.naturalSize.height, height: videoTrack.naturalSize.width)
          videoComposition.instructions = [instructions]
          videoComposition.frameDuration = CMTimeMake(value: 1, timescale: 30)
          
          guard let exporter = AVAssetExportSession(asset: compostion, presetName: AVAssetExportPresetHighestQuality) else{return}
          exporter.outputFileType = .mp4
          exporter.outputURL = tempURL
          exporter.videoComposition = videoComposition
          completion(exporter)
      }
  }
  </code></pre>
  <p>Here are my CameraPreview.swift codes:</p>
  <pre><code>   struct CameraPreview: UIViewRepresentable {
      
      @EnvironmentObject var cameraModel : CameraViewModel
      var size: CGSize
      
      func makeUIView(context: Context) -&gt;  UIView {
          
          let view = UIView()
          
          cameraModel.preview = AVCaptureVideoPreviewLayer(session: cameraModel.session)
          cameraModel.preview.frame.size = size
          
          cameraModel.preview.videoGravity = .resizeAspectFill
          
          view.layer.addSublayer(cameraModel.preview)
          
          cameraModel.session.startRunning()
      
          return view
      }
      
      func updateUIView(_ uiView: UIView, context: Context) {
          
      }
  }
  </code></pre>