Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

iOS Swift - how to get aspect ratio of local and remote video?

Tags:

ios

swift

swift5

Scenario: I'm building a WebRTC view inside an app The container for videos will always have a height of 160.

In the center of the container there should be displayed the remote video with a max height of 160, width should be scaled to respect the aspect ratio of the video. Width also cannot be bigger than the view width, in that case the width will be equal to view width and the height should be adapted to aspect ratio.

In top right corner there should be displayed the local video from front camera with a max width of 100 and the height should be adapted to respect the aspect ratio of local video

my code so far:

func createPeerConnection () {
    // some other code

    self.localStream = self.factory.mediaStream(withStreamId: "stream")
    let videoSource = self.factory.videoSource()

    let devices = RTCCameraVideoCapturer.captureDevices()
    if let camera = devices.last,
        let format = RTCCameraVideoCapturer.supportedFormats(for: camera).last,
        let fps = format.videoSupportedFrameRateRanges.first?.maxFrameRate {
        let intFps = Int(fps)
        self.capturer = RTCCameraVideoCapturer(delegate: videoSource)
        self.capturer?.startCapture(with: camera, format: format, fps: intFps)
        videoSource.adaptOutputFormat(toWidth: 100, height: 160, fps: Int32(fps))
    }

    let videoTrack = self.factory.videoTrack(with: videoSource, trackId: "video")
    self.localStream.addVideoTrack(videoTrack)

    DispatchQueue.main.async {
        if self.localView == nil {
            let videoView = RTCEAGLVideoView(frame: CGRect(x: self.view.frame.size.width - 105, y: 5, width: 100, height: 160))
            videoView.backgroundColor = UIColor.red

            self.view.addSubview(videoView)
            self.localView = videoView
        }
        videoTrack.add(self.localView!)
    }
}

func peerConnection(_ peerConnection: RTCPeerConnection, didAdd stream: RTCMediaStream) {
    self.remoteStream = stream
    if let videoTrack = stream.videoTracks.first {
        DispatchQueue.main.async {
            if self.remoteView == nil {
                let videoView = RTCEAGLVideoView(frame: CGRect(x: self.view.frame.size.width - 50, y: 0, width: 100, height: 160))
                videoView.backgroundColor = UIColor.green
                if let local = self.localView {
                    self.view.insertSubview(videoView, belowSubview: local)
                } else {
                    self.view.addSubview(videoView)
                }
                self.remoteView = videoView
            }
            videoTrack.add(self.remoteView!)
        }
    }
}

I don't know how to get the aspect ratio of either of the videos, local or remote. If i had that, i could compute the appropriate width and heights for each of them

// Edit with solution:

I did not find a way to get the exact size but I found a way to render the video at scale All I had to do was:

let videoView = RTCEAGLVideoView(frame: CGRect(x: self.view.frame.size.width - 105, y: 5, width: 100, height: 134))
videoView.contentMode = .scaleAspectFill

Now the video scales itself based on the container size

like image 543
John Avatar asked Dec 17 '19 19:12

John


People also ask

How do I find the aspect ratio of a video?

You can calculate the aspect ratio of a video by dividing the video's width by its height. However, to calculate the video resolution, you'll multiply the video's width by its height.

How do I change the aspect ratio in Swiftui?

If your source image asset does not have a 1:1 aspect ratio, set the contentMode to . fill , and constrain the frame height of either the HStack or the CustomView inside its parent using . frame(height: ..) . I try to display a 480x270 size image.


1 Answers

You can use the AVURLAsset and CGSize to get the resolution for video

private func resolutionForLocalVideo(url: URL) -> CGSize? {
   guard let track = AVURLAsset(url: url).tracks(withMediaType: AVMediaTypeVideo).first else { return nil }
   let size = track.naturalSize.applying(track.preferredTransform)
   return CGSize(width: fabs(size.width), height: fabs(size.height))
} 

Now, Use natural size and preferredTransform

var mediaAspectRatio: Double! // <- here the aspect ratio for video with url will be set

func initAspectRatioOfVideo(with fileURL: URL) {
  let resolution = resolutionForLocalVideo(url: fileURL)

  guard let width = resolution?.width, let height = resolution?.height else { 
     return 
  }

  mediaAspectRatio = Double(height / width)
}

Also, you can find the scale factor

float xScale = destination.size.width / imageSize.width; //destination is the max image drawing area.

float yScale = destination.size.height / imageSize.height;

float scaleFactor = xScale < yScale ? xScale : yScale;

This can also be achieved by GPUImageMovie, GPUImageCropFilter and GPUImageMovieWriter

like image 144
Sreeram Nair Avatar answered Sep 17 '22 01:09

Sreeram Nair