In order to measure the quality of service of video playback in my App, I need to measure the initial buffer size of AVPlayer when the content actually start playing.
To do so, I am adding a one-time periodic time observer to the first millisecond of the playback and inspecting from there the property segmentsDownloadedDuration of the last AVPlayerItemAccessLogEvent.
Sadly the values that I am getting with this approach don't match the values that I see server-side.
Server-side, if I multiply the numbers of segments initially requested by segments duration, the value that I get mismatch by up to 6 seconds compared with the reports from my client App.
Is there any better approach for getting this data? Is there something we might be missing or doing wrong?
You can find here below an example of the client approach:
To do so, I am adding a one-time periodic time observer to the first millisecond of the playback and inspecting from there the property segmentsDownloadedDuration of the last AVPlayerItemAccessLogEvent.
Sadly the values that I am getting with this approach don't match the values that I see server-side.
Server-side, if I multiply the numbers of segments initially requested by segments duration, the value that I get mismatch by up to 6 seconds compared with the reports from my client App.
Is there any better approach for getting this data? Is there something we might be missing or doing wrong?
You can find here below an example of the client approach:
Code Block import UIKitimport AVFoundationclass PlaygroundViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() let videoURL = URL(string: "https://devstreaming-cdn.apple.com/videos/streaming/examples/img_bipbop_adv_example_ts/master.m3u8")! // Setup Player Layer playerLayer = AVPlayerLayer(player: player) playerLayer.frame = view.bounds view.layer.addSublayer(playerLayer) // Setup Player Item let asset = AVAsset(url: videoURL) playerItem = AVPlayerItem(asset: asset) // Setup AVPlayer player = AVPlayer(playerItem: playerItem) // Setup one time observer var contentStartedObserver: Any? contentStartedObserver = player?.addPeriodicTimeObserver(forInterval: CMTimeMake(value: 1, timescale: 1000), queue: DispatchQueue.main, using: { [weak self] _ in print("Content Started Playing") guard let accessLog = self?.playerItem.accessLog() else { return } guard let lastEvent = accessLog.events.last else { return } print(">> Buffered Duration:") print(lastEvent.segmentsDownloadedDuration) // Ok, we are done. Remove the observer self?.player?.removeTimeObserver(contentStartedObserver) }) // Play playerLayer.player = player player.play() } // MARK: - Private private var playerLayer: AVPlayerLayer! private var player: AVPlayer! private var playerItem: AVPlayerItem!}