vastlint

VAST XML for Samsung Tizen Smart TV

Samsung Smart TVs run Tizen OS and account for a large share of global Smart TV ad inventory. Ad playback on Tizen apps is handled either by the Google IMA SDK for Cast/CTV or by a custom VAST parser built on top of Tizen's native AVPlay media engine. Both paths share the same core VAST requirements.

Quick reference

VAST versions2.0, 3.0, 4.0, 4.1 (IMA SDK); 2.0–3.0 (AVPlay native)
VPAIDCompletely blocked
Wrapper chain limit4 hops (IMA); 3 hops recommended (AVPlay)
Required media formatMP4 H.264 + AAC; HLS supported
HTTPSRequired for all URLs

AVPlay state machine and lifecycle

Tizen's webapis.avplay object exposes a state machine. Calling a method in the wrong state throws an InvalidStateError.

StateDescription
NONEPlayer not yet created. No URL loaded.
IDLEPlayer created after open(); not yet prepared.
READYPrepared and buffered; ready to play.
PLAYINGActively playing media.
PAUSEDPlayback paused.

The typical ad playback lifecycle:

// 1. Open with the ad media URL (NONE → IDLE)
webapis.avplay.open('https://cdn.example.com/ad.mp4');

// 2. Set display region (must be called in IDLE state)
webapis.avplay.setDisplayRect(0, 0, 1920, 1080);

// 3. Register playback callbacks before prepare()
webapis.avplay.setListener({
  onbufferingstart: function() { console.log('Buffering started'); },
  onbufferingcomplete: function() { console.log('Buffering complete'); },
  onstreamcompleted: function() {
    // Ad finished — resume content
    webapis.avplay.stop();
    webapis.avplay.close();
    resumeContent();
  },
  onerror: function(eventid) {
    console.error('AVPlay error:', eventid);
    resumeContent(); // fall back to content
  },
  oncurrentplaytime: function(currentTime) {
    // currentTime is in milliseconds
  },
});

// 4. Prepare (IDLE → READY) — use prepareAsync for non-blocking
webapis.avplay.prepareAsync(
  function() {
    // Success: now READY → PLAYING
    webapis.avplay.play();
  },
  function(error) {
    console.error('Prepare failed:', error);
    resumeContent();
  }
);

// Cleanup after ad:
// webapis.avplay.stop();
// webapis.avplay.close();

Playback callbacks

setListener() accepts an AVPlayPlaybackCallback object. Implement the relevant methods:

CallbackWhen fired
onbufferingstart()Buffering begins (show spinner)
onbufferingprogress(percent)Buffering percentage update
onbufferingcomplete()Initial buffering done; playback will start
oncurrentplaytime(ms)Periodic playback position update in milliseconds
onstreamcompleted()End of stream reached
onevent(eventid, data)Miscellaneous events including PLAYER_MSG_BITRATE_CHANGE, PLAYER_MSG_CUE_TAG_INFO
onerror(eventid)Player error (see AVPlayError enum)
ondrmevent(type, data)DRM challenge data received; app must fetch license and call setDrm()

Adaptive bitrate control

For HLS or MPEG-DASH ad streams, call setStreamingProperty(“ADAPTIVE_INFO”, ...)in IDLE state (after open(), before prepare()) to constrain the bitrate range:

webapis.avplay.open('https://cdn.example.com/ad/playlist.m3u8');

// Cap bitrate between 1 Mbps and 8 Mbps; start at the lowest available
webapis.avplay.setStreamingProperty(
  'ADAPTIVE_INFO',
  'STARTBITRATE=LOWEST|BITRATES=1000~8000'
);

webapis.avplay.setDisplayRect(0, 0, 1920, 1080);
webapis.avplay.prepareAsync(function() {
  webapis.avplay.play();
}, errorHandler);

The bitrate range format is minKbps~maxKbps (kilobits per second).STARTBITRATE accepts LOWEST, HIGHEST, or AVERAGE, or a numeric kbps value.

DRM support

AVPlay supports PlayReady and Widevine CDM for encrypted ad streams. Set up DRM in IDLE state before calling prepare():

