Revenir à une coupure publicitaire ignorée

Sélectionnez une plate-forme : HTML5 Android iOS tvOS Roku

En tant qu'éditeur de vidéos, vous pouvez empêcher vos spectateurs de passer vos annonces mid-roll. Lorsqu'un utilisateur passe une coupure publicitaire en sélectionnant un point précis de la vidéo, vous pouvez le ramener au début de cette coupure, puis le renvoyer à cet emplacement, une fois la coupure publicitaire terminée. Cette fonctionnalité est appelée "retour rapide".

Par exemple, consultez le diagramme ci-dessous. Votre spectateur regarde une vidéo et décide de passer de la 5e à la 15e minute. Toutefois, il y a une coupure publicitaire à 10 minutes que vous souhaitez qu'ils regardent avant de pouvoir regarder le contenu qui suit :

Pour afficher cet emplacement publicitaire, procédez comme suit :

  1. Vérifiez si l'utilisateur a effectué une recherche qui a sauté une coupure publicitaire non regardée et, si c'est le cas, ramenez-le à la coupure publicitaire.
  2. Une fois la coupure publicitaire terminée, renvoyez-le à l'emplacement qu'il avait sélectionné.

Sous forme de diagramme, cela se présente comme suit :

Voici comment implémenter ce workflow dans le SDK IMA DAI, comme dans l'AdvancedExample.

Empêcher l'utilisateur de passer les annonces non regardées

Si un utilisateur tente d'ignorer une coupure publicitaire, le lecteur doit détecter le saut et forcer la lecture au début de cette coupure publicitaire spécifique. Pour empêcher l'utilisateur d'ignorer les annonces non regardées :

  1. Lorsque l'utilisateur commence à interagir avec la barre de recherche, enregistrez sa durée de lecture actuelle.
  2. Une fois que l'utilisateur a terminé de rechercher un autre moment dans le flux, identifiez la coupure publicitaire la plus récente située avant ce moment.
  3. Si la coupure publicitaire commence après l'heure de début enregistrée, ce qui indique un saut, et qu'elle n'a pas encore été diffusée, faites revenir le lecteur au début de la coupure publicitaire.
  4. Activez un indicateur snapbackMode pour indiquer que cette coupure publicitaire a été forcée.

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

Reprendre la recherche d'origine

Une fois la coupure publicitaire forcée terminée, le lecteur redirige l'utilisateur vers le point de contenu prévu.

Pour reprendre la recherche initiale de l'utilisateur, procédez comme suit :

  1. Écoutez l'événement AD_BREAK_ENDED dans votre gestionnaire de flux.

  2. Vérifiez si l'indicateur snapbackMode est actif pour vous assurer que ce saut se produit après l'affichage forcé d'une annonce.

  3. Si la lecture est active, recherchez le point de destination enregistré pour ramener l'utilisateur au code temporel souhaité.

L'exemple suivant écoute la fin d'un bloc d'annonces et renvoie l'utilisateur à la position de recherche d'origine :

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)