Webサーバ

HLS(HTTP Live Streaming)で動画を配信・再生してみよう

2017年5月21日

目次Category


やってみよう、入門記事です。

本記事の内容

本記事の内容は以下の通りです。

動画配信の主なキーワード

動画配信技術の中で出てくる主な用語について簡単に説明します。

VOD/LIVE

動画配信サービスの配信形態にはVODとLIVEの2種類があります。
VOD(Video On Demand)は、視聴者が見たい時にコンテンツを見ることのできる形態のサービスです。動画コンテンツがすでに存在する場合の配信形態になります。
LIVEは、ライブストリーミング(デジタルビデオカメラなどからネットワーク上に動画を配信すること)によるリアルタイム動画配信サービスです。

HTTPアダプティブストリーミング

ネットワークの帯域に合わせて最適なビットレートに切り替えて再生できる仕組みで、モバイルでは特に必要とされている技術です。

HLS/MPEG-DASH

動画配信の規格です。現在主流なものとしてHLSとMPEG-DASHがあります。
HLSはApple HTTP Live Streamingの略で、Apple社の独自規格です。
DASHはDynamic Adaptive Streaming over HTTPの略で、ISO(国際標準化機構)の規格です。

JavaScriptライブラリ

HTML5の登場により、特別なプラグインなしでHTML5+JavaScriptによるブラウザでの動画再生が可能になっています。

コーデック

データのエンコード(符号化)とデコード(復号)を双方向にできる装置やソフトウェア、アルゴリズムのことを言います。

CDN

CDN(Contents Delivery Network)とは、Webコンテンツをインターネット経由で配信するために最適化されたネットワークのことです。

デジタル著作権管理(DRM:Digital Rights Management)

デジタルコンテンツの無制限な利用を防ぐための技術です。

HTTP Live Streaming(HLS)とは

HLSはAppleが実装したHTTPベースのメディアストリーミングプロトコルです。
以下のような特長があります。

  • オンデマンド配信(VOD)とライブ配信(LIVE)に対応
  • ビットレートの異なる複数の代替ストリーム(HTTPアダプティブストリーミング)をサポート
    (各帯域幅またはデバイスごとに品質レベルを変えて、同じコンテンツの複数のストリームの配信をサポート)
  • HTTPSを使用したメディアの暗号化とユーザ認証に対応

構成

HLSではインデックスファイル(プレイリスト)と小さく分割したセグメントファイルを配信して動画再生します。
配信リソースは、H.264ビデオ圧縮方式のMPEG-4ビデオ、AACまたはMP3圧縮方式のオーディオファイルから生成できます。

HLS構成図

インデックスファイル(m3u8プレイリスト)

セグメントファイルの場所、再生時間、再生順序などを記述したメタデータファイルです。
拡張子.m3u8インデックスファイルとして保存されます。

メディアセグメントファイル(tsファイル)

MPEG2 Transport Stream形式のコンテナに格納された分割された動画データファイルです。
拡張子.tsメディアファイルとして分割保存されます。
AESによる暗号化が可能です。

※インデックスファイルについて、オンデマンドの場合は全ての動画を含んだ静的なファイル、ライブの場合は指定された時間内に制限されたスライドウインドウ(新しいメディアファイルの作成とともに更新される)として提示されます。

プレイリスト例

インデックスファイル(m3u8プレイリスト)は以下のようになっています。

#EXTM3U
#EXT-X-TARGETDURATION:10
#EXT-X-VERSION:3
#EXT-X-MEDIA-SEQUENCE:0
#EXT-X-PLAYLIST-TYPE:VOD
#EXTINF:9.97663,
media-0.ts
#EXTINF:9.97663,
media-1.ts
#EXTINF:7.10710,
media-2.ts
#EXT-X-ENDLIST

