kintoneに乗るっ!

非エンジニアが勉強がてら kintone で遊ぶブログ

kintoneに添付した動画ファイルをレコード詳細画面で再生しよう!

f:id:ibukintone:20210603214710p:plain

今日は2021年のエアコン初めでした、いぶろぐです。

cybozu developer networkにはさまざまなTipsが用意されているのですが、 意外とカバーされていないのが"添付ファイルの動画再生"です。

割と簡単なカスタマイズで実現できるので、やっていきましょう。

やりたいこと

通常、kintoneに添付した動画を再生する場合は、いったんローカルにファイルをダウンロードし、動画再生ソフトで再生する必要があります。

これを、レコード詳細画面で直接再生しようぜ!というお話です。

f:id:ibukintone:20210603210952p:plain

アプリ作成

まずはkintoneのアプリを作りましょう。こんな感じで、スペースフィールドと添付ファイルフィールドを配置しておきます。

f:id:ibukintone:20210603210522p:plain

アプリを作成できたら、レコード追加画面で添付ファイルとして動画をアップロード。アップロードできる動画のデータサイズは最大1GBなので、割と余裕あります。

f:id:ibukintone:20210603211232p:plain

コードを書き書き

ここからはカスタマイズとして適用するJavaScriptを書いていきます。

レコード詳細画面が開いたタイミングで処理を行いたいので、イベントはapp.record.detail.showですね。

   kintone.events.on('app.record.detail.show', event => {

イベントオブジェクトから添付ファイルのファイルキーを取得し、kintone.api.urlと組み合わせて添付ファイルをダウンロードするためのURLを生成します。

    const key = event.record['video'].value[0].fileKey;
    const apiUrl = kintone.api.url('/k/v1/file.json') + `?fileKey=${key}`;

cybozu developer networkでは添付ファイルの取得にXMLHttpRequestを利用していますが、そのままでは面白くないので、今回はfetchを使いましょう。 fetchXMLHttpRequestと同じくHTTPリクエストを発行するAPIですが、より「シンプルでモダン」らしいです。 qiita.com

fetchを使って添付ファイルを取得するコードはこんな感じ。非同期関数を定義していろいろやります。

    const playVideo = async (apiUrl, el) => {
      const response = await fetch(apiUrl, {
        headers: {
          'X-Requested-With': 'XMLHttpRequest' 
        }
      });
      const blob = await response.blob();

ブラウザのメモリに保存されたファイルのURLを生成して...

      const url = window.URL || window.webkitURL;
      const blobUrl = url.createObjectURL(blob);

videoタグのel要素に動画の保存先や自動再生プロパティを指定して、非同期関数のコーディングは終わり。なぜこのタイミングで要素のプロパティを指定するのかは後ほど説明します。

      el.src = blobUrl;
      el.autoplay = true;
    }

非同期関数を定義したあとは、スペースフィールドの要素を取得して、videoタグの要素を生成し、プロパティを設定して、スペースフィールドの子要素として追加するコードを書きます。

    const space = kintone.app.record.getSpaceElement('space');
    const el = document.createElement('video');
    el.controls = true;
    el.width = 500;
    space.appendChild(el);

定義しておいた非同期関数にkintone.api.urlで生成したURLと先ほど生成した要素を渡して実行すれば、コードの完成!

    playVideo(apiUrl, el);

コード全体はこんな感じになります。

(function() {
    "use strict";

    kintone.events.on('app.record.detail.show', event => {
    const key = event.record['video'].value[0].fileKey;
    const apiUrl = kintone.api.url('/k/v1/file.json') + `?fileKey=${key}`;
    
    const playVideo = async (apiUrl, el) => {
      const response = await fetch(apiUrl, {
        headers: {
          'X-Requested-With': 'XMLHttpRequest' 
        }
      });
      const blob = await response.blob();

      const url = window.URL || window.webkitURL;
      const blobUrl = url.createObjectURL(blob);

      el.src = blobUrl;
      el.autoplay = true;
    }
    
    const space = kintone.app.record.getSpaceElement('space');
    const el = document.createElement('video');
    el.controls = true;
    el.width = 500;
    space.appendChild(el);
    
    playVideo(apiUrl, el);
  });
})();

要素の生成などをplayVideo関数の中でやってしまうと、動画の読み込みが完了するまで動画プレイヤーが表示されず、読み込み後に画面がズレてしまいます。 videoタグの要素を描画した上でplayVideo関数を実行し、動画の保存先を指定することで、ズレを防げるわけですね。

非公開なウェブサイトなので関係ありませんが、Googleのウェブサイト評価指標のCLSに関係があるのかな?

あと、もっと真面目にコードを書くなら、メモリに保存したファイルを解放するrevokeObjectURL()をいい感じに実行する必要があると思います。

動作確認

記述したJavaScriptをkintoneのアプリに適用し、レコード一覧画面からレコード詳細画面を開くと...

f:id:ibukintone:20210603214724p:plain

やったぜ。

f:id:ibukintone:20210603214710p:plain

動画再生カスタマイズはけっこう需要あるんじゃないでしょうか!

今回は動画再生だけでしたが、いずれはもうちょっと「面白く」動画を再生する方法を紹介予定ですので、お楽しみに^^