Debian12とPX-Q3U4で作る録画サーバ

大昔にCentOS6を使って録画サーバを作ったわけですが、さすがにCentOS6を使い続けていると新しいLinuxからSSHできなくなったりと不便極まりなく、ハードウェアの老朽化も考慮すると新しいものにしたくなりました。
(とはいえ現行サーバでは、チューナー、CPU、ケースを交換し、SSD増設をしています…)

そこで新たにチューナーとサーバを調達し、最新のOSで録画サーバを構築しましたので、その記録を残します。

ハードウェア構成

種類 型番 備考
ベアボーンキット Intel NUC 12 Pro NUC12WSHi3 Core i3-1220P
メモリ AD4S32008G22-DTGN DDR4 SO-DIMM
SSD Transcend TS2TMTE220S 2TB (4400TBWの高耐久品)
メガネケーブル(電源ケーブル) アイネックス ACP-C5180 NUCには電源ケーブルが付属しない
チューナー PLEX PX-Q3U4 TS抜きチューナーPX-Q3U4を魔改造(静音化)するもご覧下さい

構成について

今回、MiniITXやMicroATXのマザーボードとケース、PCI-Express接続のチューナーを組み合わせた構成にするか迷ったのですが、それなりに筐体が大きくなるので、NUCとUSB接続のチューナーを組み合わせる構成にしました。

ベアボーンキットの選定

CPU性能的には、最近のi3であれば十分という情報があったので、i3のNUCを中心に探しました。
第13世代のi3 NUCも存在したのですが、搭載CPUがi3-1315Uで低電圧版となることから、第12世代のi3-1220P(ベンチマーク的にi3-1315Uより高速)を搭載したものを最終的には選択しました。

SSDの選定

常時稼働させるため省電力であり、録画データという大きなデータを扱いやすい高速なストレージということでSSDを利用します。
現行の録画サーバは構築した時期が古くSATA SSDを採用していましたが、現代ではNVMe SSDも安価なためこちらを採用します。
容量がそれなりにあり、長寿命(TBWが大きい)な製品を選択しています。

チューナーの選定

NUCを筐体に採用したことで、PCI-Express接続のチューナーは利用できません。
必然的にUSB接続になる訳ですが、地デジ4チューナー以上となるとPX-Q3U4に限られます。

ソフトウェア構成

OSの選定

実は最初にCentOS Stream9を使って構築を一通り行ったのですが、Intel QSVのハードウェアデコード・エンコードに必要なドライバIntel Media Driverが、第12世代Core i3-1220P(Alder Lake P)に対応するのがカーネル5.17以降だということが分かりました。

CentOS Stream9ではカーネル5.14系列であり非対応だったため、カーネル6.1系列のDebian 12で再構築を行ったという経緯になります。
CPU世代が古いものを使う場合や、Intel QSVを使わない場合はCentOS Stream9でも問題なく録画サーバとして動作します。

以降の構築手順では主にDebian12を前提として記載していますが、CentOS Stream9でもほぼ同様の手順です。
一応CentOS Stream9の場合の差分は覚えている範囲で記載しています。

構築手順

事前設定

チューナードライバが動作しなくなるため、Secure Bootを無効化しておきます。

Linuxの導入

手順は省略しますが、netinstでDebian12をインストールします。
GUIは使用しないので、minimal installしました。
コンパイルに必要なパッケージなどは別途導入します。

チューナードライバの導入

PX-Q3U4の公式ドライバはドロップが多いという情報があり、改善版も公開されているようではあるのですが、安定の非公式版を導入します。

$ cd
$ git clone https://github.com/nns779/px4_drv.git
$ cd px4_drv/fwtool/
$ make

この先、PLEXの公式ドライバをダウンロードして、fwtoolでファームウェアを抽出します。
2023年現在、公式ドライバに2021年4月版が出ているようですが、fwtoolで抽出できるのは旧ドライバなのでご注意下さい。

$ wget http://plex-net.co.jp/download/pxq3u4v1.4.zip
$ unzip -oj pxq3u4v1.4.zip pxq3u4v1/x64/PXQ3U4.sys
$ ./fwtool PXQ3U4.sys it930x-firmware.bin
$ mkdir -p /lib/firmware
$ sudo cp it930x-firmware.bin /lib/firmware/

