Cómo volver a una pausa publicitaria omitida

Selecciona la plataforma: HTML5 Android iOS tvOS Roku

Como publicador de videos, es posible que quieras evitar que los usuarios adelanten tus anuncios durante el video. Cuando un usuario adelanta una pausa publicitaria, puedes llevarlo al inicio de esa pausa y, luego, regresarlo a su ubicación de búsqueda una vez que se haya completado. Esta función se llama "restablecimiento automático".

Como ejemplo, consulta el siguiente diagrama. El usuario está mirando un video y decide adelantar desde la marca de 5 minutos hasta la de 15 minutos. Sin embargo, hay una pausa publicitaria en la marca de 10 minutos que quieres que mire antes de que pueda ver el contenido posterior:

Para mostrar esta pausa publicitaria, sigue estos pasos:

  1. Comprueba si el usuario realizó una búsqueda que saltó una pausa publicitaria no vista y, si es así, llévalo de regreso a la pausa publicitaria.
  2. Una vez que se complete la pausa publicitaria, regresa a la búsqueda original.

En forma de diagrama, se ve así:

A continuación, se muestra cómo implementar este flujo de trabajo en el SDK de IMA DAI, como se hizo en el AdvancedExample.

Evita que se omitan los anuncios no vistos

Si un usuario intenta omitir una pausa publicitaria, el reproductor debe detectar el salto y forzar la reproducción al inicio de esa pausa publicitaria específica. Para evitar que se omitan los anuncios sin mirar, haz lo siguiente:

  1. Cuando el usuario comience a interactuar con la barra deslizante de búsqueda, registra su tiempo de reproducción actual.
  2. Una vez que el usuario termine de buscar un momento diferente en la transmisión, identifica la pausa publicitaria más reciente ubicada antes de este momento.
  3. Si la pausa publicitaria comienza después de la hora de inicio registrada, lo que indica una omisión, y aún no se reprodujo, busca el reproductor al comienzo de la pausa publicitaria.
  4. Habilita una marca snapbackMode para hacer un seguimiento de que se forzó esta pausa publicitaria.

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))
    }
  }
}

Reanuda la búsqueda original

Una vez que finaliza la reproducción de la pausa publicitaria forzada, el reproductor lleva al usuario al punto de contenido deseado.

Para reanudar la búsqueda original del usuario, haz lo siguiente:

  1. Escucha el evento AD_BREAK_ENDED en tu administrador de transmisiones.

  2. Comprueba si la marca snapbackMode está activa para asegurarte de que este salto se produzca después de una vista de anuncio forzada.

  3. Si está activa, busca el reproductor en la hora de destino guardada para devolver al usuario a la marca de tiempo deseada.

En el siguiente ejemplo, se escucha una pausa publicitaria finalizada y se devuelve al usuario a la búsqueda 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)