mirakc / PX-S1UD / Raspberry Pi 3B で録画鯖

# 動機
唐突に湧いてきた長期連休に、偶然箪笥の奥から発掘されたラズパイ。
テレビを見なくなって久しいが、どうにもYoutubeはめぼしい動画を見尽くした感もある。
NASNEもTORNEも持ってるけれど、PS3を起動するのが面倒で使ってない。
スマホのアプリはPinPできないし。
だいたいかなりの時間をPCのモニタ向かってるのであって、テレビはPCで見たい。
どうせ暇なんだから、遊んで作って、実用に耐えなかったら元通り箪笥に戻せばいい。

録画鯖作ろう。ラズパイで。
※つまり、2億番煎じくらいの出涸らし記事である

# 環境
Raspberry Pi 3 model B
SoC : Broadcom BCM2837 1.2 GHz ARM Cortex-A53
Memory : 1 GB
OS: Raspbian 9.13 stretch
TV tuner : PX-S1UD * 2
BCAS Card Reader : SCR3310/v2.0

## あれこれ雑感
チューナーの仕様上、地デジしか取れない。BS/CS録画には別のHWが必要になるだろう。

3BはUSB2.0のみ、有線LANも100Mbpsである。
同時2ch録画環境を構築したが、それ以上の負荷がかかった時
それらの通信速度ネックがどう働くか分からない。

またSDカード起動がメジャーのため、ディスクI/Oと領域に余力はそれほどない。
録画生データ(.ts)はそれなりに容量を食うので、
別途NASなどに録画データを逃がすといいだろう。

最後に、MPEG2のHWデコード用キーまで購入してRaspberry piで完結するエンコード環境も作ってみたが、
速度と品質の面で実用的ではない。3Bはそれほど強力な処理能力を持たない、というのが率直な感想だ。
そこで、メインPCを都度WOLで起こして.ts -> .mp4変換(CMカット)を自動化している。

mirakc周辺ソフトウェアの構成としては、以下で今のところ落ち着いている。
録画管理にEPGStation
CMカット & エンコードにAmatsukaze
録画済み番組視聴にPlex Media Server
PC生視聴にTVTest
Android生視聴に任意のIPTVアプリ


