In qualità di editore di video, potresti voler impedire ai tuoi spettatori di saltare gli annunci mid-roll. Quando un utente avanza oltre un'interruzione pubblicitaria, puoi riportarlo all'inizio dell'interruzione e poi alla posizione che aveva raggiunto dopo che l'interruzione pubblicitaria è terminata. Questa funzionalità si chiama "ritorno".
Ad esempio, vedi il diagramma riportato di seguito. Lo spettatore sta guardando un video e decide di passare dal minuto 5 al minuto 15. Tuttavia, c'è un'interruzione pubblicitaria al minuto 10 che vuoi che guardino prima di poter guardare i contenuti successivi:

Per mostrare questa interruzione pubblicitaria, segui questi passaggi:
- Controlla se l'utente ha eseguito un avanzamento che ha saltato un'interruzione pubblicitaria non guardata e, in caso affermativo, riportalo all'interruzione pubblicitaria.
- Al termine dell'interruzione pubblicitaria, riporta l'utente alla posizione di avanzamento originale.
Sotto forma di diagramma, la situazione è la seguente:

Ecco come implementare questo flusso di lavoro nell'SDK IMA DAI, come fatto in AdvancedExample.
Impedire l'omissione degli annunci non visualizzati
Se un utente tenta di saltare un'interruzione pubblicitaria, il player deve rilevare il salto e forzare la riproduzione all'inizio di quell'interruzione pubblicitaria specifica. Per evitare di saltare gli annunci non visualizzati:
- Quando l'utente inizia a interagire con la barra di ricerca, registra il tempo di riproduzione corrente.
- Dopo che l'utente ha terminato la ricerca di un altro momento dello stream, identifica l'interruzione pubblicitaria più recente che si trova prima di questo momento.
- Se l'interruzione pubblicitaria inizia dopo l'ora di inizio registrata, a indicare un salto, e non è ancora stata riprodotta, sposta il player all'inizio dell'interruzione pubblicitaria.
- Attiva un flag
snapbackModeper monitorare se questa interruzione pubblicitaria è stata forzata.
Objective-C
- (IBAction)videoControlsTouchStarted:(id)sender {
[NSObject cancelPreviousPerformRequestsWithTarget:self
selector:@selector(hideFullscreenControls)
object:self];
self.currentlySeeking = YES;
self.seekStartTime = self.contentPlayer.currentTime;
}
- (IBAction)videoControlsTouchEnded:(id)sender {
if (self.fullscreen) {
[self startHideControlsTimer];
}
self.currentlySeeking = NO;
if (!self.adPlaying) {
self.seekEndTime = CMTimeMake(self.progressBar.value, 1);
IMACuepoint *lastCuepoint =
[self.streamManager previousCuepointForStreamTime:CMTimeGetSeconds(self.seekEndTime)];
if (!lastCuepoint.played && (lastCuepoint.startTime > CMTimeGetSeconds(self.seekStartTime))) {
self.snapbackMode = YES;
// Add 1 to the seek time to get the keyframe at the start of the ad to be our landing
// place.
[self.contentPlayer
seekToTime:CMTimeMakeWithSeconds(lastCuepoint.startTime + 1, NSEC_PER_SEC)];
}
}
}
Swift
@IBAction func progressBarTouchStarted(_ sender: UISlider) {
guard !isAdPlaying else { return }
currentlySeeking = true
seekStartTime = contentPlayer.currentTime().seconds
}
// MARK: Snapback Logic
@IBAction func progressBarTouchEnded(_ sender: UISlider) {
guard !isAdPlaying else { return }
if isFullScreen {
startHideControlsTimer()
}
currentlySeeking = false
seekEndTime = Float64(sender.value)
guard let streamManager else { return }
if let lastCuepoint = streamManager.previousCuepoint(forStreamTime: seekEndTime) {
if !lastCuepoint.isPlayed, lastCuepoint.startTime > seekStartTime {
logMessage(
"Snapback to \(String(format: "%.2f", lastCuepoint.startTime)) from \(String(format: "%.2f", seekEndTime))"
)
snapbackMode = true
contentPlayer.seek(
to: CMTime(seconds: Double(sender.value), preferredTimescale: 1000))
}
}
}
Riprendere la ricerca originale
Al termine della riproduzione dell'interruzione pubblicitaria forzata, il player riporta l'utente al punto dei contenuti previsto.
Per riprendere la ricerca originale dell'utente:
Ascolta l'evento
AD_BREAK_ENDEDin Stream Manager.Controlla se il flag
snapbackModeè attivo per assicurarti che il salto avvenga dopo la visualizzazione forzata di un annuncio.Se è attivo, cerca il momento in cui il giocatore ha salvato la destinazione per riportare l'utente al timestamp previsto.
L'esempio seguente rileva la fine di un'interruzione pubblicitaria e riporta l'utente alla posizione di ricerca originale:
Objective-C
case kIMAAdEvent_AD_BREAK_ENDED: {
[self logMessage:@"Ad break ended"];
self.adPlaying = NO;
if (self.snapbackMode) {
self.snapbackMode = NO;
if (CMTimeCompare(self.seekEndTime, self.contentPlayer.currentTime)) {
[self.contentPlayer seekToTime:self.seekEndTime];
}
}
break;
}
Swift
case .AD_BREAK_ENDED:
logMessage("Ad break ended")
isAdPlaying = false
progressBar.isUserInteractionEnabled = true
if snapbackMode {
snapbackMode = false
if contentPlayer.currentTime().seconds < seekEndTime {
contentPlayer.seek(to: CMTime(seconds: Double(seekEndTime), preferredTimescale: 1000))
}
} else if pendingBookmarkSeek, let time = bookmarkStreamTime {
logMessage(String(format: "AD_BREAK_ENDED: Seeking to bookmark streamTime: %.2f", time))
imaVideoDisplay.seekStream(toTime: time)
pendingBookmarkSeek = false
bookmarkStreamTime = nil
}
updatePlayHeadState(isPlaying: self.isContentPlaying)