ハイライト
HLS Interstitials は、メインコンテンツのタイムライン上に独立した広告セグメントを挿入する Apple の方式。広告をメインコンテンツストリームに直接スプライスするより、広告決定の遅延バインディングと正片と一緒に処理不要な広告コンテンツをサポートし、柔軟性が高い。
主要内容
動画プレイヤーに広告を挿入する最も素朴な方法は、広告セグメントをメインコンテンツストリームに直接スプライスすること。問題は明らか——広告決定はコンテンツ準備段階で確定必須。再生時の動的差し替え不可。広告を変えるたびにストリーム全体を再スプライス。HLS Interstitials は異なるアプローチ——広告は独立リソース。メインコンテンツタイムラインの指定位置にマウント。再生がその時点に達して初めてロード・再生。広告は遅延バインディング可能。正片ストリームは一切変更不要。
今年の焦点は Integrated Timeline API。以前開発者が直面した難題: タイムラインに正片と広告セグメントが混在——プログレスバーをどう描く?広告未ロード位置へシークしたら?新 API は AVPlayerItemIntegratedTimeline と AVPlayerItemSegment で解決。各時間帯(正片または広告)が Segment。開始・終了時間、タイプ、occupancy などの属性付き。Snapshot メカニズムでタイムライン状態読み取り時に一貫データを保証。タイムライン動的変化でも読み取り不整合を回避。SharePlay も Interstitials 同期再生をサポート開始——全参加者間で広告コンテンツが同一とマークすれば、広告中も同期維持可能。
詳細
3 つのタイムライン表示モード
Interstitials にはタイムライン上で 3 つの表示方式(03:40):
- Point: プログレスバー上に点をマーク。再生ヘッド到達時に前進停止、広告後に再開。VOD コンテンツの広告マーカー向け。
- Fill: プログレスバー上に範囲を占有。広告時間が総時間に計上。ライブストリームで焼き込みコンテンツを置換するシーン向け。
- Supplements Primary Content: Fill と類似だが UI 上正片と区別不可。リキャップ、トランジション、レーティング表示など正片と密接な補助コンテンツ向け。
AVPlayerInterstitialEvent の timelineOccupancy と supplementsPrimaryContent で制御(03:54):
// Creating a single point interstitial event
let pointEvent = AVPlayerInterstitialEvent(primaryItem: playerItem, time: ten)
pointEvent.timelineOccupancy = .singlePoint
キーポイント:
timelineOccupancyを.singlePointに設定。タイムライン上に点マーカーのみ- Point タイプは再生時に総時間を増やさない。広告中は再生ヘッド停止
// Creating a fill interstitial event
let fillEvent = AVPlayerInterstitialEvent(primaryItem: playerItem, time: ten)
fillEvent.timelineOccupancy = .fill
fillEvent.plannedDuration = CMTime(value: 15, timescale: 1)
キーポイント:
timelineOccupancyを.fillに設定。タイムライン上に範囲占有plannedDurationは Fill タイプの時間フォールバック。広告実時間は遅れて判明する場合ありplannedDuration設定は Fill イベントのベストプラクティス(04:19)
// Creating a fill interstitial event supplementing primary
let fillEvent2 = AVPlayerInterstitialEvent(primaryItem: playerItem, time: ten)
fillEvent2.supplementsPrimaryContent = true
fillEvent2.timelineOccupancy = .fill
fillEvent2.plannedDuration = CMTime(value: 15, timescale: 1)
キーポイント:
supplementsPrimaryContent = trueは UI 上正片と区別不可を意味- レーティング表示、リキャップ、エンドカードなど(04:30)
Integrated Timeline API
AVPlayerItem から AVPlayerItemIntegratedTimeline を取得(07:14)。currentSnapshot で UI 描画に必要な全一貫状態を含む不変スナップショットを返す。
// Create AVPlayerItem and obtain its integrated timeline
let item = AVPlayerItem(url: ...)
let integratedTimeline = item.integratedTimeline
// Any time we need a new representation of the timeline state, we can request for a snapshot
let snapshot = integratedTimeline.currentSnapshot
// Using our snapshot, we can build a simple transport bar
drawUISlider(start: .zero, duration: snapshot.duration, currentPosition: snapshot.currentTime)
// Draw single-point interstitials on the transport bar
let pointSegments = snapshot.segments.filter { segment in
segment.segmentType == .interstitial &&
segment.interstitialEvent?.timelineOccupancy == .singlePoint
}
for segment in pointSegments {
drawPoint(position: segment.timeMapping.target.start)
}
// Draw range interstitials on the transport bar
let highlightFillSegments = snapshot.segments.filter { segment in
if (segment.segmentType == .interstitial) {
if let interstitialEvent = segment.interstitialEvent {
return interstitialEvent.timelineOccupancy == .fill &&
!interstitialEvent.supplementsPrimaryContent
}
}
return false
}
for segment in highlightFillSegments {
let range = segment.timeMapping.target
highlightRegion(start: range.start, end: range.end)
}
キーポイント:
item.integratedTimelineで AVPlayerItem からタイムラインオブジェクト取得integratedTimeline.currentSnapshotは不変スナップショット。再生状態変化で変異しないsnapshot.durationは Fill 広告の総時間含む。snapshot.currentTimeは Point 広告再生中に前進停止supplementsPrimaryContent == trueのセグメントをフィルタ。UI 上区別マークしない- 各 Segment に
segmentType(.primaryまたは.interstitial)とtimeMapping属性
タイムライン変化の監視
タイムラインは動的——広告は動的解決、ライブストリームは継続更新。snapshotsOutOfSyncNotification で監視(08:26):
// Listen to integrated timeline notifications to update our logic
for await _ in NotificationCenter.default.notifications(named: AVPlayerItemIntegratedTimeline.snapshotsOutOfSyncNotification, object: integratedTimeline) {
let reason = _.userInfo![AVPlayerItemIntegratedTimeline.snapshotsOutOfSyncReasonKey]
as! AVPlayerIntegratedTimelineSnapshotsOutOfSyncReason
switch(reason) {
case .segmentsChanged:
redrawTransportBar(snapshot: integratedTimeline.currentSnapshot)
case .currentSegmentChanged:
updatePlayerControls(snapshot: integratedTimeline.currentSnapshot)
}
}
キーポイント:
segmentsChanged: セグメント構造変化(広告解決または削除)。プログレスバー再描画currentSegmentChanged: 再生ヘッドが正片↔広告に移動。プレイヤーコントロール更新- 通知後
currentSnapshotを再取得すれば最新一貫状態
HLS サーバー側新属性
HLS DateRange タグに 2 つの新属性でタイムライン動作制御(09:50):
X-TIMELINE-OCCUPIES: 値POINTまたはRANGE。.singlePointと.fillに対応X-TIMELINE-STYLE: 値HIGHLIGHT(UI 上マーク)またはPRIMARY(正片と区別不可)
SharePlay サポート
Interstitials が SharePlay 同期再生に参加可能に(10:57)。前提: 全参加者間で広告コンテンツが同一。contentMayVary = false でマーク:
// Set contentMayVary to false for SharePlay support
let event = AVPlayerInterstitialEvent(primaryItem: playerItem, time: ten)
event.contentMayVary = false
event.timelineOccupancy = .fill
event.plannedDuration = CMTime(value: 15, timescale: 1)
event.supplementsPrimaryContent = true
キーポイント:
contentMayVary = falseは全参加者間で広告コンテンツ同一。同期再生可能- HLS DateRange では
X-CONTENT-MAY-VARY=NOに対応(11:59) - パーソナライズ広告(推薦ベースなど)は同期を有効にしない
- 同期中、一時停止・シークなどの操作は参加者間で自動同期
重要ポイント
-
何をするか: Integrated Timeline で広告を含むプレイヤープログレスバーを描画。なぜ価値があるか: 統一タイムラインモデルがなければ、プログレスバーは広告占有を正確反映できず、広告位置へのシークも失敗。始め方:
AVPlayerItem.integratedTimelineからタイムライン取得。currentSnapshotで segment リスト読み取り UI 描画。 -
何をするか:
supplementsPrimaryContentで動画ストリームの discontinuity セグメントを置換。なぜ価値があるか: リキャップ、トランジションなどは通常 discontinuity として正片に焼き込み——置換コスト高。Interstitials なら補助コンテンツを独立管理し UI 上正片とシームレス。始め方:supplementsPrimaryContent = trueの Fill イベント作成。plannedDuration設定。HLS でX-TIMELINE-STYLE=PRIMARYマーク。 -
何をするか: SharePlay シーンの共通広告で同期再生を有効化。なぜ価値があるか: 複数人でライブ視聴時、広告中に各自異なるコンテンツだと同期破壊。
contentMayVary = falseで広告再生・一時停止・シークが自動同期。始め方: 全参加者間で広告コンテンツ同一を確認。イベントにcontentMayVary = false設定。または HLS DateRange にX-CONTENT-MAY-VARY=NO追加。
関連セッション
- Explore dynamic pre-rolls and mid-rolls in HLS — HLS Interstitials 基本と動的広告挿入の深掘り
- Discover media performance metrics in AVFoundation — 新メディアパフォーマンス指標 API で再生をモニタリング・最適化
- Coordinate media experiences with Group Activities — Group Activities と SharePlay で共有メディア体験を構築
コメント
GitHub Issues · utterances