# 録画環境
## Mirakurun / EPGStation構築
[Raspberry Pi 4で地デジ4チャンネル同時録画するには](https://denor.jp/raspberry-pi-4%E3%81%A7%E5%9C%B0%E3%83%87%E3%82%B84%E3%83%81%E3%83%A3%E3%83%B3%E3%83%8D%E3%83%AB%E5%90%8C%E6%99%82%E9%8C%B2%E7%94%BB%E3%81%99%E3%82%8B%E3%81%AB%E3%81%AF)
を参考に、まずMirakcではなくMirakurunで環境を構築した。
それぞれの役割が理解できて良かったように思う。
MirakcはDockerでの動作が前提となるため、Docker固有の問題にも当たりやすい。
前もって全コンポーネントが動作することを確認しておくとよい。

あと、チャンネル一覧はMirakurunで作成したものを
少しの改変で使いまわしている。

## Docker環境構成
[Raspberry Piにdockerとdocker-composeを入れてみた](https://qiita.com/hoshi621/items/7906274326ef3013a73d)
を参考に。Docker / Docker-Composeコマンドの両方のバージョン表示ができればよい。

## mirakc構築
[できる mirakc](https://medium.com/chinachu/c98v-mirakc-cde04fb67531) を全力で参照する。
一部差異があるため、そこを補完する。

### チューナー設定
```mirakc/config.yml
tuners:
    - name: PX-S1UD_0
      types: [GR]
      command: >-
          recdvb --dev 0 {{channel}} {{duration}} -
    - name: PX-S1UD_1
      types: [GR]
      command: >-
          recdvb --dev 1 {{channel}} {{duration}} -
```

### フィルター設定
Mirakcコンテナ本体ではスクランブル解除がうまくできなかったため、
TSストリームのスクランブル解除のために別コンテナを起こし、そちらで解除している。

ということで、mirakcは以下のdocker-composeファイルを使って起動している。
※とんでもなく愚かなことをしているのかもしれないが、動いているのでよし…

```docker/docker-compose.yml
version: '3.7'

services:
  mirakc:
    image: mirakc/mirakc:alpine
    container_name: mirakc
    init: true
    restart: unless-stopped
    devices:
      - /dev/dvb
    ports:
      - 40772:40772
    volumes:
      - mirakc-epg:/var/lib/mirakc/epg
      - ./config.yml:/etc/mirakc/config.yml:ro
    environment:
      # Log level of `mirakc`.
      # See README.md in masnagam/mirakc.
      RUST_LOG: info
      # Output info-level log messages from child processes like
      # `mirakc-arib collect-eits` for debugging purpose.
      #
      # Normally, you don't need to define the following environment variables.
      # MIRAKC_DEBUG_CHILD_PROCESS: ''
      # MIRAKC_ARIG_LOG: debug
      TZ: Asia/Tokyo
  b25:
    build:
      context: b25
    image: 68fpjc/b25
    container_name: b25
    ports:
      - 40773:40773
    environment:
      TZ: Asia/Tokyo
    depends_on:
      - bcas
    restart: unless-stopped
  bcas:
    build:
      context: bcas
    image: 68fpjc/bcas
    container_name: bcas
    privileged: true
    ports:
      - 40774:40774
    environment:
      TZ: Asia/Tokyo
    restart: unless-stopped

volumes:
  mirakc-epg:
    name: mirakc_epg
    driver: local
```

```mirakc/config.yml
epg:
  cache-dir: /var/lib/mirakc/epg

server:
  addrs:
    - http: 0.0.0.0:40772
  stream-chunk-size: 4096
  stream-max-chunks: 30000

channels:
    - name: ＮＨＫＥテレ
      type: GR
      channel: '13'

tuners:
    - name: PX-S1UD_0
      types: [GR]
      command: >-
          recdvb --dev 0 {{channel}} {{duration}} -
    - name: PX-S1UD_1
      types: [GR]
      command: >-
          recdvb --dev 1 {{channel}} {{duration}} -

filters:
# Optionally, you can specify a command to process TS packets before sending
# them to a client.
# The following command processes TS packets on a remote server listening on
# TCP port 40774.
    decode-filter:
        command: >-
            socat - tcp-connect:b25:40773
```

~~現時点ではEPGStationとの連携時、囲い文字[]を含む番組名が文字化けするため、
mirakcのmasterバージョン(alpine) を使用している。
Stableなタグリリースでその点が修正されたら、タグ版を使うのがよいかもしれない。~~

[2020/8/27追記]mirakc開発者様がプロジェクトを整理した結果、
DockerImageの配置がmirakc/mirakcへと変わった。
また、囲い文字問題の修正は現時点の最新タグリリースにマージされたため、
mirakc/mirakc:alpine利用に変更している。

# [追記]雑感
・録画時のCPU負荷はMPEG2のHWデコードで軽減できる。
MPG2用のキー購入とconfig.txtへの設定後、
rpi-configでカメラモジュールをオンにしておく。

EPGStationの録画設定例

```json:config/config.json
// const codec = 'libx264';
const codec = 'h264_omx';

...

//H264 HW Decode. Input設定の前に配置
Array.prototype.push.apply(args,['-fflags', "+discardcorrupt"]);
Array.prototype.push.apply(args,['-c:v', "mpeg2_mmal"]);

// input 設定
Array.prototype.push.apply(args,['-i', input]);

...

// // video filter 設定
// let videoFilter = 'yadif';
// if (videoHeight > 720) {
//     videoFilter += ',scale=-2:720'
// }
// Array.prototype.push.apply(args, ['-vf', videoFilter]);

// その他設定
Array.prototype.push.apply(args,[
    //H264 HW Encode
    '-c:a', 'copy',
    '-bsf:a', 'aac_adtstoasc',
    //'-preset', preset,
    //'-aspect', '16:9',
    '-c:v', codec,
    '-b:v', '5000k',
    //'-crf', crf,
    '-f', 'mp4',
    //'-c:a', 'aac',
    //'-ar', '48000',
    //'-ab', audioBitrate,
    //'-ac', '2',
    output
]);

...

```


・2番組録画時の負荷でも、ファン/ヒートシンクなしでは
真夏の室内だと80-85度の温度によるクロック制限を受けた。
SBC程度のサイズでヒートシンクの効果はさほど大きくないそうだが、
ファンによる空冷は明確に効果があった。
現在はファン付きケースに切り替え、同条件でも60度近辺で抑えられている。

# 参考
[Raspberry Pi 4で地デジ4チャンネル同時録画するには](https://denor.jp/raspberry-pi-4%E3%81%A7%E5%9C%B0%E3%83%87%E3%82%B84%E3%83%81%E3%83%A3%E3%83%B3%E3%83%8D%E3%83%AB%E5%90%8C%E6%99%82%E9%8C%B2%E7%94%BB%E3%81%99%E3%82%8B%E3%81%AB%E3%81%AF)
[できる mirakc](https://medium.com/chinachu/c98v-mirakc-cde04fb67531)