TVを録画するためRaspberry Pi4にdocker-mirakurun-epgstationをインストールする

## 録画サーバを作ろうと思った経緯

みなさんこんにちは。まずは録画サーバを作ろうと思った経緯を話したいと思います。  
私自身はそんなにテレビを見ませんw　が、以下の理由から作ろうと思いました。  
**・サーバの知識があまりないから勉強になると思った**  
**・子供や嫁さんがテレビ好きのためいつでも見れるようにしてあげたいと思った**  
**・家にあるレコーダだと出先に見れない＆古くなってきたのでいつ壊れてもおかしくない（15年選手）**  
正直3つ目の理由がメインで車で出かけた時に見れたらいいなーって気持ちで作成しました。  
なぜラズパイ？ってのは手元にあったサーバになりそうなものがラズパイだけだったからです。  

## docker-mirakurun-epgstation とは

l3tnun様が公開しているEPGstationという録画管理システム？のDocker版です。  
<https://github.com/l3tnun/docker-mirakurun-epgstation>  
Docker版じゃないものもありますが、個人的にスクラップビルド（試行錯誤）しやすいDocker版を選びました。  
※詳細設定等はDocker版じゃないものも一緒に見たほうが理解しやすいと思います。  
ちなみに私の認識だと以下の区分けだと思っています。  
なのでmirakurunさえ入っていればコマンドベースでの録画は可能です。  
TV：mirakurun  
レコーダ：EPGstation  
  
<font color="Red">**一点重要なことがこの記事もそうですが、github上には公式版を改造した亜種版がいくつかあります。**</font>  
<font color="Red">**各管理者が各々更新しているものもありますが、公式版に比べると陳腐化しやすいので  
個人的には公式版を使用したほうがいいと思います。**</font>  
(私は最初亜種版を使用し沼にハマりました、、、決して亜種版が悪いというわけではないですが、、、)  
![キャプチャ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/236296/baa2245c-f8c0-cb7b-c375-928d4c9edb83.png)

## 環境

|物品 |品名  |
|---|---|
|サーバ  |Raspberry Pi4 4GB |
|チューナ  |PLEX Q1UD |
|カードリーダ  |ACR39-NTTcom |
|B-cASカード  |地デジ専用 |
|SDカード  |Samsung microSDカード64GB EVO Plus microSDXC UHS-I U1 |
|充電ケーブル  |Anker PowerLine III USB-C & USB-C 2.0ケーブル  |
|充電器  |Anker PowerPort Atom III (Two Ports) (PD対応 60W 2ポートUSB-A & USB-C 急速充電器)  |
|テレビアンテナケーブル  |ノイズフィルタ対策済みのやつがいいかも  |
|アッテネータ  |Q1UDが内部で増幅してるっぽいので信号レベルが問題なければ不要  |

```:OS(32bit-armv7l)
No LSB modules are available.
Distributor ID: Raspbian
Description:    Raspbian GNU/Linux 11 (bullseye)
Release:        11
Codename:       bullseye
```
```:OS(64bit-armv64)
No LSB modules are available.
Distributor ID: Debian
Description:    Debian GNU/Linux 11 (bullseye)
Release:        11
Codename:       bullseye
```

## 手順

使えないコマンドが合った場合は適宜パッケージのインストールが必要。

1. **SDカードにラズパイOSをインストールする**  
先駆者を参考にしてください~(今後別記事で書く予定)

2. **ラズパイの初期設定を行う**  
先駆者を参考にしてください~(今後別記事で書く予定)

3. **Dockerをインストールする**  
先駆者を参考にしてください~(今後別記事で書く予定)

4. **Docker-composeをインストールする**  
先駆者を参考にしてください~(今後別記事で書く予定)

5. **チューナとカードリーダの設定**  

- 以下のコマンドで公式サイトからドライバをDL、解凍する

```:ドライバインストール
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/x86/i386/isdbt_rio.inp /lib/firmware/
```

- ドライバを反映させるため再起動する

```:再起動
sudo reboot
```

- ドライバが認識されているか確認(PX-S1UDが4つ認識されていればOK)  
Q1UDはS1UDが4つ搭載されてるイメージになります。

