こんにちは、エンジニアの永井です。
video.jsを利用する機会がありましたが、古いバージョンの情報が多く、実装に苦労したので記事にしていきます。
環境
react: 18.2.0
video.js: 8.6.0
実装
公式のサンプルを参考に、TypeScript化して実装します。
import { FC, useEffect, useRef } from 'react';
import videojs from 'video.js';
import Player from 'video.js/dist/types/player';
import 'video.js/dist/video-js.css';
type Props = {
/**
* 動画のURL、またはURLの配列
*/
sources: string | { src: string; type: string }[];
/**
* 動画の設定
*/
options?: {
/**
* 自動再生を有効にするか
* @default false
*/
autoplay?: boolean;
/**
* 動画の制御を可能にするか
* @default false
*/
controls?: boolean;
};
/**
* プレーヤーが準備完了した時に呼び出されるコールバック
*/
onReady?: (player?: Player) => void;
};
export const VideoJsPlayer: FC<Props> = ({ sources, options, onReady }) => {
const videoRef = useRef<HTMLVideoElement>(null);
useEffect(() => {
const video = videoRef.current;
if (!video) return;
const videojsOptions = { sources, ...options };
const player = videojs(video, videojsOptions);
player.on('ready', () => onReady?.(player));
return () => {
if (player) player.dispose();
};
}, []);
return (
<div data-vjs-player>
{/* クラス名の`video-js`は、video-js.cssのスタイルを適用するために必要 */}
<video ref={videoRef} className="video-js" />
</div>
);
};
解説
video.jsを使うには、videojs
の関数をインポートして実行します。実行には第一引数に video要素のID or video要素 が必要です。第一引数以外は必須ではないですが、オプションや準備完了時のコールバックも設定可能です。
/node_modules/video.js/dist/types/video.d.ts
declare function videojs(id: string | Element, options?: any, ready?: ReadyCallback): Player;
video要素の定義
基本的にID指定ではなく、video要素を定義して渡した方がいいです。
同じ画面に複数表示する場合、IDが重複してしまう可能性があるためです。
オプションの定義
オプションは必要に応じてPropsに定義します。video.js 8.0.0 から型定義がパッケージに含まれるようになりましたが、オプションはany
で定義されているので自前で用意する必要があります。
@types/videojs
という型定義のパッケージもありますが、8.xには対応していないので使用できません。こちらにはvideojs.PlayerOptions
が用意されていたので、わざわざ自前で用意する必要はありませんでした。。(改悪)
今回の実装例ではautoplay
、controls
を定義していますが、他にもオプションはたくさんあります。こちらに載っているので必要なものは追加してください。
スタイルの指定
video.js/dist/video-js.css
のインポートが必要なのと、video要素のクラス名にvideo-js
の設定が必要です。設定しないとvideo.jsのスタイルが当たらないので、見た目が崩れてしまいます。
独自のスタイルに変えたい場合は、video.jsで生成されるDOMのクラス名に対してスタイルを当てて上書きします。
まとめ
video.js 8.x台の使用方法を紹介しました。@types/videojs
が使えなくなったのがすごい不便ですが、今後のバージョンアップで整備されることに期待です。