In streaming media applications for smart TVs (LG and Samsung), maintaining consistent performance during long playback sessions is essential. While developing our streaming apps using Shaka Player v4.16.0, we encountered escalating JavaScript heap usage that eventually led to crashes during extended playback. The culprit? Inefficient EMSG (Event Message Boxes) handling for ad signaling in DASH streams. This post explains the problem, how we diagnosed it, and our targeted fix applied across multiple TV apps.
Our apps are designed for continuous playback of live and on-demand content. During testing on mid-range smart TVs, playback was smooth initially. However, after roughly 90 minutes of continuous streaming, problems appeared:
Profiling in Chrome DevTools revealed a dramatic surge in heap usage—from 40-50 MB at startup to over 450 MB. Heap snapshots showed Uint8Array objects accumulating from media segment parsing, which became critical on resource-constrained TV hardware.
Shaka Player is widely used for DASH and HLS playback in web-based TV apps. One feature of DASH is EMSG boxes, which carry inband metadata for events such as ad signaling, SCTE-35 markers, or accessibility cues. Shaka routes these events internally, usually into a timeline for synchronization with media playback.
In compiled Shaka v4.16.0, the function handling EMSG events appeared as:
Ck: function (f) {
a.ib &&
am(a.ib, {
schemeIdUri: f.schemeIdUri,
startTime: f.startTime,
endTime: f.endTime,
id: String(f.id),
emsg: f,
});
}
This function stores each EMSG event in memory through the call am(a.ib, { ... }), which adds it to Shaka’s region timeline (a.ib). Since Shaka retains full segment buffers, memory can grow over time—especially in streams with frequent ad markers.
In the uncompiled source, this logic appears in lib/player.js around line 2640, where EMSG events are parsed and added to shaka.media.RegionTimeline via addRegion().
Shaka includes pruning logic in lib/media/region_timeline.js within the prune(startTime) method, which removes regions whose endTime <= startTime. However, this may not always clear all old entries if events have long durations or the live window moves slowly.
To mitigate memory buildup, developers can monitor the timeline size or manually prune old regions when needed.
The main issue was that Shaka stored full segment buffers from EMSG events indefinitely. In streams with frequent markers, thousands of these buffers accumulated, causing heap growth and performance degradation. On TV devices with limited RAM and slower garbage collection, this problem became particularly severe.
To address the memory accumulation, we worked directly with the compiled Shaka v4.16.0 build. We downloaded the compiled code and commented out the contents of the EMSG function , preventing unnecessary memory accumulation:
Ck: function (f) {
// Disabled to prevent memory growth
// a.ib && am(a.ib, {
// schemeIdUri: f.schemeIdUri,
// startTime: f.startTime,
// endTime: f.endTime,
// id: String(f.id),
// emsg: f,
// });
}
💡 Important notes:
This lightweight change solved the memory accumulation problem and improved long-session performance across all our TV apps.
At Inellipse, we’ve been closely following everything that came out of the Roku Developer Summit 2025 and it...
In streaming media applications for smart TVs (LG and Samsung), maintaining consistent...
As a proud Fastly partner, Inellipse leverages the full power of Fastly’s edge cloud platform...