Video.js Blog

Gary Katsevman2019-01-11

Video.js 7.4

It's time to have an overview of Video.js 7.4, first released early December. The big new feature for this release is a UI that allows you to seek during live streams. We updated focus-visible to work with our Menus, added more translations, added a replay option to the Play/Pause button, and many, many fixes, multiple of which are accessibility related.

We also dropped our usage of Grunt from our build process. We owe a lot to Grunt as it has served us well but it was time to move on.

Video.js 7.4.1 is currently the latest release with 7.4.2 out as a pre-release until next week.

Thanks

Before continuing, I'd like to thank everyone that was involved, we really appreciate your contributions! There were a total of 14 first time contributors, I think this is a historic high for us and I hope this continues!

Live UI

Video.js has supported live streams for a while, either natively, or via videojs-http-streaming (VHS). However, this UI was very minimal, it disabled the progress bar and basically only allowed pausing, though, there was an indicator that this was a live stream.

Video.js, with the new Live UI, playing a live stream
Video.js, with the new Live UI, playing a live stream

The new UI looks pretty similar to the previous live UI and the regular control bar. The "live" indicator moves to the right side of the progress bar and also indicates whether we are playing back live or we are behind live. Clicking this button will seek to the "live point". The time displays and tooltips will show time with respect to the live point; so, current time at the live point will be 0 and if you seek back 30 seconds it'll show -00:30.

This feature is still somewhat experimental, so, it is behind an option that is off by default. We hope that you try it out and give us feedback and that we can enable it by default in a future release.

To enable the feature, pass in liveui: true to the player: In JavaScript:

var player = videojs('my-id', {
  liveui: true
  }
);

Or HTML:

<video-js id="my-id" data-setup='{"liveui": true}'}>
  <source src="https://example.com/live.m3u8" type="application/x-mpegurl">
</video-js>

Languages

We've had a bunch of language additions and updates in the 7.4 release line. In addition, we now copy the JSON files into the dist/lang folder for easier inclusion your projects.

Languages added and updated

  • Occitan (oc)
  • Russian (ru)
  • Welsh/Cymraeg (cy)
  • Ukrainian (uk)
  • Serbian (sr)
  • Swedish (sv)

Accessibility

As always, we aim to make Video.js as accessible and usable as we can. To that end, we've had a bunch of accessibility related fixes in these releases.

  • Time displays accessibility with VoiceOver
  • remove hidden control text in progress bar
  • make the seek-to-live button announce itself to screen readers properly
  • Make the - in the remaining time display be visual only and not readable by screen readers

Other Features Updates

Responsive Captions Settings Dialog

This uses the new responsive setting and breakpoints to make the dialog respond to the size of the player and improves the user experience.

replay option for PlayToggle

The PlayToggle button changes the icon to a replay icon when the video ends, most users don't mind it and it was a highly requested feature previously. This adds an option to turn it off.

focus-visisble menu backgrounds

Like outlines for other buttons, we use a different background color to represent the focus in menus. We should respect focus-visible there like we do for outlines in buttons.

playerreset event

When the player is reset with the reset() method, it'll now trigger a playerreset event to let components and users know.

Other Fixes

  • Fix fullscreen event triggering twice (7.4.2)
  • PlayToggle cursor pointer
  • select default subtitles on loadedmetadata not loadstart
  • don't apply user preference to subtitles if no language is set
  • make sure that vjs-waiting is only removed if we started playback again
  • allow duration to be set to NaN, making Video.js more spec compliant
  • fix locking menus when the menu button is pressed
  • remove child component from old parent when moving the component to a new parent
  • remove vjs-ended when seeking after video has ended
  • don't autohide the control bar when hovering with the mouse

Full CHANGELOG for 7.4.0, 7.4.1, and 7.4.2

## [7.4.2](https://github.com/videojs/video.js/compare/v7.4.1...v7.4.2) (2019-01-08)

