Applications sold as source

Playing HLS on Samsung Tizen and LG webOS

AÖArif Özelci, developer of VelaPublished 7 min read

Both TV platforms play HLS natively, and both run hls.js. Which one you should use depends less on the TV than on what you need from the player: a progress bar you control, quality switching you can see, previews inside posters. Here is how to choose, the canPlayType trap that sends desktop testing down the wrong path, and the CORS headers a packaged TV app needs.

A title detail screen offering to resume playback from where the viewer stopped.
Resume, seek and a visible buffer all need a player you control.

Native playback or hls.js

Setting an .m3u8 URL as a <video> element’s src works on webOS and Tizen: the platform’s media pipeline handles the playlist and switches quality on its own. It is the simplest path and the one with the best hardware decoding behaviour.

hls.js parses the playlist in JavaScript and feeds segments to the video element through Media Source Extensions, which TV engines support. You get events for every level switch and buffer change, control over the starting quality, and the same behaviour on every platform, which makes bugs reproducible on your laptop. The cost is CPU on low-end sets. For a content app with a custom progress bar and previews, hls.js first with native as the fallback is a reasonable default; for a single full-screen live channel, native is often enough.

The canPlayType trap

The usual snippet checks video.canPlayType('application/vnd.apple.mpegurl') first and only falls back to hls.js when native HLS is missing. Desktop Chrome now answers “maybe” to that question, so the native branch runs and, depending on the version, playback fails or behaves differently from the TV. Check Hls.isSupported() first, and use native playback only where MSE is unavailable:

if (Hls.isSupported()) {
  const hls = new Hls()
  hls.loadSource(url)
  hls.attachMedia(video)
} else if (video.canPlayType('application/vnd.apple.mpegurl')) {
  video.src = url
}

CORS for a packaged app

A packaged webOS or Tizen app is not served from your domain, so every request it makes for a playlist, segment, poster or catalogue file is cross-origin. hls.js fetches with XHR, which means your CDN must send Access-Control-Allow-Origin on .m3u8 and .ts responses — not just on the page. Serve playlists as application/vnd.apple.mpegurl and segments as video/mp2t; some TV engines are strict about the type.

location /media/ {
  types { application/vnd.apple.mpegurl m3u8; video/mp2t ts; }
  add_header Access-Control-Allow-Origin "*" always;
}

When to reach for Samsung AVPlay

Tizen also offers AVPlay, a platform player API that renders video outside the web page. It is the route for DRM-protected streams and for some formats the web engine will not handle. It is also a different programming model — no <video> element, no CSS on the video layer — so keep it for when you need it. Clear HLS for a catalogue app plays well through the web path on both platforms.

Vela plays HLS this way on both platforms$199 once. hls.js with native fallback, a progress bar with buffer and ±10 s seek, resume from where the viewer stopped, muted previews inside posters, and a mini player that keeps going while you browse. Clear HLS only: DRM is integration work Vela leaves to you.
Open the demo →
AÖ
Arif ÖzelciBuilds the WebKoding plugins. Answers support himself.