חזרה להפסקה למודעה שדילגתם עליה

בחירת פלטפורמה: HTML5 Android iOS tvOS Roku

אם אתם מפרסמים סרטונים, יכול להיות שתרצו למנוע מהצופים לדלג על המודעות באמצע הסרטון. כשמשתמש מדלג מעבר להפסקת פרסומות, אפשר להחזיר אותו לתחילת הפסקת הפרסומות הזו, ואז להחזיר אותו למיקום הדילוג אחרי שההפסקה מסתיימת. התכונה הזו נקראת 'חזרה מהירה'.

לדוגמה, ראו את התרשים הבא. הצופה צופה בסרטון ומחליט לדלג מנקודת הזמן של 5 דקות לנקודת הזמן של 15 דקות. עם זאת, יש הפסקת פרסומות אחרי 10 דקות צפייה, ואתם רוצים שהצופים יצפו בה לפני שהם יוכלו לצפות בתוכן שאחריה:

כדי להציג את ההפסקה המסחרית הזו, פועלים לפי השלבים הבאים:

  1. בודקים אם המשתמש דילג על הפסקת פרסומות שלא צפה בה, ואם כן, מחזירים אותו להפסקת הפרסומות.
  2. אחרי שהפסקת הפרסום מסתיימת, מחזירים אותם למיקום המקורי בסרטון.

בתרשים, זה נראה כך:

כך מטמיעים את תהליך העבודה הזה ב-IMA DAI SDK, כמו שנעשה ב-AdvancedExample.

מניעת דילוג על מודעות שלא נצפו

אם משתמש מנסה לדלג על הפסקת פרסום, נגן המדיה צריך לזהות את הדילוג ולהכריח את הפעלת הסרטון מתחילת הפסקת הפרסום הספציפית הזו. כדי למנוע דילוג על מודעות שלא נצפו:

  1. כשמשתמש מתחיל אינטראקציה עם סרגל ההתקדמות, צריך לתעד את זמן ההפעלה הנוכחי שלו.
  2. אחרי שהמשתמש מסיים את ההזזה לזמן אחר בשידור, צריך לזהות את הפסקת הפרסומות האחרונה שהייתה לפני הזמן הזה.
  3. אם ההפסקה לפרסומות מתחילה אחרי שעת ההתחלה שתועדה, מה שמצביע על דילוג, ועדיין לא הופעלה, צריך להעביר את נגן הווידאו לתחילת ההפסקה לפרסומות.
  4. מפעילים סימון snapbackMode כדי לעקוב אחרי הפסקת הפרסום הזו שנכפתה.

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

המשך החיפוש המקורי

אחרי שפרסומת שמופעלת בכוח מסתיימת, המשתמש מועבר בנגן לנקודה שבה הוא רצה לצפות בתוכן.

כדי לחזור למיקום המקורי של המשתמש בסרטון:

  1. מחפשים את האירוע AD_BREAK_ENDED בכלי לניהול השידור.

  2. בודקים אם הדגל snapbackMode פעיל כדי לוודא שהמעבר הזה יקרה אחרי צפייה במודעה שנכפתה על המשתמש.

  3. אם ההגדרה פעילה, המערכת תעביר את הצופה למיקום בזמן ששמור בנגן כדי להחזיר אותו לחותמת הזמן הרצויה.

בדוגמה הבאה, המערכת מאזינה לסיום של הפסקת פרסום ומחזירה את המשתמש למיקום המקורי בסרטון:

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)