EXTM3U : m3u8形式であることを示しています
EXT-X-TARGETDURATION : 作成される各tsファイルがこの秒数以下であることを示しています(ライブの場合はこの秒数に基づきインデックスファイルが更新されます)
EXT-X-VERSION : m3u8形式のバージョンを示しています
EXT-X-MEDIA-SEQUENCE : 本リストの最初のtsファイルが動画全体の何番目のtsファイルかを示しています
EXT-X-PLAYLIST-TYPE : 配信形式がオンデマンド(VOD)かライブ(EVENT)かを示しています
EXTINF : tsファイルの秒数とファイル名を示しています
EXT-X-ENDLIST : リストの最後であることを示しています

再生デバイス

以下のデバイスや実装などにて再生が可能です。

  • ブラウザ

HLSに対応したブラウザで再生できます。

  • iOS(ネイティブ)

OS標準ライブラリを使用する場合は、AVKitとAVFoundationフレームワークによる再生が可能です。

  • Android(ネイティブ)

OS標準ライブラリを使用する場合は、VideoViewまたはMediaPlayerによる再生が可能です。

インデックスファイルとメディアセグメントファイルの作成

本記事では、Appleから配布されているツールを使用します。
ツールのダウンロードにはApple Developer Programへの登録が必要です。
HLS対応ファイルは、ffmpegツールを使用することでも作成できます。

オンデマンド用のHLSファイルの作成を例に説明します。

ツールのダウンロード

「HTTP Live Streaming Tools」をダウンロードします。

Apple Developerサイトの「HTTP Live Streaming」ページを開きます。
https://developer.apple.com/streaming/

Downloadsから「Sign in」をクリックします。

「HTTP Live Streaming Tools」が表示されます。
dmgファイルをダウンロードしてインストールします。
(HTTPLiveStreamingTools_xxx.dmg)

インストールプログラム

以下のプログラムがインストールされます。

Media Stream Segmenter
Media File Segmenter
Media Subtitle Segmenter
Variant Playlist Creator
Media Stream Validator
HLS Report
ID3 Tag Generator

標準インストール先は以下の通りです。

/usr/local/bin/mediastreamsegmenter
/usr/local/bin/mediafilesegmenter
/usr/local/bin/mediasubtitlesegmenter
/usr/local/bin/variantplaylistcreator
/usr/local/bin/mediastreamvalidator
/usr/local/bin/hlsreport.py
/usr/local/bin/id3taggenerator

コマンドの使い方については以下のコマンドで確認できます。

man mediastreamsegmenter
man mediafilesegmenter
man mediasubtitlesegmenter
man variantplaylistcreator
man mediastreamvalidator
man hlsreport
man id3taggenerator

メディアファイルセグメンター

オンデマンド用のHLSファイルを作成するには「Media File Segmenter(mediastreamsegmenter)」を使用します。
使い方を簡単に説明します。

変換したいメディアファイルが有効なファイルかどうかチェックします。
(mediafilesegmenter -V メディアファイル名)

$ mediafilesegmenter -V originmedia.mp4
originmedia.mp4 can be segmented

メディアファイルからHLSファイルを生成します。
オプション「-B ベースファイル名」を指定することで、プレフィックスの付いた連番ファイルが生成されます。
(mediafilesegmenter -f ファイルベースパス -i インデックスファイル名 -B ベースファイル名 メディアファイル名)

$ mkdir hls
$ mediafilesegmenter -f hls -i index.m3u8 -B media- originmedia.mp4
ls -la hls
total 86320
drwxr-xr-x 7 hls staff 238 4 22 11:43 .
drwxr-xr-x 4 hls staff 136 4 22 11:42 ..
-rw-rw-r-- 1 hls staff 3495 4 22 11:43 iframe_index.m3u8
-rw-r--r-- 1 hls staff 201 4 22 11:43 index.m3u8
-rw-r--r-- 1 hls staff 16522380 4 22 11:43 media-0.ts
-rw-r--r-- 1 hls staff 15999176 4 22 11:43 media-1.ts
-rw-r--r-- 1 hls staff 11657692 4 22 11:43 media-2.ts

コマンドのパラメータについて、詳しくはmanコマンドにて確認できます。

$ man mediafilesegmenter

Webサーバの設定

