Como editor de vídeo, talvez você queira impedir que os espectadores pulem seus anúncios intermediários. Quando um usuário pula um intervalo de anúncio, você pode levá-lo de volta ao início desse intervalo de anúncio e, em seguida, retornar ao ponto do vídeo buscado pelo usuário após a conclusão do intervalo de anúncio. Esse recurso é chamado de "snapback".
Por exemplo, confira o diagrama abaixo. O espectador está assistindo um vídeo e decide procurar do minuto 5 ao minuto 15. No entanto, há um intervalo de anúncio aos 10 minutos que você quer que eles assistam antes de poder assistir o conteúdo depois dele:

Para mostrar esse intervalo de anúncio, siga estas etapas:
- Verifique se o usuário fez uma busca que pulou um intervalo de anúncio não assistido e, em caso afirmativo, retorne ao intervalo de anúncio.
- Depois que o intervalo de anúncio terminar, retorne ao ponto original do vídeo.
Em forma de diagrama, isso fica assim:

Confira como implementar esse fluxo de trabalho no SDK DAI do IMA, como feito no AdvancedExample.
Impedir que anúncios não assistidos sejam ignorados
Se um usuário tentar pular um intervalo de anúncio, o player vai detectar o salto e forçar a reprodução para o início desse intervalo específico. Para evitar que os anúncios não assistidos sejam pulados, faça o seguinte:
- Quando o usuário começar a interagir com a barra de busca, registre o tempo de reprodução atual.
- Depois que o usuário terminar de buscar um horário diferente no stream, identifique o intervalo de anúncio mais recente localizado antes desse horário.
- Se o intervalo de anúncio começar depois do horário de início gravado, indicando uma ação de pular, e ainda não tiver sido reproduzido, avance o player para o início do intervalo de anúncio.
- Ative uma flag
snapbackModepara rastrear que esse intervalo de anúncio foi forçado.
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))
}
}
}
Retomar a busca original
Depois que o intervalo de anúncio forçado terminar, o player vai levar o usuário ao ponto de conteúdo desejado.
Para retomar a busca original do usuário, faça o seguinte:
Aguarde o evento
AD_BREAK_ENDEDno gerenciador de streams.Verifique se a flag
snapbackModeestá ativa para garantir que esse salto ocorra após uma visualização forçada de anúncio.Se estiver ativo, procure o player no tempo de destino salvo para retornar o usuário ao carimbo de data/hora pretendido.
O exemplo a seguir detecta um intervalo de anúncio concluído e retorna um usuário para a busca original:
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)