// PlayReady
webapis.avplay.open('https://cdn.example.com/ad-pr.mp4');
webapis.avplay.setDrm(
  'PLAYREADY',
  'SetProperties',
  JSON.stringify({
    LicenseServer: 'https://license.example.com/pr',
    // GenChallenge: false — AVPlay fetches license automatically
  })
);

// Widevine CDM
webapis.avplay.open('https://cdn.example.com/ad-wv.mp4');
webapis.avplay.setDrm(
  'WIDEVINE_CDM',
  'SetProperties',
  JSON.stringify({
    LicenseServer: 'https://license.example.com/widevine',
    AppSession: 'session-id',
    DataType: 'MPEG-DASH',
  })
);
// For Widevine, handle the ondrmevent() callback to install the license:
// webapis.avplay.setDrm('WIDEVINE_CDM', 'widevine_license_data', base64EncodedLicense);

HLS ad cue tags

If the content stream uses HLS SCTE-35 ad markers, AVPlay fires a PLAYER_MSG_CUE_TAG_INFO event through the onevent() callback. The event data contains the cue-out/cue-in timestamps:

webapis.avplay.setListener({
  onevent: function(eventid, data) {
    if (eventid === 'PLAYER_MSG_CUE_TAG_INFO') {
      // data example:
      // "CUE_TAG_INFO: {CUEOUT-> timestamp : 18000, Expected AdDuration : 18000}"
      // "               {CUEIN-> timestamp : 36000, Actual AdDuration : 18000}"
      console.log('Ad cue tag:', data);
      // Parse and use to trigger VAST ad request at the right moment
    }
  },
});

This is relevant for server-side ad insertion (SSAI) workflows where the VAST ad is stitched into the HLS manifest.

VPAID is blocked

Tizen's media layer does not execute JavaScript in the ad pipeline. Whether the app uses IMA SDK or AVPlay directly, any <MediaFile> with apiFramework="VPAID" is silently discarded. Always include a native MP4 creative.

→ vastlint rule: VAST-4.1-vpaid-in-interactive-context

Media file requirements

Samsung Smart TVs require MP4 H.264 video with AAC audio. HLS adaptive streams are supported and preferred for longer creatives or variable-bandwidth living-room connections. Provide at least a 1080p and a 720p variant.

<MediaFiles>
  <MediaFile type="video/mp4" width="1920" height="1080"
             bitrate="5000" delivery="progressive">
    <![CDATA[https://cdn.example.com/ad-1080p.mp4]]>
  </MediaFile>
  <MediaFile type="video/mp4" width="1280" height="720"
             bitrate="2500" delivery="progressive">
    <![CDATA[https://cdn.example.com/ad-720p.mp4]]>
  </MediaFile>
</MediaFiles>

AVPlay native VAST parsers

Some Tizen apps implement a custom lightweight VAST parser using AVPlay rather than integrating the full IMA SDK. These parsers often support only VAST 2.0 and 3.0, and may not process VAST 4.x elements like <UniversalAdId> or <AdVerifications>. If you are unsure which integration a publisher uses, target VAST 3.0 for maximum compatibility.

Custom parsers also have varying behaviour around wrapper chain depth. Treat 3 hops as the safe maximum when targeting Samsung Smart TV inventory without knowing the player.

HTTPS requirement

All URLs in your VAST tag must use https://. Tizen OS blocks HTTP network requests in streaming contexts. This includes media files, impression pixels, wrapper URIs, and all event tracking URLs.

Duration format

<Duration> must use HH:MM:SS format. Both IMA SDK and most AVPlay-based parsers reject bare integer values.

→ vastlint rule: VAST-2.0-duration-format

Pre-flight checklist for Samsung Tizen

  • No VPAID creatives — native MP4 or HLS only
  • Target VAST 3.0 if publisher's player integration is unknown
  • All URLs use HTTPS
  • Wrapper chain ≤ 3 hops
  • MP4 H.264 <MediaFile> at 1080p and 720p
  • <Duration> in HH:MM:SS format
  • <Impression> with HTTPS URL present
  • version attribute on root <VAST> element
  • Call webapis.avplay.setListener() before prepare()
  • Call webapis.avplay.setDisplayRect() in IDLE state
  • Always stop() and close() after ad playback
  • For encrypted streams: configure DRM with setDrm() in IDLE state

References

Validate your tag against all 118 IAB rules →