Video.js 5: The Only Thing That’s Changed Is Everything...except for like 3 things that didn't (including the name).

First and foremost, THANK YOU to the 25 contributors who completed and merged 146 pull requests and updated just about every line of code in the project. And thank you to the hundreds of issue commenters and plugin authors who helped shape this latest version. For a widget, we’ve got a pretty awesome community.

For 5.0 we have some interesting new features, and we made A LOT of new technology choices. This will include an exhaustive dive into those choices, because… why not?

  • Redesigned and rebuilt the UI
    • Using a flex-box-based controls layout for easier add-ons
    • Improved accessibility of the controls
    • Switched from LESS to SASS
    • Switched to Material Icons
  • Rebuilt the library in ES6/Babel/Browserify including Modules and Classes
  • Added support for responsive layouts including auto-sizing to the video content
  • Added support for HLS in desktop browsers without Flash
  • Improved audio-only support
  • Added 6 more language translations bringing the total to 25
  • Switched from Closure Compiler to UglifyJS (we STOPPED mangling object properties)
  • Switched to JSDoc for documentation
  • Switched to BrowserStack for automated browser testing
  • Switched to Fastly for our CDN
  • New definition around plugins
  • New player skin designer on Codepen
  • New definition around playback technologies (“techs”)
  • New project governance model
  • New Website and Logo!

If you’re a Video.js user or lover of semver, you’re probably looking at the changelog and dying inside (or out). You’re probably already thinking about how little you want to do the mega-upgrade dance every time the major version is bumped. To be clear, there will be at least some upgrade cost between major versions because that’s just how things go. However, from 5.0 on, we plan on being a lot more liberal with major versions to avoid stop-the-world mega releases like this.

The fact is, this release cleaned up a lot of technical debt and cruft over years of maintaining a popular open source library. Working with the codebase is fun again (not like it wasn’t before, Judgy McJudgerson) and we think we’ve bought ourselves at least 6 months before we have to upgrade to ES9000. In all seriousness, we plan on being quicker with releases, both breaking and non, in order to make incremental upgrades less painful and, well, quicker. Besides, Chrome and Firefox are going to be in the thousands soon for their releases, and we want some of that fun.

Redesigned and rebuilt UI

Video.js has had an all-CSS skin (including for Flash) since it was created in 2010 (the first version was literally all CSS, no images, fonts, or svgs. And still works today!) Over those years we’ve seen some very creative customizations and learned a lot about what users are hoping to do with player design when they’re able to use native web techologies. For 5.0 we’ve both simplified the default layout and added more flexibility than ever before.

Flex Box Layout

One of our biggest challenges with the layout of the controls is keeping the control bar flexible and able to accomodate any new buttons that a plugin author might want to add. In 4.0 we used CSS floats to allow a new button to be appended to the control bar and flow into space. This however led to a very awkward tab order for anyone navigating the controls with the tab key. In 5.0 we were finally able to take advantage of flex box, which improves on the flexibility of the previous version while also maintaining the right tab order. In IE8 (because yeah, we still support that) we fall back to display:table, which works surprisingly well.

Improved accessibility

Accessibility has been a hot topic as of late, with new regulations helping push the industry forward and defining what accessbility means for a player. The tab-order mentioned previously was an eye sore in our accessiblity support, and we’re all happy to have that fixed in 5.0. Addtionally, after a long debate, we switched our Button elements to use the actual HTML button tag instead of divs. Using divs previously gave us a large degree of safety from external styles clobbering our own styles. This can be a big problem for html-based widgets that are dropped into other frameworks that add styles directly to native elements (ahem Foundation). In the end however the accessibility experts in our community made a strong enough case, pointing out that there’s still a number of devices that do not handle ARIA roles and javascript enhanced divs well enough to fully rely on them.

Switched from LESS to SASS

The original decision to use Less over Sass in version 4 was largely driven by the fact that it could be run in the browser. We knew we wanted to start using a preprocessor, but we still wanted to provide things like the skin designer which meant we needed to be able to do all pre-processing on the client. Less was totally appropriate for the job and allowed us to start modernizing the skin in appearance and tooling.

Since then, thanks to Emscripten, Sass has joined Less in the browser. This meant that we were free to use whichever of the two we liked, so all the contributors put on Less or Sass branded boxing gloves and fought until two gloves were still standing, which turned out to be Sass. Aside from the battle royale, there were a few reasons we decided to go with Sass for the new base skin in version 5.

  • Familiarity. Core contributors that started working on the new base skin were a little more experienced with Sass and simply preferred it.
  • Speed. On top of allowing us to use Sass without requiring Ruby, LibSass is fast.
  • Popularity. Your parents are right, not everything’s a popularity contest… but it is when you want to pick between two basically equivalent* tools. We wanted to pick something that more devs would be familiar with, and that seems to be Sass. On that note, it was also requested fairly often on the issue tracker.
  • Community. This goes hand in hand with popularity, but the Sass community is large and growing, with currently popular projects using it (and switching to it) and new tooling popping up every day along side industry standards such as Compass and Bourbon.

Big changes that we made during the switch that are unrelated to the tooling:

  • We broke apart the source files.
  • As mentioned above, we switched to a Flexbox-based layout. “What about IE8,” you say again? Tables. Srsly.
  • Improved support for responsive layouts.
  • We simplified the amount of customization we explicitly allow in the source to encourage people to build on top of the base skin, not edit it directly.
  • On the simplification note, we tried to simplify the base skin as much as possible. Our goal was to allow designers to build anything on top of the base without having to entirely start from scratch.
  • And more!

