16

I am working on a video editing app where each video gets squared in such a way that no portion of the video gets cropped.For this, in case of portrait video, it contains black portion on left & right and for landscape video, it contains black portion on top & bottom side of the video. Black portions are part of the video, they are not for AVPlayerViewController. Here is the sample, enter image description here

I need to cover these black portions with some CALayers.

What will be the frame(CGRect) of the CALayer?

I am getting the video dimension with naturalSize property which includes the black portions.

Is there any way to get the video dimension without the black portions?(I mean the dimension of actual video content) or is there any way to get the CGRect of black area of the video?

pigeon_39
  • 1,503
  • 2
  • 22
  • 34

3 Answers3

54
func initAspectRatioOfVideo(with fileURL: URL) -> Double {
  let resolution = resolutionForLocalVideo(url: fileURL)
  guard let width = resolution?.width, let height = resolution?.height else {
     return 0
  }
  return Double(height / width)
}

private func resolutionForLocalVideo(url: URL) -> CGSize? {
    guard let track = AVURLAsset(url: url).tracks(withMediaType: AVMediaType.video).first else { return nil }
   let size = track.naturalSize.applying(track.preferredTransform)
   return CGSize(width: abs(size.width), height: abs(size.height))
}
Nimantha
  • 6,405
  • 6
  • 28
  • 69
Vlad Pulichev
  • 3,162
  • 2
  • 20
  • 34
  • this is amazing. thanks a lot. apparently just using "natural size" doesn't work but your code is great! thanks! – Tung Fam Feb 25 '18 at 13:13
  • 1
    @RoiMulia I don't remember actually. I think it should. You can give it a try – Vlad Pulichev Sep 17 '18 at 14:43
  • :/ my bad i'm facing the same problem with objective-C using the (natural size + preferredTransform) it always returns an obsolete value ! (with remote video) – sarra.srairi Sep 20 '18 at 10:48
  • 1
    @VladPulichev hello. Thanks for answer. Do you know why for this url `https://devstreaming-cdn.apple.com/videos/streaming/examples/bipbop_adv_example_hevc/master.m3u8` always get `nil`? I also check all another media types (audio, metadata etc), but have the same result - `nil`. – Taras Jan 04 '21 at 13:48
  • 1
    Doesn't work for me. first is returning nil always. – ScottyBlades Mar 26 '21 at 01:24
  • When I try this, the Bundle file works fine, but the files in the Documents directory always return nil. Is there a solution? – gncc Aug 09 '22 at 23:40
  • This is returning the wrong information for height + width – Mark Thomas Jan 05 '23 at 16:32
5

This is a more concise version of Vlad Pulichev's answer.

var aspectRatio: CGFloat! // use the function to assign your variable

func getVideoResolution(url: String) -> CGFloat? {
    guard let track = AVURLAsset(url: URL(string: url)!).tracks(withMediaType: AVMediaType.video).first else { return nil }
    let size = track.naturalSize.applying(track.preferredTransform)
    return abs(size.height) / abs(size.width)
}
Nimantha
  • 6,405
  • 6
  • 28
  • 69
Tad
  • 889
  • 9
  • 23
0

~New

func getVideoResolution(url: String) async throws -> CGSize? {
        guard let track = try await AVURLAsset(url: URL(string: url)!).loadTracks(withMediaType: AVMediaType.video).first else { return nil }
        let size = try await track.load(.naturalSize).applying(track.load(.preferredTransform))
        return size
}