DixieFlatline
DixieFlatline

Reputation: 8035

How to get video size for HLS stream inside AVPlayer?

I am trying to get video resolution when playing hls stream. I have typical player init:

let urlAsset = AVURLAsset(URL: currentVideoUrl)
 self.player=AVPlayer(playerItem: AVPlayerItem(asset:urlAsset))
 .......

I use KVO and i try to get video size when i get .ReadyToPlay status for AVPlayerItem:

    func resolutionSizeForVideo() {

    guard let videoTrack = self.player.currentItem?.asset.tracksWithMediaType(AVMediaTypeVideo).first else
    { return
    }

    let size = CGSizeApplyAffineTransform(videoTrack.naturalSize, videoTrack.preferredTransform)
    let frameSize = CGSize(width: fabs(size.width), height: fabs(size.height))
    print ("video size: \(frameSize)")

}

The problem is that tracksWithMediaType() always returns empty array (but works for non-stream files, e.g. for .mov).

How can i get size (CGRect) of the HLS video playing inside AVPlayer?

Upvotes: 26

Views: 16211

Answers (4)

Alexander Khitev
Alexander Khitev

Reputation: 6861

We can use a new implementation since iOS 16 because previous is deprecated (since iOS 16 and newer versions).

import AVKit
import Foundation

extension AVAsset {
    func videoSize() async throws -> CGSize? {
        guard let track = try await loadTracks(withMediaType: .video).first else { return nil }
        let size = try await track.load(.naturalSize)
        return size
    }
}

Upvotes: 0

ScottyBlades
ScottyBlades

Reputation: 14033

You can concisely make it as so:

import AVKit

extension AVAsset {

    var videoSize: CGSize? {
        tracks(withMediaType: .video).first.flatMap {
            tracks.count > 0 ? $0.naturalSize.applying($0.preferredTransform) : nil
        }
    }
}

Upvotes: 5

Edison
Edison

Reputation: 11987

Are you able to log at least the video info using this method?

extension AVAsset{
    func videoSize()->CGSize{
        let tracks = self.tracks(withMediaType: AVMediaType.video)
        if (tracks.count > 0){
            let videoTrack = tracks[0]
            let size = videoTrack.naturalSize
            let txf = videoTrack.preferredTransform
            let realVidSize = size.applying(txf)
            print(videoTrack)
            print(txf)
            print(size)
            print(realVidSize)
            return realVidSize
        }
        return CGSize(width: 0, height: 0)
    }

}

let videoAssetSource = AVAsset.init(URL: videoURL)
print("size:",videoAssetSource.videoSize())

Upvotes: 15

Max
Max

Reputation: 1163

Tracks will always return nil when using HLS. If you have a UIView subclass that overrides its layerClass with an AVPlayerLayer for playing the video you can get the size with

playerView.layer.videoRect

This is the size of just the video and not the entire layer.

Alternatively you can use KVO to observe the presentationSize of the item

player.addObserver(self, forKeyPath: "currentItem.presentationSize", options: [.Initial, .New], context: nil)

Upvotes: 16

Related Questions