Unable to dynamically change the title of 'track' in Video.js

I encode the base area of ​​the video, and one of the key requirements is that the videos must be able to advance while keeping the player in full screen.

Using Video.js (4.1.0), I was able to work correctly, except that I can’t change the titles when switching to another video.

Any insertion of a “track” tag when you first create an HTML player or add a track to an “options” object when the player is initialized is the only way I can get the player to display the “CC” button and show the captions. However, I cannot reinitialize the player in full screen mode, so changing the track this way will not work.

I tried addTextTrack and addTextTracks, and both show that the tracks were added - using something like console.log (videoObject.textTracks ()), but the player never shows them or the "CC" button.

Here is my code, any help is much appreciated:

;(function(window,undefined) { // VIDEOS OBJECT var videos = [ {"volume":"70","title":"TEST 1","url":"test1.mp4","type":"mp4"}, {"volume":"80","title":"TEST 2","url":"test2.mp4","type":"mp4"}, {"volume":"90","title":"TEST 3","url":"test3.mp4","type":"mp4"} ]; // CONSTANTS var VIDEO_BOX_ID = "jbunow_marquee_video_box", NAV_TEXT_ID = "jbunow_marquee_nav_text", NAV_ARROWS_ID = "jbunow_marquee_nav_arrows", VIDEO_OBJ_ID = "jbunow_marquee_video", NAV_PREV_ID = "jbunow_nav_prev", NAV_NEXT_ID = "jbunow_nav_next"; // GLOBAL VARIABLS var videoObject; var currentTrack = 0; var videoObjectCreated = false; var controlBarHideTimeout; jQuery(document).ready(function(){ // CREATE NAV ARROWS AND LISTENERS, THEN START MARQUEE var navArrowsHtml = "<div id='" + NAV_PREV_ID + "' title='Play Previous Video'></div>"; navArrowsHtml += "<div id='" + NAV_NEXT_ID + "' title='Play Next Video'></div>"; jQuery('#' + NAV_ARROWS_ID).html(navArrowsHtml); jQuery('#' + NAV_PREV_ID).on('click',function() { ChangeVideo(GetPrevVideo()); }); jQuery('#' + NAV_NEXT_ID).on('click',function() { ChangeVideo(GetNextVideo()); }); ChangeVideo(currentTrack); }); var ChangeVideo = function(newIndex) { var videoBox = jQuery('#' + VIDEO_BOX_ID); if (!videoObjectCreated) { // LOAD PLAYER HTML videoBox.html(GetPlayerHtml()); // INITIALIZE VIDEO-JS videojs(VIDEO_OBJ_ID, {}, function(){ videoObject = this; // LISTENERS videoObject.on("ended", function() { ChangeVideo(GetNextVideo()); }); videoObject.on("loadeddata", function () { videoObject.play(); }); videoObjectCreated = true; PlayVideo(newIndex); }); } else { PlayVideo(newIndex); } } var PlayVideo = function(newIndex) { // TRY ADDING MULTIPLE TRACKS videoObject.addTextTracks([{ kind: 'captions', label: 'English2', language: 'en', srclang: 'en', src: 'track2.vtt' }]); // TRY ADDING HTML //jQuery('#' + VIDEO_OBJ_ID + ' video').eq(0).append("<track kind='captions' src='track2.vtt' srclang='en' label='English' default />"); // TRY ADDING SINGLE TRACK THEN SHOWING USING RETURNED ID //var newTrack = videoObject.addTextTrack('captions', 'English2', 'en', { kind: 'captions', label: 'English2', language: 'en', srclang: 'en', src: 'track2.vtt' }); //videoObject.showTextTrack(newTrack.id_, newTrack.kind_); videoObject.volume(parseFloat(videos[newIndex]["volume"]) / 100); // SET START VOLUME videoObject.src({ type: "video/" + videos[newIndex]["type"], src: videos[newIndex]["url"] }); // SET NEW SRC videoObject.load(); videoObject.ready(function () { videoObject.play(); clearTimeout(controlBarHideTimeout); controlBarHideTimeout = setTimeout(function() { videoObject.controlBar.fadeOut(); }, 2000); jQuery('#' + NAV_TEXT_ID).fadeOut(150, function() { currentTrack = newIndex; var navHtml = ""; navHtml += "<h1>Now&nbsp;Playing</h1><h2>" + videos[newIndex]["title"] + "</h2>"; if (videos.length > 1) { navHtml += "<h1>Up&nbsp;Next</h1><h2>" + videos[GetNextVideo()]["title"] + "</h2>"; } jQuery('#' + NAV_TEXT_ID).html(navHtml).fadeIn(250); }); }); } var GetPlayerHtml = function() { var playerHtml = ""; playerHtml += "<video id='" + VIDEO_OBJ_ID + "' class='video-js vjs-default-skin' controls='controls' preload='auto' width='560' height='315'>"; playerHtml += "<source src='' type='video/mp4' />"; //playerHtml += "<track kind='captions' src='track.vtt' srclang='en' label='English' default='default' />"; playerHtml += "</video>"; return playerHtml; } var GetNextVideo = function() { if (currentTrack >= videos.length - 1) { return 0; } else { return (currentTrack + 1); } } var GetPrevVideo = function() { if (currentTrack <= 0) { return videos.length - 1; } else { return (currentTrack - 1); } } })(window); 
+6
source share
2 answers

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({ /** @constructor */ 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.

+6
source

Doing the same thing (or rather, DO NOT do the same) ... you really need to figure out how to dynamically change / add a signature track.

This works to make it play through basic HTML5, but does not show the videojs CC button:

 document.getElementById("HtmlFiveMediaPlayer_html5_api").innerHTML = '<track label="English Captions" srclang="en" kind="captions" src="http://localhost/media/captiontest/demo_Brian/demo_h264_1.vtt" type="text/vtt" default />'; 
+1
source

Source: https://habr.com/ru/post/951259/


All Articles