Switched to Material Icons

The switch to an icon font in version 4 was a huge win for Video.js. It allowed designers to do things as basic as style component icon colors with just CSS. It simplified the code base by allowing us not not worry about things like image sprites or other image optimizations. The only recurring issue we ran into was the process around adding new icons to the set, which ultimately involved just uploading the font back to IcoMoon and re-exporting.

In version 5, we’ve switched everything about our icon set. First we went with a new set of icons: Google’s Material Icons. This was a big step forward in terms of appearance, but we had the same issue as far as adding new icons. To fix that process we created new Font tooling for the project.

The tooling is really simple, but it allows anyone to write out a JSON configuration file pointing to any SVGs they have access to. The output of that tool is the font files themselves along with a new SCSS partial that gets imported into our Sass workflow in the core project at build.

We primarily use the Material icons, but occasionally we have to pull in a social media icon from another set, which this process greatly simplifies. See icons missing in the set that you’d like to use? Give the tool a try and let us know what you think!

Rebuilt the library in ES6/Babel/Browserify including Modules and Classes

5.0 comes with bit of enlightenment as we ditch our not-built-here syndrome and make a leap to post-modern development practices.

When we started work on the new version we originally planned to just use browserify and CommonJS modules, but when we took a closer look at the great work being done on Babel, it only made sense to jump again to ES6 modules and save ourselves another code transition down the road, while at the same time gaining a lot of great new JavaScript features.

Side-stepping any argument of the validity of JavaScript Classes, Video.js has always used classes for the internal UI framework. We used a custom class implementation that was of course incompatible with other custom implementations, so the move to ES6 opens the door for some potential interoperability with other frameworks as more people use ES6 classes specifically.

With the move to modules we’ve also opened the door to using more of the glorious ecosystem that is npm. We’ve started to toss out some of the non-core internal libraries that required us to be experts in just about everything, and replace them with other community-built modules. So far this includes libraries like lodash and raynos/xhr, and we’re actively looking for opportunies where we can share more code.

What does this mean for the end user?

This should make it easier for end-users of videojs, especially if they use browserify themselves. With this change, users can just
require('video.js') in their app.js or whenever they need it to instantiate players. In addition, plugins that were written
using browserify themselves can be added very easily using browserify and require as well. Of course, you can use Babel and
ES6 modules as well. For example, your app.js could look like the following, assuming browserify and babel for ES6 syntax:

// import videojs
import videojs from 'video.js';
// import several plugins.
// Each requires videojs itself and registers itself accordingly.
import 'videojs-playlist';
import 'videojs-thumbnail';
// this isn't ready yet, unfortunately
import 'videojs-contrib-hls';

// make a player
let player = videojs('my-video');
// initialize some plugins

Added support for responsive layouts including auto-sizing to the video content

Check out this video from the SF Vid Tech meetup for quick overview.

Proper support for responsive layouts has been a long time request. We’ve had tips and guides for how to make it work in the old version, but now it’s seamlessly built into the player. First we have two easy CSS classes you can just add to the embed code, vjs-16-9 and vjs-4-3.

<video class="video-js vjs-16-9 vjs-default-skin" ...></video>;

Or you can set the player to a fluid layout in the options and it will automatically update to match the aspect ratio of the content., whether you set a width, height, or neither.

var myPlayer = videojs(id, { fluid: true, preload: 'metadata' });

This was very tricky to implement, but well worth the effort. We have a jsbin example page where you can try out different options.

Added support for HTTP Live Streaming in desktop browsers WITHOUT Flash

We’ve been chasing down the last excuses for using Flash for video for awhile now and have reached some major milestones. videojs-contrib-hls 1.0 (it’s about time!) will use Media Source Extensions, an advanced video element API, to provide HLS playback in Chrome and Microsoft Edge. Besides the enhanced debuggability of doing everything in Javascript, most of the computation has been moved to a web worker and is hardware accelerated on platforms that support it. That means even 60fps or 4k streams should play back without a stutter and your battery will get less of a workout, too. As part of that work, we’ve split off the code we use to repackage HLS video into a separate project in the video.js org: mux.js. If you’re interested in how video works down at the bit level, check it out! We’re always looking for new contributors.

Switched from Closure Compiler to Uglify (We STOPPED mangling object properties)

In version 4.0 we introduced Google’s Closure Compiler into our build chain. It’s advanced optimizations mode saved us 25% in filesize over UglifyJS at the time. The downsides were that it required us to write the code in very specific ways and mangled internal object properties, which made contributing, debugging, and writing plugins much more difficult. The reality today is that with gzip and improved bandwidth, video.js users are pushing us less and less to squeeze the last bit of filesize out of the library. So for 5.0 we’ve switched back to UglifyJS. Plugin authors rejoice!

Improved audio-only support

Hey did you know? Video.js also supports the HTML5 audio tag. Try it out and let us know what you think.

<audio id="my_audio_1" class="video-js vjs-default-skin" controls data-setup="{}"><source src="MY_AUDIO_FILE.mp3" type="audio/mp3"></source></audio>

Added 6 more language translations

Ever since we implemented localization in Video.js there’s been a wave of contributions from all over the world. With 5.0 comes Danish, Bosnian, Serbian, Croatian, Finnish, and Turkish. This brings the number of lanugages supported to 25!

New definition around plugins

