Ask me anything
Ithy Logo
Sign in to save

Unveiling the Signals: Which HLS.js Event Marks the End of Your VOD Stream?

Discover the key events in HLS.js that signify your Video on Demand has concluded, ensuring a seamless user experience.

hlsjs-vod-end-stream-event-9k6y1dhq

When streaming Video on Demand (VOD) content using HLS.js, accurately detecting the end of the stream is crucial for functionalities like autoplaying the next video, displaying end screens, or triggering analytics. HLS.js, in conjunction with the HTML5 MediaElement, provides specific events to pinpoint this moment.

Key Takeaways: End-of-Stream Detection

  • The HTMLMediaElement ended event is the primary indicator for VOD stream completion, fired when playback reaches the end of a properly formatted stream with an #EXT-X-ENDLIST tag.
  • HLS.js emits Hls.Events.BUFFER_EOS (End Of Stream) when it has buffered all available media segments and no more data is expected, serving as a valuable confirmation.
  • Proper HLS manifest formatting, especially the #EXT-X-ENDLIST tag, is essential for reliable end-of-stream detection in VOD scenarios.

Understanding the Core Events

Detecting the end of a VOD stream in HLS.js involves understanding events from both the HLS.js library itself and the underlying HTML <video> element it controls.

The HTMLMediaElement ended Event: Your Primary Signal

For VOD streams, the most direct and standard way to know the stream has finished playing is by listening to the ended event on the HTML <video> element. HLS.js facilitates the loading and buffering of the HLS stream, but the browser's media element handles the actual playback state.

When Does It Fire?

The ended event is triggered when the following conditions are typically met:

  • The playback position (currentTime) reaches or exceeds the media's total duration.
  • The HLS playlist (manifest) for the VOD stream contains the #EXT-X-ENDLIST tag. This tag explicitly signals to the player that no more media segments will be added to the playlist, marking it as a finite VOD stream. Without this tag, the player might assume it's a live stream or an incomplete VOD, and the ended event may not fire as expected.

This event is part of the standard HTML5 media specification, making it a widely supported mechanism.

Conceptual image representing Video on Demand streaming

Video on Demand (VOD) streaming relies on clear signals for playback completion.

The HLS.js BUFFER_EOS Event: A Library-Level Confirmation

HLS.js provides its own set of events to give developers finer-grained control and insights into the streaming process. One such event relevant to the end of a stream is Hls.Events.BUFFER_EOS.

What Does It Indicate?

The BUFFER_EOS event is fired by the HLS.js instance when it has successfully downloaded and appended all available media segments from the VOD playlist to the browser's media buffer (SourceBuffer). It essentially means HLS.js has done its job of fetching the entire stream content.

While BUFFER_EOS indicates that HLS.js has buffered to the end of the stream, playback might still be ongoing for the last few buffered segments. Therefore, it often fires slightly before the ended event of the video element.

Usage and Synergy

Listening for BUFFER_EOS can be useful for:

  • Confirming that all data has been loaded.
  • Implementing logic that depends on the complete availability of the stream data, even if playback hasn't technically finished.
  • Debugging scenarios where the ended event might not fire as expected due to stream or browser issues.

For robust end-of-stream detection, it's often recommended to use the HTMLMediaElement's ended event as the primary trigger, potentially in conjunction with BUFFER_EOS for more comprehensive state tracking or diagnostics.


The Crucial Role of #EXT-X-ENDLIST

The #EXT-X-ENDLIST tag in an HLS manifest is paramount for VOD playback. It explicitly tells the player that the playlist is complete and no new media segments will be added. Without this tag, HLS.js and the browser might treat the stream as a live stream that has simply stopped broadcasting, potentially leading to the ended event not firing, or the player attempting to re-buffer indefinitely.

Always ensure your VOD HLS manifests correctly include the #EXT-X-ENDLIST tag at the end of the segment list.


Implementing End-of-Stream Event Listeners

Here's a practical example of how to set up event listeners for both the HTMLMediaElement ended event and the HLS.js BUFFER_EOS event:


if (Hls.isSupported()) {
    const video = document.getElementById('myVideoElement'); // Your HTML video element
    const hls = new Hls();

    // Load the HLS stream
    hls.loadSource('path/to/your/vod_stream.m3u8');
    hls.attachMedia(video);

    // Optional: Listen for manifest parsing to know when HLS.js is ready
    hls.on(Hls.Events.MANIFEST_PARSED, function(event, data) {
        console.log('HLS.js: Manifest parsed and ready for playback.');
        // You might want to call video.play() here if not autoplaying
        // video.play();
    });

    // Listen for the HLS.js BUFFER_EOS event
    hls.on(Hls.Events.BUFFER_EOS, function() {
        console.log('HLS.js: Buffer End Of Stream reached. All segments loaded.');
        // This event indicates HLS.js has finished buffering all content.
        // Playback might still be ongoing for the last buffered segments.
    });

    // Listen for the HTMLMediaElement 'ended' event
    video.addEventListener('ended', function() {
        console.log('HTMLMediaElement: Video playback has ended.');
        // This is typically the primary event to handle end-of-VOD actions.
        // e.g., show related videos, display a replay button, etc.
    });

    // Optional: Listen for HLS.js errors for robust handling
    hls.on(Hls.Events.ERROR, function(event, data) {
        if (data.fatal) {
            switch (data.type) {
                case Hls.ErrorTypes.NETWORK_ERROR:
                    console.error('HLS.js: Fatal network error encountered:', data);
                    // Potentially retry loading or show an error message
                    break;
                case Hls.ErrorTypes.MEDIA_ERROR:
                    console.error('HLS.js: Fatal media error encountered:', data);
                    // Potentially try to recover or show an error message
                    break;
                default:
                    // An unrecoverable error has occurred
                    console.error('HLS.js: An unrecoverable fatal error occurred:', data);
                    hls.destroy();
                    break;
            }
        } else {
             // Non-fatal errors can also provide insights, e.g., bufferStalledError
             if (data.details === Hls.ErrorDetails.BUFFER_STALLED_ERROR) {
                 console.warn('HLS.js: Buffer stalled. This might indicate issues if it happens unexpectedly at stream end.');
             }
        }
    });
} else if (video.canPlayType('application/vnd.apple.mpegurl')) {
    // For browsers that support HLS natively (e.g., Safari)
    video.src = 'path/to/your/vod_stream.m3u8';
    video.addEventListener('ended', function() {
        console.log('Native HLS: Video playback has ended.');
    });
}
    

In this example, console.log messages indicate when each event fires. You would replace these with your application-specific logic.


Visualizing Event Relationships for VOD End Detection

The following mindmap illustrates the key components and events involved in determining the end of an HLS VOD stream when using HLS.js.

