Events
Vesper SDK surfaces every significant player, ads, system, and UI interaction through the VesperSDK event layer. You can subscribe to these events by implementing Output protocols you already pass into createPlayerManager.
final class PlayerViewController: UIViewController {
private var playerManager: PlayerManager?
func attachPlayer() {
vesperSDKManager.createPlayerManager(
playerOutput: self,
userInterfaceConfig: .default(output: self)
) { [weak self] result in
guard case .success(let manager) = result else { return }
self?.playerManager = manager
}
}
}
extension PlayerViewController: DorisPlayerOutputProtocol, DorisViewOutputProtocol {
func onPlayerEvent(_ event: DorisPlayerEvent) { … }
func onPlayerStateChanged(old: DorisPlayerState, new: DorisPlayerState) { … }
func onAdvertisementEvent(_ event: DorisAdsEvent) { … }
func onRemoteCommandEvent(_ event: DorisRemoteCommandEvent) { … }
func onSystemEvent(_ event: DorisSystemEvent) { … }
func onViewTapEvent(_ event: DorisViewTapEvent) { … }
func onViewUniversalEvent(_ event: DorisViewUniversalEvent) { … }
}
Below is a full reference of every event enum exposed by VesperSDK.
System lifecycle (DorisSystemEvent)
| Case | Fired when |
|---|---|
didEnterBackground |
The hosting app moved to the background. |
willEnterForeground |
The app is transitioning back to foreground. |
willResignActive |
The app is about to become inactive (incoming call, Control Center, etc.). |
didBecomeActive |
The app became active again after being inactive/backgrounded. |
Use these events to pause analytics, throttle UI updates, or prepare for PiP transitions.
Player pipeline (DorisPlayerEvent)
| Case | Fired when |
|---|---|
didCurrentItemChange(old:new:) |
The underlying AVPlayerItem changed. |
playerItemFailed(logs:error:) |
Vesper failed to load or play the current item. Includes diagnostics and a DorisPlayerError. |
playbackStalled |
Playback stalled because of buffering/network issues. |
didTimeControlStatusChange(status:) |
AVPlayer.timeControlStatus changed (e.g. waiting, paused, playing). |
loadInitiated |
A new ResolvableSource has been handed over to the player. |
willLoadAfterDelay(delay:initialSeek:) |
Loading is queued—typically awaiting stream to become available prerequisites—optionally with an initial seek. |
willLoadNow(initialSeek:) |
Loading will start immediately with optional initial seek instructions. |
metadataChanged(metadata:) |
Fresh DorisSourceMetadata became available (title, artwork, etc.). |
willSeek(info:) |
User, code or the UI initiated a seek; includes seek ID and target. Can be canceled |
didSeek(info:) |
Seek finished (success or cancellation). |
finishedPlaying(endTime:) |
Playback reached the end of stream/content. |
currentTimeChanged(contentPosition:streamPosition:date:) |
Periodic time updates (content position excludes SSAI, stream includes). |
itemDurationChanged(contentDuration:streamDuration:) |
Asset duration changed (e.g. DVR window updates). |
streamTypeRecognized(streamType:) |
The SDK determined the stream type (LIVE, VOD). |
seekableTimeRangesChanged(contentSeekableRanges:streamSeekableRanges:) |
Seekable window changed. |
loadedTimeRangesChanged(contentLoadedRanges:streamLoadedRanges:) |
Buffered ranges changed. |
queueItemsChanged(items:) |
Playlist/queue contents changed. |
availableMediaTracksChanged(tracks:) |
Audio or text track list changed. |
playbackReceiverChanged(old:new:) |
Output switched (AirPlay, Chromecast, default). |
playbackLogsUpdated(logs:) |
Diagnostic log payload updated. |
readyToPlay |
The current AVPlayerItem reached .readyToPlay. |
pipWillStart |
Player is about to enter Picture in Picture mode. |
pipDidStop |
PiP session ended and control returned to the in-app player. |
trackChanged(track:autoSet:) |
Active audio/text track changed (either automatically or by the user). |
presentationSizeChanged(size:) |
The video’s presentation size changed. (Player layer’s video frame bounds) |
bitrateChanged(bitrate:policy:) |
Adaptive bitrate switched quality, including the policy that caused it. |
volumeChanged(volume:) |
Player volume changed. |
didUnload |
The player fully unloaded its item (e.g. after unload()). |
Ads (DorisAdsEvent)
| Case | Fired when |
|---|---|
daiStreamStarted |
SSAI stream initialization completed. |
adTagParametersRequired |
The SDK requests additional ad tag parameters (client can provide dynamic values). |
adRangesChanged |
The list of available ad breaks updated. |
adProgressChanged |
The current ad’s progress changed (quartiles, countdown). |
adBreakEnded |
An ad break finished. |
adBreakStarted(adBreak:pendingSeekPosition:) |
A break started; includes pending seek info if playback will resume elsewhere. |
adRequested |
A client-side ad request kicked off with the optional tag URL. |
adLoaded |
A client-side ad payload loaded. |
adStarted |
A specific ad creative started playing within active adBreak. |
adFirstQuartile / adMidpoint / adThirdQuartile |
Standard quartile beacons for the active ad. |
adEnded |
The ad creative finished. |
adPaused / adResumed |
Ad playback paused/resumed. |
adSkipped |
User skipped the ad. |
shouldSeekTo(position:willPlayAdBreak:) |
SDK instructs the player to jump to content position (e.g. after SSAI break). |
errorOccured |
Ad subsystem hit an error (see DorisAdsError). |
Remote commands (DorisRemoteCommandEvent)
Emitted when the system’s remote-command center (lock screen, Control Center, external accessories) interacts with playback.
| Case | Fired when |
|---|---|
play, pause, playPause, stop |
Corresponding transport commands were invoked. |
skipBackward(_:), skipForward(_:) |
User activated skip controls (value is seconds). |
previousTrack, nextTrack |
Previous/next commands triggered. |
changePosition(_:) |
User scrubbed via the system slider (value is seconds). |
Configure availability through DorisRemoteCommandsConfig.
View tap events (DorisViewTapEvent)
Fine-grained tap/gesture signals from the default UI.
playPauseButtonTapseekBackButtonTapseekForwardButtonTapviewLeftTap/viewRightTapseekBarLeftTap/seekBarRightTapseekBarRemoteTapseekBarVoiceOverDecrement/seekBarVoiceOverIncrementfavouritesButtonTapwatchlistButtonTapstatsButtonTapscheduleButtonTapmoreRelatedVideosTapbackButtonTaprestartButtonTapliveBadgeTappedretryButtonTapfullScreenButtonTapoverlayOpenButtonTapmenuButtonTappedinfoButtonTappedtracksButtonTappedepisodesButtonTappedsettingsButtonTappedcastButtonTappedoverlayCloseButtonTapshareButtonTaptapOnViewlongPressedLeftOnView/longPressedRightOnViewnextEpisodeButtonTap(_:)prevEpisodeButtonTap(_:)currentPlaybackTimeLabelTapped(_:)annotationsButtonTapadsLearnMoreTapadsSkipTapskipMarkerButtonTap(_:)watchFromStartButtonButtonTapadChoicesTappedwhyThisAdCloseTapped
View lifecycle & gestures (DorisViewUniversalEvent)
Higher-level view state transitions and gestures from the default UI.
viewLoaded,viewDidAppear,viewDidDisappearviewRotated(isExternalOverlayForbidden:)subtitleSelected(_:),audioTrackSelected(_:)bandwidthPolicyModeSelected(_:)seekBarAnnotationTapped(value:)seekBarPanned(state:offsetPercent:isRemote:)progressiveSeekDidUpdate(interval:)relatedVideoSelected(_:)pinched(_:)playbackRateChanged(value:)userInteractionEndedplaylistAnimationStateChanged(_:),playlistAnimationStateWillChangeviewPanned(state:offsetPercent:isRemote:)bottomContainerFocusRemoved,bottomContainerFocusSetepisodesScrolledannotationFocused(_:)nextEpisodeViewProgressAnimationCompleted(_:)errorOccuredreadyForDisplayChanged(_:)adChoicesTappedlayoutTypeChanged(_:)voiceOverStatusChanged(_:)voiceOverFocusChanged
Use these events to add custom logic if needed.
For player and default UI state diagrams, see the States reference.