ラズパイでテレビ配信サーバを構築する

# 注意
テレビ番組を不特定多数に向けて配信する等、個人の範囲を超えた利用は違法となる場合があります。
この記事を参考にしたことで生じるあらゆる損害について、著者は一切の責任を負いません。

# 記事の内容
この記事では、Raspberry Pi(以下ラズパイ)と地デジチューナを使ってLAN内に地デジ番組を配信し、Fire TV stick等でリアルタイム視聴する方法をまとめます。具体的には録画コマンドである「recdvb」を使用し、配信のみ行うサーバをつくります。録画については一切考慮していません。

# 目的
著者の目的は、Fire TV stickを接続したPCディスプレイでテレビを視聴できるようにし、テレビを処分することでした。そのため、テレビに接続して使用することを想定しているFire TV stickでテレビを観る、という一見無意味なことをしていますが、その意図をご理解ください。

# 準備したもの

* Raspberry Pi 4-B 4 GB
* 地デジチューナ PLEX PX-S1UD V2.0 
* カードリーダ NTT Communications CLOUD2700-NTTCom
* B-CASカード (以前に購入した地デジチューナのものを流用)

もちろんmicroSDや電源なども必要ですが、ここでは割愛します。また、この記事で立ち上げるサーバは受信した地デジのデータを復号しネットワークに配信するだけですので、ラズパイ3でも十分だと思われます。

