LoginSignup
4

More than 1 year has passed since last update.

はじめに

前回、「Web Video Player, VideoJSの紹介」を投稿しました。
今回はVideoJS内部Componentという解釈と簡単の作成チュートリアルを記事したいと思います。

VideoJS Componentとは

VideoJSにある、全部のコントロールやUIなどはComponentというからクラス継承されています。
デフォルトの設計でComponentを継承して、さまさまのComponentを作成しました。

Player
├── MediaLoader (has no DOM element)
├── PosterImage
├── TextTrackDisplay
├── LoadingSpinner
├── BigPlayButton
├── LiveTracker (has no DOM element)
├─┬ ControlBar
│ ├── PlayToggle
│ ├── VolumePanel
│ ├── CurrentTimeDisplay (hidden by default)
│ ├── TimeDivider (hidden by default)
│ ├── DurationDisplay (hidden by default)
│ ├─┬ ProgressControl (hidden during live playback, except when liveui: true)
│ │ └─┬ SeekBar
│ │   ├── LoadProgressBar
│ │   ├── MouseTimeDisplay
│ │   └── PlayProgressBar
│ ├── LiveDisplay (hidden during VOD playback)
│ ├── SeekToLive (hidden during VOD playback)
│ ├── RemainingTimeDisplay
│ ├── CustomControlSpacer (has no UI)
│ ├── PlaybackRateMenuButton (hidden, unless playback tech supports rate changes)
│ ├── ChaptersButton (hidden, unless there are relevant tracks)
│ ├── DescriptionsButton (hidden, unless there are relevant tracks)
│ ├── SubtitlesButton (hidden, unless there are relevant tracks)
│ ├── CaptionsButton (hidden, unless there are relevant tracks)
│ ├── SubsCapsButton (hidden, unless there are relevant tracks)
│ ├── AudioTrackButton (hidden, unless there are relevant tracks)
│ ├── PictureInPictureToggle
│ └── FullscreenToggle
├── ErrorDisplay (hidden, until there is an error)
├── TextTrackSettings
└── ResizeManager (hidden)

目標

VideoJS ControlBarにあるCustomButton Componentというボタンを付属して、
そのボタンを押すと外部関数を走るようにします。

このようなのものです

example.gif

Github Repo: https://github.com/tokidoki11/video-js-component
このRepoではNuxtJSを使っていますが、NuxtJS知識は要りません。
本記事ではVideoJS Componentを中心にして、そのことだけを記事します。

実践

CustomButton作成

以下のコードご覧ください。解釈は後につけています

import videojs, { VideoJsPlayer, VideoJsPlayerOptions } from 'video.js'
const Button = videojs.getComponent('Button')


const iconSVG = `
<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" fill="currentColor" viewBox="0 0 20 16">
<path d="M17.218,2.268L2.477,8.388C2.13,8.535,2.164,9.05,2.542,9.134L9.33,10.67l1.535,6.787c0.083,0.377,0.602,0.415,0.745,0.065l6.123-14.74C17.866,2.46,17.539,2.134,17.218,2.268 M3.92,8.641l11.772-4.89L9.535,9.909L3.92,8.641z M11.358,16.078l-1.268-5.613l6.157-6.157L11.358,16.078z"></path>
</svg>
`

interface CustomButtonOption extends VideoJsPlayerOptions{
  onClick: () => void
}

export default class CustomButton extends Button {
  constructor(
    player: VideoJsPlayer,
    options: CustomButtonOption
  ) {
    super(player, options)
    this.controlText("My Custom Button")
    this.el().innerHTML = iconSVG
  }

  handleClick(){
    (this.options_ as CustomButtonOption).onClick()
  }

  createEl(): HTMLButtonElement {
    return super.createEl('button', {
      className: 'vjs-custom'
    })
  }
}

解釈

1. Extending Button Component

今回はButtonComponentをもとに自作CustomButton Componentを作成します。
videojs.getComponentにComponent名を指定したら、Class Templateを取得します。

const Button = videojs.getComponent('Button')

取得してからベースクラスにして、継承を行います。

export default class CustomButton extends Button

2. Optionを展開する

基本的にはComponentをextendする時には2つの引数が示さなければなりません。
VideoJSPlayerとVideoJSOption。VideoJSOptionを展開して、onClick関数をもらえるようにします。

