@@ -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 , * )
177180extension 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