```:ドライバ確認
pi@raspberry:~ $ dmesg | grep PX-S1UD
[    2.766557] usb 1-1.3.1: Product: PX-S1UD Digital TV Tuner
[    3.003321] usb 1-1.3.2: Product: PX-S1UD Digital TV Tuner
[    3.233368] usb 1-1.3.3: Product: PX-S1UD Digital TV Tuner
[    3.493271] usb 1-1.3.4: Product: PX-S1UD Digital TV Tuner
```

- カードリーダを認識させるため必要なパッケージをインストール

```:パッケージインストール
sudo apt install build-essential
sudo apt install pcscd libpcsclite-dev libccid pcsc-tools -y
```

- pcscdが動いていることを確認

```:pcscd確認
pi@raspberry:~ $ service pcscd status
 ● pcscd.service - PC/SC Smart Card Daemon
      Loaded: loaded (/lib/systemd/system/pcscd.service; indirect; vendor preset: enabled)
      Active: inactive (dead)
 TriggeredBy: ● pcscd.socket
        Docs: man:pcscd(8)
```

- カードリーダを接続しB-CASカードを挿入し、認識されているか確認する

```:B-CASカード確認
 pi@raspberry:~ $ pcsc_scan | grep B-CAS
 	Japanese Chijou Digital B-CAS Card (pay TV)
```

- pcscdはdocker-mirakurun-epgstationで管理するため停止する

```:pcscd停止
sudo systemctl stop pcscd.socket
sudo systemctl disable pcscd.socket
```

6. **必要なものをDL、インストールする**  

- B-CASデコード用ライブラリ(libarib25)をインストール(ビルド)
※docker上で動作確認するのであれば不要

```:cmakeが既に入ってる場合は不要
sudo apt install cmake -y
git clone https://github.com/stz2012/libarib25
cd libarib25
cmake .
make
sudo make install
```

- 録画用ライブラリ(recdvb-1.3.2)をDL、解凍
※docker上で動作確認するのであれば不要

```:automakeが既に入ってる場合は不要
sudo apt install automake -y
wget http://www13.plala.or.jp/sat/recdvb/recdvb-1.3.2.tgz
tar xvzf recdvb-1.3.2.tgz
cd recdvb-1.3.2
```

- HTTPストリームをできるようにするため以下を編集
※docker上で動作確認するのであれば不要かも

```:NW内全機器でのHTTPストリーム配信許可設定
vi recpt1.c
↓をコメントアウト
//              struct hostent *peer_host;
//              peer_host = gethostbyaddr((char *)&peer_sin.sin_addr.s_addr,
//                                sizeof(peer_sin.sin_addr), AF_INET);
//              if ( peer_host == NULL ){
//                      fprintf(stderr, "gethostbyname failed\n");
//                      return 1;
//              }

↓を編集
・編集前
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));
```

- 信号レベルの表示を詳細化するため以下を編集
※信号レベル確認しないのであれば不要(個人的には推奨)

```:信号レベル表示変更
vi recpt1core.c
↓を編集(/* globals */のvoid以下に追記)
/* globals */
<snip>
void
print_stat(struct dtv_stats stat)
{
    switch (stat.scale) {
    case FE_SCALE_NOT_AVAILABLE:
        fprintf(stderr, "N/A");
        break;
    case FE_SCALE_COUNTER:
        fprintf(stderr, "%lld", stat.uvalue);
        break;
    case FE_SCALE_RELATIVE:
        fprintf(stderr, "%lf", (float)stat.uvalue / 655.35);
        break;
    case FE_SCALE_DECIBEL:
        fprintf(stderr, "%lf", (float)stat.svalue / 1000);
        break;
    }
}

void
↓を編集(calc_cn(void)以下をコメントアウトおよび追記)
calc_cn(void)
{
//      int strength=0;
//      ioctl(fefd, FE_READ_SNR, &strength);
//      fprintf(stderr,"SNR: %d\n",strength);
    struct dtv_property prop[4];
    struct dtv_properties props;

    prop[0].cmd = DTV_STAT_CNR;
    prop[1].cmd = DTV_STAT_ERROR_BLOCK_COUNT;
    prop[2].cmd = DTV_STAT_TOTAL_BLOCK_COUNT;
    prop[3].cmd = DTV_STAT_SIGNAL_STRENGTH;
    props.props = prop;
    props.num = 4;

    if (ioctl(fefd, FE_GET_PROPERTY, &props) < 0) {
        fprintf(stderr,"Error\n");
    } else {
        fprintf(stderr, "CNR: ");
        print_stat(prop[0].u.st.stat[0]);
        fprintf(stderr, " ERRBLK: ");
        print_stat(prop[1].u.st.stat[0]);
        fprintf(stderr, " TOTALBLK: ");
        print_stat(prop[2].u.st.stat[0]);
        fprintf(stderr, " SIG: ");
        print_stat(prop[3].u.st.stat[0]);
        fprintf(stderr, "\n");
    }
}
```