CentOS Stream9向け情報

新しいコンパイラでは/* fall through */コメントがエラーになってしまう場合があるので、ソースコードを書き換えます。
Debian 12ではワーニングでコンパイル自体は正常に終了するようなので、エラーにならなければ特に書き換えなくても良さそうです。

$ cd ../
$ sed -ie 's/\/\* fall through \*\//fallthrough;/g' driver/px4_usb.c

DKMS化をしておきます。

$ sudo cp -a ./ /usr/src/px4_drv-0.2.1
$ sudo dkms add px4_drv/0.2.1
$ sudo dkms install px4_drv/0.2.1
$ sudo modprobe px4_drv
$ lsmod | grep px4_drv
px4_drv 167936 0
usbcore 344064 4 xhci_hcd,px4_drv,btusb,xhci_pci

libarib25のインストール

$ cd
$ git clone https://github.com/stz2012/libarib25.git
$ cd libarib25
$ mkdir build
$ cd build
$ cmake ..
$ make
$ sudo make install

CentOS Stream9向け情報

CentOS Stream9ではインストール先が/usr/local/lib64になり、Debian12では/usr/local/libになります。
/usr/local/lib64がライブラリパスに登録されていないため、CentOS Stream9ではrecpt1が以下のエラーとともにlibarib25の読み込みに失敗します。

b25: error while loading shared libraries: libarib25.so.0: cannot open shared object file: No such file or directory

そのため以下のようにパスを登録しておきます。

$ sudo sh -c "echo /usr/local/lib64 > /etc/ld.so.conf.d/00-usrlocal.conf"

recpt1のインストール

$ git clone https://github.com/stz2012/recpt1.git
$ cd recpt1/recpt1
$ ./autogen.sh
$ ./configure --enable-b25
$ make
$ sudo make install

nodejsのインストール

Debian12ではnodejs 18系が標準なのですが、EPGStationがnodejs 16系でないと動作しないため、16指定でインストールします。

$ curl -sL https://deb.nodesource.com/setup_16.x | sudo bash -
$ sudo apt install nodejs=16.20.0-deb-1nodesource1

CentOS Stream9向け情報

CentOS Stream9ではnodejs 16系がインストールされるので、無心でdnf install nodejsをすれば問題ありません。

mirakurunのインストール

sudoではうまくインストールできないようなので、rootになって作業します。

$ sudo su -
# npm install pm2 -g
# npm install mirakurun -g --production
# npm install rivarun -g
# npm install arib-b25-stream-test -g

mirakurunの初期設定

うちでは内部DNSでサーバにホスト名を割り当てているので、hostnameを設定しておきます。
ちなみにhostnameを設定しないと、FQDNでmirakurunに接続した際に画面が表示されません。
その辺は以下のページが参考になります。

# mirakurun config server
hostname: hostname.domainname

続けてPX-Q3U4向けのチューナー設定をします。
サンプルの設定が入っていますが、以下のようにPX-Q3U4の設定にまるっと置き換えます。
一応、GUIからも設定可能です。

BS/CSチューナーの設定では、ご使用のアンテナによって--lnb 15オプションが必要になるかもしれません。
うちはマンションの共用アンテナのためオプションを外しています。

# mirakurun config tuners
- name: PXQ3U4-S1
types:
- BS
- CS
command: recpt1 --b25 --strip --device /dev/px4video0 <channel> - -
isDisabled: false
- name: PXQ3U4-S2
types:
- BS
- CS
command: recpt1 --b25 --strip --device /dev/px4video1 <channel> - -
isDisabled: false
- name: PXQ3U4-S3
types:
- BS
- CS
command: recpt1 --b25 --strip --device /dev/px4video4 <channel> - -
isDisabled: false
- name: PXQ3U4-S4
types:
- BS
- CS
command: recpt1 --b25 --strip --device /dev/px4video5 <channel> - -
isDisabled: false
- name: PXQ3U4-T1
types:
- GR
command: recpt1 --b25 --strip --device /dev/px4video2 <channel> - -
isDisabled: false
- name: PXQ3U4-T2
types:
- GR
command: recpt1 --b25 --strip --device /dev/px4video3 <channel> - -
isDisabled: false
- name: PXQ3U4-T3
types:
- GR
command: recpt1 --b25 --strip --device /dev/px4video6 <channel> - -
isDisabled: false
- name: PXQ3U4-T4
types:
- GR
command: recpt1 --b25 --strip --device /dev/px4video7 <channel> - -
isDisabled: false