interface CustomButtonOption extends VideoJsPlayerOptions{
  onClick: () => void
}
constructor(
    player: VideoJsPlayer,
    options: CustomButtonOption
  )

handleClick関数をオーバーライドして、optionにあるonClickを実行するように

handleClick(){
    (this.options_ as CustomButtonOption).onClick()
}

3. Styling

Elementを作成します、createEl関数にParent ClassのcreateElを実行して。
<button class="vjs-custom"></button>が作成されるように

  createEl(): HTMLButtonElement {
    return super.createEl('button', {
      className: 'vjs-custom'
    })
  }

SVGアイコンを用意します

const iconSVG = `
<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" fill="currentColor" viewBox="0 0 20 16">
<path d="M17.218,2.268L2.477,8.388C2.13,8.535,2.164,9.05,2.542,9.134L9.33,10.67l1.535,6.787c0.083,0.377,0.602,0.415,0.745,0.065l6.123-14.74C17.866,2.46,17.539,2.134,17.218,2.268 M3.92,8.641l11.772-4.89L9.535,9.909L3.92,8.641z M11.358,16.078l-1.268-5.613l6.157-6.157L11.358,16.078z"></path>
</svg>`

文言とSVGアイコンをボタンにつけます

constructor(
    player: VideoJsPlayer,
    options: CustomButtonOption
  ) {
    super(player, options)
    this.controlText("My Custom Button") //これはボタンTitleです
    this.el().innerHTML = iconSVG //ボタンElementのなかにSVGを付属する
  }

VideoJSにつけたあるCustomButtonを作成

以下のコードご覧ください。解釈は後につけています

<template>
  <div id="video-player-component">
    <h1>I'm counting: {{count}}</h1>
    <video
      ref="videoPlayer"
      class="video-js vjs-show-big-play-button-on-pause vjs-big-play-centered"
      muted
    />
  </div>
</template>

<script lang="ts">
import Vue from 'vue'
import videojs, { VideoJsPlayerOptions } from 'video.js'
import CustomButton from '@/video-components/customButton'

videojs.registerComponent('CustomButton', CustomButton)

const videoConfig = {
  autoplay: true,
  controls: true,
  html5: {
    vhs: {
      allowSeeksWithinUnsafeLiveWindow: true,
      enableLowInitialPlaylist: true,
      overrideNative: false,
      smoothQualityChange: true,
      withCredentials: false
    }
  },
  inactivityTimeout: 0,
  sources: [{
    src: "https://live.unified-streaming.com/scte35/scte35.isml/.m3u8",
    type: 'application/x-mpegURL'
  }],
  liveui: true,
  muted: true,
  preload: 'auto',
  width:720
} as VideoJsPlayerOptions

export default Vue.extend({
  data:()=>{
    return {
      count : 0
    }
  },
  mounted(){
    const videoPlayer = this.$refs["videoPlayer"]
    const player = videojs(videoPlayer, videoConfig, ()=>{
      player.controlBar.addChild("CustomButton", {
        onClick:()=>{
          this.count++
        }
      })
    })
  }
})
</script>
<style>
.vjs-custom{
  cursor: pointer;
  font-size: 1.8em!important;
  color:white;
}
</style>

解釈

1. Import CustomButton Class
CustomButtonをImportして

import CustomButton from '@/video-components/customButton'

その後videoJSにComponentを紹介します。
引数1: Component name (好みで)
引数1: Component class

videojs.registerComponent('CustomButton', CustomButton)

2. VideoJS Instanceを作成

 const videoPlayer = this.$refs["videoPlayer"]
 const player = videojs(videoPlayer, videoConfig, ()=>{
 ...

3. VideoJS PlayerのControlBarにCustomButtonを追加

addChild関数には3つの引数を受けます
引数1: Component Name
引数2: Option(今回は CustomButtonOption Interfaceに参考)
引数3: 順番(なければ後ろに)

このonClickではdataにあるcountを加算してます。

player.controlBar.addChild("CustomButton", {
  onClick:()=>{
    this.count++
  }
})

最後

このチュートリアルは終了になります。
色々VideoJS Componentがありまして、Extend方法も多少違っています。
Button ComponentにはhandleClickがありますが、他にはそうでもないでしょう。

基本的には同じ流れになります。

この記事が役に立つなるように

参考に

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
What you can do with signing up
4