1. 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 Dash.as. 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 Dash.as, 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 (dash.as)


    • 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. Dash 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.

  2. 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 videojs.com and has been added to the CDN.


  3. 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 videojs.com and has been added to the CDN.


  4. 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 videojs.com and has been added to the CDN.


  5. Video.js version 4.3.0 released w/ shiny new API docs

    The biggest change in this update is actually an overhaul of the API docs. The best example of the new docs is the Player doc, which is the API most video.js users will work with.

    The new docs are now automatically generated from the code and code comments, making it easier to keep them up to date with what’s currently in the codebase.

    One interesting note about the doc-generator is that it uses esprima, a tool that reads javascript files and gives back the “abstract syntax tree” of the code.

    For the following javascript:

    var hi;

    Esprima would generate:

        "type": "Program",
        "body": [
                "type": "VariableDeclaration",
                "declarations": [
                        "type": "VariableDeclarator",
                        "id": {
                            "type": "Identifier",
                            "name": "hi"
                        "init": null
                "kind": "var"

    We’re using the AST of the video.js codebase to generate the majority of the information in the docs, which means it requires fewer comments and less work to keep the docs really great as we continue to build. If you’re interested in seeing how we’re handling that, check out the doc-generator repo (it’s currently only useful with the video.js codebase, but it could be extended to support more).

    New CSS Options

    Additional updates include new loading spinner icon options, and a new class for centering the big play button.

    Many users have been clear that they’d prefer the big play button in the center of the video. While we feel the trend is still moving towards getting the play button out of the way of the content, we wanted to make this feature easier to customize. You can now use the vjs-big-play-centered class on your video tag to center the play button.

    To try the new spinner icon options, check out the designer and change the icon name used by the spinner class.

    Even more plugins!

    Finally, the most exciting developments are actually happening in the video.js community, with more and more plugins being built. We’re up to 26 in the plugins list, with more on the way.

    If you have some code you’ve built on top of video.js that you think might be valuable to others, please share it on the plugins list, or post an issue on the video.js repo if you have questions about the plugin process.

    Full list from the changelog

    • Added Karma for cross-browser unit testing (view)
    • Unmuting when the volume is changed (view)
    • Fixed an accessibility issue with the big play button (view)
    • Exported user activity methods (view)
    • Added a classname to center the play button and new spinner options (view)
    • Added API doc generation (view)
    • Added support for codecs in Flash mime types (view)

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


  6. The Guardian uses Video.js in feature article

    It’s always nice to find Video.js in the wild, but this article from The Guradian is an especially cool use case. Most of the players don’t use controls at all, but rather play/pause based on the user scrolling the page. The ones that do use controls are styled with a white on light gray theme that matches the rest of the page really well.

    The article begins with a full-width video that includes controls. Big Player

    Most of the videos are short dialogs that are triggered based on scrolling to a certain point in the page. These have no controls other than an external play/pause button. No Controls

    Smaller player with controls. Small Player

  7. 4.2.2 Patch Release

    Two bugs have been squashed with this patch:

    • An issue most commonly seen in Firefox where video playback would break when a race condition would occur during video loading (#756)
    • An issue where the duration would get stuck at 0:00 when loading the player dynamically (#775)

    See the changes made

    This version can be downloaded on videojs.com, is available on the CDN, and the existing /4.2/ CDN version has been updated to 4.2.2. (may take time to propagate to your area)


  8. Running Video.js unit tests in real browsers with Karma

    If you’ve ever cloned the video.js repository, either to contribute or to build your own version, you’ve no doubt run the video.js unit tests. Until just recently, though, we only had support for running unit tests with grunt, using the PhantomJS browser. Well, that’s changed, with the first phase of our integration with Karma. Now, you’ll be able to run your tests in real browsers.

    Setting things up is a snap. After you pull down the latest from video.js and run `npm install`, simply copy the test/karma.conf.js.example file to test/karma.conf.js, add the browsers you wish to test to the browsers array, and run `grunt karma:dev`. That’s it. Of course, there are more options that you can configure, but if you want to get the ball rolling quickly, just add browsers, and run the tests. See the test/karma.conf.js.example file for more instructions.

    For our next phases of integration, we’re planning to include support for running tests on mobile devices, as well as running these tests in a publicly-available location, so that anyone can tell at a glance how things are going.

    You can learn more about Karma here.


  9. Unauthorized modification of Video.js CDN files

    UPDATE 2013-09-19:

    The CDN continues to be secure and we have taken significant steps to ensure it never falls under a similar attack again.

    • Access to the CDN has been restricted to a few key individuals
    • A third-party service is now monitoring changes made to the CDN
    • Processes have been defined for responding to any such future issues

    The original source of this event was the Sendori Auto-update Hack, which possibly affected millions of people including, unfortunately, an admin of the CDN.

    On the morning of September 14, 2013 at 6:25am PDST, we discovered that certain versions of video.js being served from our content delivery network (CDN) had been modified by an unknown attacker. The file was changed to contain malicious code that would attempt to install malware on any Windows or Macintosh computer that loaded the video.js file. The malware has been identified to be a variant of Trojan.PWS.Stealer.1932 or Trojan.Ransom.ED. We quickly reverted to safe versions of the video.js file, and took steps to ensure that the issue could not reoccur.

    The specific files affected were:

    No patch-level versions (e.g. vjs.zencdn.net/4.1.0/video.js) were affected, and neither was the latest version (4.2). Users who host their own copy of Video.js were also not affected.

    Potential Impact: Any browsers that loaded the affected files during the compromised period may have prompted users to install malicious software on their computers.

    It has been determined that the files were originally modified at 4:30am PDST. The files were repaired at 7:15am PDST and completed propagation to CDN edge caches around the world at 7:51am PDST.

    Rest assured that video.js is once again safe to load. We are currently investigating the root cause. Once we fully understand the nature of the incident, we will provide an update with additional information.

    Keeping our users safe is one of our top priorities, and we sincerely apologize to anyone who was negatively impacted by this event.

  10. Video.js 4.2.0 released! RTMP, CSS designer, and stability

    Happy September! The 4.2.0 release of Video.js has a few interesting updates, and a bunch of stability and polish.

    RTMP Support

    First of all, thanks to an impressive collaboration of community members, we now have RTMP support (in beta). Check out the example.

    It’s still pretty basic support for RTMP, but we think it will cover a lot of the general use cases. The feature support includes:

    • Single stream (no client-side adaptive support)
    • Flash only, HTML5 video doesn’t support RTMP (but HLS is supported on iOS devices)
    • On-demand only. We haven’t updated the UI to support live yet.

    To load an RTMP stream in a Video.js player, you’ll use a source tag in the same way you would other source types:

    <source src="rtmp://your.streaming.provider.net/cfx/st/&mp4:path/to/video.mp4" type="rtmp/mp4">

    The connection and stream parts are determined by splitting the URL on the first ampersand (&) or the last slash (/).

    http://myurl.com/streaming&/is/fun -->
      connection: http://myurl.com/streaming
      stream: /is/fun
    http://myurl.com/streaming/is/fun -->
      connection: http://myurl.com/streaming/is
      stream: fun

    The available source types include rtmp/mp4 or rtmp/flv.

    RTMP has been a much requested feature over the years and it’s great to finally have it in the player. Thanks to everyone involved in that work.

    Player Skin Designer

    If you missed the previous blog post, be sure to check out the new interface for designing the player skin. It really shows off the customizability of the video.js controls, which are built completely in HTML and CSS.

    With the 4.2 release the styles in the designer have been brought up-to-date with the latest player styles.

    Control Bar Updates

    Also in a previous post, I described a number of updates that were made to the control bar to fix cross browser/device issues and improve the overall functionality. As of 4.2.0 all of those updates have made it into the stable release.

    Other Updates

    Along with previous updates there’s been a number of patches and enhancements along the way. Here’s a full list:

    • Added LESS as a CSS preprocessor for the default skin (view)
    • Exported MenuButtons for use in the API (view)
    • Fixed ability to remove listeners added with one() (view)
    • Updated buffered() to account for multiple loaded ranges (view)
    • Exported createItems() for custom menus (view)
    • Preventing media events from bubbling up the DOM (view)
    • Major reworking of the control bar and many issues fixed (view)
    • Fixed an issue with minifiying the code on Windows systems (view)
    • Added support for RTMP streaming through Flash (view)
    • Made tech.features available to external techs (view)
    • Minor code improvements (view)
    • Updated time formatting to support NaN and Infinity (view)
    • Fixed an undefined error in cases where no tech is loaded (view)
    • Exported addClass and removeClass for player components (view)
    • Made the fallback message customizable (view)
    • Fixed an issue with the loading spinner placement and rotation (view)
    • Fixed an issue with fonts being flaky in IE8

    The latest version can be found on videojs.com through the download link or the CDN hosted version.