HLSストリーミング配信の作成と録画（pythonとffmpeg）

もうすぐ5G通信が到来し、ライブ配信を活用した案件が増えると思われます。今回はpythonとffmpegを使った、HLSの作成と録画を紹介します。

# HLSについて

**概要**

* HLSとは HTTP Live Streaming の略。アップルが開発しています。ブラウザではMacのSafariとWindowsのEdgeが対応しています。

**特徴**

* ファイルであること。基本的にはMP4ファイルを5秒ごとに分割しただけです。なのでHttpサーバーに置くだけで使えます（5秒は変更可能）
* アダプティブビットレート。環境によって高画質と低画質が自動的に切り替わります。自動的なのがポイント。

**ファイル**

* 連番の付いた ts ファイルと、再生する m3u8 ファイルがあります。フリーソフトVLCなどでは、m3u8 ファイルをそのまま再生できます。

|Video|HLS|
|---|---|
|input.mp4<br><br><br><br><br><br>|playlist.m3u8<br>001.ts<br>002.ts<br>003.ts<br>004.ts<br>005.ts|

# HLSの作成

ビデオMP4ファイルからHLSを作成します。input.mp4ファイルとhlsフォルダを用意して、以下のmain.pyを実行してください。

* Macの場合、ffmpegを brew install ffmpeg でインストールしてください。
* Windowsの場合、ffmpeg.exeを入手して、以下のffmepgをffmepg.exeに書き換えればOKです。

```python:main.py
# -*- coding: utf-8 -*-
import sys, os
import subprocess
import codecs

def create_hls():
    # 高画質m3u8の作成 (input.mp4 -> hls/h.m3u8)
    c = 'ffmpeg'
    c += ' -i input.mp4'
    c += ' -codec copy -vbsf h264_mp4toannexb -map 0'
    c += ' -f segment -segment_format mpegts -segment_time 5'
    c += ' -segment_list hls/h.m3u8'
    c += ' hls/h_%5d.ts'
    code = subprocess.call(c.split())
    print('process=' + str(code))
    
    # 低画質mp4の作成 (input.mp4 -> input_low.mp4)
    c = 'ffmpeg'
    c += ' -i input.mp4'
    c += ' -f mp4 -vcodec h264 -vb 500k -s 640x360 -pix_fmt yuv420p'
    c += ' -ac 2 -ar 48000 -ab 128k -acodec aac -strict experimental'
    c += ' -movflags faststart'
    c += ' input_low.mp4'
    code = subprocess.call(c.split())
    print('process=' + str(code))
    
    # 低画質m3u8の作成 (input_low.mp4 -> hls/l.m3u8)
    c = 'ffmpeg'
    c += ' -i input_low.mp4'
    c += ' -codec copy -vbsf h264_mp4toannexb -map 0'
    c += ' -f segment -segment_format mpegts -segment_time 5'
    c += ' -segment_list hls/l.m3u8'
    c += ' hls/l_%5d.ts'
    code = subprocess.call(c.split())
    print('process=' + str(code))
    
    # 低画質高画質を含めたm3u8の作成 (->hls/playlist.m3u8)
    t = '#EXTM3U'
    t += '\n##EXT-X-VERSION:3'
    t += '\n#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=500000'
    t += '\nl.m3u8'
    t += '\n#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=4000000'
    t += '\nh.m3u8'
    f = codecs.open('hls/playlist.m3u8', 'w', 'utf-8')
    f.write(t)
    f.close()

if __name__ == "__main__":
    create_hls()
```
実行すると、hls フォルダに m3u8 と ts が作られます。
<img width=70% alt="2019-0601-01.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253995/d3da879d-22f0-5a1c-cf70-f7cb2b6c6f44.png">

# Httpサーバーに置く

HLSは Mac の Safari と Windows の Edge が対応しています。上記でできた hls フォルダを Http サーバーに置いて、以下をブラウザでアクセスしてください。
http\://localhost:8080/hls/playlist.m3u8

Httpサーバーがない場合は、pythonでも構築できます。

```
cd yourdirectory
（python 2）
python -m SimpleHTTPServer 8080
（python 3）
python -m http.server 8080
```

# HLSの録画

HLSをffmepgを使い録画します。iOSフリーソフト「it's my Live」を使った例を紹介します（iOSのみです）

1. HLSモードを選択してURLが表示されるので控えます。
2. ブラウザでアクセスします。ブラウザはSafariかEdgeをお使いください。
3. Wifiのローカルネットのみです（社内LANや家庭内LAN）

<img src='https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253995/b5fd7f71-cd1d-453b-f14a-dda3b12ed315.png' width=35%> <img src='https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253995/3eeccd2d-219c-008e-218f-02a9c86d701a.png' width=35%>

以下のrec.pyをアドレスを変えて実行します。

```python:rec.py
# -*- coding: utf-8 -*-
import sys, os
import subprocess

def recode_hls():
    c = 'ffmpeg'
    c += ' -i http://10.255.114.14:8080/my/playlist.m3u8' ←要変更
    c += ' -movflags faststart -c copy rec.mp4'
    code = subprocess.call(c.split())
    print('process=' + str(code))

if __name__ == "__main__":
    recode_hls()
```

**注意点**
録画 rec.mp4 はできたのだが、QickTimeで再生できない場合
以下を試してください（aacを有効）
brew uninstall ffmpeg
brew install ffmpeg --with-fdk-aac --with-libvo-aacenc
brew install ffmpeg

アプリ設定のビットレート、フレームレート、サイズを変えても録画可能でした。1分以上長めに録画してみるとか、再起動してみるなど試してください。

# まとめ
RTMP や次世代の SRT はライブサーバーが必要です。遅延を気にしないならHLSが楽です。ドライブレコーダーや会議の録画なんかは大手企業がやるでしょう。私のような中小企業は隙間商法で入り込みたいところ。何かいいアイデアがないかなぁと模索しているところです。