Bug Fixes

  • Control-bar autohide when cursor placed over it #5258 (#5692) (6ebc772)
  • css animation shorthand property order (#5687) (0e69ce9)
  • fs: make sure there's only one fullscreenchange event (#5686) (2bc90a1), closes #5685
  • lang: adds sv translation used by liveui component (#5704) (f38726e)
  • package: update @videojs/http-streaming to version 1.6.0 🚀 (#5705) (3d093ed)
  • player: remove vjs-ended class on seeked (#5728) (f1637cd), closes #5654
  • remaining-time-display: make the '-' be visual and not readable by screen readers (#5671) (05513f8), closes #5168
  • seekbar: don't disable if live tracker's seekable is infinity (#5721) (7f507df)
  • remove child from old parent when moving to new parent via addChild (#5702) (8a3e2a7)

Chores

Documentation

  • liveui: Add a guide for the live ui and live api (#5677) (c147581)
## [7.4.1](https://github.com/videojs/video.js/compare/v7.4.0...v7.4.1) (2018-12-11)

Bug Fixes

Chores

  • package: update autoprefixer to version 9.4.2 (#5647) (19f3465)
  • package: update rollup-plugin-node-resolve to version 4.0.0 🚀 (#5666) (d07b6c2)

Documentation

  • remove grunt and update usage of build scripts (#5656) (62f9e78)

Tests

  • verify null-checks with player and control bar children set to false (#5670) (13b42ad)
# [7.4.0](https://github.com/videojs/video.js/compare/v7.3.0...v7.4.0) (2018-12-03)

Features

Bug Fixes

  • add correct cursor pointer for the play toggle (#5463) (aed337a)
  • default subtitles not enabled (#5608) (8329e64)
  • tracks: don't select tracks based on user pref if no langauge is set (#5556) (c1cbce3), closes #5553
  • Don't remove vjs-waiting until time changes (#5533) (0060747)
  • lang: add is loading ru translation (#5630) (0090b75)
  • lang: Occitan: harmonisation plural/singular (#5602) (4842201)
  • package: update @videojs/http-streaming to version 1.4.2 🚀 (#5543) (dbaca33)
  • package: update @videojs/http-streaming to version 1.5.0 🚀 (#5587) (d95ef6f)
  • duration reset and allow duration NaN or 0 for duration display (#5348) (ab0e29a), closes #5347
  • not inline volume slider showing up after mouse hovering on it (#5503) (7d127c8), closes #5502 #5505
  • vjs-lock-showing class gets removed from menu when no longer hovering on menu-button. (#5465) (58f638e), closes #1690

Chores

Documentation

Gary Katsevman2017-04-03

Video.js 6.0 Release!

After months of hard work, I am proud to annouce the release of Video.js 6.0 🎉!

This release is pretty exciting. It greatly improves the accessibility of the controls and components, and we are committed to making Video.js the most accessible player we can. Video.js also provides some shiny, and awesome, new features for developers in middleware and advanced plugins. Video.js 6.0 is also the first release where Flash is unbundled from core -- though, it is still available as a plugin, if necessary.

Today's release is a pre-release and will stay that way for about a week or two before being promoted to latest. Just to make sure that any last bugs, if any, are ironed out.

Things you should know

Most things have not changed between 5.x and 6.x. In fact, in most of our work in plugins we maintain, the majority of the work was to use new methods and fallback to old methods because they were logging deprecation warnings. Those plugins would've continued working otherwise.

However, there are definitely some changes that are breaking and would require action on your part. For example, if you require Flash, that's something that would now need to be included manually.

One of the other big changes is that source selection is now asynchronous. This was necessary for middleware support and most likely won't affect users if they are waiting for the player to be ready before interacting with the player.

These are written up on our wiki. We'll make sure to update it if there's anything that we missed.

Feedback Wanted

If you are using Video.js and have comments or questions, please drop by on Slack. If you find a bug, please open an issue on GitHub, preferably with a reduced test case.

5.x Support

We're still going to be supporting the Video.js 5.x release line. This will mostly be bug fixes but features will be considered on a case-by-case basis.

If IE8 support is still required, it is probably best to stick to 5.x.

npm tags

Once Video.js 6 is promoted to latest, it'll take over the next and latest tags on npm. The 5.x release line will then be given its own set of tags: latest-5 and next-5.

Code of Condunct

We strive to be open and inclusive and so we have adopted a Code of Conduct, based on Contributor Covenant that applies to all Video.js projects.

Conclusion

We are super excited for this release! Please take it for a spin from next tag on npm or from the CDN. And please come chat with us on Slack.

Brandon Casey2017-02-03

Feature Spotlight: Accessibility

Accessibility! The most important feature you never knew about.

In the Video.js organization we try hard to have good accessibility. Like most other software, any change can affect the system in unintended ways. For example MuteToggle and VolumeControl were married into VolumeMenuButton in Video.js 5. While this change did allow these controls to work in tandem visually, it also did something unintended. It broke accessibility. In this post we will go over what broke, what the fix was, what accessibility is, and how to test and make sure it works.

Feel free to skip to the last section if you already know what accessibility is.

Accessibility? What's that?

Accessible software has support for users with vision, hearing, movement/dexterity, or other impairments. It also helps users that want to use the keyboard to navigate. Out of the box web applications have some accessibility due to the nature of HTML, but this is only the case if you are using native elements in intended ways. If you cannot use native DOM elements, like <button>, and instead must use a <div> for buttons, then you need worry about accessibility in your page.

Supporting users with hearing impairment is not something that we can do directly for the users of Video.js. Instead we must indirectly support these users by adding support for captions in videos. In Video.js we have had support for captions and subtitles for some time, internally they are called TextTracks. In fact Video.js has had support for WebVTT format TextTrack, which is much more accessible, since version 4.

Supporting users with vision impairment is harder, but partly in our control. To support this group of users our player must be accessible to screen readers. A screen reader is an application that reads elements off of the screen to the user (as the name implies). On top of reading from the screen it also allows the user to interact with the page using only the keyboard or specific gestures on a touchscreen (without using a mouse or needing to directly touch visible items). HTML has certain rules that must be followed so that a page can be accessible. We will go over the basics of these rules in the next section. Screen readers are further supported by having description tracks that can be read out during video playback. Description tracks are a sub-type of TextTrack, and as previously stated we cannot automatically add them to videos, we can only have support for them in the Video.js.

See the resources section at the end of this post for a list of screen readers.

How do you make a web application screen reader accessible?

If you use the native elements for the purposes that they were intended, you will already have most of the work done.This is why the use of the native element is the recommended way to make anything accessible for a screen reader. For instance if you use a <button> element you will get the following accessibility attributes (without them actually being on the button):

  • tabIndex which allows users to tab to the button
  • role="button" which tells the screen reader that this is a button
  • The space and the enter key will both press the button

In some cases, such as in Video.js, it will not be possible to use the native <button> element. You will have to mimic the accessible functionality from the list above and use a div. Here is a list of what you will have to add:

  • You have to add the role="button" attribute to classify it as a button.
  • You have to add a tabIndex which will allow the div to be navigated to using the tab key
  • You have to add handling for the space and enter key that press the button

A list of role attribute values can be found on Mozilla Developer Network.

After mimicking or adding native accessibility on the controls and content in your webpage, the next thing to look over are aria attributes. For instance, we use aria-live="polite" for our ProgressBar slider. By default aria-live is set off, which means updates to controls should not be read to the user unless they un-focus and re-focus an element. The value of polite which we use allows us to convey the position of the slider to screen reader without them having to change focus on the control. This is useful because the ProgressBar is always updating while a video is playing. A value of polite will also wait to convey said updates until the screen reader is done reading other information to the user.

For a more complete list of ARIA attributes see the specification.

Finally you need to add an accessible "name" to an element so that it can be referred to. A good example of this is can be seen in the MuteToggle control. Since it is not a simple "button" we include innerHTML/innerText of "Mute" or "Unmute" in a way that is hidden from most users but announced to screen readers. In Video.js we refer to the accessible name and the action that a control performs as "control text". Control text also updates the title attribute of an element in most cases, which is important for visual accessibility. When the action the a control performs changes so does the control text. This will allow the screen reader to refer to the MuteToggle as "Mute Toggle" rather than "button". It will also convey the current action of the MuteToggle. In this case that will be either "Mute" or "Unmute" depending on what the button would do when pressed (ie the state of the button).

Here are some examples of accessibility straight from Video.js:

  • The MuteToggle <button>:
    • Has aria-live set to polite, rather than the default value of off. aria-live with any value other than off indicates that innerText/innerHTML updates can be sent to the screen reader without the user needing to move focus off of the control. The value of polite means that the screen reader should wait until it is done speaking to convey these updates to the user.
    • Has control text of "Mute" or "Unmute" which indicates the current status of the button to the use
  • The VolumeBar slider <div>:
    • Has a role attribute with a value of slider. Like this: role="slider"
    • Has a tabIndex attribute as it is not a native control element
    • Has EventHandlers that listen for:
      • The up and right arrow keys to increase the volume and the slider percentage
      • The down and left arrow keys to decrease the volume and the slider percentage
    • Has aria-label of "volume level" which is an accessible label that the screen reader will use to refer to it
    • Has aria-valuenow and aria-valuetext properties that update to indicate the current volume level (so the screen reader can read it)
    • Has aria-live set to polite, rather than the default value of off. aria-live with any value other than off indicates that innerText/innerHTML updates can be sent to the screen reader without the user needing to move focus off of the control. The value of polite means that the screen reader should wait until it is done speaking to convey these updates to the user.

The problem and the solution

Now let's talk about how screen reader accessibility broke in Video.js 5. First VolumeMenuButton replaced MuteToggle and VolumeControl on the ControlBar. VolumeMenuButton was set to mimic MuteToggle when clicked. It would also show the VolumeControl on mouseover or focus. This was a problem because a VolumeControl was a now a child of a button, and buttons should not contain other controls. To the screen reader and to the DOM there are two MuteToggle button controls. When visually there is a VolumeControl and a MuteToggle. Below you can see a gif of this behavior in action :

macOS `VoiceOver` Before The FixmacOS `VoiceOver` Before The Fix

The solution to this problem was to use a regular div to house the MuteToggle and VolumeControl. This regular div would have no role or control text so that it would be invisible to a screen reader. From that point forward we just needed to mimic the old UI. For those who are wondering, this new Component is called the VolumePanel. See the new behavior in a gif below:

macOS `VoiceOver` After The FixmacOS `VoiceOver` After The Fix

Outlines

Another big accessibility fix for controls comes from the removal of one small css rule:

outline: none;

Why did we do it? With feedback from the community and external resources, we learned that outlines should always be on. Without outlines there is no visual indication of keyboard focus on control elements and without that, keyboard users who are not visually impaired have a hard time using the controls.

Wrap up

Hopefully this post has given you some insight into making a web application accessible. If you find any issues or have any suggestions for our accessibility or in general feel free to contribute to Video.js.

If you want to keep up to date on the current state of accessibility work see the a11y label on PRs and issues.

Resources

Here are some popular screen readers that are actually used in the wild:

Resources for learning more about web accessibility: