Tornare a un'interruzione pubblicitaria saltata

Seleziona la piattaforma: HTML5 Android iOS tvOS Roku

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:

  1. Controlla se l'utente ha eseguito un avanzamento che ha saltato un'interruzione pubblicitaria non guardata e, in caso affermativo, riportalo all'interruzione pubblicitaria.
  2. 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:

  1. Quando l'utente inizia a interagire con la barra di ricerca, registra il tempo di riproduzione corrente.
  2. 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.
  3. 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.
  4. Attiva un flag snapbackMode per 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:

  1. Ascolta l'evento AD_BREAK_ENDED in Stream Manager.

  2. Controlla se il flag snapbackMode è attivo per assicurarti che il salto avvenga dopo la visualizzazione forzata di un annuncio.

  3. 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)