react 中使用 video.js

2021/7/31 reactvideo

video.js 是一个比较成熟的 HTML5 视频播放框架,兼容包括桌面和移动端在内的现代浏览器,支持从“传统“的 MP4 和 WebM 到流形式的 HSL 和 DASH 等多种格式播放,不仅提供很多插件去扩展播放器,还可以通过修改 css 方便的去调整样式。

# 安装

可以使用 CDN 或者 NPM 包安装,具体参考 Get Started (opens new window)

npm install --save-dev video.js
1

# 使用

video.js 使用比较简单,直接通过 videojs(id: string | Element, options?: VideoJsPlayerOptions | undefined, ready?: videojs.ReadyCallback | undefined) 形式使用即可。

const player = videojs('my-video', {
  autoplay: 'muted'
});
1
2
3

# react 使用

videojs-react.png

在 react 中使用需要注意一点就是,如果在 useEffect 中创建了播放器,然后在返回值中 dispose 的话会把 video 标签干掉导致报错,因此 tutorial-react (opens new window) 文档中给出的方案是每次创建一个新的 VideoHtml 标签,这样组件刷新的时候就不会报错。

但是在使用过程中会发现一个新的问题,每次任意一个的 options 发生变化都会造成播放器的重新渲染,比如调节一个视频的声音都会让视频重新生成明显是不符合需求的。很显然,我们希望播放器在组件销毁时要 dispose,但是部分属性改变时不应该重新渲染,那就分开在不同的 useEffect 中处理吧。

export const VideoPlayer = (props: VideoPlayerProps) => {
  const { options, width, height, volume = 0, src } = props;

  const videoRef = useRef<HTMLVideoElement>(null);
  const player = useRef<VideoJsPlayer>();

  // 根据options初始化播放器
  useEffect(() => {
    const videoElement = videoRef.current;

    if (videoElement) {
      player.current = videojs(videoElement, options);
    }
    return () => {
      player.current?.dispose();
    };
  }, []);

  // 如果时播放器的src改变了单独处理一下,因此这时候视频会重新开始播放
  useEffect(() => {
    if (src) {
      player.current?.src(src);
    }
  }, [src]);

  // 如果时诸如声音之类的配置改动,直接设置就行,不影响视频播放
  useEffect(() => {
    player.current?.controls(!!options.controls);
    player.current?.autoplay(options.autoplay || false);
    player.current?.loop(!!options.loop);
    player.current?.volume(volume / 100);
  }, [volume, options.autoplay, options.loop, options.controls]);

  return (
    <div data-vjs-player>
      <video
        width={width}
        height={height}
        ref={videoRef}
        className="video-js"
      />
    </div>
  );
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44

# 参数配置

使用 videojs 创建一个播放器很简单,通过配置参数也能很方便的个性化定制播放器,tutorial-options (opens new window) 给出了常见的一些配置项。

{
  // 和video标签类似的选项
  autoplay: false, // 是否自动播放,muted会静音视频然后播放;any是先播放,如果失败了就再静音然后播放
  controls: true, // 是否显示控制工具
  preload: "auto",

  // 下面是一些videojs自己选项
  responsive: true,
  fluid: true, // 自适应宽高
  language: "zh-CN", // 设置语言
  muted: false, // 是否静音
  controlBar: { // 设置控制条组件
    // 使用children的形式可以控制每一个控件的位置,以及显示与否
    children: [
      { name: "playToggle" }, // 播放按钮
      { name: "currentTimeDisplay" }, // 当前已播放时间
      { name: "progressControl" }, // 播放进度条
      { name: "durationDisplay" }, // 总时间
      {
        // 倍数播放
        name: "playbackRateMenuButton",
        playbackRates: [0.5, 1, 1.5, 2, 2.5],
      },
      {
        name: "volumePanel", // 音量控制
        inline: false, // 不使用水平方式,垂直方向的声音
      },
      { name: "FullscreenToggle" }, // 全屏控制
    ],
  },
  sources: [ // 视频源
    {
      src: "http://www.w3school.com.cn/example/html5/mov_bbb.mp4",
      type: "video/mp4",
    },
  ],
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37

上面只是列出了部分常用的配置项,还有很多配置项可以参考官方文档 (opens new window)或者一些中文文档有描述每个选项具体是做什么的。

注意:在当前 7.14.3 版本使用的时候,有一个问题就是配置了 currentTimeDisplay 后发现界面上怎么都不会生效,需要参考这个 issues (opens new window) 通过配置 css 解决

.video-js {
  .vjs-control-bar {
    .vjs-time-control {
      display: block;
    }
    // 顺便改了一下间距
    .vjs-current-time {
      padding-right: 2px;
    }
    .vjs-time-divider {
      padding: 0;
      min-width: auto;
    }
    .vjs-duration {
      padding-left: 2px;
    }
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

# 参考