AWS+hls.jsでストリーミング再生（その２）

hls.jsを使ってストリーミング再生を試みます。

mp4からHLSに変換するところは[前回の記事](https://qiita.com/spring_i/items/e33896afa27c4391a110)をご覧ください。
この記事ではHLS形式の動画をブラウザからhls.jsを使って再生する部分を書きます。

## 条件
・AWS S3のバケット上にhls形式の動画がある。
・ブラウザはChromeを使用。
・ビデオを再生するフロント部分はfirebaseでデプロイ。

## さっそく
[hls.js](https://github.com/video-dev/hls.js/blob/master/docs/API.md)のread.meに書いてある通りなのですが(本当にすっごく親切に書いてあります)


```html:index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <script src="https://cdn.jsdelivr.net/npm/hls.js@latest"></script>
</head>
<body>
   <video id="video" style="display: none;"></video>
   <button id="button">play video</button>
   <script>
   if (Hls.isSupported()) {
       let video = document.getElementById('video');
       let hls = new Hls();
       // bind them together
       hls.attachMedia(video);
       hls.on(Hls.Events.MEDIA_ATTACHED, function () {
         console.log("video and hls.js are now bound together !");
         hls.loadSource("動画が保存されているS3バケット/hls_sample/hls_400k_.m3u8");
         hls.on(Hls.Events.MANIFEST_PARSED, function (event, data) {
             console.log(data)
           console.log("manifest loaded, found " + data.levels.length + " quality level");
           let fragments = data.levels[0].details.fragments
           let play_time = 0
           for(let i in fragments) {
               console.log(fragments[i]);
               play_time += fragments[i].duration
            }
            console.log("play_time : ",play_time)  
            play_time = Math.floor((play_time*1000)+1000)
            console.log(play_time)        
           button.addEventListener('click', function() {
               video.style.display="block"
               video.muted = false;
               video.play();
               setTimeout(function(){console.log("end")}, play_time);
            });
        })
    })
    }
   </script>   
</body>
</html>
```
こんな感じです。
これをfirebaseにあげました。


```html
<script src="https://cdn.jsdelivr.net/npm/hls.js@latest"></script>
```
今回はcdnでhls.jsを読み込みました。

```html
<video id="video" style="display: none;"></video>
<button id="button">play video</button>
```
videoタグで動画を再生する場所を確保し、
ボタンが押されたら動画を再生するようにしました。
（理由は後述します）

```javascript

hls.loadSource("動画が保存されているS3バケット/hls_sample/hls_400k_.m3u8");
```
ここでHLSのプレイリストファイル（.m3u8）を読み込み、


```javascript
 button.addEventListener('click', function() {
               video.style.display="block"
               video.muted = false;
               video.play();
               setTimeout(function(){console.log("end")}, play_time);
            });
```
ボタンが押された時にvideo.play()で再生しています。
play_timeの時間でタイムアウトを設定しているのは、ちょっと事情があって、動画の再生が終了したことを知りたかったからです・・・

## はまったところ
### Chromeブラウザでautoplayができない・・・？
はじめ、動画は再生されるのに音声が全く再生されず、なんでや・・・？と悩みました。
調べてみたところ、Chromeのバージョン６６以上では、音声付き動画について、videoタグのautoplay属性が無効になるとのこと・・・
確かに、video.mutedをtrueにして、videoタグにautoplayを指定していると、音声なしで再生されます。
FirefoxやIEではこのような問題は起こっていないようなので、Chromeブラウザを使う場合は注意が必要です。

今回はページを読み込んだタイミングでビデオを再生するのではなく、任意のタイミング（ボタンを押した時）に再生したかったので、ボタンを押したタイミングで再生されるようにしました。

### CORSで引っかかる・・・？
（もはやHLSの話ではないので手短に・・・）
S3とfirebaseの両方でCORSの設定が必要でした。
当たり前すぎてこんなことに躓いた自分が恥ずかしい・・・

S3のCORSの設定

```
<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
<CORSRule>
    <AllowedOrigin>*</AllowedOrigin>
    <AllowedMethod>GET</AllowedMethod>
</CORSRule>
</CORSConfiguration>
```
AllowedOriginはワイルドカード（*）ではなく、許可したいものだけ（今回の場合はfirebaseのエンドポイント）にすると良いと思います・・・

firebaseは

```json:firebase.json
      "headers": [ {
        "source" : "**/*.@(eot|otf|ttf|ttc|woff|font.css)",
        "headers" : [ {
          "key" : "Access-Control-Allow-Origin",
          "value" : "*"
        } ]
      }],
```
これを追記します。
headerにCORSの設定を追加します。

## 感想
hls.jsは本当に分かりやすくて使い勝手がいいと思いました。
ドキュメントがとても丁寧:relaxed:
Chromeでautoplayが使えないのは知らなかったので、勉強になりました・・・