mindmap root["HLS.js VOD End-of-Stream Detection"] id1["HTMLMediaElement ()"] id1a["ended event
Primary signal for VOD completion"] id1b["Relies on #EXT-X-ENDLIST in manifest"] id1c["Standard HTML5 event"] id2["HLS.js Instance"] id2a["Hls.Events.BUFFER_EOS
Indicates all segments buffered by HLS.js"] id2b["Confirmatory event, often precedes ended"] id2c["Hls.Events.ERROR
(e.g., bufferStalledError)
Can indicate issues if stream doesn't end cleanly"] id3["HLS Manifest (.m3u8)"] id3a["#EXT-X-ENDLIST tag
Essential for VOD: signals stream completeness"] id3b["Segment list"] id4["Key Considerations"] id4a["Browser Compatibility
Event behavior can have nuances"] id4b["Stream Integrity
Well-formed manifest and segments are crucial"] id4c["Combined Event Listening
Using ended + BUFFER_EOS for robustness"]

This mindmap helps to understand how the ended event from the video element and the BUFFER_EOS event from HLS.js, along with the critical #EXT-X-ENDLIST tag in the manifest, work together to reliably detect the end of a VOD stream.


Comparing Detection Approaches for VOD Streams

The reliability and utility of different factors and events can vary. The radar chart below compares two conceptual approaches to VOD end-of-stream detection: relying primarily on the ended event versus a more comprehensive approach that also leverages BUFFER_EOS.

This chart illustrates that while focusing on the ended event is generally reliable (especially with a correct #EXT-X-ENDLIST), a comprehensive approach incorporating BUFFER_EOS can enhance robustness, particularly in understanding buffer state and improving cross-browser consistency or diagnosing stream errors. The #EXT-X-ENDLIST tag remains critically important (rated 10) in both approaches for VOD.


Summary of Key HLS.js and Media Events for VOD End

The table below summarizes the main events relevant to detecting the end of a VOD stream when using HLS.js.

Event Name Source Description Role in VOD End Detection
ended HTMLMediaElement (<video> element) Fired when playback has stopped because the end of the media was reached. Requires #EXT-X-ENDLIST for VOD. Primary and most direct indicator that the VOD stream has finished playing.
Hls.Events.BUFFER_EOS HLS.js Instance Fired when HLS.js has appended the last segment to the buffer and considers the stream complete from a data loading perspective. Confirmatory signal; indicates all data is loaded. Useful for comprehensive state tracking and can fire slightly before the ended event.
Hls.Events.ERROR HLS.js Instance Fired when an error occurs. Details (e.g., data.details === Hls.ErrorDetails.BUFFER_STALLED_ERROR) can sometimes give clues if a stream ends unexpectedly. Primarily for error handling and diagnostics. Not a direct indicator of a normal VOD end, but can be relevant if the stream terminates prematurely.
Hls.Events.MANIFEST_PARSED HLS.js Instance Fired after the HLS manifest has been successfully loaded and parsed. Indicates HLS.js is ready to start buffering and playback. Not an end-of-stream event, but important in the setup phase.

Contextualizing HLS: How HTTP Live Streaming Works

Understanding the basics of HTTP Live Streaming (HLS) can provide better context for why these events are important. HLS works by breaking down a video stream into a sequence of small HTTP-based file downloads, or segments. A manifest file (typically with an .m3u8 extension) lists these segments. For VOD, this list is finite and ends with the #EXT-X-ENDLIST tag.

The following video provides a good overview of HLS mechanics:

"How Video Streaming Works: HTTP Live Streaming [Part 2]" by The Net Ninja, explaining HLS fundamentals.

Knowing that HLS.js is responsible for fetching these segments and feeding them to the browser's media engine helps clarify why both HLS.js-specific events (like BUFFER_EOS) and standard HTMLMediaElement events (like ended) play a role.


Frequently Asked Questions (FAQ)

What if the ended event doesn't fire for my VOD stream?

If the ended event isn't firing, check these common causes:

  • Missing #EXT-X-ENDLIST tag: Ensure your HLS manifest for the VOD stream includes this tag at the very end. Without it, the player may not recognize the stream as finite.
  • Browser-specific behavior: Some browsers or specific versions might have quirks in handling HLS or the ended event. Test across different browsers. Safari, for example, has native HLS support which can behave differently from HLS.js implementations in other browsers.
  • Stream errors: Underlying network or media errors could prevent the stream from playing to completion correctly. Monitor Hls.Events.ERROR for clues.
  • Player configuration: Incorrect player setup or interference from other scripts could affect event handling.
  • Infinite loop or seeking issues: If the player is stuck in a loop or if seeking logic interferes with reaching the actual end, the event might not trigger.
Is the Hls.Events.BUFFER_EOS event sufficient on its own to detect the end of a VOD stream?

BUFFER_EOS indicates that HLS.js has finished downloading and buffering all segments. While it's a strong signal that the end of the content is in the buffer, the video element might still be playing out the last few seconds of buffered content. Therefore, BUFFER_EOS typically fires slightly before the ended event.

For actions tied to the absolute visual end of playback (e.g., showing an end-screen), the HTMLMediaElement's ended event is generally more precise. BUFFER_EOS is excellent as a confirmation or for tasks that can proceed once all data is loaded, even if playback isn't quite finished.

How does end-of-stream detection differ for live HLS streams compared to VOD?

For live HLS streams, the concept of an "end" is different:

  • No #EXT-X-ENDLIST: Live stream manifests are continuously updated and do not contain the #EXT-X-ENDLIST tag (unless it's a live event that has concluded and transitioned to VOD).
  • ended event behavior: The ended event is generally not expected to fire for a live stream unless the broadcast itself stops and the manifest is updated to reflect this (e.g., by adding #EXT-X-ENDLIST).
  • Detecting live stream end: Detecting the end of a live stream often involves monitoring for other signals, such as:
    • Hls.Events.BUFFER_EOS might fire if the server stops sending segments and the player buffers everything available.
    • Hls.Events.ERROR with details like bufferStalledError or manifestLoadError if the player can no longer fetch new segments or refresh the manifest.
    • Custom server-side signals or WebSocket messages.

Detection for live streams is often more about identifying when the stream is no longer available or has transitioned, rather than reaching a predefined end like in VOD.

Why is the #EXT-X-ENDLIST tag so important for VOD HLS streams?

The #EXT-X-ENDLIST tag is a fundamental part of the HLS specification for defining a VOD (or "complete") stream. Its importance stems from several factors:

  • Signals Finiteness: It explicitly tells the client (player) that no more media segments will be added to the playlist. This is the primary distinction between a VOD asset and an ongoing live stream.
  • Enables ended Event: Most HTML5 video players rely on this signal to correctly determine when the media has truly finished, which in turn allows them to fire the ended event.
  • Player Behavior: Without #EXT-X-ENDLIST, a player might:
    • Assume it's a live stream and continuously try to refresh the manifest or fetch new segments, even if none are forthcoming.
    • Not enable seeking to the very end of the content accurately.
    • Fail to transition to an "ended" state, potentially leaving the UI in a buffering or playing state indefinitely.
  • Buffering Logic: HLS.js and other players use this tag to know when they have buffered all available content (leading to events like BUFFER_EOS).

In short, #EXT-X-ENDLIST is the standard mechanism by which an HLS VOD stream declares "I am complete," allowing players to behave predictably at the end of playback.


Recommended Further Exploration


References

nochev.github.io
src/events.js | hls.js
npmjs.com
hls.js - NPM
npmjs.com
hls.js - npm
hlsjs.video-dev.org
hls.js demo
nochev.github.io
Home | hls.js

Last updated May 16, 2025

AI-assisted research. Sources, methodology and corrections · Source-checked guides and tools · Explore published answers

Ask Ithy AI