# OSの準備
Ubuntu Server 20.04.2 LTS 64bitのイメージを[ここ](https://ubuntu.com/download/raspberry-pi)から入手し、Win32DiskImagerを使ってmicroSDに書き込みました。

デフォルト状態ではディスプレイ(Dell P2715Q, HDMI接続)に映像が映らなかったため、Ubuntuを書き込んだmicroSDのconfig.txtに`hdmi_safe=1`という行を追加しました。

# ビルド環境の準備

recdvbなどのコンパイルが必要になので、必要なパッケージをインストールします。

```
sudo apt install build-essential git autoconf
sudo apt install cmake g++
```

# チューナーのセットアップ

Windows版のドライバからファームウェアをコピーします。ドライバはLinuxカーネルに組み込み済みなのでインストール不要です([ここ](http://blog.lwlv.net/archives/911)を参考いたしました)。

```
wget http://plex-net.co.jp/plex/px-s1ud/PX-S1UD_driver_Ver.1.0.1.zip
unzip PX-S1UD_driver_Ver.1.0.1.zip
sudo cp PX-S1UD_driver_Ver.1.0.1/x64/amd64/isdbt_rio.inp /lib/firmware/
```

# カードリーダのセットアップ

B-CASを読み込むために、以下のパッケージをインストールします。

```
sudo apt install pcscd libpcsclite-dev libccid pcsc-tools
```

# Recdvbのインストール

まず受信データの復号に必要なライブラリのインストールします。

```
git clone https://github.com/stz2012/libarib25
cd libarib25
cmake .
make
sudo make install
```

つづいてrecdvbをビルド・インストールします。まずrecdvbを取得し、ファイルを展開します。

```
wget http://www13.plala.or.jp/sat/recdvb/recdvb-1.3.3.tgz
cd recdvb-1.3.3
```

このままではサーバへの接続時にエラーが発生するため、[ここ](https://nyanonon.hatenablog.com/entry/20151117/p3)を参考にソースを書き換えます。

```
--- recpt1.orig.c       2021-02-21 06:45:20.891192078 +0000
+++ recpt1.c    2021-02-21 06:53:25.023240786 +0000
@@ -950,7 +950,7 @@
                        perror("accept");
                        return 1;
                }
-
+/*
                peer_host = gethostbyaddr((char *)&peer_sin.sin_addr.s_addr,
                                  sizeof(peer_sin.sin_addr), AF_INET);
                if ( peer_host == NULL ){
@@ -959,7 +959,8 @@
                }

                fprintf(stderr,"connect from: %s [%s] port %d\n", peer_host->h_name, inet_ntoa(peer_sin.sin_addr), ntohs(peer_sin.sin_port));
-
+*/
+               fprintf(stderr,"connect from: %s port %d\n", inet_ntoa(peer_sin.sin_addr), ntohs(peer_sin.sin_port));
                char buf[256];
                read_line(connected_socket, buf);
                fprintf(stderr,"request command is %s\n",buf);
```

書き換えが完了したらビルド・インストールします。```--enable-b25```オプションをオンにして、B-CASカードを使って復号できるようにします。

```
./autogen.sh
./configure --enable-b25
make
sudo make install
```

# 動作確認

recdvbのhttp broadcastingで地デジ番組が配信できるかテストします。つぎのコマンドで配信をスタートします。

```
recdvb --b25 --strip --http 5555
```

続いてVLCから接続してテレビを視聴してみます。URL「http://(ラズパイのIPアドレス):5555/(チャンネル番号)/hd」を再生して、視聴できればOKです。チャンネル番号は[ここ](https://www.maspro.co.jp/contact/channel.pdf)で確認できます。例えばスカイツリーからの電波を受信している地域でNHK総合を視聴する場合、チャンネル番号は「27」となります。

# サービスの登録

ラズパイ起動時に自動的にhttp broadcastingが開始されるように、systemctlを使ってサービスを登録します。まずrecdvb起動・終了のコマンドをシェルスクリプトにします。標準出力やエラー出力を見ることはないと考え、いずれも捨てることにしました。

```sh:tvserver_start.sh
#!/bin/sh

/usr/local/bin/recdvb --b25 --strip --http 5555 1> /dev/null 2> /dev/null
```

```sh:tvserver_stop.sh
#!/bin/sh

pkill  -KILL -f /usr/local/bin/recdvb
```

次に、以下のファイルを「/etc/systemd/system/」に置きます。

```plaintext:tvserver.service
[Unit]
Description = TV server
After=network.target

[Service]
Restart = always
StartLimitInterval=30
StartLimitBurst=10
Type=forking
ExecStart = /usr/local/bin/tvserver_start.sh
ExecStop = /usr/local/bin/tvserver_stop.sh

[Install]
WantedBy=multi-user.target
```

```sudo systemctl start tvserver```でrecdvbが起動することを確認し、```sudo systemctl enable tvserver```で起動時にサービス開始となるようにします。

# Fire TV stickで視聴しやすくする

Fire TV stickのリモコンを使ってテレビ視聴のURLを入力するのは面倒ですので、ラズパイにWebサーバを立ててVLCのプレイリストを配信できるようにします。今回、Webサーバにはnginxを採用しました。せっかくnginxを使うので、recdvbのhttp broadcastingにリバースプロキシ機能を使ってアクセスできるようにします。

インストールはaptから行います。

```
sudo apt install nginx
```

次に、以下のファイルを「/etc/nginx/conf.d/」に置きます。この設定では、URL「http://(ラズパイのIPアドレス)/tv/channel/(チャンネル番号)」とアクセスするとrecdvbの配信にアクセスできるようにします。

```plaintext:tvserver.conf
server{
        server_name xxx.xxx.xxx.xxx; #ラズパイのIPアドレス
        listen 80;
        proxy_set_header        Host    $host;
        proxy_set_header        X-Real-IP $remote_addr;
        proxy_set_header        X-Forwarded-Host        $host;
        proxy_set_header        X-Forwarded-Server      $host;
        proxy_set_header        X-Forwarded-For         $proxy_add_x_forwarded_for;

        location ^~  /tv/channel {
                rewrite /tv/channel/(\d+) /$1/hd break;
                proxy_buffering off;
                proxy_read_timeout 130;
                proxy_pass      http://localhost:5555;
        }

        location /tv {
                root /var/www/html/tvserver;
        }
}
```

VLCのプレイリストは次のように作成し、「/var/www/html/tvserver/tv/」に置きます。以下はスカイツリーから受信している地域のものですので、お住まいの地域に合わせた内容の変更が必要です。

```plaintext:programs.m3u
#EXTM3U
#EXTVLCOPT:network-caching=1000

#EXTINF:-1,NHK総合
http://(ラズパイのIPアドレス)/tv/channel/27
#EXTINF:-1,NHK Eテレ
http://(ラズパイのIPアドレス)/tv/channel/26
#EXTINF:-1,日本テレビ
http://(ラズパイのIPアドレス)/tv/channel/25
#EXTINF:-1,テレビ朝日
http://(ラズパイのIPアドレス)/tv/channel/24
#EXTINF:-1,TBS
http://(ラズパイのIPアドレス)/tv/channel/22
#EXTINF:-1,テレビ東京
http://(ラズパイのIPアドレス)/tv/channel/23
#EXTINF:-1,フジテレビ
http://(ラズパイのIPアドレス)/tv/channel/21
#EXTINF:-1,東京MX
```

最後にnginxを起動、サービス登録をします。

```
sudo systemctl start nginx
sudo systemctl enable nginx
```

# Fire TV stickから視聴する
Fire TV StickにVLCをインストールします。VLCの「ブラウジング」にある「ストリーム」を選択し、「http://(ラズパイのIPアドレス)/tv/programs.m3u」と入力します。このプレイリストを使うことで、素早くチャンネルを切り替えられます。

# 他のデバイスからの視聴
著者がテストした範囲では、VLCをインストールしたWindows PC、iPhone、Androidタブレットから視聴可能でした。ただし、iPhoneではプレイリストを使ったチャンネル切り替えができず、Androidタブレットはチャンネルの切り替えはできましたが放送局名が表示されず、手動での訂正が必要でした。

本当はデバイスに依存しない視聴環境を構築したかったので、Webアプリとffmpeg + nginxを使ったHLSによる配信が良いように考えていました。しかし2021年2月時点でのffmpegではリアルタイムでのデインターレースが難しいらしく断念しました。デインターレースしていない動画はiPhoneでは再生できないらしく、できたとしても字幕が読みづらいなど画質がイマイチです。

# 最後に
テレビ視聴環境を構築いたしましたが、著者はテレビをほとんど観ていません。テレビ以外の動画視聴はディスプレイに接続したFire TV stickとタブレットで十分であり、1Kの部屋にテレビを置いておくのはスペースがもったいないと考えていました。ただ、テレビが全く観られないのは問題、と思い処分できずにいました。配信サーバを立ち上げたことで、ついにテレビを処分できました。

配信サーバの最大の利点はスマホやタブレットを使い、場所を選ばずテレビ視聴できるようになることだと思います。テレビを良く観る方、観ない方、どちらにも利点があるラズパイ+テレビチューナによるテレビ配信サーバ構築を推して、この記事を締めます。