Video.js を使おうと思って、 Vue.js (3.2) + TypeScript の環境でうまく使えるものがないかなと探していました。結果は見つけられずだったので、自分で基本となる部分を書いてみました。
サンプルコード
今回作成したコード一式は、GitHub リポジトリで公開しています。このまま多くの人が使えるものというわけではなく、ここから始めて好きな状態に組み上げるというのを想定しています。
背景など
動画を再生するのに Video.js を使用するというのは割と定番のようなので、それを使いたかったというのがあります。また、チュートリアルや videojs-vue/player というものなども読んだのですが、私の環境では期待する状況ではなかったのです。
実現しておきたかったこととしては、 TypeScript で記述できること、Vue.js 3.x 系列の Composition API を使ったもので記述できていること、という点です。実際の動作という点では、 JavaScript で実装してしまっても全く問題のないことではあるのですが、少しでも慣れている TypeScript にしておきたかったというのがあります。
Vue.js 3.x 系列でも従来のような書き方 (Options API) も使えなくはないみたいですし、無理に Composition API へ変更していく必要は今のところはないのかもしれません。
実装について
詳しくはリポジトリ上のコードを見てもらうのがよいと思います。この分野の実装に慣れているわけではないので、怪しげな部分があるかもしれませんが、シンプルなコードで実現できています。
video.js を扱っている部分を TypeScript で扱っているほか、動画プレイヤーの部分をコンポーネント(SFC) として作成しています。このとき、 Vue3 の Composition API を使うようにしています。
ソース URL 変更の検知について
watch で変更を検知するようにしました。このとき、deep: true によって監視設定することがポイントでした。
- 参考: https://tekrog.com/vue3-watch/ の ネストされたオブジェクトの監視
設定されたソースを変更監視している部分の一例としては、以下の通りです。 一度再生中のものを pause してから切り替えるようにしているのは、 Stack overflow などで類似コードを見かけたためです。
watch(
() => props.options?.sources,
(newSources, _ ) => {
videoJsPlayer.pause();
videoJsPlayer.src( newSources );
videoJsPlayer.play();
},
{
deep: true
}
);
時刻表示関連について
現在も残る課題の1つですが、使用した video.js のバージョンに由来するのか、再生時間・総時間などの情報をコントロール部分に表示させることが標準状態ではできませんでした。scoped css の部分でなんとかやりたかったですが、それでも実現できずでした。
仕方ないので、グローバルに css を以下のように書き換えることで時間情報の表示ができるようになりました。
.video-js .vjs-current-time,
.video-js .vjs-time-divider,
.video-js .vjs-duration {
/* この設定をグローバルで適用しないと時間情報が表示されない */
display: block !important;
}
他のハマり事
Vue.js のプロジェクト生成で作成されるスタイルシートとの組み合わせが悪く、 video.js の各種コントロールの描画位置がずれました。今回は標準生成されたものはすべて削除して、 Vuetify によるレイアウト・スタイルを適用してみました。今のところは問題ないようです。
コメント