Aug 4, 2014

How to dynamically change video.js videos and captions, with JavaScript

Video Playing

I am involved in a multidisciplinary data visualization research project. A part of it relies on qualitative data, namely video interviews. Regarding the videos, the Web designer wired the following layout:


Pretty neat and simple, isn’t it? The user clicks on one of the thumbnails below the video player. The thumbnail is marked as selected via a change of background-color of its container. The video player starts playing. On the right-side of the player, the quotes from the interview are displayed. They are actually outside the video-player.
The code layout is simple, as well. It employs a series of HTML div and some new HTML5 tags such as video, source, and track.

Before jumping to the code, a disclaimer.

The code and style reported in this post were written during developing/exploration stages. They do not show a latest, polished code of quality. This holds especially true for the CSS parts

Video 1

The video names are numbered, e.g., 1.mp4, 2.mp4, etc. Same holds for the subtitles, and the thumbnails. Everything else is handled by the opensource video.js project. Now, the load of the first video works perfectly. On page load, video.js automatically finds the element video.video-js.vjs-default-skin, and it constructs the real video player by substituting the HTML5 tags with normal divs.

That was the issue for me. The project is a single landing page full of infographics. Users simply have to click on the thumbnail in order for the new video to load, play, and display the new quotes. No refresh of the page could be done.

Although Video.js APIs do offer ways for changing the video in the video player, there is no way to load the new captions/subtitles, as well. The source code suggested that such method did not exist. There was only a method to get the current subtitles.

One idea was to change the element on-the-fly right-before changing the player source file. Unfortunately, video.js needs the tags to be in place before loading the player object. In addition, once the player is loaded, the HTML5 tags are substituted with more normal divs.

Luckily, video.js provides a .dispose() method to destroy the player object. However, the method destroys the HTML5 code, too. There is a bug report about this issue. The issue was opened some months ago, and there are now some pull requests to sort it out.

Meanwhile, I needed a quick working solution. I found it. It is so simple that I am ashamed of how long it took me to find it out.

First of all, the contents of div.video-background were removed from the HTML. Then, the following JavaScript was added.

The function videoHTML simply returns the now deleted HTML5 part of the video player, adapted via the videoNumber parameter to load the desired set of video, captions, and thumbnails. The function is called with argument value 1 on page load (document ready), in order to load the first video. The global variable player will also contain the video player object.

Whenever the user clicks on a div.thumbnail, its related video number is gathered. The player gets destroyed. The div.video-background HTML content is filled up with a fresh series of HTLM5 video tags through the videoHTML function. The player is recreated, so that it will use the new set of HTML5 tags related to the selected video.

That was it. I hope it will be of help.

As a bonus, I am sharing here the CSS code for putting the captions outside the video itself.

UPDATE: I added the whole sourcecode in a GitHub repository. The link is provided below. Feel free to inspect it.

written by dgraziotin

Dr. Daniel Graziotin received his PhD in computer science, software engineering at the Free University of Bozen-Bolzano, Italy. His research interests include human aspects in empirical software engineering with psychological measurements, Web engineering, and open science. He researches, publishes, and reviews for venues in software engineering, human-computer interaction, and psychology. Daniel is the founder of the psychoempirical software engineering discipline and guidelines. He is associate editor at the Journal of Open Research Software, academic editor at the Research Ideas and Outcomes (RIO) journal, and academic editor at the Open Communications in Computer Science journal. He is the local coordinator of the Italian Open science local group for the Open Knowledge Foundation. He is a member of ACM, SIGSOFT, and IEEE.

  • Nijik Atok Sep 5, 2014 Reply

    I’m looking at doing something almost identical (with video.js), but I’m curious if you can put up your full code page wise, or point me to a github checking if you have one. I can’t seem to get your sample code bits here to do what you describe, and I’d love to see your full example if you have it working.

    • dgraziotin Sep 8, 2014 Reply

      Hi Nijik. That is a nice idea, indeed. I setup a github repository (dgraziotin/video.js-dynamic), which implements this tutorial. The code is the same unpolished one that I referred in the article 🙂 but it works.

  • gigi Dec 21, 2014 Reply

    very good 🙂

  • Karlos Mar 4, 2015 Reply

    hi, awesome script, but, when i have a different parameters for video path or for multiple subtitles, this code with [numbers] is useless. I must wirte another scripts 🙁

Leave a comment