ここまでやったらmirakurunを再起動し、rootでの作業を終了します。

# mirakurun restart
# exit
$

mariadbのインストール

EPGStation向けにmariadbをインストールします。
sudo apt install mariadb-serverなり、sudo dnf install mariadb-serverでインストールできます。

データベースの文字コード設定をしておきます。
[server]ディレクティブの下に、character-set-server=utf8を追記します。

vim /etc/mysql/mariadb.conf.d/50-server.cnf

[server]
character-set-server=utf8

CentOS Stream9向け情報

設定ファイルが/etc/my.cnf.d/mariadb-server.cnfになりますが、設定値は同じです。

設定ファイルを修正したら、mariadb-serverを再起動し初期設定を済ませておきましょう。

$ sudo systemctl enable --now mariadb
$ sudo mysql_secure_installation

EPGStation向けのユーザとデータベースを作成します。

$ mysql -u root -p
MariaDB [(none)]> create database epgstation;
MariaDB [(none)]> create user 'epgstation'@'localhost' identified by 'password';
MariaDB [(none)]> grant all privileges on epgstation.* to epgstation@localhost;
MariaDB [(none)]> exit;
$

EPGStationのインストール

再びrootになって作業します。

$ sudo su -
# cd /opt/
# git clone https://github.com/l3tnun/EPGStation.git
# cd EPGStation
# npm run all-install
# npm run build

CentOS Stream9向け情報

opensslのバージョンの問題で、ERR_OSSL_EVP_UNSUPPORTEDエラーが出るので、npm run build時には以下のように環境変数を設定します。

# NODE_OPTIONS=--openssl-legacy-provider npm run build

EPGStationの初期設定

コンフィグテンプレートをコピーし、EPGStationディレクトリ全体のパーミッションを変えておきます。

  • <user>の部分は一般ユーザのアカウント名に置き換え
# cp config/config.yml{.template,}
# cp config/operatorLogConfig{.sample,}.yml
# cp config/epgUpdaterLogConfig{.sample,}.yml
# cp config/serviceLogConfig{.sample,}.yml
# cp config/enc.js{.template,}
# chown -R <user>: /opt/EPGStation

コンフィグを修正します。

  • <user>の部分は一般ユーザのアカウント名に置き換え
  • sqliteの行はコメントアウト
  • mysqlの行のコメントアウトを解除し、アカウントやDB情報を設定
  • ffmpeg, ffprobeのパスを修正
# vim config/config.yml

uid: <user>

#dbtype: sqlite

dbtype: mysql
mysql:
    host: localhost
    port: 3306
    user: epgstation
    password: password
    database: epgstation
    charset: utf8mb4

ffmpeg: /usr/bin/ffmpeg
ffprobe: /usr/bin/ffprobe

EPGStationのサービス登録

pm2のサービスに登録します。
pm2には既にmirakurunが登録されているので、epgstationは2つめのサービスになります。
rootの作業は終了します。

# pm2 start dist/index.js --name "epgstation"
# pm2 save
# exit
$

ffmpeg, libva関連パッケージのインストール

debian multimediaリポジトリを追加して、VAAPIに対応したffmpegとドライバをインストールします。

$ sudo sh -c 'echo -e \\ndeb https://www.deb-multimedia.org bookworm main non-free > /etc/apt/sources.list'
$ sudo apt update -oAcquire::AllowInsecureRepositories=true
$ sudo apt install -oAcquire::AllowInsecureRepositories=true deb-multimedia-keyring
$ sudo apt install ffmpeg vainfo intel-media-va-driver-non-free

CentOS Stream9向け情報

残念ながら第12世代Core iプロセッサーではVA-APIが動かなそうですが、CentOS Stream9でのインストール方法も記載しておきます。

$ sudo rpm -ivh https://download1.rpmfusion.org/free/el/rpmfusion-free-release-9.noarch.rpm
$ sudo dnf --enablerepo=rpmfusion-free-updates install ffmpeg

