ミドルウェアは、バージョン6.0でVideo.jsに搭載されるクールな新機能のひとつだ。
ミドルウェアを使用することで、プレーヤーとテックがどのように対話するかを変更することができます。テックは、Video.js がプレーヤーから抽象化したもので、プレーヤー API と再生技術を分離しています。テクニカルを使用すると、外部 API やプレーヤーのルックアンドフィールを変更することなく、Video.js に Flash フォールバックや Youtube 埋め込みなどをプラグインできます。
Video.jsミドルウェアはExpressミドルウェアに似ているが、ルートはビデオのMIMEタイプに基づいている。
Video.jsのユーザーの多くは、Expressのようなプロジェクトのミドルウェアになじみがあるかもしれない。Video.jsのミドルウェアは、それらとそれほど違いはない。どちらの場合も、特定のルートに対してミドルウェアを登録し、ルートがトリガーされたときにチェーンを呼び出します。Expressでは、ルートはURLパスに基づいています。Video.jsでは、これらのルートは動画のMIMEタイプに基づいている。また、Expressと同様に、「スター」(*
)のミドルウェアは、すべてのルートにマッチする。
ミドルウェアには2つの重要なポイントがある:
- ダイナミックなソース処理
- 選手と技術の相互作用を遮断する
ビデオカタログ
動的なソース処理を使えば、カスタム・タイプとソースでビデオをロードし、それを非同期で解決することができる。この良い例は、ビデオ・カタログ・システムである。特定のカタログ ID と特殊な MIME タイプを使用して、次のようにページをレンダリングすることができる:
<video controls class="video-js">
<source src="123" type="video/my-catalog">
</video>
そして、そのルート用のミドルウェアを登録することができます。 video/my-catalog
.
// middleware methods get the player instance as an argument
videojs.use('video/my-catalog', function(player) {
// middleware are expected to return an object with the methods on it.
// It can be a plain object or an instance of something.
return {
// setSource allows you to tell Video.js whether you're going to be handling the source or not
setSource(srcObj, next) {
const id = srcObj.src;
videojs.xhr({
uri: '/getVideo?id=' + id
}, function(err, res, body) {
// pass null as the first argument to say everything is going fine and we can handle it.
next(null, {
src: body.sourceUrl,
type: body.sourceType
})
});
}
};
});
その後、Video.jsが初期化されると、以下のように設定されたミドルウェアを呼び出す。 video/my-catalog
.
サーバーサイド広告挿入
サーバーサイド広告挿入(SSAI)はミドルウェアに最適です。これは、再生と技術的なインタラクションをインターセプトする能力を示している。例えば、HLSマニフェストに30秒の広告と5分の動画があるとします。タイムラインに、広告の時間とコンテンツの時間を表示したい。現在、表示される時間は、5分と30秒を合わせた時間になります (5:30
).解決策は、広告が再生されているときに、再生時間が30秒であることをプレーヤーに伝え、コンテンツが再生されているときに、再生時間が5分であることをプレーヤーに伝えるミドルウェアを追加することである。
// register a star-middleware because HLS has two mimetypes
videojs.use('*', function(player) {
return {
setSource(srcObj, next) {
const type = srcObj.type;
if (type !== 'application/x-mpegurl' && type !== 'application/vnd.apple.mpegurl') {
// call next with an error to signal you cannot handle the source
next(new Error('Source is not an HLS source'));
} else {
// in here we know we're playing back an HLS source.
// We don't want to do anything special for it, so, pass along the source along with a null.
next(null, srcObj);
}
},
// this method gets called on the tech and then up the middleware chain providing the values as you go along
duration(durationFromTech) {
if (areWeCurrentlyPlayingAnAd(durationFromTech)) {
// since we're now in an ad, return the ad duration
// in a real example you'd calculate this based on your playlist
// rather than hardcode a value in here
return 30;
} else {
// we're playing back content, so, return that duration
return 5 * 60;
}
}
}
});
プレイバックレートの調整 - ケーススタディ
シンプルだが興味深いミドルウェアとして、プレイバックレート・アジャスターがある。このミドルウェアは、現在のレートに応じてコントロールの時間を変更する。例えば、20分のビデオを再生しているときにレートを2倍に変更すると、コントロールは10分を表示するように調整される。コードを見てみよう。
videojs.use('*', function(player) {
/* ... */
return {
setSource(srcObj, next) {
next(null, srcObj);
},
duration(dur) {
return dur / player.playbackRate();
},
/* ... */
};
});
そこで、ここでは、MIMEタイプに関係なく、どんな動画にも適用できるようにしたいので、スター・ミドルウェアを添付している。つまり setSource
と呼ぶ。 next
直接 null
そして srcObj
というのも、このミドルウェアをあらゆるソースで使いたいからだ。また duration
メソッドを使って、前のミドルウェアからデュレーションを受け取り、プレーヤーから得た再生レートで割る。
を見ると コード を見ると、durationの隣に他のメソッドがいくつかあるのがわかる。これは、タイミングに依存する他のメソッドが更新されるようにするためのものだ。注目すべき2つのメソッドは currentTime
& setCurrentTime
. currentTime
は、現在時刻を知りたいときに呼び出される。 setCurrentTime
が呼び出される。ユーザーはシフトされた時間でシークしているので、変更操作を逆に適用したい。分割するのではなく、乗算するのだ。
currentTime(ct) {
return ct / player.playbackRate();
},
setCurrentTime(ct) {
return ct * player.playbackRate();
},
ここまでの内容を適用してみると、何も変わらず、コントロール・バーには20分と表示されたままであることに気づくだろう。これは、Video.jsが知る限り、何も変わっていないからです。そこで、Video.jsにデュレーションが変更されたことを伝える必要がある。ソースの選択が完了した後にVideo.jsが表示するテックを保存することで、それを行うことができる。
videojs.use('*', function(player) {
let tech;
return {
setTech(newTech) {
tech = newTech;
}
/* ... */
};
});
そして ratechange
イベントがトリガーされると、Video.jsに持続時間が変更されたことを伝え、Video.jsはそれに応じてコントロールを更新します:
videojs.use('*', function(player) {
let tech;
player.on('ratechange', function() {
tech.trigger('durationchange');
tech.trigger('timeupdate');
});
return {
/* ... */
}
});
これはもともとVideo.jsブログに投稿されたものです。