The current implementation of VideoJS (4.4.2) loads all types of text tracks (subtitles, titles, chapters) during the initialization of the player itself, so it correctly captures only those that are defined between the <video > tags.
EDIT: I meant that it loads them when addTextTrack is called, but the player’s user interface will never be updated after the initialization time and will always show the text tracks of the initialization time.
One possible way to solve the problem is to destroy the video game player and recreate it when you change the video source after updating the content between the <video> tags. Thus, you do not update the source using the videojs player, but by dynamically adding the necessary DOM elements and initializing a new player on them. Probably, this solution will cause outbreaks of some user interfaces, and this is absolutely not optimal for the problem. Here is a video game destruction link
The second option is to add the processing of a dynamic text track to the existing code, which doesn’t sound so strong if it knows where to look (I did this only for chapters, but could look like other text tracks). The code below works with the latest official build 4.4.2. Please note that I am using jQuery to remove text track elements, so if anyone applies these changes as is, jQuery needs to be downloaded before the videojs.
Modify the video.dev.js file as follows:
1: add clearTextTracks function to Player
vjs.Player.prototype.clearTextTracks = function() { var tracks = this.textTracks_ = this.textTracks_ || []; for (var i = 0; i != tracks.length; ++i) $(tracks[i].el()).remove(); tracks.splice(0, tracks.length); this.trigger("textTracksChanged"); };
2: add a new textTracksChanged event trigger to the end of the existing addTextTrack method
vjs.Player.prototype.addTextTrack = function(kind, label, language, options) { ... this.trigger("textTracksChanged"); }
3: handle the new event in the TextTrackButton constructor function
vjs.TextTrackButton = vjs.MenuButton.extend({ init: function(player, options) { vjs.MenuButton.call(this, player, options); if (this.items.length <= 1) { this.hide(); } player.on('textTracksChanged', vjs.bind(this, this.refresh)); } });
4: Implement update method in TextTrackButton
// removes and recreates the texttrack menu vjs.TextTrackButton.prototype.refresh = function () { this.removeChild(this.menu); this.menu = this.createMenu(); this.addChild(this.menu); if (this.items && this.items.length <= this.kind_ == "chapters" ? 0 : 1) { this.hide(); } else this.show(); };
Sorry, but for now I can’t refer to a real working example, I hope that the above snippets will be sufficient as a starting point for all who are interested.
This code can be used when updating a source to a new video. Just call the clearTextTracks method and add new text tracks using the addTextTrack method, and now the menu should be updated.