$ sudo rpm -ivh https://download1.rpmfusion.org/nonfree/el/rpmfusion-nonfree-release-9.noarch.rpm
$ sudo dnf --enablerepo=rpmfusion-nonfree-updates install intel-media-driver libva-utils

VA-APIでは/dev/dri/renderD128というデバイスファイルを扱うわけですが、EPGStationの権限を一般ユーザにしたためうまく扱えません。
udevルールで権限を変更しておきます。

$ sudo sh -c 'echo KERNEL==\"renderD128\", MODE=\"0666\" > /etc/udev/rules.d/99-renderD128.rules'

簡単に動作チェック

ここまでやったら再起動して簡単にチェックしておきます。

  • vainfoでVA-APIの情報を確認
  • recpt1で録画テスト
  • ffmpegでVA-APIを使ったエンコードテスト
$ sudo reboot

$ vainfo
error: can't connect to X server!
libva info: VA-API version 1.17.0
libva info: Trying to open /usr/lib/x86_64-linux-gnu/dri/iHD_drv_video.so
libva info: Found init function __vaDriverInit_1_17
libva info: va_openDriver() returns 0
vainfo: VA-API version: 1.17 (libva 2.12.0)
vainfo: Driver version: Intel iHD driver for Intel(R) Gen Graphics - 23.1.1 ()
vainfo: Supported profile and entrypoints
...(snip)...

$ recpt1 --strip --b25 27 10 test.ts
...(snip)...

$ ffmpeg -vaapi_device /dev/dri/renderD128 -i test.ts -vf 'format=nv12|vaapi,hwupload,deinterlace_vaapi,scale_vaapi=w=1280:h=720' -qp 18 -c:v h264_vaapi -c:a copy test2.ts
...(snip)...

EPGStationのVA-API化

せっかくVA-APIを使えるようにしたので、EPGStationでVA-APIを使うように設定します。
以下にWeb上でのリアルタイム視聴(mp4)設定の一例を載せておきます。

$ vim /opt/EPGStation/config/config.yml
            mp4:
                - name: 高画質 VAAPI H.264
                  cmd:
                      '%FFMPEG% -hwaccel vaapi -vaapi_device /dev/dri/renderD128 -hwaccel_output_format vaapi
                      -re -dual_mono_mode main -i pipe:0 -sn -threads 0 -c:a aac -ar 48000 -b:a 192k -ac 2
                      -vf deinterlace_vaapi -c:v h264_vaapi -b:v 15M -preset veryfast
                      -tune zerolatency -movflags frag_keyframe+empty_moov+faststart+default_base_moof -y -f mp4 pipe:1'

enc.jsを弄ることで、録画後のエンコードにもVA-APIを利用可能です。
以下のような条件で設定したenc.jsのdiffを載せておきます。

  • VA-APIによるH.264変換
  • VA-APIによるインターレース解除
  • VBRで最大ビットレートは5Mbps
  • 解像度変換は無効
$ diff /opt/EPGStation/config/enc.js /opt/EPGStation/config/enc.js.template
14,15c14,15
< const codec = 'h264_vaapi';
< const vbr = '5M';
---
> const codec = 'libx264';
> const crf = 23;
17,24c17
< const args = [
< '-hwaccel', 'vaapi',
< '-vaapi_device', '/dev/dri/renderD128',
< '-hwaccel_output_format', 'vaapi',
< '-y',
< '-analyzeduration', analyzedurationSize,
< '-probesize', probesizeSize
< ];
---
> const args = ['-y', '-analyzeduration', analyzedurationSize, '-probesize', probesizeSize];
41,44c34,37
< let videoFilter = 'deinterlace_vaapi';
< //if (videoHeight > 720) {
< // videoFilter += ',scale=-2:720'
< //}
---
> let videoFilter = 'yadif';
> if (videoHeight > 720) {
> videoFilter += ',scale=-2:720'
> }
52c45
< '-maxrate', vbr,
---
> '-crf', crf,

終わり

この手順ではBCAS関連の手順は意図的に省略しています。

最後に参考にしたページを紹介します。

おすすめ

コメントを残す

Amazon プライム対象