@streamlayer/web-os
v0.5.3
Published
> **Alpha Version**: This feature is currently in alpha. Expect potential instability, including occasional freezes.
Maintainers
Keywords
Readme
StreamLayerSDKTv Pause Ad Integration
Alpha Version: This feature is currently in alpha. Expect potential instability, including occasional freezes.
Prerequisites
1. PAL SDK
Add the Google PAL SDK to your HTML <head>:
<script type="text/javascript" src="https://imasdk.googleapis.com/pal/sdkloader/pal.js"></script>2. Spatial Navigation
This feature uses @noriginmedia/norigin-spatial-navigation with shouldFocusDOMNode: true mode for remote control support.
Integration
Props
| Prop | Type | Description |
|------|------|-------------|
| showPauseAd | boolean | Controls pause ad visibility. Set to true when video pauses. |
| onRenderPauseAd | (params: { rendered: boolean }) => void | Called when pause ad overlay renders. Use to hide your UI elements. |
| onClosePauseAd | () => void | Called when pause ad closes without resuming video (user dismissed overlay). |
| videoPlayerController | VideoPlayerCallback | Called when user resumes video via the pause ad overlay button. |
| pauseAdVastUrl | Array<{ template: string; url: string }> | VAST tag configuration. |
pauseAdVastUrl Configuration
pauseAdVastUrl={[
{
template: 'default', // Currently only 'default' template is supported
url: 'https://your-vast-tag-url.com/vast.xml',
},
]}Note: Only the first item in the array is used. Multi-item rotation is not yet supported.
Understanding showPauseAd vs pauseAdRendered
These two flags serve different purposes and are controlled by different parties:
| Flag | Controlled By | Purpose |
|------|---------------|---------|
| showPauseAd | You (integrator) | Request to show/hide pause ad |
| pauseAdRendered | SDK (via callback) | Actual visibility state on screen |
Why two flags?
showPauseAd is your intent — "I want the pause ad to appear/disappear."
pauseAdRendered is the actual state — "The pause ad is currently visible on screen."
These values don't always match due to animation delays:
- Opening delay (5 seconds): SDK waits before showing the overlay
- Closing delay (400ms): SDK animates the overlay before removing it
State combinations
| showPauseAd | pauseAdRendered | State |
|---------------|-------------------|-------|
| false | false | Video playing or paused without ad |
| true | false | Video paused, SDK preparing overlay (5s delay) |
| true | true | Pause ad visible on screen |
| false | true | Closing animation in progress (400ms) |
Timeline
Video pauses
│
▼
showPauseAd = true ← You set this on video pause
pauseAdRendered = false
│
│ ← 5 second delay (SDK loads ad, prepares overlay)
▼
showPauseAd = true
pauseAdRendered = true ← SDK calls onRenderPauseAd({ rendered: true })
Hide your UI controls now
│
│ ← User resumes video or closes overlay
▼
showPauseAd = false ← You set this on play/close
pauseAdRendered = true ← Still true! Closing animation playing
│
│ ← 400ms closing animation
▼
showPauseAd = false
pauseAdRendered = false ← SDK calls onRenderPauseAd({ rendered: false })
Safe to show your UI controlsWhy this matters
Always use pauseAdRendered to control your UI visibility:
// Correct: hide UI based on actual render state
const showControls = !pauseAdRendered
// This ensures:
// 1. Your controls don't disappear 5s before the ad appears
// 2. Your controls don't reappear during the 400ms closing animationIf you used showPauseAd instead, your controls would:
- Disappear immediately on pause (5s before the ad shows)
- Reappear during the closing animation (overlapping with the ad)
Implementation Example
import { useState, useCallback, useRef } from 'react'
import { StreamLayerSDKTv, type VideoPlayerCallback } from '@streamlayer/sdk-web-os'
export const VideoView = () => {
const [showPauseAd, setShowPauseAd] = useState(false)
const [pauseAdRendered, setPauseAdRendered] = useState(false)
const videoRef = useRef<HTMLVideoElement>(null)
// Called when pause ad overlay renders/hides
const onRenderPauseAd = useCallback((params: { rendered: boolean }) => {
setPauseAdRendered(params.rendered)
}, [])
// Called when pause ad closes without video resumption
const onClosePauseAd = useCallback(() => {
setShowPauseAd(false)
}, [])
// Called when user clicks resume on pause ad overlay
const videoPlayerController: VideoPlayerCallback = useCallback((data) => {
if (data.play === true) {
videoRef.current?.play()
}
}, [])
// Video event handlers
const onVideoPause = useCallback(() => {
setShowPauseAd(true)
}, [])
const onVideoPlay = useCallback(() => {
setShowPauseAd(false)
}, [])
// Hide your UI controls when pause ad is rendered
const showControls = !pauseAdRendered
return (
<StreamLayerSDKTv
showPauseAd={showPauseAd}
onRenderPauseAd={onRenderPauseAd}
onClosePauseAd={onClosePauseAd}
videoPlayerController={videoPlayerController}
pauseAdVastUrl={[
{
template: 'default',
url: 'https://your-vast-tag-url.com',
},
]}
>
{/* Your video container */}
<div>
<video
ref={videoRef}
onPause={onVideoPause}
onPlay={onVideoPlay}
/>
{/* Hide controls when pause ad is displayed */}
{showControls && (
<div className="video-controls">
{/* Play button, timeline, etc. */}
</div>
)}
</div>
</StreamLayerSDKTv>
)
}Lifecycle Flow
Video Pauses
│
▼
setShowPauseAd(true) ──► StreamLayerSDKTv receives showPauseAd=true
│
▼
onRenderPauseAd({ rendered: true })
│
▼
Hide your UI (controls, timeline, etc.)
│
┌───────────────────────┴───────────────────────┐
▼ ▼
User clicks RESUME User closes overlay
│ │
▼ ▼
videoPlayerController({ play: true }) onClosePauseAd()
│ │
▼ ▼
Resume video playback setShowPauseAd(false)
setShowPauseAd(false) (video stays paused)Key Points
- You control
showPauseAd: Set it totrueon video pause,falseon play/resume. - Hide UI on render: When
onRenderPauseAdfires withrendered: true, hide your video controls (play button, timeline, etc.). - Handle both exit paths: User can either resume video (via
videoPlayerController) or dismiss the overlay (viaonClosePauseAd). - Single VAST tag: Only one item in
pauseAdVastUrlis processed; additional items are ignored.