- 録画用ライブラリ(recdvb-1.3.2)をビルドする
※docker上で動作確認するのであれば不要

```:recdvb-1.3.2をビルド
./autogen.sh
./configure --enable-b25
EXTRA_SID=1 make
sudo make install
```

- 録画できるかどうか確認(内容まで確認して問題なければOK)

```:録画確認(TBSを10秒録画する)
pi@raspberry:~ $ recdvb --b25 --strip --sid hd 22 10 test.m2ts
using B25...
enable B25 strip
pid = 16318
device = /dev/dvb/adapter0/frontend0
Using DVB card "Siano Mobile Digital MDTV Receiver"
tuning to 527143 kHz
polling.
Overflow error, trying again (status = -1, errno = 75)..ok
CNR: 0.000000 ERRBLK: N/A TOTALBLK: N/A SIG: -37.000000
bcas->init failed
Cannot start b25 decoder
Fall back to encrypted recording

Recording...
Available sid = 1048 1049 1432 1183
Chosen sid    = 1048
Available PMT = 0x101 0x102 0x1fc8 0x7f0
Recorded 10sec
```

- 信号レベルが取得できるかどうか確認する(CNR：25、ERRBLK：0、SIG：-35~-40程度あればOK)

```:信号レベル確認(チューナ0でTBSの信号レベルを5秒確認)
pi@raspberry:~ $ timeout 5 recdvbchksig --dev 0 22
device = /dev/dvb/adapter0/frontend0
Using DVB card "Siano Mobile Digital MDTV Receiver"
tuning to 527143 kHz
polling..ok
CNR: 0.000000 ERRBLK: N/A TOTALBLK: N/A SIG: -38.000000
CNR: 25.000000 ERRBLK: 2413 TOTALBLK: 5178 SIG: -37.000000
CNR: 25.000000 ERRBLK: 0 TOTALBLK: 2656 SIG: -37.000000
CNR: 25.000000 ERRBLK: 0 TOTALBLK: 16186 SIG: -37.000000
CNR: 25.000000 ERRBLK: 0 TOTALBLK: 26560 SIG: -37.000000

SIGTERM received. cleaning up...
```

7. **docker-mirakurun-epgstationをインストール**

- docker-mirakurun-epgstationをセットアップする
※gitが入ってない場合はインストールが必要

```:docker-mirakurun-epgstationをgitから取得しインストール
curl -sf https://raw.githubusercontent.com/l3tnun/docker-mirakurun-epgstation/v2/setup.sh | sh -s
cd docker-mirakurun-epgstation
```

- Docker-compose.ymlを修正する

```:DBを変更(その他変更したいものがあれば適宜修正)
vi docker-compose.yml
↓を修正する(mariadb:10.5はラズパイだと上手く動作しない)
    mysql:
        image: jsurf/rpi-mariadb
#        image: mariadb:10.5
```

- Dockerfileを修正する
※Amatsukazeをリモート実行しないのであれば不要

```:monoをインストールするようにを修正（Amatsukazeをリモート実行するため）
cd epgstation
vi debian.Dockerfile
↓を追記する(末尾に追加)　※debianのversionが10以外の場合は別途確認が必要
# Install mono
RUN apt-get update && \
    apt-get install -y apt-transport-https dirmngr gnupg ca-certificates && \
    apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 3FA7E0328081BFF6A14DA29AA6A19B38D3D831EF && \
    echo "deb https://download.mono-project.com/repo/debian stable-buster main" | tee /etc/apt/sources.list.d/mono-official-stable.list && \
    apt-get update && \
    apt-get install -y mono-complete
```

