1
0
mirror of https://github.com/videojs/video.js.git synced 2025-01-17 10:46:00 +02:00
video.js/docs/guides/middleware.md

212 lines
8.3 KiB
Markdown
Raw Normal View History

# Middleware
Middleware is a Video.js feature that allows interaction with and modification of how the `Player` and `Tech` talk to each other. For more in-depth information, check out our [feature spotlight](http://blog.videojs.com/feature-spotlight-middleware/).
## Table of Contents
* [Understanding Middleware](#understanding-middleware)
* [setSource](#setsource)
* [setTech](#setTech)
* [Middleware Setters](#middleware-setters)
* [Middleware Getters](#middleware-getters)
* [Middleware Mediators](#middleware-mediators)
* [Termination and Mediators](#termination-and-mediators)
* [Using Middleware](#using-middleware)
* [Terminating Mediator Methods](#terminating-mediator-methods)
## Understanding Middleware
Middleware are functions that return an object, a class instance, a prototype, etc, scoped to the Player with methods matching those on the `Tech`. There are currently a limited set of allowed methods that will be understood by middleware. These are: `buffered`, `currentTime`, `setCurrentTime`, `duration`, `seekable`, `played`, `play`, `pause` and `paused`. These allowed methods are split into three categories: [getters](#middleware-getters), [setters](#middleware-setters), and [mediators](#middleware-mediators).
There are a few special methods that affect middleware: `setSource` and `setTech`. These are called internally by Video.js when you call `player.src()`.
### setSource
`setSource` is a required method for all middleware and must be included in the returned object. This method will setup the routing between a specific source and middleware and eventually sets the source on the `Tech`.
If your middleware is not manipulating, redirecting or rejecting the source, you can pass along the source by doing the following:
```javascript
videojs.use('*', function(player) {
return {
setSource: function(srcObj, next) {
// pass null as the first argument to indicate that the source is not rejected
next(null, srcObj);
}
};
});
```
### setTech
`setTech` is a method that associates middleware with a specific `Tech` once it has been selected by the `Player`, after middleware make a decision on which source to set. This does not need to be included in your middleware.
### Middleware Setters
```
+----------+ +----------+
| | setter middleware | |
| +----------------------> |
| Player | | Tech |
| <----------------------+ |
| | getter middleware | |
+----------+ +----------+
```
Setters will be called on the `Player` first and run through middleware in the order they were registered in (from left to right in the diagram) before calling the method, with its arguments, on the `Tech`.
### Middleware Getters
Getters are called on the `Tech` first and are run though middleware in reverse of the order they were registered in (from right to left in the diagram) before returning the result to the `Player`.
### Middleware Mediators
Mediators are methods that not only change the state of the `Tech`, but also return some value back to the `Player`. Currently, these are `play` and `pause`.
Mediators are called on the `Player` first, run through middleware in the order they were registered (from left to right in the below diagram), then called on the `Tech`. The result is returned to the `Player` unchanged, while calling the middleware in the reverse order of how they were registered (from right to left in the diagram.) For more information on mediators, check out the [mediator section](#termination-and-mediators).
```
+----------+ +----------+
| | | |
| +---mediate-to-tech----> |
| Player | | Tech |
| <--mediate-to-player---+ |
| | | |
+----------+ +----------+
```
### Termination and Mediators
Mediators make a round trip: starting at the `Player`, mediating to the `Tech` and returning the result to the `Player` again. A `call{method}` method must be supplied by the middleware which is used when mediating to the `Tech`. On the way back to the `Player`, the `{method}` will be called instead, with 2 arguments: `terminated`, a Boolean indicating whether a middleware terminated during the mediation to the tech portion, and `value`, which is the value returned from the `Tech`.
```
+----------+ +----------+
| | | |
| +----+call{method}+----> |
| Player | | Tech |
| <------+{method}+------+ |
| | | |
+----------+ +----------+
```
A skeleton of a middleware with Mediator methods is given below:
```
var myMiddleware = function(player) {
return {
callPlay: function() {
// mediating to the Tech
...
},
play: function(terminated, value) {
// mediating back to the Player
...
},
...
};
};
```
Middleware termination occurs when a middleware method decides to stop mediating to the `Tech`. We'll see more examples of this in the [next section](#terminating-mediator-methods).
## Using Middleware
Middleware are registered to a video MIME type, and will be run for any source with that type.
```javascript
videojs.use('video/mp4', myMiddleware);
```
You can also register a middleware on all sources by registering it on `*`.
```javascript
videojs.use('*', myMiddleware);
```
Your middleware should be a function that is scoped to a player and returns an object, class instance, etc, with methods on it that match those on the `Tech`. An example of a middleware that returns an object is below:
```javascript
var myMiddleware = function(player) {
return {
setSource: function(srcObj, next) {
// pass null as the first argument to indicate that the source is not rejected
next(null, srcObj);
},
currentTime: function(ct) {
return ct / 2;
},
setCurrentTime: function(time) {
return time * 2;
}
};
};
videojs.use('*', myMiddleware);
```
This middleware gives the appearance of the video source playing at double its speed, by halving the time we _get_ from the `Tech`, and doubling the time we _set_ on the `Tech`.
An example of a middleware that uses Mediator methods is below:
```javascript
var myMiddleware = function(player) {
return {
setSource: function(srcObj, next) {
// pass null as the first argument to indicate that the source is not rejected
next(null, srcObj);
},
callPlay: function() {
// Do nothing, thereby allowing play() to be called on the Tech
},
play: function(terminated, value) {
if (terminated) {
console.log('The play was middleware terminated.');
// the value is a play promise
} else if (value && value.then) {
value
.then(function() {
console.log('The play succeeded!')
})
.catch(function (err) {
console.log('The play was rejected', err);
});
}
}
};
};
videojs.use('*', myMiddleware);
```
This middleware allows the call to `play()` to go through to the `Tech`, and checks in `play` whether the play succeeded or not. A more detailed example can be found in our [sandbox](https://github.com/videojs/video.js/blob/master/sandbox/middleware-play.html.example).
### Terminating Mediator Methods
Mediator methods can terminate, by doing the following:
```javascript
var myMiddleware = function(player) {
return {
setSource: function(srcObj, next) {
// pass null as the first argument to indicate that the source is not rejected
next(null, srcObj);
},
callPlay: function() {
// Terminate by returning the middleware terminator
return videojs.middleware.TERMINATOR;
},
play: function(terminated, value) {
// the terminated argument should be true here.
if (terminated) {
console.log('The play was middleware terminated.');
}
}
};
};
videojs.use('*', myMiddleware);
```
This middleware always terminates calls to `play()` by returning the `TERMINATOR` in `callPlay`. In `play` we are able to see that the call to `play()` was terminated and was never called on the `Tech`.