Skip to content

Commit a25b31f

Browse files
committed
Merge branch 'master' into feature/github_actions
2 parents c7b89c2 + 11f859b commit a25b31f

4 files changed

Lines changed: 75 additions & 26 deletions

File tree

CHANGELOG.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,18 @@
1+
5.2.3 / 2025-08-12
2+
==================
3+
4+
Other Changes
5+
-------------
6+
* Add video analytics duration event
7+
* Add flush events support to video analytics
8+
9+
5.2.2 / 2025-07-30
10+
==================
11+
12+
Other Changes
13+
--------------
14+
* Fix video analytics duration event
15+
116
5.2.1 / 2025-06-25
217
==================
318

Cloudinary.podspec

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
Pod::Spec.new do |s|
1010
s.name = 'Cloudinary'
11-
s.version = '5.2.1'
11+
s.version = '5.2.3'
1212
s.summary = "Cloudinary is a cloud service that offers a solution to a web application's entire image management pipeline."
1313

1414
s.description = <<-DESC

Cloudinary/Classes/Core/Network/CLDNetworkCoordinator.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ import UIKit
2727

2828
internal class CLDNetworkCoordinator: NSObject {
2929

30-
static let DEFAULT_VERSION = "5.2.1"
30+
static let DEFAULT_VERSION = "5.2.3"
3131

3232
fileprivate struct CLDNetworkCoordinatorConsts {
3333
static let BASE_CLOUDINARY_URL = "https://api.cloudinary.com"

Cloudinary/Classes/ios/Video/CLDVideoPlayer.swift

Lines changed: 58 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ import AVKit
3939

4040
var transformation: CLDTransformation?
4141

42-
var eventsManager: VideoEventsManager = VideoEventsManager()
42+
var eventsManager: VideoEventsManager = VideoEventsManager()
4343

4444
var providedData: [String: Any]?
4545

@@ -73,7 +73,7 @@ import AVKit
7373
super.init()
7474
return
7575
}
76-
super.init(url: url)
76+
super.init(url: url)
7777
}
7878

7979
/**
@@ -128,14 +128,22 @@ import AVKit
128128
}
129129
}
130130

131+
public func flushEvents() {
132+
guard analytics else { return }
133+
eventsManager.sendEvents()
134+
}
135+
136+
public func flushEventsAndCloseSession() {
137+
guard analytics else { return }
138+
eventsManager.sendViewEndEvent(providedData: providedData)
139+
flushEvents()
140+
}
141+
131142
deinit {
132-
if analytics {
133-
removeObserver(self, forKeyPath: PlayerKeyPath.status.rawValue)
134-
removeObserver(self, forKeyPath: PlayerKeyPath.timeControlStatus.rawValue)
135-
removeObserver(self, forKeyPath: PlayerKeyPath.duration.rawValue)
136-
eventsManager.sendViewEndEvent(providedData: providedData)
137-
eventsManager.sendEvents()
138-
}
143+
guard analytics else { return }
144+
removeObserver(self, forKeyPath: PlayerKeyPath.status.rawValue)
145+
removeObserver(self, forKeyPath: PlayerKeyPath.timeControlStatus.rawValue)
146+
flushEventsAndCloseSession()
139147
}
140148

141149
func setAnalyticsObservers() {
@@ -144,7 +152,6 @@ import AVKit
144152
}
145153
addObserver(self, forKeyPath: PlayerKeyPath.status.rawValue, options: [.new], context: nil)
146154
addObserver(self, forKeyPath: PlayerKeyPath.timeControlStatus.rawValue, options: [.new], context: nil)
147-
addObserver(self, forKeyPath: PlayerKeyPath.duration.rawValue, options: [.new], context: nil)
148155
}
149156

150157
open override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
@@ -162,10 +169,6 @@ import AVKit
162169
if let newStatusNumber = changes[.newKey] as? NSNumber, let newStatus = AVPlayer.TimeControlStatus(rawValue: newStatusNumber.intValue) {
163170
handleTimeControlStatusChanged(newStatus)
164171
}
165-
case PlayerKeyPath.duration.rawValue:
166-
if let playerItem = changes[.newKey] as? AVPlayerItem {
167-
observeDuration(of: playerItem)
168-
}
169172
default:
170173
super.observeValue(forKeyPath: path, of: object, change: changes, context: context)
171174
}
@@ -175,22 +178,15 @@ import AVKit
175178

176179
@available(iOS 10.0, *)
177180
extension CLDVideoPlayer {
178-
func observeDuration(of playerItem: AVPlayerItem) {
179-
let duration = playerItem.asset.duration
180-
181-
let durationInSeconds = Int(CMTimeGetSeconds(duration))
182-
if !loadMetadataSent {
183-
loadMetadataSent = true
184-
self.eventsManager.sendLoadMetadataEvent(duration: durationInSeconds)
185-
}
186-
}
187181
func handleStatusChanged(_ status: AVPlayer.Status) {
188182
switch status {
189183
case .readyToPlay:
190184
if let assetURL = self.currentItem?.asset as? AVURLAsset {
191185
let mediaURL = assetURL.url
192186
eventsManager.sendViewStartEvent(videoUrl: mediaURL.absoluteString, providedData: providedData)
193187
isIntialized = true
188+
189+
loadDurationAsynchronously()
194190
}
195191
break
196192
case .failed:
@@ -203,6 +199,44 @@ extension CLDVideoPlayer {
203199
break
204200
}
205201
}
202+
203+
private func loadDurationAsynchronously() {
204+
guard let currentItem = self.currentItem else { return }
205+
206+
let asset = currentItem.asset
207+
let durationKey = "duration"
208+
209+
// Load the duration key asynchronously
210+
asset.loadValuesAsynchronously(forKeys: [durationKey]) { [weak self] in
211+
DispatchQueue.main.async {
212+
guard let self = self else { return }
213+
214+
var error: NSError?
215+
let status = asset.statusOfValue(forKey: durationKey, error: &error)
216+
217+
switch status {
218+
case .loaded:
219+
let duration = asset.duration
220+
let durationInSeconds = Int(CMTimeGetSeconds(duration))
221+
222+
if !self.loadMetadataSent && durationInSeconds > 0 && duration.isValid {
223+
self.loadMetadataSent = true
224+
self.eventsManager.sendLoadMetadataEvent(duration: durationInSeconds)
225+
}
226+
case .failed, .cancelled:
227+
print("Failed to load duration: \(error?.localizedDescription ?? "Unknown error")")
228+
case .loading:
229+
// Still loading, could retry or wait
230+
break
231+
case .unknown:
232+
// Unknown status
233+
break
234+
@unknown default:
235+
break
236+
}
237+
}
238+
}
239+
}
206240

207241
func handleTimeControlStatusChanged(_ status: AVPlayer.TimeControlStatus) {
208242
switch status {
@@ -222,7 +256,7 @@ extension CLDVideoPlayer {
222256
}
223257
}
224258

225-
func setProvidedData(data: [String: Any]) {
259+
public func setProvidedData(data: [String: Any]) {
226260
providedData = data
227261
}
228262
}

0 commit comments

Comments
 (0)