- config.ymlを修正する

```:monoを使用できるようにするため設定(不要かも)
cd config
vi config.yml
↓を修正する(monoを追加)
ffmpeg: /usr/local/bin/ffmpeg
ffprobe: /usr/local/bin/ffprobe
mono: /usr/local/bin/mono
```

8. **docker-mirakurun-epgstationを起動する**  

```:コンテナを作成、起動する
docker-compose up -d
```

9. **mirakurunとEPGstationにアクセスできるか確認**  

```:アクセス確認
EPGstation・・・http://[ラズパイIPアドレス]:8888
mirakurun・・・http://[ラズパイIPアドレス]:40772
```

10.   **mirakurunをチャンネルスキャンする**
※初回は全チャンネルスキャン推奨だがやらなくても勝手にスキャンは始めてくれる

```:チャンネルをスキャン、再起動
curl -X PUT "http://localhost:40772/api/config/channels/scan"
sudo reboot
```

11.   **番組表が表示されていることを確認し録画、エンコードを試してみる**  
EPGstationに再度アクセスして番組表が表示されることを確認  
※1時間程度反映までかかる  
録画やエンコードを試してみて正常に録画されていることを確認する

## デバッグに便利なコマンド

```:EPG更新機能ログ
tail -n10000 ~/docker-mirakurun-epgstation/epgstation/logs/EPGUpdater/system.log | grep -e WARN -e ERROR
```

```:録画機能ログ
tail -n10000 ~/docker-mirakurun-epgstation/epgstation/logs/Operator/system.log | grep -e WARN -e ERROR
```

```:エンコード機能ログ
tail -n10000 ~/docker-mirakurun-epgstation/epgstation/logs/Service/system.log | grep -e WARN -e ERROR
```

## 課題、問題点、ハマったこと

- 4つあるチューナのうち一部のチャンネル、チューナで信号レベルが弱い時がある  
Q1UDの問題？可能性としては熱暴走、ノイズを拾っちゃってるとか、、、
32bit版が問題？64bit版に移行してみたので結果は後程

- チューナの動作が安定しない  
Q1UDの問題？とりあえずACアダプタはつなげずにラズパイのバスパワーのみにしたら安定した
いつの間にかアダプタつないでたけど特に問題ない(原因不明)

- ハードウェアエンコードが使えない  
32bit版のbullseyeOS以降だとOMX_H.264が対応してないっぽい  
⇒メインPC(win10 pro)でAMATSUKAZE(エンコードソフト)サーバを立ててエンコード自体はメインPCで実施する形で解決

- 番組表が初回しか更新されない  
亜種版を使ったのが原因、公式サイト手順でEPGstationを入れたら解決した！
※DBが上手く動作しなかったのが原因っぽい

- 公式サイト手順で上手く動作しなかった  
「mariadb:10.5」がラズパイだと動作しない  
⇒ラズパイ用mariaDBを使用することで解決した！
※64bit版でも問題なく動作

- VLCでテレビをリアルタイムに見たい  
⇒参考サイト見て！

## 参考にさせてもらったサイト
- [docker-mirakurun-epgstation(公式サイト)](https://github.com/l3tnun/docker-mirakurun-epgstation)  
- [EPGstation(公式サイト)](https://github.com/l3tnun/EPGStation)  
- [EPGstation作成者(Twitter)](https://twitter.com/l3tnun)  
- [USB接続で地デジ4チャンネル録画できるチューナーPX-Q1UDを買ったそして試した](https://diary.hatenablog.jp/entry/2018/03/15/215147)  
- [How To Install Mono on Debian 10](https://idroot.us/install-mono-debian-10/)  
- [ラズパイ用mariaDB](https://hub.docker.com/r/jsurf/rpi-mariadb)  
- [mirakurun を使って VLC でテレビを視聴する。](http://www.mousou.org/node/428)
- [PLEX PX-Q3PE4 で docker-mirakurun-epgstation を使いたい](https://qiita.com/nanbuwks/items/640ee4405e1fdd2ca497)