Issue with video.js text track memory leakage (WebVTT/VTT)

I am utilizing Video Text Tracks to showcase advanced live information on top of the video.
A new video is loaded every few minutes, each with its own .webvtt file (consisting of 2-3k lines).

Although everything is functioning properly, there is a persistent issue with memory usage increasing continuously.

This problem stems from a memory leak where additional VTTCue and TextTrack records are added for each new video, leading to an accumulation of unnecessary data. https://i.stack.imgur.com/HN3Ln.png

After trying several approaches without success, I find myself stuck with the current method:

The text tracks are implemented according to the guidelines in the Video.js documentation (remote text tracks):

player.ready(() => {
  if (videoOptions.subtitles) {
    player.addRemoteTextTrack(
      {
        src: videoOptions.subtitles,
        kind: 'subtitles',
      },
      false,
    );
  }
});

And they are removed before disposing of the player:

const remoteTextTracks = this.player.remoteTextTracks();
for (let i = remoteTextTracks.length - 1; i >= 0; i -= 1) {
  this.player.removeRemoteTextTrack(remoteTextTracks[i]);
}

Even though they are successfully removed from the player, they linger in memory. Is there a way to prompt/urge/force the GC to completely eliminate old text tracks?

Answer №1

To prevent Video.js' memory leak when working with text tracks, consider implementing the following steps:

if (player && player.remoteTextTracks().length) {
  while (player.remoteTextTracks().length > 0) {
    player.removeRemoteTextTrack(player.remoteTextTracks()[0]);
  }
  player.remoteTextTracks().forEach(function(track) {
    track.src = '';
    player.removeRemoteTextTrack(track);
  });
}

Answer №2

If someone is facing a similar problem and needs a solution, here's what worked for me:

const remoteTextTracks = this.player.remoteTextTracks();
for (let i = remoteTextTracks.length - 1; i >= 0; i -= 1) {
    
    remoteTextTracks[i].activeCues_.forEach((val, key) => {
        delete remoteTextTracks[i].activeCues_[key];
    });

    remoteTextTracks[i].cues_.forEach((val, key) => {
        delete remoteTextTracks[i].cues_[key];
    });

    if (!isNil(remoteTextTracks[i].lastCue)) {
        delete remoteTextTracks[i].lastCue;
    }

    this.player.removeRemoteTextTrack(remoteTextTracks[i]);
}

To free up memory, all items had to be deleted individually — other solutions didn't cut it.

After digging deeper due to additional memory leaks, I found out this was the culprit - the issue stemmed from Vue Dev Tools, but disabling it resolved everything.

The memory leak was actually present in production, and though I fixed it using the mentioned method, Vue Dev Tools masked my realization of the fix. :|

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

The discrepancy between the heights of a div using Jquery and JavaScript

There is a container div encompassing all the site's content, which dynamically stretches. Additionally, there are multiple other divs that also stretch using the same method as in 20 other sites. Despite trying various methods with jQuery and JavaSc ...

An unanticipated SyntaxError was encountered while attempting to utilize an Ajax post, specifically in relation

