Help us understand the problem. What is going on with this article?

AWS+hls.jsでストリーミング再生(その2)

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

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

条件

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

さっそく

hls.jsのread.meに書いてある通りなのですが(本当にすっごく親切に書いてあります)

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にあげました。

<script src="https://cdn.jsdelivr.net/npm/hls.js@latest"></script>

今回はcdnでhls.jsを読み込みました。

<video id="video" style="display: none;"></video>
<button id="button">play video</button>

videoタグで動画を再生する場所を確保し、
ボタンが押されたら動画を再生するようにしました。
(理由は後述します)

hls.loadSource("動画が保存されているS3バケット/hls_sample/hls_400k_.m3u8");

ここでHLSのプレイリストファイル(.m3u8)を読み込み、

 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のバージョン66以上では、音声付き動画について、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は

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が使えないのは知らなかったので、勉強になりました・・・

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした