Là nhà xuất bản video, bạn có thể muốn ngăn người xem tua qua quảng cáo trong video. Khi người dùng tua qua một điểm chèn quảng cáo, bạn có thể đưa họ trở lại điểm bắt đầu của điểm chèn quảng cáo đó, rồi đưa họ quay về vị trí tua ban đầu sau khi điểm chèn quảng cáo đã hiển thị xong. Tính năng này được gọi là "quay lại quảng cáo".
Để xem ví dụ, hãy tham khảo sơ đồ bên dưới. Người xem đang xem một video và quyết định tua từ phút thứ 5 đến phút thứ 15. Tuy nhiên, có một điểm ngắt quảng cáo ở phút thứ 10 mà bạn muốn họ xem trước khi có thể xem nội dung sau đó:

Để hiển thị (điểm) chèn quảng cáo này, hãy làm theo các bước sau:
- Kiểm tra xem người dùng có tua qua một điểm ngắt quảng cáo chưa xem hay không. Nếu có, hãy đưa họ trở lại điểm ngắt quảng cáo đó.
- Sau khi điểm chèn quảng cáo hiển thị xong, hãy đưa họ quay về vị trí tua ban đầu.
Ở dạng sơ đồ, quá trình này sẽ có dạng như sau:

Sau đây là cách triển khai quy trình làm việc này trong SDK IMA DAI, như trong AdvancedExample.
Ngăn người dùng bỏ qua quảng cáo chưa xem
Nếu người dùng cố gắng bỏ qua một điểm chèn quảng cáo, thì trình phát phải phát hiện lượt tua và buộc phát lại từ đầu điểm chèn quảng cáo cụ thể đó. Để ngăn người dùng bỏ qua quảng cáo chưa xem, hãy làm như sau:
- Khi người dùng bắt đầu tương tác với thanh tua, hãy ghi lại thời gian phát hiện tại của họ.
- Sau khi người dùng tua đến một thời điểm khác trong luồng, hãy xác định điểm ngắt quảng cáo gần đây nhất nằm trước thời điểm này.
- Nếu điểm chèn quảng cáo bắt đầu sau thời gian bắt đầu đã ghi (cho biết người dùng đã tua) và chưa được phát, hãy tua trình phát đến đầu điểm chèn quảng cáo.
- Bật cờ
snapbackModeđể theo dõi rằng điểm ngắt quảng cáo này đã bị buộc.
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))
}
}
}
Tiếp tục vị trí tua ban đầu
Sau khi điểm chèn quảng cáo bị buộc phát xong, trình phát sẽ đưa người dùng đến điểm nội dung dự định.
Để tiếp tục vị trí tua ban đầu của người dùng, hãy làm như sau:
Nghe sự kiện
AD_BREAK_ENDEDtrong trình quản lý luồng.Kiểm tra xem cờ
snapbackModecó đang hoạt động hay không để đảm bảo rằng lượt tua này xảy ra sau khi lượt xem quảng cáo bị buộc phát.Nếu đang hoạt động, hãy tua trình phát đến thời gian đích đã lưu để đưa người dùng trở lại dấu thời gian dự định.
Ví dụ sau đây sẽ nghe một điểm chèn quảng cáo đã hoàn tất và đưa người dùng trở lại vị trí tua ban đầu:
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)