I can't seem to figure out how to troubleshoot an ajax/jquery error. Here is the function I'm working with: var LogIn = { Email: $("#Name").val(), MobileNo: $("#txtMobileNumber").val(), PinCode: '', ...

Is there a way for me to showcase the latitude and longitude retrieved from JSON data on a Google Map using modals for each search result in Vue.js?

After receiving JSON data with search results, each containing latitude and longitude coordinates, I am attempting to display markers on a Google map modal when clicking "View Map". However, the code I'm using is not producing the desired outcome. Th ...

Conditionally render a component only if a calculated property is not activated

When the state preference in my vuex store changes, I need to update the DOM by calling the checkValue method each time. This is how my index.html looks like: <div id="app"> <my-component></my-component> <my-other-component&g ...

Issue with Vue.js component not properly retrieving value from variable

Having recently started using Vue.js in my laravel application, I have incorporated the following component from https://github.com/saintplay/vue-swatches. It works well, but I am encountering an issue when trying to pass a HEX color value from a variable ...

Ensuring correct association of values to avoid redundancies

There are 5 fields available for users to fill out on this form: Leave Code, From Date, Input Time1, To Date, and Input Time2. These variables are declared as a dates object in the .ts file, as shown below. interface Supervisor { name: string; code: s ...

Unlock a multitude of outcomes with Sequelize

Is there a way to retrieve multiple results from Sequelize and store them in an array? For example, I want to fetch all the values in the name field from the test table and display them in the console. This is what I tried: test.findAll().them(function(re ...

Sharing state between two functions in React using Hooks

Coming from a background in Vue, I am struggling to comprehend how to conditionally show something when the HTML is fragmented into different parts. Imagine having this structure: import React, { useState } from "react"; const [mobileNavOpen, setMobi ...

How to use Javascript to toggle a popup containing an autoplaying Vimeo video

I am looking to create a pop-up window containing a Vimeo video inside. I have a div on my webpage with an id of "showVideo". When this div is clicked, I want to display a pop-up (new div with the id of "opened-video"). The "opened-video" div contains an i ...

What is the process for creating a folder using Firebase Cloud Functions with Storage?

How do I create a folder named "posts"? Storage bucket path --> gs://app.appspot.com/posts Code to generate thumbnail from storage object exports.generateThumbnail = functions.storage.object() .onChange(event => { const object = event.data ...

Enable next-i18next to handle internationalization, export all pages with next export, and ensure that 404 error pages are displayed on non-generated pages

After carefully following the guidelines provided by i18next/next-i18next for setting up i18n and then referring to the steps outlined in this blog post on locize on how to export static sites using next export, I have managed to successfully generate loca ...

Modifying the default text within a select box using jQuery

Within a select box identified as 'edit-field-service-line-tid', there is default text displayed as '-Any-'. This particular select field has been generated by Drupal. I am looking to use jQuery to change the text '-Any-' to ...

The Vue.js v-on:mouseover function is not functioning properly in displaying the menu

When I hover over a LI tag, I want to display a menu. I have successfully implemented it using a simple variable with the following code: @mouseover="hoverFormsControls=true" @mouseleave="hoverFormsControls=false" However, when I attempted to use an arr ...

While executing a for loop, the variable $.ajax is found to be null in Javascript

When I click on a button with the function btn-book, there is a for loop inside it that fetches data from Ajax. Despite knowing that the data holds values, I constantly receive null. Below is the code snippet for the onclick event: $('#mapContainer&a ...

The necessary directive controller is missing from the element in the current DOM structure

Can anyone explain the meaning of "required directive controller is not present on the current DOM element"? I encountered this error and would like some clarity. For reference, here is the link to the error: https://docs.angularjs.org/error/$compile/ctr ...

A guide to presenting array data retrieved from an Ajax call within HTML using Laravel 4.1

I have an AJAX call to a controller that returns array data to my view. I want to display this array data in HTML upon clicking, but I'm not sure how to do it yet. Here's what I have so far: AJAX Call: request = $.ajax({ url: "/fans/ ...

Conceal the scroll bar while still allowing for scrolling functionality

In this code snippet, I am trying to maintain the scroll position of two blocks by syncing them together. Specifically, I want to hide the scrollbar of the left block while scrolling the right one. If anyone has any suggestions or solutions for achieving ...

What causes the findByIDAndUpdate method to return a `null` value in Mongoose 6?

I am working with nodejs v18, Express v4, and Mongoose v6. I am attempting to update a document, but when using the line below, it returns null. const doc = await User.findByIdAndUpdate(userId, newUser, { new: true }) // doc is null The object newUser con ...

The alertify.alert function encounters issues when used within the response of a mithril m.request

I'm currently working on a project utilizing mithril.js and also integrating alertify.js. I am encountering an issue when trying to alert some data in the response. Strangely, it doesn't work as expected. However, if I use the same alert function ...

After fetching, null is returned; however, refreshing the page results in the object being returned. What is the

I have a specific case where I am dealing with an array of 500 post IDs and I need to retrieve the first 100 posts. To achieve this, I implemented the following code: API https://github.com/HackerNews/API BASE_URL = 'https://hacker-news.firebaseio.com ...