浜松のWEBシステム開発・スマートフォンアプリ開発・RTK-GNSS関連の開発はお任せください
株式会社シーポイントラボ
TEL:053-543-9889
営業時間:9:00~18:00(月〜金)
住所:静岡県浜松市中区富塚町1933-1 佐鳴湖パークタウンサウス2F

【JavaScript】動画にチャプターをつける

 HTML には video 要素があり、これは内部に様々な情報を持つことができます。その中にはチャプターについての情報もあり、JavaScript でこれを操作することによって web ページ上で再生する動画にチャプターとチャプターごとのジャンプ機能を付けられます。
<video>: 動画埋め込み要素 – HTML: HyperText Markup Language | MDN
 チャプターを操作する前にチャプターを定義する必要があります。これは vtt (VideoTextTrack)ファイルと vtt ファイルを読み込む track 要素で定義できます。
Web ビデオテキストトラックフォーマット (WebVTT) – Web API | MDN
<track>: 埋め込みテキストトラック要素 – HTML: HyperText Markup Language | MDN

 vtt ファイルは基本的に次の様な簡素なテキストファイルです。

WEBVTT

NOTE チャプター例

00:00:00.000 --> 00:00:30.000
冒頭

00:00:30.000 --> 00:01:00.000
中盤

00:01:00.000 --> 00:01:15.000
終わり

 一行目に WEBVTT と記述して、これが VTT ファイルであると宣言します。部品単位の区切りは空行です。空行で挟まれている部分に”hh:mm:ss.ttt –> hh:mm:ss.ttt”で記述された時間帯とその時間帯に紐づくテキストを記述できます。コメントは NOTE というキーワードを使うことで使えます。詳しくは MDN の次リンク参照です。
Web ビデオテキストトラックフォーマット (WebVTT) – Web API | MDN
 vtt ファイルで特徴的なのはその中身自体では意味付けがなされていない点です。 track 要素で読み込む際、これは○○の vtt ファイル、といった具合に意味付けできます。
 また、ここではチャプターのために vtt ファイルを使うため紹介しませんが字幕も vtt ファイルで定義でき、字幕に対して CSS を適用することができます。

 track 要素は次の様に vtt ファイルを読み込むために用います。
 <track>: 埋め込みテキストトラック要素 – HTML: HyperText Markup Language | MDN

<video controls>
  <source src="/animate_css_anime.mp4" type="video/mp4" />
  <track default kind="chapters" srcLang="ja" src="/example.vtt" />
</video>

 kind 属性でどの様な種別か指定され、この指定によって video 要素の振る舞いが変わります。いくつかのブラウザは JavaScript で特別なことをせずとも track 要素を読んで字幕、キャプションといった機能を web ページ上の動画プレイヤーに自動で追加します。これは例えば、次の様に動作します。

ソースコードを展開
<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="utf-8" />
    <meta
      name="viewport"
      content="width=device-width, initial-scale=1, shrink-to-fit=no"
    />
    <meta name="theme-color" content="#000000" />
    <link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
    <link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico" />
    <title>React App</title>
  </head>

  <body>
    <video controls style="max-width: 500px;">
      <source src="/animate_css_anime.mp4" type="video/mp4" />
      <track
        default
        kind="subtitles"
        label="日本語"
        srclang="ja"
        src="/example.vtt"
      />
    </video>
  </body>
</html>

 この記事を書いている時点では少なくとも Google Chrome, Firefox で字幕を設定できることを確認しています。

 この kind を chapters に変えると、現状のプレイヤーには何も出てこなくなりますが DOM の中にはしっかりと情報が入っています。

 自家製コードでこれを読み取って、ボタンに紐づけて適宜 video.currentTime を変えてチャプタージャンプを実現するのもありですが、いくつかの動画再生用ライブラリはこのチャプター機能をいい感じに実装してくれています。例えば、 Video.js がその一つです。
videojs/video.js: Video.js – open source HTML5 & Flash video player
Video.js – Make your player yours | Video.js
 次のデモは React に Video.js を組み込んでチャプター機能を付けた動画プレイヤーです。

ソースコード

チャプター用 vtt ファイル

WEBVTT

NOTE チャプター例

00:00:00.000 --> 00:00:30.000
冒頭

00:00:30.000 --> 00:01:00.000
中盤

00:01:00.000 --> 00:01:15.000
終わり

React 上の動画プレイヤー

import React from "react";
import videojs, { VideoJsPlayer, VideoJsPlayerOptions } from "video.js";
import "video.js/dist/video-js.css";

type VideoPlayerProps = { options: VideoJsPlayerOptions };
export class VideoPlayer extends React.Component<VideoPlayerProps> {
  public player?: VideoJsPlayer;
  public videoNode?: HTMLVideoElement | null;
  componentDidMount() {
    // Video.jsのインスタンス化
    this.player = videojs(
      this.videoNode,
      this.props.options,
      function onPlayerReady() {
        console.log("onPlayerReady");
      }
    );
  }

  // Video.js の掃除。これをしないと音が鳴りっぱなしになったりも
  componentWillUnmount() {
    if (this.player) {
      this.player.dispose();
    }
  }
  // videojs が DOM に追加のラッパーを作成しないように、
  // `data-vjs-player` 属性でプレーヤーを div でラップします。
  // @see https://github.com/videojs/video.js/pull/3856
  render() {
    return (
      <div>
        <div data-vjs-player>
          <video
            controls
            ref={(node) => (this.videoNode = node)}
            className="video-js"
          >
            {this.props.children}
          </video>
        </div>
      </div>
    );
  }
}

React 上の動画プレイヤーの呼び出し

import * as React from "react";
import "./styles.css";
import { VideoPlayer } from "./VideoPlayer";

export default function App() {
  const player = React.useRef<VideoPlayer>();
  return (
    <div className="App">
      <VideoPlayer ref={player}>
        <source src="/animate_css_anime.mp4" type="video/mp4" />
        <track
          default
          kind="chapters"
          label="チャプター"
          srcLang="ja"
          src="/example.vtt"
        />
      </VideoPlayer>
    </div>
  );
}

 こんな感じで web ページ上の動画に比較的簡単にチャプター機能を付けられます。

  • この記事いいね! (0)