WWDC Quick Look 💓 By SwiftGGTeam
What's new in HLS Interstitials

What's new in HLS Interstitials

观看原视频

Highlight

HLS Interstitials 2022 新增了广告排期选项(CUE 属性)、直播场景精确对齐(SNAP 属性)和服务端广告优化查询参数(HLS_start_offset 和 HLS_primary_id),让广告插入更灵活、直播时钟漂移问题得到解决,并支持根据剩余播放时间优化广告投放。


核心内容

HLS Interstitials 在 2021 年推出,把广告视为独立资产通过 multivariant playlist 引用,而非传统方式拼接在主内容流中。开发者只需要在播放列表中用 DATERANGE 标签指定广告开始时间,就能实现广告调度。(00:0901:09

这种设计简化了广告插入流程。过去需要在主内容里用 discontinuity 标签拼接广告,现在直接指向广告的 multivariant playlist。如果主内容里已经有拼接的广告,还可以通过 resume offset 替换,offset 等于被替换广告的时长即可。(01:1801:57

2022 年的更新聚焦三个方向:更精确的广告排期控制、直播场景下的时钟漂移处理,以及服务端广告优化。


详细内容

CUE 属性:控制广告播放时机

02:26)CUE 属性强制把广告放到播放位置的前后,而不是基于内容时间线的某个时间点。它支持三种值:

  • PRE:广告在主内容开始前播放,适合直播场景的 premium ad spot(黄金广告位)。
  • POST:广告在主内容结束后播放,适合活动结束时的片尾字幕。
  • ONCE:广告只播放一次,用户回退到广告位置不会再看到,适合评级屏幕或法律声明。

02:4603:25)示例展示了 preroll、postroll 和 midroll 混合使用。Preroll 设为 ONCE,确保只播放一次;10 秒处的 midroll 同样设为 ONCE,用户回退到 10 秒前不会重复播放。

SNAP 属性:解决直播时钟漂移

03:40)直播场景中,packager 和编码器可能使用不同的时钟。如果 packager 时钟比编码器时钟快,程序日期时间标签显示的 800 秒差异,实际媒体时长会略少于 800 秒。

这个时钟漂移会导致问题。广告按计划时间开始播放时,实际媒体时间可能落在 slate 内部;如果按广告时长作为 offset 返回主内容,就会错过广告后面那部分主内容。(04:17

04:37)解决方法是 SNAP 属性。SNAP-OUT 让广告在接近计划开始时间的 segment 边界切入主内容,SNAP-IN 让广告在接近计划返回时间的 segment 边界切回主内容。

示例展示了直播播放列表里的广告同时设置 SNAP-OUT 和 SNAP-IN。(05:04

HLS_start_offset:优化直播中途加入的广告体验

05:10)直播中途加入时,服务端需要知道当前广告 pod 播放了多久,才能在剩余时间里展示最有价值的广告。

HLS_start_offset 查询参数会附加到 interstitial asset-list URL 请求。直播内容下,它指定加入直播时 asset-list 中的播放偏移;VOD 内容下,它指定 seek 到被替换区域时的偏移。(05:54

示例里,15 秒广告在播放列表开始 5 秒后调度。直播中途加入时,客户端通常在 live edge 后 3 个 target duration,此时广告已经播了 10 秒。服务端收到 HLS_start_offset=10 后,可以把最贵的广告放在最后 5 秒。(06:0506:20

HLS_primary_id:跨请求关联播放会话

06:30)服务端需要追踪同一个播放会话的多个广告请求,避免重复播放相同广告。

HLS_primary_id 查询参数关联广告请求和主播放会话。如果客户端为所有 HTTP 请求设置了 playback session ID 请求头,就用这个 ID 作为 HLS_primary_id;否则为每个主播放会话生成唯一值,并在主内容和插播广告请求中使用。(06:40

AVFoundation API 变更

07:15)AVFoundation 的 AVPlayerInterstitialControllerAVPlayerInterstitialEvent 现在支持 CUE 和 SNAP 选项。

  • cue 属性:设置 preroll 或 postroll。
  • willPlayOnce 属性:对应 CUE 的 ONCE 值。
  • alignsStartWithPrimarySegmentBoundary 属性:对应 SNAP-OUT。
  • alignsResumptionWithPrimarySegmentBoundary 属性:对应 SNAP-IN。

07:58)Session 示例展示了客户端在 10 秒处调度 ad pod:

// Client schedules an ad pod at 10s into primary asset
let player = AVPlayer(url: movieURL)  // no ads in primary asset
let controller = AVPlayerInterstitialEventController(primaryPlayer: player)
let adPodTemplates = [AVPlayerItem(url: ad1URL), AVPlayerItem(url: ad2URL)]
let event = AVPlayerInterstitialEvent(primaryItem: player.currentItem,
                             time: CMTime(seconds: 10, preferredTimescale: 1))
event.templateItems = adPodTemplates
event.identifier = "Ad1"
event.restrictions = []
event.resumptionOffset = .zero
event.playoutLimit = .invalid
event.cue = .none

controller.events = [event]
player.currentItem.translatesPlayerInterstitialEvents = true
let vc = AVPlayerViewController()
vc.player = player
player.play()

关键点:

  • AVPlayerInterstitialEvent 用 primary item 和时间创建,随后设置属性。
  • templateItems 是广告 pod 里的广告列表。
  • cue 设为 .none 表示不用 preroll/postroll,基于时间调度。
  • translatesPlayerInterstitialEvents 设为 true 让播放器处理插播事件。

08:06AVPlayerInterstitialEvent 现在可变。创建时只需要 primary item 和开始时间,随后设置配置属性。事件设置到 controller 后,后续修改不会生效,因为 controller 会复制对象;要修改需要重新设置事件。


核心启发

  • 做什么:为直播流加 premium preroll 广告位。 为什么值得做:CUE 属性的 PRE 值让广告在节目开始前播放,适合直播黄金广告位;ONCE 值确保用户刷新或重连后不再重复播放。 怎么开始:在 multivariant playlist 里为 preroll 广告 DATERANGE 设置 X-CUE="PRE,ONCE"

  • 做什么:解决直播广告时钟漂移导致的主内容丢失。 为什么值得做:直播中 packager 和编码器时钟不同步会让广告切入切回位置不准确,可能错过节目内容。 怎么开始:为 DATERANGE 设置 X-SNAP="OUT,IN",让广告在最近的 segment 边界切入和切回。

  • 做什么:为直播中途加入用户优化广告投放。 为什么值得做:HLS_start_offset 告诉服务端广告剩余时间,可以把最贵的广告放在最后。 怎么开始:服务端检查 X-Asset-List 请求的 HLS_start_offset 参数,根据偏移调整 asset-list 顺序。

  • 做什么:避免同一会话重复播放相同广告。 为什么值得做:用户在一个播放会话里看到相同广告多次体验差。 怎么开始:客户端用 playback session ID 作为 HLS_primary_id 参数,服务端据此追踪已播放广告。

  • 做什么:用 AVFoundation 调度客户端侧广告。 为什么值得做AVPlayerInterstitialEvent 支持新的 CUE 和 SNAP 属性,可以和 HLS playlist 行为一致。 怎么开始:创建 AVPlayerInterstitialEvent,设置 cuewillPlayOncealignsStartWithPrimarySegmentBoundary 等属性。


关联 Session

评论

GitHub Issues · utterances