HLSは通常のWebサーバから配信できます。
HLSファイル一式をサーバに配置、配信されるファイルのMIMEタイプをファイル拡張子に関連付けすれば準備完了です。

ファイル拡張子MIMEタイプ
.m3u8application/vnd.apple.mpegurl
.tsvideo/mp2t

Apacheの場合

「httpd.conf」または「.htaccess」にAddTypeを使用して記述します。

AddType application/vnd.apple.mpegurl .m3u8
AddType video/mp2t .ts

nginxの場合

mime.typesファイルにMIME Typeを指定します。
(mime.typesファイルはnginx.confファイルにincludeでパス指定されています)

types {
    application/vnd.apple.mpegurl m3u8;
    video/mp2t ts;
    ・・・
}

ブラウザによる再生

HTML5の<video>タグを使用した方法を紹介します。
以下のようなHTMLページを作成します。
srcにはインデックスファイルを指定します。

サンプルコード

<!DOCTYPE html>
<html>
<head>
    <title>HTTP Live Streaming Example</title>
</head>
<body>
    <video src="/hls/index.m3u8" width="400" height="300" controls></video>
</body>
</html>

※PC:MacOS Safari10.0で再生確認
(macOS Safari以外では再生しません。再生にはVideo.jsなどのJavaScriptライブラリを用いる必要があります)
※スマホ:Android 6 Chrome57、iOS 10.3 Safariで再生確認

videoタグの属性

src:メディアファイルのURLを指定
controls:プレイヤーのコントローラーを表示するブール属性
poster:プレーヤーに表示するプレースホルダー画像のURLを指定(再生可能なメディアファイルが取得できない場合に表示されます)
loop:ループ再生を指定するためのブール属性
muted:オーディオトラックを含むメディアの場合に音声をオフにするためのブール属性
autoplay:自動的に再生を開始するためのブール属性
preload:ページ表示時にメディアを予め読込むかどうかを指定(auto:事前読込、metadata:メタデータのみ読込、none:読込まない)
width:プレーヤーの幅をピクセル単位で指定
height:プレーヤーの高さをピクセル単位で指定

iOS(ネイティブ)による再生

本記事ではAVKit.framework、AVFoundation.frameworkを用いた動画再生について説明します。
Xcode8.3.2、Swift3.1、iOS Deployment Target10.0で実装しています。

プロジェクトの作成

新規プロジェクトを作成します。
Create a new Xcode projectを選択、iOSのSingle View Applicationを選択します。

今回は、プロダクト名「MyApplication」、Language「Swift」で作成しています。

ViewController.swift

/MyApplication/MyApplication/ViewController.swift

AVKitとAVFoundationをインポートします(Link Binary With Librariesへの追加は不要です)。
ViewControllerの継承元としてAVPlayerViewControllerを指定します。
index.m3u8ファイルまでのURLを変数urlに指定、urlからplayerItemを作成、playerItemからplayerを作成します。
作成したplayerをself(ViewController)のplayerにセットします。

import UIKit
import AVKit
import AVFoundation

class ViewController: AVPlayerViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.

        let url = URL(string: "https://xxx.xxx.xxx/hls/index.m3u8")
        let playerItem = AVPlayerItem(url: url!)
        let player = AVPlayer(playerItem: playerItem)

        self.player = player
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
}

access.log(サーバログ)

m3u8ファイルとtsファイルがリクエストされているのが分かります。

x.x.x.x - - [14/May/2017:04:58:08 +0000] "GET /hls/index.m3u8 HTTP/1.1" 200 496 "-" "AppleCoreMedia/1.0.0.14E304 (iPhone; U; CPU OS 10_3_1 like Mac OS X; ja_jp)"
x.x.x.x - - [14/May/2017:04:58:08 +0000] "GET /hls/media-0.ts HTTP/1.1" 200 16522673 "-" "AppleCoreMedia/1.0.0.14E304 (iPhone; U; CPU OS 10_3_1 like Mac OS X; ja_jp)"
x.x.x.x - - [14/May/2017:04:58:22 +0000] "GET /hls/media-1.ts HTTP/1.1" 200 15999469 "-" "AppleCoreMedia/1.0.0.14E304 (iPhone; U; CPU OS 10_3_1 like Mac OS X; ja_jp)"
x.x.x.x - - [14/May/2017:04:58:35 +0000] "GET /hls/media-2.ts HTTP/1.1" 200 11657985 "-" "AppleCoreMedia/1.0.0.14E304 (iPhone; U; CPU OS 10_3_1 like Mac OS X; ja_jp)"

