AVPlay vs MSE on Samsung TVs: pick the player the hardware can run
When Samsung AVPlay beats Media Source Extensions for HLS and DASH on Tizen - DRM, live streams, legacy devices, and a player layer that can switch.
On a phone or a desktop, MSE is the player. HLS.js or Shaka appends fragments, ABR lives in JavaScript, ads and captions share a timeline you control. On a Samsung TV, AVPlay is sitting under webapis.avplay, wired to the hardware decoder, and it does not care about your nice media pipeline.
On Tizen 3 and other 2017 Samsung panels, that fork is already decided. MSE is incomplete, the heap is small, and a JavaScript HLS player is not what we shipped. AVPlay is: native HLS, hardware decode, a display rect, buffering events. The job is to play the stream in the room. The job is not to make Tizen look like Chrome.
What each engine is for
MSE is the right call when the browser's SourceBuffer is complete enough to hold a short window, EME is present for the DRM you need, and you need fragment-level control - client ads, custom ABR, in-band metadata you parse yourself. Shaka against DASH, HLS.js against HLS, same app chrome.
AVPlay is the right call when the decoder should own the stream: older Tizen, PlayReady through the native path, HLS that the firmware already understands, or any device where JS transmuxing is the outage. You set a URL, a display rect, a few streaming properties, and you listen to buffering events. You do not inspect NAL units.
- AVPlay: hardware decode, better live stability on weak chips, native DRM, less JS CPU. Weak timeline control, awkward CSAI, captions often as an overlay you sync yourself.
- MSE: one player model across Tizen versions that can run it, shared code with webOS HTML5, better ad insertion. Not the path on Tizen 3 or other 2017 Samsung hardware - those boxes use AVPlay.
A layer, not a wrapper fantasy
The useful abstraction is small: load({ url, drm, live }), play, pause, seek, setRect, destroy, and a currentTime you can lie about if the native clock is jumpy. Behind it, pick an engine at start. Do not wrap every AVPlay streaming property and every Shaka configuration in one mega-adapter. That adapter becomes the bug.
Engine choice belongs on a matrix: Tizen version, MSE self-test, DRM system, stream type. A 2022 Tizen 6 box can run Shaka for VOD and still use AVPlay for a live channel that needs firmware-level robustness. The UI should not know which one ran. The telemetry should.
Ads, clocks, and the focus ring
Client-side ads are where MSE fans get hurt on TV. You cannot stitch as freely when AVPlay owns the decoder. Server-side insertion plus a native player is the grown-up path for living-room hardware. If the business insists on CSAI, that is an argument for MSE on the devices that can hold it - and a different ad product on the ones that cannot.
Then there is the 10-foot UI: currentTime must drive the progress bar, audio-description toggles, and subtitle rendering. AVPlay's time events are coarser than MSE's. Budget for a clock you smooth, and never block the key handler on a player promise. A TV remote is not a mouse click. If play() is late, the user has already hit Back.
Build the AVPlay path first on the oldest Samsung you claim to support. Bring MSE in where the self-test passes. The opposite order is how teams ship a beautiful player that only works in the office.
More notes ยท Tomasz Szewczyk