Permalink
Browse files

docs(liveui): Add a guide for the live ui and live api (#5677)

Add documentation of the new line ui feature.
  • Loading branch information...
BrandonOCasey authored and gkatsev committed Dec 18, 2018
1 parent bc7d530 commit c1475819b2e2983ece6e0c42ae7a29daaf4ae51b
Showing with 106 additions and 0 deletions.
  1. +106 −0 docs/guides/live.md
@@ -0,0 +1,106 @@
# The live user interface and API in Video.js
> Note the the "old" live user interface is currently the default, see the section on [the new user interface](#the-new-user-interface) for information on setting that up.

## The default live user interface
The default user interface hides the `ProgressControl` component on the controlbar and shows the `LiveDisplay` component when Video.js detects that the video that it is playing is live (via a `durationchange` event).

> Note: It does this by adding the `vjs-live` class to the player and the showing/hiding of components is all handled in css.
This makes the player have hide the progress bar, seek bar, and display text indicating that the player is live. All of those will be shown again if a non-live video is switched to (via another `durationchange` event).

To view a sample of this user interface please:
1. clone the repository, and move into that directory
2. run `npm install` or `npm ci` to install all necessary packages
3. run `npm start` to start the local server
4. open `http://localhost:9999/sandbox/live.html` in a web browser

## The new user interface
> Note: This user interface is will not work on Android due to the live HLS implementation not supporting seekable ranges during live streams. We reccommend overriding the native hls implementation with @videojs/http-streaming this will make the new liveui work.
The new user interface is currently opt-in to prevent breaking backwards compatiblity. We feel that the new user interface is much better and it will likely become the new default in the next major version. If you want to use the new user interface you will have to pass `{liveui: true}` during player setup. This can be done in two ways:

Using `data-setup`
```html
<video-js data-setup='{"liveui": true}'>
</video-js>
```

Using the `videojs` function

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

The new user interface shows the `ProgressControl` component on the control bar, hides the `LiveDisplay` component, and shows the new `SeekToLive` component when Video.js detects that the video that it is playing is live (via a `durationchange` event). Along with the `ProgressControl` update we also updated all the time tooltips on the player to indicate a negative number from the live current time, rather than seeking to a specific time.

> Note: It does this by adding the `vjs-live` and `vjs-liveui` class to the player and the showing/hiding of components is all handled in css.
The new live user interface shows the progress/seek bar and lets the user seek backwards/forwards within the live window. Next it adds a button, via the `SeekToLive` component that can be clicked when the user is behind live that will seek to the live current time. That same button indicates if the `currentTime` of the player is live via a grey circle when not live and a red circle when live.

To view a sample of this user interface please:
1. clone the repository, and move into that directory
2. run `npm install` or `npm ci` to install all necessary packages
3. run `npm start` to start the local server
4. open `http://localhost:9999/sandbox/liveui.html` in a web browser


## LiveTracker
> Note: this component can be turned off by passing `liveTracker: false` to the player during initialization.
Along with the new liveui we implemented an API that can be used regardless of which user interface is in use. This API is a child of the player and should be on the player at `player.liveTracker`. `LiveTracker` provides several useful helper functions and events for dealing with live playback, all of which are used and tested internally. Internally this component keeps track of the live current time through a function that runs on a 30ms interval.

### The seekableendchange event
The live tracker will fire this event every time that the `seekableEnd` for the player changes. This is used internally to keep our `pastSeekEnd()` function up to date.

### The liveedgechange event
As the name implies the live tracker will fire this event when it detects that the current time is no longer at the live edge.

### startTracking() and stopTracking()
These functions can be called to arbitrarily start/stop tracking live playback. Normally these are handled by automatically when the player triggers a `durationchange` with a duration of `Infinity`. You won't want to call them unless you are doing something fairly specific.

### seekableEnd()
seekableEnd gets the time in seconds of the furthest seekable end. For instance if we have an array of seekable `TimeRanges` where the first element in the array is the `start()` second and the last is the `end()` second:

```js
// seekable index 0: 0 is start, 1 is end
// seekable index 1: 2 is the start, 3 is the end
const seekableExample = [[0, 1], [2, 3]];
```

seekableEnd would return `3` as that is the furthest seekable point for the current media.

> Note: that if Infinity is anywhere in seekable end, this will return Infinity
### seekableStart()
seekableStart gets the time in seconds of the earliest seekable start. For instance if we have an array of seekable `TimeRanges` where the first element in the array is the `start()` second and the last is the `end()` second:


```js
// seekable index 0: 0 is start, 1 is end
// seekable index 1: 2 is the start, 3 is the end
const seekableExample = [[0, 1], [2, 3]];
```

seekableStart would return `0` as that is the first seekable point for the current media.

> Note: that if Infinity is anywhere in seekable start, this will return Infinity
### liveWindow()
This function gets the amount of time between the `seekableStart()` and the `liveCurrentTime()`. We use this internally to update the total length of our bars, such as the progress/seek bar.

### atLiveEdge() and behindLiveEdge()
Determines if the currentTime of the player is close enough to live to be considered live. We make sure its close enough, rather than absolutely live, because there are too many factors to determine when live actually is. We consider the currentTime live when it is within two seekable increments and 70ms (two ticks of the live tracking interval). The seekable increment is a number that is determined by the amount that seekable end changes as playback continues. See the `seekableendchange` event and the `pastSeekEnd()` function for more info.

### liveCurrentTime()
live current time is our best approximation of what the live current time is. Internally it uses the `pastSeekEnd()` function and adds that to the `seekableEnd()` function. It is possible for this function to return `Infinity`.

### pastSeekEnd()
This is the main value that we use to track if the player is live or not. Every `30ms` we add `0.03` seconds to this value and every `seekableendchange` it is reset to 0 and `0.03` is added to it right away.

### isTracking() and isLive()
`isTracking` and `isLive` do the same thing they tell you if the `LiveTracker` is currently tracking live playback and since we assume that live tracking will only be done during live they should be the same.

### seekToLiveEdge()
This function sets the players `currentTime` to the result of the `liveCurrentTime()` function. It will also start playback if playback is currently paused. It starts playback because it is easy to fall behind the live edge if the player is not playing.

0 comments on commit c147581

Please sign in to comment.