Android(ネイティブ)による再生

本記事ではVideoViewを用いた動画再生について説明します。
Android Studioで実装しています。

プロジェクトの作成

新規プロジェクトを作成します。
メニューから File > New > New Project を選択します。

今回は、Minimum SDK「API 19:Android 4.4(KitKat)」、テンプレート「Empty Activity」、プロジェクト名「MyApplication」で作成しています。

Androidmanifest.xml

MyApplication/app/src/main/AndroidManifest.xml

マニフェストファイルです。
Internet接続を許可しておきます。

<manifest package="com.example.test.myapplication"
          xmlns:android="http://schemas.android.com/apk/res/android">

    <uses-permission android:name="android.permission.INTERNET" />
    <application

activity_main.xml

MyApplication/app/src/main/res/layout/activity_main.xml

レイアウトファイルです。
VideoViewを追加し、IDにvideoViewを付与しておきます。

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.example.test.myapplication.MainActivity">

<VideoView
    android:id="@+id/videoView"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content" />
</RelativeLayout>

MainActivity.java

MyApplication/app/src/main/java/com/example/test/myapplication/MainActivity.java

レイアウトのIDに指定したvideoViewを指定してVideoViewのインスタンスを取得します。
index.m3u8ファイルまでのURLを変数urlに指定、videoView.setVideoURI(url) で設定します。
コントローラを表示するには「videoView.setMediaController」を記述します。

package com.example.test.myapplication;

import android.net.Uri;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.MediaController;
import android.widget.VideoView;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        VideoView videoView = (VideoView) findViewById(R.id.videoView);
        Uri url = Uri.parse("https://xxx.xxx.xxx/hls/index.m3u8");
        videoView.setVideoURI(url);
        videoView.setMediaController(new MediaController(this));
    }
}

access.log(サーバログ)

m3u8ファイルとtsファイルがリクエストされているのが分かります。

x.x.x.x - - [14/May/2017:08:04:23 +0000] "GET /hls/index.m3u8 HTTP/1.1" 200 496 "-" "stagefright/1.2 (Linux;Android 6.0.1)"
x.x.x.x - - [14/May/2017:08:04:23 +0000] "GET /hls/media-0.ts HTTP/1.1" 200 16522673 "-" "stagefright/1.2 (Linux;Android 6.0.1)"
x.x.x.x - - [14/May/2017:08:04:36 +0000] "GET /hls/media-1.ts HTTP/1.1" 200 15999469 "-" "stagefright/1.2 (Linux;Android 6.0.1)"
x.x.x.x - - [14/May/2017:08:04:50 +0000] "GET /hls/media-2.ts HTTP/1.1" 200 11657985 "-" "stagefright/1.2 (Linux;Android 6.0.1)"

参考サイト

<Wikipedia>

HTTP Live Streaming
https://en.wikipedia.org/wiki/HTTP_Live_Streaming

<Apple>

HTTPライブストリーミングの概要
https://developer.apple.com/jp/documentation/StreamingMediaGuide.pdf

HTTP Live Streaming
https://developer.apple.com/streaming/

<Android(Google)>

Supported Media Formats
https://developer.android.com/guide/topics/media/media-formats.html

VideoView
https://developer.android.com/reference/android/widget/VideoView.html

MediaPlayer
https://developer.android.com/guide/topics/media/mediaplayer.html

<Amazon>

動画配信プラットフォームとしてのAWS活用
https://www.slideshare.net/AmazonWebServicesJapan/on-aws

以上です。おつかれさまでした。

この記事を書いた人

泰松 猛雄