なでしこv3ブラウザ版で動画を扱う

[以前](https://qiita.com/oza-jv/items/2552bee6774e325b2889)作ったプラグイン試作バージョン[plugin_media.js](https://oza-jv.github.io/plugin_media.js)には，動画を扱う命令も作ってあるので，今回はそれのまとめを書きたいと思います。

この記事は、なでしこのv3ブラウザ版で実行できるようにしています。

# v3ブラウザ版で動画ファイルを表示したい

以下に，自分が悩んだ経過をまとめていますが，[完成したテストプログラムはここ](https://oza-jv.github.io/sample-movie.html)に置いておきます。読込に少し時間がかかると思いますが，２種類の動画が表示されたら，ボタンを押してみてください。

> ![pic1.GIF](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/942750/17b7b94d-80a8-5eb2-2803-f8cbe64f15ce.gif)

# 動画ファイルを再生する

## フォルダとファイルの準備

まず，自分のPC上（WindwosでもChromebookでも同じです）に，プログラムを保存するためのフォルダを作ります。
その中に，HTMLファイル，画像ファイル，プラグインファイル(試作バージョン[plugin_media.js](https://oza-jv.github.io/plugin_media.js))を入れておきます。
詳細は[以前](https://qiita.com/oza-jv/items/2552bee6774e325b2889)と同じです。

## plugin_media(試作)の動画関連部分

今回作った命令は`動画読込`，`動画追加`，`動画再生`，`動画停止`，`動画再開`，`動画音オン`，`動画音オフ`の7つです。実は[以前](https://qiita.com/oza-jv/items/2552bee6774e325b2889)作った音関連のルーチンを，video要素用に修正した程度です。

```plugin_media.js
// 今回のサンプルに関係する部分のみ抜き出しています。

const PluginMedia = {
  // --- 動画関係 ---
  '動画読込': { // @id=aIDのvideo要素にaSrcファイルを読み込む // @ドウガヨミコミ
    // あらかじめvideo要素を設置しておく場合はこっち。
    type: 'func',
    josi: [['に'],['を']],
    fn: function (aID, aSrc, sys) {
      try {
        const video = document.querySelector("#" + aID);
        video.playsinline = true;
        video.muted = true;
        video.src = aSrc;
      } catch(e) {
	    // エラーを表示
	    window.alert('動画読込 ' + e.message);
	    return -1;
      }
    }
  },

  '動画追加': { // @video要素を追加して，aSrcファイルを読み込む // @ドウガツイカ
    // aIDを指定するとそれを親要素とする。省略するとdefault親要素の子要素として追加。
    // 生成されたid名を返す。
    type: 'func',
    josi: [['を'],['へ', 'に']],
    isVariableJosi: true,
    return_none: true,
    fn: function (aSrc, ...pID) {
      try {
	      const sys = pID.pop();
	      var parent = sys.__v0['DOM親要素'];
	      if ( pID.length > 0 ) {
	        parent = document.querySelector("#" + pID[0]);
	      };
	      const video = document.createElement('video');
	      video.src = aSrc;
	      video.id = 'nadesi-dom-' + sys.__v0['DOM生成個数'];
	      video.width = '320';
	      video.controls = false;
	      video.playsinline = true;
              video.muted = true;
	      parent.appendChild(video);
	      sys.__v0['DOM生成個数']++;
	      return video.id;
	  } catch(e) {
		// エラーを表示
	    window.alert('動画追加 ' + e.message);
	    return -1;
	  }
    }
  },

  '動画再生': { // @id=aIDのvideo要素に設定されている動画を頭から再生する // @ドウガサイセイ
    type: 'func',
    josi: [['を']],
    fn: function (aID, sys) {
      try {
        const video = document.querySelector("#" + aID);
        video.currentTime = 0;
        video.play();
      } catch(e) {
        // エラーを表示
        window.alert('動画再生 ' + e.message);
        return -1;
      }
    }
  },
  
  '動画停止': { // @id=aIDのvideo要素に設定されている動画を一時停止する // @ドウガテイシ
    type: 'func',
    josi: [['を']],
    fn: function (aID, sys) {
      try {
        const video = document.querySelector("#" + aID);
        video.pause();
      } catch(e) {
        // エラーを表示
        window.alert('動画停止 ' + e.message);
        return -1;
      }
    }
  },

  '動画再開': { // @id=aIDのvideo要素に設定されている動画を停止位置から再生する // @ドウガサイカイ
    type: 'func',
    josi: [['を']],
    fn: function (aID, sys) {
      try {
        const video = document.querySelector("#" + aID);
        video.play();
      } catch(e) {
        // エラーを表示
        window.alert('動画再開 ' + e.message);
        return -1;
      }
    }
  },

  '動画音オン': {
    type: 'func',
    josi: [['の']],
    fn: function (aID, sys) {
      const video = document.querySelector("#" + aID);
      video.muted = false;
    }
  },

  '動画音オフ': {
    type: 'func',
    josi: [['の']],
    fn: function (aID, sys) {
      const video = document.querySelector("#" + aID);
      video.muted = true;
    }
  }
}

// モジュールのエクスポート(必ず必要)
if (typeof module !== 'undefined' && module.exports) {
  module.exports = PluginMedia
}
//プラグインの自動登録
if (typeof (navigator) === 'object') {
  navigator.nako3.addPluginObject('PluginMedia', PluginMedia)
}
```

`「(ID名)」に「(ファイル名)」に動画読込`とすると，すでに存在するvideo要素(指定したID名のもの)に動画ファイルを読み込みます。

`ID=「(ファイル名)」を動画追加`とすると，video要素を新たに追加して，ファイル名にある画像を表示します。その時，video要素に付けたIDの文字列を戻り値として返します。これを，変数に保存しておくと，その位置の動画を後で別ファイルに切り換えることができます。

`動画音オン`と`動画音オフ`については，動画の音が出ない問題があったので作成しました。これは別の記事で説明します。

## 動画を扱うプログラム例(HTML+なでしこ)

次のサンプルは，ボタンを押すと動画の再生・停止・再開と，動画の切り替えができます。

```sample-movie.html
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <title>なでしこ　動画読込のテスト</title>
</head>

<body>
<h1>なでしこ３ブラウザ版で動画を扱うテスト</h1>

<div>↓★あらかじめ埋め込んだvideo要素 id=video1</div>
<video id="video1" width="320"></video>
<hr />
<div>↓プラグインで定義した命令で追加していくエリア id=div1</div>
<div id="div1"></div>

<!-- なでしこ3のエンジンを取り込み -->
<script type="text/javascript" src="https://nadesi.com/v3/cdn.php?v=3.1.8&f=release/wnako3.js&run"></script>
<!-- プラグインを取り込み -->
<script type="text/javascript" src="plugin_media.js"></script>

<!-- なでしこのプログラム -->
<script type="なでしこ">
// 初期設定 -- HTML内でなでしこを使うときは必ず実行する
結果領域＝「#div1」。
結果領域へDOM親要素設定。結果領域に「」をHTML設定。

// 定数の定義と初期設定
埋込動画ID＝「video1」。  // あらかじめ埋め込んだvideo要素のID
埋込動画IDの動画音オン。
Ｆ１＝「test1.mp4」。
Ｆ２＝「test2.mp4」。

// あらかじめ埋め込んだvideo要素に動画を読み込む
埋込動画IDにＦ１を動画読込。  // #1
ＦＮ＝１。

// コントロールボタンの設置
ボタン１＝「★の動画を再生」のボタン作成。
ボタン１をクリックした時には
　　埋込動画IDを動画再生。
ここまで。

ボタン２＝「★の動画を停止」のボタン作成。
ボタン２をクリックした時には
　　埋込動画IDを動画停止。
ここまで。

ボタン３＝「★の動画を再開」のボタン作成。
ボタン３をクリックした時には
　　埋込動画IDを動画再開。
ここまで。

ボタン４＝「★の動画を変更」のボタン作成。
ボタン４をクリックした時には
　　もし、ＦＮ＝１ならば、
　　　　ＦＮ＝２。
　　　　埋込動画IDにＦ２を動画読込。
　　違えば
　　　　ＦＮ＝１。
　　　　埋込動画IDにＦ１を動画読込。
　　ここまで。
ここまで。
改行作成。改行作成。


// video要素を動的に追加する。
動的動画ID＝Ｆ２を動画追加。  // #2
動的動画IDの動画音オン。
改行作成。
「▲この動画のID={動的動画ID}」を書く。
ＦＮＮ＝２。

// コントロールボタンの設置
ボタン５＝「▲の動画を再生」のボタン作成。
ボタン５をクリックした時には
　　動的動画IDを動画再生。
ここまで。

ボタン６＝「▲の動画を停止」のボタン作成。
ボタン６をクリックした時には
　　動的動画IDを動画停止。
ここまで。

ボタン７＝「▲の動画を再開」のボタン作成。
ボタン７をクリックした時には
　　動的動画IDを動画再開。
ここまで。

ボタン８＝「▲の動画を変更」のボタン作成。
ボタン８をクリックした時には
　　もし、ＦＮＮ＝１ならば、
　　　　ＦＮＮ＝２。
　　　　動的動画IDにＦ２を動画読込。
　　違えば
　　　　ＦＮＮ＝１。
　　　　動的動画IDにＦ１を動画読込。
　　ここまで。
ここまで。

</script>
</body></html>
```

ここまで作って，[HTMLファイルをブラウザで開く](https://oza-jv.github.io/sample-movie.html)と，サンプルが開きます。ボタンを押して動画を切り替えられるので，自分では満足！

**#1**では，`<id名>に<ファイル名>を動画読込`と書いています。あらかじめ組み込んでいる`id=video1`のvideo要素に，ファイル名を設定しています。ローカルで作っている場合，ファイル名には`file:///d:/xxx.mp4`形式も使えます（やった！）。

**#2**のように，`<ファイル名>を動画追加`と書いた場合は，なでしこ側で「DOM親要素設定」しているidの子要素としてvideo要素を追加します。`<親id>へ<ファイル名>を絵追加`とすると，親IDの子要素としてvideo要素を追加し，指定したファイルを読み込みます。戻り値は，追加されたvideo要素に付されたIDです。

# まとめ

## プラグイン完成した！…のか？

これで，なんとか音声，静止画，動画を「なでしこv3ブラウザ版」で利用できるようになりました。ChromeBookでも使えるので，プログラミングでマルチメディアを扱う勉強がしやすくなるといいな。
しかし，動画の音が出ないという問題が発生したので，それはまた別の記事に整理します。

## テンプレ

次のリンクを右クリックして「リンク先を保存」して、ご活用ください。

- HTMLでなでしこを使うためのテンプレ [template.html](https://oza-jv.github.io/template.html)
- [plugin_media.js](https://oza-jv.github.io/plugin_media.js)

## サンプル

- [音関連のテスト](https://oza-jv.github.io/sample-audio.html)
- [画像関連のテスト](https://oza-jv.github.io/sample-pic.html)
- [動画関連のテスト](https://oza-jv.github.io/sample-movie.html)

## 参考

- なでしこv3 [ユーザープラグイン](https://nadesi.com/v3/doc/index.php?%E3%83%A6%E3%83%BC%E3%82%B6%E3%83%BC%E3%83%97%E3%83%A9%E3%82%B0%E3%82%A4%E3%83%B3&show)
- [プラグインAPIの仕様](https://github.com/kujirahand/nadesiko3/blob/master/doc/plugins.md)