はじめに
Raspberry Pi 4が手に入って色々と遊んでいたタイミングでちょうどよく(?)ブルーレイレコーダーが壊れたので、買い直すくらいなら自作するかという事で今回地デジ録画サーバを構築した時のメモです.
ひとまず録画してエンコードできれば良いのでストリーミング再生手順は省略。
簡易ですがMirakurun APIを使用したストリーミング再生について追記しました。
なお、本記事は以下の記事を参考に環境構築しています。
https://qiita.com/shotasano/items/3809b8f3e0b62d51d3c3
⚠︎注意
以下の手順は全て自己責任でお願いします。
テレビ番組のコピー、配信は違法です。私的利用だけにして下さい。
TS抜き自体が現状グレーなのでそこらへん理解した上で利用できる方だけ利用して下さい。
この記事を参考にしたことにより生じたあらゆる損害について筆者は一切の責任を負いません。
使用ハード
Raspberry Pi 4 Model B / 4GB
Raspberry Pi 3でも同じ手順でいけます。
Raspberry Pi 4ではCPU性能上がったのでエンコード速度が多少向上してます。
PLEX USB接続型フルセグ対応地上デジタルTVチューナー PX-Q1UD
PX-S1UD V2.0 でも可。違いはチューナーの数(同時録画出来る番組数)。
PT3 では構築してませんがdriverが違うのでそこら辺の手順が変わります。
SCM ICカードリーダー/ライター SCR3310/v2.0
B-CASが読めるカードリーダー
アンテナ分配器 S-A2SP05WH4C TAROS
TVに出力する線とチューナーに接続する線を分ける分配器。
くれぐれも間違えて分波器を買わないように。
電流通過型であれば何でも良いですが、間に別のレコーダーが入っていたりするとケーブルがない版では構造的に上手く接続出来なかったりするかも。
B-CASカード
これがないと地デジ信号デコード出来ません。
今回は壊れたブルーレイレコーダーから拝借。
カードだけ欲しい場合は、B-CAS社経由で再発行(2,160円)出来ます。
アンテナケーブル
ブルーレイレコーダーで使ってたものを使用。
HDD
そこら辺に転がっていたのを適当に使用。
先日アキバに行ったら「WD Blue 4TB」辺りが7K円くらいで売ってました。
HDDケースに関しては「電源連動**"しない"**」ケースの方が良いです。
電源連動ケースではラズパイが起動しても電源連動でONになってくれなかったりします。
電源連動しないケースは価格.comのここらへんが参考になるのかな。知らんけど。
https://kakaku.com/specsearch/0539/
セルフパワーのUSBハブ
録画サーバの場合多くの機器をラズパイにUSBで接続することになるので出力不足に陥りがちです。
そのため「セルフパワー」のUSBハブでラズパイの出力を補うと安定して動作するようになります。
Raspberry Piの準備
OSインストール
時間はかかりますが特に詰まるところはありません。
今回は以下の記事を参考にしました。
https://pcmanabu.com/raspberry-pi4-install/
Raspbion Full
をインストールしましたが、GUI使わないので Raspbion Lite
でも良かった気がします。
Raspbion Lite
だと ffmpeg
が入らないです。自前でbuildするの非常にめんどくさいのでRaspbion Full
入れておいた方が良いと思います。
ラズパイ4からWi-fi 5GHzに対応したのが良いですね。
Wi-fi設定
有線LANで利用するなら不要な手順です。
ラズパイ起動時にWi-Fiに自動で接続するように設定します。
SSIDを検索
$ sudo iwlist wlan0 scan | grep ESSID
たまにbusyになったりしますが、大抵再実行すればいけます。
SSIDを追加
$ sudo raspi-config
> 1 System Options
> S1 Wireless LAN
> SSIDを入力
> SSIDに対応するパスフレーズを入力
WPAサプリカントに追加されていることを確認
$ sudo cat /etc/wpa_supplicant/wpa_supplicant.conf
Wi-Fiインターフェース再起動
$ sudo ifconfig wlan0 down
$ sudo ifconfig wlan0 up
繋がらない場合はDHCPからIPアドレスを再発行。
$ sudo dhclient wlan0
IPアドレス確認
$ ip a
IPアドレス固定化
IPアドレスを固定化しておかないとリモートから接続する際に困るので固定化しておきます。
ルーターのIPアドレスを事前に調べておく必要があります。
IO-DATA製ルーターなら 192.168.0.1
ASUS製ルーターなら 192.168.1.1
NEC製ルーターなら 192.168.10.1
Buffalo製ルーターなら 192.168.11.1
辺り。
DHCPでのIPアドレス固定設定
$ sudo vi /etc/dhcpcd.conf
ファイルに以下の設定を追加。
interface wlan0
static ip_address=<割り当てるIPアドレス>/24
static routers=<ルータのIPアドレス>
static domain_name_servers=<ルータのIPアドレス>
interface eth0
static ip_address=<割り当てるIPアドレス>/24
static routers=<ルータのIPアドレス>
static domain_name_servers=<ルータのIPアドレス>
LANよりwifiの方を優先させる場合interface eth0
のstatic routers=0.0.0.0
に設定する
Wi-fi再接続スクリプトの登録
標準ではWi-fiが途切れた際に再接続してくれないので
Wi-fiの接続が切れた際にスクリプトで再接続するようにしておきます。
Wi-fi再接続スクリプト
#!/bin/sh
ping -c 1 <ルーターのIPアドレス> > /dev/null
test $? -eq 1 && sudo ip link set wlan0 up
exit 0
スクリプトをcronに登録
# rsyslogを編集
# cron のコメントアウトを外す
$ sudo vi /etc/rsyslog.conf
cron.* /var/log/cron.log
# rsyslogの再起動
$ sudo /etc/init.d/rsyslog restart
# cronログレベルの設定
# 全部ログ出す場合は15
$ sudo vi /etc/default/cron
EXTRA_OPTS="-L 15"
# cronデーモンの再起動
$ sudo /etc/init.d/cron restart
# crontab設定
$ crontab -u <実行ユーザ> -e
# cron実行時いちいちメールが飛ばないようにする
MAILTO=""
# Wi-fi再接続スクリプトを1分毎に実行する
* * * * * /sh /home/pi/tools/reconnect.sh
SSH接続設定
リモートからSSH接続するための設定です。
ラズパイはdefaultではSSHでの接続は無効化されています。
$ sudo raspi-config
> 4 Interfacing Options
> P2 SSH
> [はい]
再起動
SSH接続設定まで終わったら一旦再起動し pi
ユーザでリモートから接続できるか確認。
pi
ユーザのパスワード設定するの忘れていたら raspi-config
から設定可能。
sudo shutdown -r now
HDDマウント
HDD確認
$ sudo fdisk -l | grep /dev/sd
> Disk /dev/sda: 3.7 TiB, 4000787030016 bytes, 7814037168 sectors
HDDパーティション作成
フォーマットするとHDDの中身が消えるので注意。
# パーティションテーブルの設定
$ sudo fdisk /dev/sda
# d でパーティションを削除
$ Command (m for help): d
# p で現在の状態を確認
$ Command (m for help): p
# n でパーティションを作成
# パーティション分けないなら全部デフォルトで良い
$ Command (m for help): n
# p で現在の状態を確認
$ Command (m for help): p
# w で変更を書き込み
$ Command (m for help): w
> The partition table has been altered!
> Calling ioctl() to re-read partition table.
> Syncing disks.
FileSytem を ext4
にフォーマット
Linuxシステムに最適化するためFileSytemを ext4
にフォーマットします。
フォーマットするとWindowsでは認識できなくなります。
$ sudo mkfs.ext4 /dev/sda
> Allocating group tables: done
> Writing inode tables: done
> Creating journal (32768 blocks): done
> Writing superblocks and filesystem accounting information: done
ちなみにWindowsでも認識できるようFAT32
でフォーマットする場合はこちら
$ sudo mkfs.vfat -F 32 /dev/sda
再起動時に自動的にマウントされるように設定
HDDの UUID
をメモしておく。
$ sudo blkid /dev/sda
> /dev/sda: UUID="92720b54-5f27-4367-8271-469eeee7caba" TYPE="ext4"
HDDが /mnt/hdd1
に自動マウントされるよう fstab
を更新。
# バックアップ
$ sudo cp /etc/fstab /etc/fstab.bak
# fstabを編集しマウント設定を追加
$ sudo vi fstab
# デバイス名 マウントポイント ファイルシステム オプション dump指定 fsck指定
UUID=92720b54-5f27-4367-8271-469eeee7caba /mnt/hdd1 ext4 nofail 0 0
# 再起動
$ sudo reboot
# HDDがマウントされたか確認
$ df -h | grep /mnt/hdd1
> /dev/sda 3.6T 0G 3.6T 0% /mnt/hdd1
ユーザ作成
$ sudo adduser <追加ユーザ>
$ sudo gpasswd -a <追加ユーザ> sudo
$ sudo adduser <追加ユーザ> video
# ディレクトリの権限変更
$ sudo chown <ユーザ>:video /mnt/hdd1
ラズパイデフォルトのユーザ pi
はセキュリティ的にあまり使いたくないのでユーザを作成。
sudo
出来るように sudo
グループに追加しておきます。
そのままだと結局 root
になれてしまうので 後で sudo
の細かい設定を別途追加してください。
video
グループに所属しておかないとChinachu経由で録画出来ないので設定しておきます。
samba設定
ラズパイのHDDを外部から覗けるようにsambaを設定。
sambaのインストール
$ sudo apt-get update
$ sudo apt-get install samba
sambaの設定
sambaをHDDのルートに紐付けます。
別のパスにしたい場合は path
を変更して下さい。
$ sudo vi /etc/samba/smb.conf
# 以下の設定を追加
[raspberrypi]
comment = Raspberry Pi
path = /mnt/hdd1
guest ok = yes
read only = no
browsable = no
force user = <追加ユーザ>
# サービス再起動
$ sudo service smbd restart
# ディレクトリのオーナーを変更
$ sudo chown <追加ユーザ>:video /mnt/hdd1
samba接続確認
\\<ラズパイのipアドレス>\raspberrypi\
ラズパイのディレクトリを覗けることを確認。
チューナーの準備
PLEXチューナのdriverインストール
$ 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の準備
driverインストール
$ sudo apt-get install build-essential git
$ sudo apt-get install pcscd libpcsclite-dev libccid pcsc-tools
カードリーダーの型番確認
$ lsusb
カードリーダーを認識しない場合はラズパイ再起動やUSBの差し直しを試してみて下さい。
一旦ラズパイからUSBを外して再起動してからまた差し直すと良いかも。
参考にした元記事の方を見てるとたまにSCM製以外のカードリーダーが混じるらしい。
その場合は /etc/libccid_Info.plist
に定義を追加する必要があります。
詳細は元記事の方を参照してください。
B-CASが読み取れるか動作確認
$ sudo pcsc_scan
> 0: SCM Microsystems Inc. SCR 3310 [CCID Interface] (XXXXXXXXXXXXX) 00 00
> ...中略...
> Japanese Chijou Digital B-CAS Card (pay TV)
Ctrl+C で終了
B-CASデコード用ライブラリのインストール
$ sudo apt-get install cmake g++ libpcsclite-dev
$ wget https://github.com/stz2012/libarib25/archive/master.zip -O libarib25.zip
$ unzip libarib25.zip
$ rm libarib25.zip
$ cd libarib25-master
$ cmake .
$ make
$ sudo make install
録画用コマンドツールのインストール
録画コマンドにrecdvbを使用します。
インストール
$ 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
$ ./autogen.sh
$ ./configure --enable-b25
字幕やデータ放送のデータが不要な場合は
$ make
字幕やデータ放送のデータが必要な場合は
$ EXTRA_SID=1 make
$ sudo make install
上手く行っていれば上記の時点で地デジ録画可能になりました。
動作確認
driverとrecdvbコマンドが導入されチューナが認識されていれば以下のコマンドで録画出来ます。
チャンネル番号はマスプロのチャンネルリストで確認すると良いでしょう。
# $ recdvb [--dev <チューナ番号>] --b25 --strip チャンネル番号 録画秒数 録画ファイル名
$ recdvb --b25 --strip 22 10 /mnt/hdd1/test.m2ts
> ...中略...
> Recording...
> Recorded 10sec
上手く動作しない場合は一旦チューナーを取り外してからラズパイを再起動し、またUSB差し直すと上手く動いたりします。
USBハブを使用している場合はハブのUSBも外した状態でハブ→その他USBの順番で刺すと良いです。
下記コマンドでUSBを抜き差ししてみてきちんとUSB機器が認識されているか確認してみて下さい。
$ dmesg -w
Ctrl+Cで終了
VLCなどで開いて問題なく録画出来ているか確認して下さい。
Mirakurun (チューナーサーバー) 設定
チューナーサーバーをインストールすると録画コマンドの並列化やチューナーの管理を自動で行ってくれ、LAN内でSSH接続しなくてもチューナー自体を操作できるREST APIが提供されます。
NodeJS v10.16.3 インストール
Mirakurun は NodeJSで動作するサーバなのでNodeJSをインストールします。
Mirakurun
は NodeJS v12.x でも動作しましたが、Chinachu v0.10.1-gamma.0
の方が v10.16.3
を利用するため当バージョンをインストールします。
普通に指定バージョンのNodeJSをインストールしても良いですが、今回は複数バージョンを管理出来るよう n
を利用します。
$ sudo apt-get install npm
$ sudo npm install -g n
$ sudo n 10.16.3
$ sudo npm install -g npm
npm
に関しては定期的にJVNに脆弱性が報告されてくる最新版にしておくのが吉。
Mirakurun インストール
$ sudo npm install pm2 -g
$ sudo npm install mirakurun -g --unsafe --production
Mirakurun チューナー設定
チューナー別録画コマンド設定を行います。
nameは何でもOK。
types設定のGRは地上波、BSはBS、CSはCS、SKYはスカパー。
commandで録画を行うコマンドを設定します。
$ sudo EDITOR=vi mirakurun config tuners
# 以下の設定を追記。
# PX-Q1UD は 4チューナーあるので4つ設定。
# PX-S1UD V2.0 の場合は 1チューナーなので --dev x オプションを外した1つだけで大丈夫。
- name: PX-Q1UD-1_1
types:
- GR
command: recdvb --b25 --strip --dev 0 <channel> - -
- name: PX-Q1UD-1_2
types:
- GR
command: recdvb --b25 --strip --dev 1 <channel> - -
- name: PX-Q1UD-1_3
types:
- GR
command: recdvb --b25 --strip --dev 2 <channel> - -
- name: PX-Q1UD-1_4
types:
- GR
command: recdvb --b25 --strip --dev 3 <channel> - -
チャンネルスキャン
channels.yml
を手動更新しても良いですがスキャンするのが手っ取り早いです。
Mirakurun の channels scan API を叩きます。
$ curl -X PUT "http://localhost:40772/api/config/channels/scan"
Chinachu (録画サーバー) 設定
MirakurunだけではAPIが提供されただけなのでまだ使いにくい
そのためMirakurunで動作する録画サーバーのChinachuを導入します。
Chinachuは最新の番組表の取得を自動で行い、録画予約もブラウザから操作出来るようになります。
インストール
$ sudo apt-get install build-essential curl git-core vainfo
# chinachu は割と容量食うので外付けHDDにインストールしておきます。
$ git clone git://github.com/kanreisa/Chinachu.git /mnt/hdd1/chinachu
$ cd /mnt/hdd1/chinachu
$ ./chinachu installer
> 1. Auto を選択
# 録画ルールの初期ファイルを作成
# 作成しない場合はアニメと笑点辺りを自動で録画するルール(rules.sample.json)が設定されます。
$ echo "[]" > rules.json
# 録画設定ファイルの作成
$ cp config.sample.json config.json
# uid, recordedDir, temporaryDir, recordedFormat 辺りを編集。
$ vi config.json
"uid": "<追加ユーザ>"
"recordedDir" : "/mnt/hdd1/recorded/",
"temporaryDir" : "/mnt/hdd1/recordtmp/",
"recordedFormat": "<title> <subtitle> <episode:2>[<channel-name>][<date:yymmdd-HHMM>].m2ts",
NodeJSのシンボリックリンク作成
.nave/installed/
以下が空の場合はNodeJSのバイナリに向けてシンボリックリンクを作成しておく必要があります。
# node のシンボリックリンク先を確認
$ cd .nave
$ ls -la
> node -> /mnt/hdd1/chinachu/.nave/installed/10.16.3/bin/node
> npm -> /mnt/hdd1/chinachu/.nave/installed/10.16.3/bin/npm
# n でインストールした上記と一致するバージョンのnodeへのシンボリックリンクを作成
$ cd installed/
$ ln -s /usr/local/n/versions/node/10.16.3 10.16.3
Chinachuの起動確認
$ cd /mnt/hdd1/chinachu/
$ ./chinachu service wui execute
Ctrl+Cで停止
ファイルが不足しているエラーが出る場合はGithubからファイルを取得して下さい。
Chinachuの起動とサービス登録
$ cd /mnt/hdd1/chinachu/
$ sudo pm2 startup
$ sudo pm2 start processes.json
$ sudo pm2 save
Chinachuの番組表更新
番組表はしばらく待っていると自然と更新されますが手動で更新することも出来ます。
$ cd /mnt/hdd1/chinachu/
$ ./chinachu update
Chinachuを使う
以下URLでChinachuのGUIにアクセスできるようになりました。
http://[ラズパイIPアドレス]:20772/
自動でエンコードする
tsファイルのままではファイルサイズがデカすぎるのでffmpegを使用してエンコードします。
ディレクトリ作成
以下のディレクトリを作成。
- エンコード中の作業ディレクトリ:
/mnt/hdd1/processing
- エンコード完了ディレクトリ:
/mnt/hdd1/encoded
スクリプト作成
ラズパイ4ではハードウェアエンコーダ h264_omx
が使えるので
ffmpeg
で h264_omx
を使用してエンコードを行います。
#! /bin/bash
# インターレース解除してブロックノイズが目立たない画質で試作
# フレームレート 23.98 はアニメ向け。実写なら 29.98 くらい。
# 画質上げたいならビットレート -b:v 4000k 辺りの数字をいじる。
X264="-f mp4 -c:v h264_omx -c:a copy -r 23.98 -s 1920x1080 -b:v 4500k -threads 0 -flags +ilme+ildct -top -1 -deinterlace -preset slower -y"
#X265="-f mp4 -c:v libx265 -c:a copy -preset veryfast -crf 23 -aq-mode 1 -deinterlace -y"
DIR1="/mnt/hdd1/tv/recorded"
DIR2="/mnt/hdd1/tv/processing"
DIR3="/mnt/hdd1/tv/encoded"
EXT="m2ts"
ENCEXT="mp4"
cd $DIR1
orgfpath=`find $DIR1 -maxdepth 1 -type f -name "*.$EXT" -print0 | xargs -0 ls -rt | awk 'NR==1' | awk '{printf $0}'`
# エンコード対象ファイルがない場合はスキップ
if ! [ -e "$orgfpath" ]; then
exit 0
fi
orgfname="${orgfpath##*/}"
encfname="${orgfname%.*}.$ENCEXT"
echo "orgfile=$orgfname"
echo "encfile=$encfname"
# 2ファイルまで処理を許す
cd $DIR2
count=`find $DIR2 -maxdepth 1 -type f -name "*.$EXT" -printf '.' | wc -c`
echo "encoding count $count"
if [ $count -lt 2 ]; then
mv "$orgfpath" "$DIR2"
ffmpeg -fflags +discardcorrupt -i "$DIR2/$orgfname" -bsf:a aac_adtstoasc $X264 "$DIR2/$encfname"
mv "$DIR2/$encfname" "$DIR3"
# 元動画の削除は一旦画質に納得してからの方が良さそう
#rm -f "$DIR2/$orgfname"
fi
echo "end"
動作確認
$ sudo chmod 755 encode.sh
$ ./encode.sh
cronで定期的に実行する
# rsyslogを編集
# cron のコメントアウトを外す
$ sudo vi /etc/rsyslog.conf
cron.* /var/log/cron.log
# rsyslogの再起動
$ sudo /etc/init.d/rsyslog restart
# cronログレベルの設定
# 全部ログ出す場合は15
$ sudo vi /etc/default/cron
EXTRA_OPTS="-L 15"
# cronデーモンの再起動
$ sudo /etc/init.d/cron restart
# crontab設定
$ crontab -u <実行ユーザ> -e
# cron実行時いちいちメールが飛ばないようにする
MAILTO=""
# 4持~10持の間、30分毎に実行する場合
*/30 4-10 * * * /mnt/hdd1/tools/encode.sh
Mirakurun APIを使用しての VLCストリーミング再生(TS)
tv-list.m3u8
のようなファイルを作成してチャンネルとサービスを記載しておくとVLCのプレイリストからチャンネル選択出来ます。
Raspberry piのホスト名は各自読み替えて下さい。
以下はスカイツリーの設定です。
各地のチャンネル番号に関してはマスプロのチャンネルリストを参考にすると良いでしょう。
#EXTM3U
#EXTVLCOPT:network-caching=1000
#EXTINF:-1,地上波 - NHK総合
http://raspberrypi.local/:40772/api/channels/GR/27/services/1024/stream/
#EXTINF:-1,地上波 - NHK Eテレ
http://raspberrypi.local:40772/api/channels/GR/26/services/1032/stream/
#EXTINF:-1,地上波 - 日本テレビ
http://raspberrypi.local:40772/api/channels/GR/25/services/1040/stream/
#EXTINF:-1,地上波 - テレビ朝日
http://raspberrypi.local:40772/api/channels/GR/24/services/1064/stream/
#EXTINF:-1,地上波 - TBS
http://raspberrypi.local:40772/api/channels/GR/22/services/1048/stream/
#EXTINF:-1,地上波 - テレビ東京
http://raspberrypi.local:40772/api/channels/GR/23/services/1072/stream/
#EXTINF:-1,地上波 - フジテレビ
http://raspberrypi.local:40772/api/channels/GR/21/services/1056/stream/
#EXTINF:-1,地上波 - MX 1
http://raspberrypi.local:40772/api/channels/GR/16/services/23608/stream
#EXTINF:-1,地上波 - MX 2
http://raspberrypi.local:40772/api/channels/GR/16/services/23610/stream
感想
Mirakurun, Chinachu も安定してきて特に詰まるところ無く動きました。
実際に運用していくとUSB側の電源不足で不安定になることが多く、セルフパワーのUSBハブはあった方が良いでしょう。
ストリーミング再生を試してみましたが字幕も取得できて数秒の遅延でそれなりに見られる感じ、ただしずっと見ているとたまにフリーズします。