Plugins mostly have not changed from how they worked in Videojs 4.x. You still register and use them the same way.
The only major change is that if you are instantiating a plugin inside the config of a player, this plugin will get run
before the player is ready. This is so that if plugins are doing some UI work or adding themselves as children of the player
they can do so early on. This means that plugins that require the player to be ready would need to handle that themselves or
else not support instantiation via the player config. Ex:

videojs('my-video', {
plugins: {
playlists: {}

As part of the update to videojs 5 and our switch from Google’s Closure Compiler to Uglify,
we’ve been focusing on making the plugin experience better.
We’ve made sure to export some of the utility functions that we use inside our own codebase to make writing plugins easier.
This way plugins don’t need to include extra code themselves if a function, merge, for example, is available from videojs.

Also, we’re encouraging plugin authors to publish their plugins on npm. If the plugins are tagged with videojs-plugin,
they’ll show up on our spiffy new plugins listing page.

New player skin designer on Codepen

We’re taking a slightly different approach with the designer now. Instead of exposing all CSS properties from the default skin, we’ve set up a template starter that has fewer options and allows you to get at the more common customizations more easily.

It’s also using Codepen, which is a great service and much better than hosting the designer ourselves. If you use it to make a cool skin, be sure to let us know. Tweet at @videojs or comment on the designer.

New project governance model

Jumping right on that band wagon, we’re implementing a governance model for the project that’s similar to Node.js/io.js and 0MQ’s C4.1. Along with some better structure around the project it comes with a lower bar for becoming an official maintainer of the project. We’re aiming to have a more diverse set of people and companies representing the leadership of Video.js.

Improved the definition of a playback technology or “tech”

The creator of our most popular plugin (the YouTube plugin) took on the task of improving the relationship between the player and techs. “Tech” is the term we use to describe the translation layer between the player API and the underlying video objects, which can be the HTML5 video element, plugins like Flash and Silverlight, or other players like Youtube and Vimeo. If you’ve built a tech or are intersted in building one, check out the changes in 5.0.

Switched to JSDoc from a home-grown docs parser

In the last version we had a custom built docs generator that used esprima to parse the AST and create a lot of the API docs just from the code, with JSDoc tags filling in the rest. That could still be a good project, but it’s become too much to maintain and too limited for plugin authors.

For 5.0 we’ve switched to jsdoc. Check out the new docs site. Anyone want to help us design it? :)

Switched to BrowserStack for automated browser testing

For 5.0 we have moved from Sauce Labs to BrowserStack as our browser provider for automated testing. BrowserStack is a cross-browser testing tool that provides desktop and mobile browsers and are currently rolling out support for real mobile devices. We moved to BrowserStack to reduce the amount of timeout errors, build time and false positives we were seeing in our builds previously. This stability has allowed us to expand our testing coverage to include iOS, Android and all supported versions of Internet Explorer.

Switched to Fastly for our CDN

The CDN-hosted version of Video.js at is downloaded over 2 BILLION times every month, even with agressive browser-side caching. Video.js is relatively small in file size but that’s still 34 TB per month. We were previously piggy-backing on Brightcove’s Akamai account, but Fastly offered to host the library for free. We gave it a shot and fell in love. In full disclosure, our testing found that Fastly didn’t perform quite as well as Akamai internationally, but Fastly’s user interface, API, and real-time purge are things of beauty and make our CDN deploy process much simpler.

Video.js Logo

We simplified it a bit. What do you think?

If you don’t feel comfortable contributing to Video.js we can always use help on the website. It gets over 200,000 unique views every month. Contribute at the website repo.


It’s our community that keeps Video.js actually decent and truly free (Apache 2), so don’t be shy. Jump in and submit a bug, build a plugin, or design a skin.

In conclusion, it’s been a good year of a lot of good work. Thanks!

It's here: 5.0 release candidates!

Today we’re releasing our first official 5.0 release candidate. We’re really excited to get this into the wild, but a lot has changed under hood. It should be stable for normal usage, but we’ve got a limited number of test devices (and testers for that matter), so what we need now is for people to bang on 5.0 and let us know what breaks!

You can either grab the master branch from Github and run grunt to create your own build, or we’ll push each new release candidate to the CDN. We’re going to be moving quickly and pushing new candidates when we uncover / fix bugs, so be sure to check for new versions! As of this post, the newest release is 5.0-rc.2. If you’d like to see a demo, we’ve got one up on JSBin.

What’s different?

New Base Theme

The most obvious difference you’ll see when you load up the release candidate is most likely going to be the new base theme. We’ve worked hard to simplify the theme and make it possible to do as much as possible with purely CSS.


There are elements in the control bar that aren’t shown by default, but can be by simply overriding a little CSS. For example, if you’d rather use an inline volume control instead of the popup menu, you could make these changes:

css .video-js .vjs-volume-menu-button { display: none; } .video-js .vjs-mute-control, .video-js .vjs-volume-control { display: flex; }

This just hides the .vjs-volume-menu-button control, and unhides the mute control / inline volume control. Other things that are available but hidden by default are a time divider (.vjs-time-devider), total duration (.vjs-duration), and a spacer (.vjs-custom-control-spacer).


Thanks to the incredible Babel project, we’re able to write ES2015 and have it transpiled to ES5. It’s fantastic, and means we get glorious things such as string interpolation, so reading our codebase just got a whole lot ${_.sample(['better', 'awesomer', 'more fantastic', 'less plus-y'])}.

On our Wiki we have a page devoted to ES6 features we use extensively. There are probably a few little things missing, but if you familiarize yourself with those features you should feel comfortable reading the Video.js source.

We’re also using Browserify (with a Babelify transform), so now we’re able to take advantage of all the browser packages NPM has to offer. One big area this has allowed us to improve is utility functions, which are now provided by Lodash.


Plugins are initialized earlier than before, giving plugin developers even more control over the player experience. They’re now initialized before other components are added (like the control bar), but after the player div is created. Keep in mind you’ll now need to wait for the ready event to do things such as append items to the control bar.

The plugin-development world should have also gotten more predictable since we’ve gotten a little less aggressive with our minification. Keep in mind that when you want to subclass a component externally (not using ES2015), you’ll want to use videojs.extends.

You can find more information on our 5.0 change details wiki page.

Want to be helpful?

Use it! We’ve spent months using this player in very specific ways while development, but there’s always the issue of “not being able to see the forest for the trees”. If you find issues while testing the player, please let us know on the issue tracker.

Video.js 4.12 - The last of the 4 minors

Much improved WebVTT support

We added basic WebVTT support really early on, which we were pretty proud of. As browsers added support, however, our shim started to lag a bit, or at the very least, cause issues with browsers that required native support (here’s looking at you, iOS).

So, we’re happy to announce that our text track support is vastly improved with this version! Instead of continuing to try and build out our own WebVTT parser, we’ve pulled in Mozilla’s fantastic work, VTT.js. This is the WebVTT implementation used in Firefox / Gecko, so we’re confident that this is a substantial leap forward for Video.js and our accessibility efforts.

Don’t use captions? Feeling disappointed?

You shouldn’t feel disappointed, this is a great day! This release includes a lot of fixes, and although fixes are always exciting to the people affected, other people can feel a hefty dose of “meh”. We’re excited to say, however, that this release is exciting for another, very important reason.

This is the last minor release in the version 4 family. There might be a few patches, but from now on, master is officially version 5.0-in-waiting. Party.


Notable updates and fixes for 4.12

  • The hide / show methods now toggle a class (.vjs-hidden) instead of applying inline styles. Make sure to update your stylesheet as well!
  • A new .vjs-scrubbing class gets applied while, you guessed it, scrubbing so menus can be prevented from erroneously showing on hover.
  • Improved url parsing in IE9.
  • Ever wondered what version you’re using? Now there’s a VERSION key. Woot.
  • New .vjs-ended class that’s added when playback reaches the end of the timeline (also known as: ended).
  • Player networkState and readyState properties available across techs
  • Video.js is now exported as a named AMD module
  • Mobile scrolling improvements
  • And more! Fixes galore!

Translation party continues

We’re now up to 19 community submitted translations! Entirely new translations in this release include:

  • Traditional Chinese
  • Vietnamese
  • Czech
  • Catalan
  • Bulgarian
  • Turkish

Video.js in the wild

To be terribly honest, there is a level of starstruck over a few of these. Normally we just do one, but hey…

Social Media

Global News Outlets

New plugins from the community

  • videojs-Background: A plugin that allows for videos to be displayed as a full background to any element.
  • videojs-brightcoveAnalytics: Allow tracking of views/impressions & engagement data in videojs for Brightcove videos
  • videojs-caption: Have the most flexibility and power for displaying caption videojs
  • videojs-transcript: Display an interactive transcript from caption or subtitle tracks.
  • videojs-autoplay-toggle: adds an autoplay toggle which will persist to cookies or localstorage.
  • videojs-offset: Allows you to play a segment of the video.
  • videojs-youtube-progress: Preserve progress seeker when control bar is hidden.
  • projectorjs: A small no-dependencies JavaScript library that enables the display of overlays on native HTML5 video elements, or (optionally) video elements powered by videojs.
  • videojs-record: A video.js plugin for recording audio/video files.
  • videojs-dashjs: Loads dash.js as a tech to support MPEG-DASH videos.
  • videojs-silverlight: Allows you to play WMV, WMA, MP4, MP3, WAV and FLAC medias through Silverlight within Video.js.
  • videojs-vlc: Allows you to play all media through VLC web plug-in within Video.js.
  • videojs-aurora: Allows you to play WAV, OGG, MP3, M4A, AAC and FLAC medias through Aurora.js within Video.js.
  • videojs-java: Allows you to play AIFF, AVI, GSM, MID, MPG, MP2, MOV, AU and WAV medias through Java within Video.js.

Raw list of changes

  • @PeterDaveHello added a Traditional Chinese translation (view)
  • @mmcc updated the hide/show functions to use a class instead of inline styles (view)
  • @mister-ben added better handling of the additional videojs() arguments when the player is already initialized (view)
  • @anhskohbo added a Vietnamese translation (view)
  • @Sxmanek added a Czech translation (view)
  • @jcaron23 added the vjs-scrubbing CSS class and prevented menus from showing while scrubbing (view)
  • @dmlap fixed URL parsing in IE9 (view)
  • @gkatsev Fixed issue where ManualTimeUpdatesOff was not de-registering events (view)
  • @brycefisher Added a guide on player disposal (view)
  • @toniher added a Catalan translation (view)
  • @mmcc added a VERSION key to the videojs object (view)
  • @mmcc fixed an issue with text track hiding introduced in #1681 (view)
  • @dmlap exported video.js as a named AMD module (view)
  • @dmlap fixed poster hiding when the loadstart event does not fire (view)
  • @chikathreesix fixed an object delete error in Chrome (view)
  • @steverandy fixed an issue with scrolling over the player on touch devices (view)
  • @mmcc improved tap sensitivity (view)
  • @mister-ben added a vjs-ended class when playback reaches the end of the timeline (view)
  • @dmlap Add network and ready state properties (view)
  • @woollybogger exported the hasClass function (view)
  • @DevGavin fixed the Chinese translation (view)
  • @iSimonWeb added font-path variable (view)
  • @shoshomiga added a Bulgarian translation (view)
  • @ragecub3 added a Turkish translation (view)
  • @gkatsev greatly improved text track support and implemented vtt.js as the webvtt parser (view)
  • @gkatsev fixed captions showing by default in Chrome and Safari (view)
  • @mister-ben fixed a woff warning in Firefox (view)

Video.js 4.9 - Now <audio> can join the party!

HTML5 Audio support

A common request we’ve seen is to be able to use Video.js with an &lt;audio&gt; tag, and now you can! Usage is almost identical, you can just include a data-setup={} attribute on an &lt;audio&gt; tag or initialize via Javascript.

&lt;audio id="audio_example" class="video-js vjs-default-skin" controls 
  preload="auto" width="600" height="600" 
  poster="/img/awesome-album-art.png" data-setup='{}'&gt;
  &lt;source src="/audio/awesome-music.mp3" type='audio/mp3'/&gt;

The only differences in behavior are that the poster image and controls are never hidden. This allows you to keep up something like album art during playback rather than a black video element. Since there’s no interesting content to hide (other than the poster image), we leave the controls showing to mimic a familiar audio player experience.

Audio Screenshot

Note: The Flash fallback still doesn’t support audio-only sources, but we’d like to add that in the future. In the meantime, audio playback with MP3 and Ogg sources should work fine in any (modern) browser that’s not IE8, so enjoy!

More translations!

We’ve been really excited by the continued support in terms of new translations. This release contains Brazilian Portuguese, Japanese, Italian, French, and Korean, as well as some improvements to the previous Spanish translation. We’d love to see the trend continue, so if you’re fluent in a language please consider submitting improvements or whole new localizations!

Video.js in the wild

Coursera is an education platform that offers free courses online from some of the world’s top institutions. They’ve built great tools for video interaction on top of Video.js, and are even going to talk about some of the work they’re doing at October’s SF Video Meetup.

Coursera Screenshot

New Plugins

videojs-wavesurfer - Adds a navigable waveform for audio files, using the excellent wavesurfer.js library.

Full list of changes

  • @deedos added a Brazilian Portuguese translation (view)
  • @baloneysandwiches added a hasClass method (view)
  • @mynameisstephen fixed an issue where slider event listeners were not being cleaned up (view)
  • @alexrqs cleaned up the Spanish translation (view)
  • @t2y added a Japanese translation (view)
  • @chikathreesix fixed an issue where data-setup options could be missed (view)
  • @seniorflexdeveloper added new translations and translation updates (view)
  • @chikathreesix exported the videojs.Flash.embed method (view)
  • @doublex fixed an issue with IE7 backwards compatibility (view)
  • @mmcc made it possible to override the font-size of captions and subtitles (view)
  • @philipgiuliani added an Italian translation (view)
  • @twentyrogersc fixed the return value when setting the poster source (view)
  • @heff updated to swf v4.5.0 to fix event issues (view)
  • @rpless made the VolumeMenuButton volume more accesible via tab navigation (view)
  • @mmcc added support for audio tags (html5 audio only) (view)

Video.js 4.8.0 released...Prost!

This isn’t the flashiest minor release ever, but it’s hot off the press and ready for use. As mentioned in the last (few) release posts, we’re making a concerted effort to be more consistent with releases, so hopefully the trend of bite-sized, scheduled releases will continue.


We only just released localization with version 4.7, but we’ve already had two pull-requests for new translations! The German translation is included with this release, and you’ll find the French translation in the next patch release. If you’re fluent in another language, you can help Video.js be even more internationally accessible by submitting a pull request translating just 24 words / phrases. &lt;/shameless_plug&gt;

Video.js in the wild

Heavybit Industries has a speaker series they host at their office, and they’ve been kind enough to start posting these sessions online in their library. The experience they’ve built using Video.js is impressive, including syncing the video progress with a transcript below the player.

Heavybit Screenshot

New plugins

  • videojs-ass: Adds Advanced SubStation Alpha subtitles support.
  • videojs-hdtoggle: HD button which toggles between HD and non-HD source.

Full list of changes

  • @andekande added a German translation (view)
  • @mattosborn fixed a bug where getting the video element src would overwrite it (view)
  • @songpete fixed a bug where keyboard events were bubbling and causing additional actions (view)
  • @knabar made the inactivity timeout configurable (view)
  • @seniorflexdeveloper added language files to the distribution for including specific languages (view)
  • @gkatsev improved handling of null and NaN dimension values (view)
  • @gkatsev fixed an issue where the controls would break if Flash was initialized too quickly (view)
  • @mmcc fixed an issue where if no playback tech was supported the error could not be caught (view)

Video.js v4.7.0 - Built mostly by NEW contributors! Also Google chooses Video.js

We’re continuing to work hard on improving the contributor experience around the Video.js project and it’s paying off. Over half of the changelog is thanks to brand new contributors! Issues and pull requests are getting addressed faster than ever, and I was even allowed to give a talk at OSCON on some of the strategies we’re using. If you’re instersted in getting involved, join the #videojs IRC room or post an issue to let us know.

Google Chooses Video.js for Google Media Framework

Google recently announced a new framework for building video experiences and monetization. There are versions of the framework for native iOS and Android apps, and for the browser they chose to use Video.js. Check out their video.js plugin, and as it says in their announcement, “Stay tuned as well for a deeper dive into Video.js with IMA soon!”


In this release we’ve built the infrastructure for displaying text in other languages. Examples of text include error messages and text used for accessibility. This feature can extend to plugins as well.

Today you can include other languages by including the JSON translations object from the language you want with the player, like in this example for Spanish (es).

videojs.options.languages['es'] = { [translations object] }

You can find translations files in the lang folder of the project. We don’t have many translations yet, but we’re looking for translators if you’d like to help!

Multiple buffered regions

With HTML5 video you can skip ahead in the video and the browser will start downloading the part of the file needed for the new position, which is different from how Flash video works by default. Flash will download from the start to the end of the file so you can only skip ahead once it has download that part of the video.

In the HTML5 video API we’re given the buffered property which returns a list of time ranges that the browser has downloaded data for. Early on in HTML5 video, browsers only ever reported one time range, but now we have a direct view of what’s been downloaded.

In the newest version of the video.js skin you can see the specific regions.

We’ve kept it subtle so it’s not too big of a change. We’d love to hear your thoughts on it.

DASH Everywhere-ish

If you haven’t seen it yet, check out the post on Tom Johson’s work getting DASH supported in Video.js, using Flash or the new Media Source Extensions. MPEG-DASH is an adaptive streaming format that Netflix and YouTube are using to stream video to cutting-edge browsers. It has the potential to replace Apple’s HTTP Live Streaming format as the main format used for adaptive streaming.

Video.js on Conan!

Conan O’Brien’s TeamCoco site is using Video.js with a nicely customized skin and ads integration. Check it out!

New Skin by Cabin

The team at Cabin put together a simple and clean new skin for video.js.

New Plugins

A lot of great new plugins have been released!

  • videojs-ima: Easily integrate the Google IMA SDK into Video.js to enable advertising on your video content.
  • videojs-brightcoveAnyaltics: Allow tracking of views/impressions & engagement data in videojs for Brightcove videos
  • videojs-logobrand: Add a logo/brand image to the player that appears/disappears with the controls. (also useful as a basic plugin template for learning how Video.JS plugins work.)
  • videojs-seek: Seeks to a specific time point specified by a query string parameter.
  • videojs-preroll: Simple preroll plugin that displays an advertisement before the main video
  • videojs-framebyframe: Adds buttons for stepping through a video frame by frame
  • videojs-loopbutton: Adds a loop button to the player
  • videojs-ABdm: Use CommentCoreLibrary to show comments (which is called as DanMu) during playing.
  • videojs-hotkeys: A plugin for Video.js that enables keyboard hotkeys when the player has focus.

New Release Schedule

As part of improving the contributor experience we’re moving to scheduled releases. We’ll now put out a release every other Tuesday as long as there’s new changes to release. This will help give everyone a better idea of when specific features and fixes will become available.

Full list from the change log

  • Added cross-browser isArray for cross-frame support. fixes #1195 (view)
  • Fixed support for webvtt chapters. Fixes #676. (view)
  • Fixed issues around webvtt cue time parsing. Fixed #877, fixed #183. (view)
  • Fixed an IE11 issue where clicking on the video wouldn’t show the controls (view)
  • Added a composer.json for PHP packages (view)
  • Exposed the vertical option for slider controls (view)
  • Fixed an error when disposing a tech using manual timeupdates (view)
  • Exported missing Player API methods (remainingTime, supportsFullScreen, enterFullWindow, exitFullWindow, preload) (view)
  • Added a base for running saucelabs tests from grunt (view)
  • Added additional browsers for saucelabs testing (view)
  • Added support for listening to multiple events through a types array (view)
  • Exported the vertical option for the volume slider (view)
  • Fixed Component trigger function arguments and docs (view)
  • Now copying all attributes from the original video tag to the generated video element (view)
  • Added files to be ignored in the bower.json (view)
  • Fixed an error that could happen if Flash was diposed before the ready callback was fired (view)
  • The up and down arrows can now be used to control sliders in addition to left and right (view)
  • Added a player.currentType() function to get the MIME type of the current source (view)
  • Fixed a potential conflict with other event listener shims (view)
  • Added support for multiple time ranges in the load progress bar (view)
  • Added vjs-waiting and vjs-seeking css classnames and updated the spinner to use them (view)
  • Now restoring the original video tag attributes on a tech change to support webkit-playsinline (view)
  • Fixed an issue where the user was unable to scroll/zoom page if touching the video (view)
  • Added “sliding” class for when slider is sliding to help with handle styling (view)



Discuss on Twitter | Discuss on Hacker News

DASH Everywhere-ish (hack project)

A couple of times a year Brightcove has an internal hackweek where engineers work on any project they’d like. In the latest hackweek (2014-07-14) Tom Johnson decided to see if he could get DASH supported in as many places as possible, by combining a few of the existing DASH player implementations with Video.js.

MPEG-DASH (Dynamic Adaptive Streaming over HTTP) is a streaming format similar to Apple’s HTTP Live Streaming (HLS). It allows you to provide multiple versions of a video at different bitrates, and then the player can switch between those versions depending on the user’s bandwidth (which is more complicated than you might think).

The two DASH playback implementations used were Dash.js and They were combined using video.js’s playback tech architecture, which means you can include plugins and custom skins and they’ll work the same with either playback method.

See the results.

Browser/Device Coverage

Using a combination of DASH.AS and DASH.JS will give us the following browser/device coverage:

DASH.JS (media source extensions support)

  • Internet Explorer: 11+
  • Chrome: 23+
  • FireFox: 25+ (upcoming version)
  • Safari (Desktop): 8+ (OSX Yosemite - Fall 2014)
  • iOS: No
  • Android: 4.2+ (Chrome)


Fallback to any environment that supports Flash Player 10.3


As you can see, the one remaining holdout is iOS and there’s currently no word when or if that will happen. Seeing media source extensions support in Safari 8 gives some hope, but my understanding is the requirements for getting support built into iOS are much more significant. My guess is it will happen eventually, but not for a while (and hopefully in-line playback + the fullscreen API will be supported at the same time).

Today, to provide adaptive streaming everywhere, you still need either DASH + HLS, or just HLS (you can use the video.js HLS plugin to support HLS in more browsers).

Tom’s Notes

The demo shows that for environments which support Media Source Extensions (MSE) we use a full Javscript implementation via Dash.js and as a fallback we use Flash built around OSMF and, an open-source plugin provided by Castlabs.

Tom has been working on videojs-osmf on the side, which helped make this possible.

DASH.AS Requirements


  • Environment must support Flash Player 10.3+
  • Video.js OSMF Tech (videojs-osmf)
  • CastLabs Dash.AS plugin for OSMF (


  • Since the requests are fired from within Flash, a crossdomain.xml file is required.* Ability to serve byte range requests via query string (myFile.mp4?range=0-1000 || myFile.m4s?bytes=0-1000) is necessary because Flash Player restricts use of the ‘Range’ request header. Castlabs has an .htaccess file which uses mod_rewrite to achieve this. Akamai edge servers accept the bytes query string var as well.


  • Something we may want to modify is handling the request/response portions of the workload outside of the Flash Player similar to the Video.js HLS solution. This would remove the need for having a crossdomain.xml, which cannot be normally expected to exist in a DASH focused environment.
  • Akamai edgesuite appear to be an exception to the above rule, as those domains do in fact have the crossdomain from it’s use as a serving platform under Akamai HD. The Akamai param syntax is ‘myFile.m4s?bytes=XXXX-YYYY’.
  • In it’s current form the Dash.AS manifest parser is very rigid. We may want to look into implementing a version of the DASH.JS manifest parsing on the AS side, as it is a lot more flexible in terms of structure recognition.
  • Deeper class inspection shows that the Dash.AS plugin is based on using Netstream in data generation mode, similar to our HLS solution. There may be better way to share the codebase between the two to reduce code duplication.

DASH.JS Requirements



  • Open CORS headers: Access-Control-Allow-Origin: *
  • Accept use of the Range request header: Access-Control-Allow-Headers:Range, Options


  • Dash.js MPD parsing is significantly more robust in comparison to the Dash.AS solution.
  • Most streams tested are Akamai based, we should probably try more local and non-Akamai hosted options moving forward.* In my testing I did see a Youtube DASH/MSE example, and those streams were confirmed to work within Dash.JS as well.
  • Dash.JS streaming lifecycle and segment loading lifecycle tend to be directly coupled and don’t necessarily fire the element media events at the time expected. For example is duration. While known at the parse complete stage of the manifest load cycle, is not reported to the player until the first of the segments is received.

Tech Compatibility

The independant techs work well together. A slight modification had to be made to the Dash.AS library to insure that it only checked for resources which 1. had a URL and 2. url contained the file extension of either ‘mpd’ or ‘m4s’ for DASH manifests/segments.

NOTE: Dash.JS tech should be loaded into DOM prior to OSMF tech to insure the OSMF tech is the fallback scenario for DASH playback.

Video.js version 4.6.0 released! It's been a productive month.

The video.js community has been in full force lately and it’s resulted in a lot of great features and fixes, including UI updates, better error messages, and even a Video.js Polymer element built by Addy Osmani himself.

New Live UI

Video.js has supported different forms of live video for a while, but a recent update has made the user experience a little clearer. Specifically, a ‘LIVE’ badge is added to the controls and the seek bar is hidden when seeking isn’t permitted.

Clearer Errors

A big effort went into improving error situations that developers and viewers might encounter. In cases where the viewer’s browser supports neither JavaScript nor HTML5 Video, a more helpful message is shown that informs the viewer how they can support video playback.

In cases where a common media error occurs (e.g. the file doesn’t exist or the network fails), an “X” icon is displayed showing that playback can’t continue, and a message is shown describing the issue. Additionally an error message is logged to the javascript console.

For developers, better logging functions have been added including videojs.log.error(), and they’re being used throughout the code base to provide better information and help track down issues.

IE11 Fullscreen

Video.js relies on native browser fullscreen even when Flash is used. IE11 is the first version of Internet Explorer to support native browser fullscreen, and video.js has now been updated to take advantage of that feature and provide a better fullscreen experience for those users.

Playback Rate Switching

If you ever wanted to speed up or slow down the rate of a video, now you can! HTML5 video browsers have been adding support for playback rate switching, and video.js now has an optional UI component that will let you select the speed. Flash however does not support playback rate switching, so unfortunately it’s not a feature that users on older browsers (e.g. IE8) can use.

See a demo.

New community plugins

The latest plugins to be added to the video.js plugins list.

  • videojs-vr: Project video onto different geometric shapes (Sphere, Cube, Cylinder) and view in 3d with optional Oculus Rift support
  • video-speed: Adds customizable video-speed control
  • OpenVideoAnnotation - create annotations in video-js using annotator
  • videojs-overlay: display simple HTML overlays during video playback
  • video.js-polymer: A video.js element for the Polymer web components framework

If you’d like a head-start on the scaffolding for a new video.js plugin, check out the Yeoman video.js plugin generator.

Full list from the change log

  • Updated the UI to support live video (view)
  • The UI now resets after a source change (view)
  • Now assuming smart CSS defaults for sliders to prevent reflow on player init (view)
  • Fixed the title element placement in menus (view)
  • Fixed title support for menu buttons (view)
  • Fixed extra mousemove events on Windows caused by certain apps, not users (view)
  • Fixed error due to undefined tech when no source is supported (view)
  • Fixed the progress bar not finishing when manual timeupdate events are used (view)
  • Added a more informative and styled fallback message for non-html5 browsers (view)
  • Added the option to provide an array of child components instead of an object (view)
  • Fixed casing on webkitRequestFullscreen (view)
  • Made tap events on mobile less sensitive to touch moves (view)
  • Fixed the default flag for captions/subtitles tracks (view)
  • Fixed compilation failures with LESS v1.7.0 and GRUNT v0.4.4 (view)
  • Added better error handling across the library (view)
  • Updated captions/subtiles file fetching to support cross-origin requests in older IE browsers (view)
  • Added support for playback rate switching (view)
  • Fixed an issue with the loadstart event order that caused the big play button to not hide (view)
  • Modernized the fullscreen API and added support for IE11 (view)
  • Added cross-browser testing with SauceLabs, and added Karma as the default test runner (view)
  • Fixed saucelabs integration to run on commits in TravisCI (view)
  • Added a clearer error message when a tech is undefined (view)
  • Added a cog icon to the font icons (view)
  • Added a player option to offset the subtitles/captions timing (view)

The new version is available on and has been added to the CDN.



Video.js version 4.5.0 released! Nothing to see here, move along

Well, sort of… this release is the result of a lot of hard work to speed up the version release process, meaning they’ll be coming a lot faster now with smaller sets of changes.

In this release we’ve added support for the Component(1) package manager, fixed the captions positioning when the controls are hidden, and helped Android devices know when they can support HLS. ;-) There were a few other changes as well but a lot of the work this round was done on the processes around the project. If you’ve spent time in the github issues, you’ll hopefully notice an improvement in the response rate on issues and the speed in which bugs get fixed.

New plugins

  • videojs-vast: A VideoJS plugin to play pre-roll videos from a VAST feed
  • videojs-comscore: Reports to comScore using their latest Streaming Tag SDK

Video.js in the wild

Toyota Europe! (click a video on that page) I was in Paris a few weeks ago and stopped by the Toyota store on Champs-Elysées. Next to the cars are multimedia touch screens that tell you details and allow you to watch videos. The video player looked kind of familiar, and sure enough it was video.js with a very nice custom skin. It turns out the Toyota Europe website uses video.js as well. Very cool.

If you find video.js on an interesting site somewhere, let us know in the comments.

Full list from the change log

  • Added component(1) support (view)
  • Captions now move down when controls are hidden (view)
  • Added the .less source file to the distribution files (view)
  • Changed src() to return the current selected source (view)
  • Added a grunt task for opening the next issue that needs addressing (view)
  • Fixed Android 4.0+ devices’ check for HLS support (view)

The new version is available on and has been added to the CDN.



Video.js version 4.4.0 released - Now supporting RequireJS and Browserify

Version 4.4.0 is here with over 20 updates and fixes. The most notable addition may be support for AMD and CommonJS module loaders, meaning you can now include Video.js using RequireJS or Browserify. Video.js can be installed through npm already, and we’ll soon add support for bower and component(1) as well.

New plugins

The plugin list continues to grow, with more in the works. Checkout the new endcard plugin built by The Onion.

Video.js in the wild

The Brightcove Play 2014 website recently went live with Video.js as the player. We’re also hard at work building Brightcove’s next-gen player with Video.js at the core, so stay tuned.

Full list from the changelog

  • Made the poster updateable after initialization (view)
  • Exported more textTrack functions (view)
  • Moved player ID generation to support video tags with no IDs (view)
  • Moved to using QUnit as a dependency (view)
  • Added the util namespace for public utility functions (view)
  • Fixed an issue with calling duration before Flash is loaded (view)
  • Added player methods to externs so they can be overridden (view)
  • Fixed html5 playback when switching between media techs (view)
  • Fixed Firefox+Flash mousemove events so controls don’t hide permanently (view)
  • Fixed a test for touch detection (view)
  • Updated the src file list for karma tests (view)
  • Added more tests for API properties after minification (view)
  • Updated projet to use npm version of videojs-swf (view)
  • Added support for dist zipping on windows (view)
  • Fixed iOS fullscreen issue (view)
  • Fixed touch event bubbling (view)
  • Fixed ARIA role attribute for button and slider (view)
  • Fixed and issue where a component’s dispose event would bubble up (view)
  • Quieted down deprecation warnings (view)
  • Update seek handle to display the current time (view)
  • Added requirejs and browserify support (UMD) (view)

The new version is available on and has been added to the CDN.