-
Notifications
You must be signed in to change notification settings - Fork 6
feat: update media content time spent calculations with ad breaks #22
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: update media content time spent calculations with ad breaks #22
Conversation
8acc683 to
2031f17
Compare
|
denischilik
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
BrandonStalnaker
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good
Co-authored-by: James Newman <[email protected]>
f35f72e to
3e48ce1
Compare
samdozor
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Likely issues introduced
- Auto-resume on ad break end can start content time when it wasn’t playing
- If content was already paused before an ad break starts, ending the ad break will incorrectly start content time tracking.
// MARK: private helpers (ad break)
private func pauseContentTimeIfAdBreakExclusionEnabled() {
guard excludeAdBreaksFromContentTime, currentPlaybackStartTimestamp != nil else { return }
storedPlaybackTime += Date().timeIntervalSince(currentPlaybackStartTimestamp!)
currentPlaybackStartTimestamp = nil
}
private func resumeContentTimeIfAdBreakExclusionEnabled() {
guard excludeAdBreaksFromContentTime, currentPlaybackStartTimestamp == nil else { return }
currentPlaybackStartTimestamp = Date()
}-
Problem:
resume...only checks thatcurrentPlaybackStartTimestamp == nil, not that the pause was caused by an ad break. If the user paused manually before the ad break,logAdBreakEnd()will set a new start timestamp and begin counting content time even though playback is still paused. -
Fix: Track an explicit state flag (e.g.,
pausedByAdBreak) that is set bypauseContentTimeIfAdBreakExclusionEnabled()and only resume if that flag is true, then clear it. -
Ad time is double-counted
mediaTotalAdTimeSpentis incremented both on ad end/skip and again in the ad summary logger.
@objc public func logAdEnd(options: Options? = nil) {
if (self.adContent?.adStartTimestamp != nil) {
self.adContent?.adEndTimestamp = Date()
self.adContent?.adCompleted = true
self.mediaTotalAdTimeSpent += self.adContent!.adEndTimestamp!.timeIntervalSince(self.adContent!.adStartTimestamp!)
}
...
self.logAdSummary()
}private func logAdSummary() {
if (self.adContent != nil) {
if (self.adContent?.adStartTimestamp != nil) {
self.adContent?.adEndTimestamp = Date()
self.mediaTotalAdTimeSpent += self.adContent!.adEndTimestamp!.timeIntervalSince(self.adContent!.adStartTimestamp!)
}
...
}
}-
Impact: Ad time gets added twice. Remove the increment in
logAdSummary()or skip if already accounted for. -
Minor: redundant assignment
excludeAdBreaksFromContentTimeis set twice in the long initializer.
self.excludeAdBreaksFromContentTime = excludeAdBreaksFromContentTime
...
if ( 100 >= completeLimit && completeLimit > 0) {
self.mediaContentCompleteLimit = completeLimit
}
self.excludeAdBreaksFromContentTime = excludeAdBreaksFromContentTime- Fix: Remove the duplicate set.
Tests
- The new tests properly use short sleeps with tolerances and validate both include/exclude behaviors:
func testAdBreakExclusionDisabledDoesNotPauseContentTime() { ... }func testAdBreakExclusionEnabledExcludesAdTime() { ... }-
They are unlikely to be flaky due to the accuracy windows used (0.08–0.1).
-
Add a test covering “ad break while paused” to catch the auto-resume bug:
- Pause content, start ad break, end ad break, assert
currentPlaybackStartTimestampis still nil andmediaContentTimeSpentunchanged.
- Pause content, start ad break, end ad break, assert
-
Optional: Consider removing timing from unit tests by injecting a time source, but the current tolerances are reasonable.
Summary:
- Ad-break resume should only happen if the ad break actually paused content; add a
pausedByAdBreakflag to gate resume. mediaTotalAdTimeSpentis double-counted; remove one of the increments (recommend removing the one inlogAdSummary()).- Clean up a redundant assignment in the long initializer.
- Tests look solid with tolerances; add a case for “ad break while paused” to prevent regressions.
|
@samdozor - Thanks for the detailed review and for calling out these issues. private func logAdSummary() {
if (self.adContent != nil) {
if (self.adContent?.adStartTimestamp != nil) {
self.adContent?.adEndTimestamp = Date()
self.mediaTotalAdTimeSpent += self.adContent!.adEndTimestamp!.timeIntervalSince(self.adContent!.adStartTimestamp!)
}
...
customAttributes[adContentStartTimestampKey] = self.adContent?.adStartTimestamp
}
}One thing I noticed as well: in the scenario where |
That's tough to say because it really depends on how the customer implements this. I'd lean towards logging what we can considering the only places we call the method is if adContent is set and if the class is deallocated or the ad is skipped or ended. In those cases I would assume the customer would want some reference of the ad they initialized even if they're not implementing the timestamps. |



Background
What Has Changed
excludeAdBreaksFromContentTimeflag toMPMediaSession.logAdBreakStartandlogAdBreakEndto pause/resume content time tracking when the flag is enabled.pauseContentTimeIfAdBreakExclusionEnabled()andresumeContentTimeIfAdBreakExclusionEnabled().Checklist
Additional Notes
Reference Issue (For employees only. Ignore if you are an outside contributor)