Raspberry Pi 4とDockerで作る小型録画サーバー(ハードウェアエンコード対応)
Raspberry Pi 4 と PX-S1UD V2.0、そしてDockerを利用して各種セットアップを単純化(効率化)しながら、地デジ録画サーバーを作った記録です。
目指した完成形
- MirakurunとEPGStationを使って地デジ録画およびライブ視聴ができること。
- Sambaを使ってmacOSから録画データにアクセスできること。
- できるだけDockerを使ってセットアップを楽にすること。
- microSDカードの寿命をなるべく延命させるための設定をすること。
注意事項
- Raspberry Pi 2や3で動作確認はしていません。
- 今回は地上波のみで、BS/CSには対応していません。
- 手元の端末はmacOS(Catalina)を想定しています(Windowsでできないというわけではありません)。
用意したもの
Raspberry Pi 4 本体
これがないと始まりません。2GBモデルだと今後の拡張を考えたときに不安だったので、メモリ4GBモデルを買いました。8GBモデルは少し高いですが、今後64bitに対応したOSを使うこともできそうです(未確認)。
Raspberry Pi 4 ケース、ヒートシンク、ファン、電源アダプタのセット
必要なものが一度に揃うので便利でした。個別に売っているものを購入するのでもよいと思います。
microSDカード
今回は大きめに128GBのものを買いましたが、もっと小さくても問題ありません。録画サーバー用途だけで考えれば、16GBもあれば足ります。
USBタイプの地デジチューナー
私が買ったのは地デジ1チャンネルのみ対応したチューナーです。
複数本USBに接続することでチャンネル数を増やすことが可能ですが、同メーカーのPX-Q1UDという機種だと4チャンネル分がまとめられているので、同時録画したい方にはこちらがおすすめです。
どちらの機種も地上波のみで、BS/CSには対応していないのでご注意ください。
Raspberry Piに接続する際、他のUSBケーブルと干渉するかもしれないと思い、短めのUSB延長ケーブルも一緒に購入しました。
B-CASカードリーダー
私はだいぶ前に購入したこちらのカードリーダーを使用しました。
こちらの新しいタイプでも問題ないようです。
B-CASカード自体は何らかの方法でご用意ください。
USB ハードディスク
ログや録画データ保存用。好みのメーカー、容量のものを使うのがよいと思います。
そのほか必要なもの
- Mac本体
- Raspberry PiとMacが接続するWi-Fi環境
- LinuxマシンもしくはmacOSにインストールされたVirtualBox(F2FS対応に必要)
- USB接続のSDカードライター/リーダー(OSインストール、F2FS対応に必要)
- DHCPが有効なネットワーク環境(有線および無線)
セットアップ
SDカードにOSイメージを展開
SDカードリーダーをMacに接続し、SDカードを挿しておきます。
SDカードにOSイメージを展開するには、macOS用のRaspberry Pi Imagerを使います。これによってSDカードにOSイメージを展開することができます。
https://downloads.raspberrypi.org/imager/imager.dmg
上のURLからダウンロードした imager.dmg
を開きアプリケーションをインストールします。インストール後起動すると以下のような画面が表示されます。
CHOOSE OS
を選択します。
今回、デスクトップ環境は不要なので Raspberry Pi OS (other)
を選びます。
もしも、Raspberry PiにHDMIケーブルを使ってディスプレイをつないでGUIを使いたい場合は with the Raspberry Pi Destop
のほうを選びます(今回は対象外)。
Raspberry Pi OS Lite (32-bit)
を選びます。
今度は CHOOSE SD CARD
を選び、接続されたSDカードを選択し、 WRITE
ボタンを選択します。書き込みが始まるので終わるまでしばらく待ちます。
無事書き込みが終わったらSDカードをいったん抜きます。
SSHの有効化
再度SDカードを挿すと、macOSにbootというディスクが認識されるので、macOSのターミナルからbootボリュームのルートディレクトリに ssh
という名前の空ファイルを作っておきます。
macOSのターミナルでtouchします。
touch /Volumes/boot/ssh
これでRaspberry Pi起動時にSSHが有効化されるようになります。 SDカードを安全に取りはずし、Raspberry Pi本体に挿します。
有線LANケーブルによる疎通確認
現時点で無線LANはまだ使えません。
DHCPが有効なネットワークに接続された有線LANケーブルをRaspberry Pi本体に挿して、電源ケーブルを挿しOSを起動します。
OSが起動し、無事IPが振られると、macOSからは raspberrypi.local
という名前でアクセスできます。
sshはデフォルトで用意されているユーザー pi
でログインします。
ssh pi@raspberrypi.local
pi
ユーザーの初期パスワードは raspberry
です。
初期設定
タイムゾーンの設定や、インストール済みパッケージへのアップデート、ロケールの設定などをおこないます。
sudo timedatectl set-timezone 'Asia/Tokyo'
sudo apt update && sudo apt upgrade -y
sudo apt install locales-all
sudo localectl set-locale 'LANG=en_US.UTF-8'
さらに
export LC_ALL=en_US.UTF-8
を.bashrcに記述します(このあたりは好みに合わせて変更してください)。
Wi-Fi設定
Wi-Fi機能がブロックされているので解除する必要があります。2019年6月20日のRaspbianのリリースノートに以下の記述がありました。
* On-board 5GHz WiFi blocked by rfkill by default
The block is removed when taking one of the following actions:
- Selecting a locale in the first run wizard
- Setting the WiFi country in the Raspberry Pi Configuration tool or the Network Settings applet
- Setting the WiFi country in raspi-config
- Providing a wpa_supplicant.conf file through the boot partition
- Running 'rfkill unblock wifi'
対処方法としてはいくつか書かれていますが、私は rfkill unblock wifi
を採用しました。
sudo rfkill unblock wifi
これで wlan0
が使えるようになります。
次にWi-Fiの設定に進みます。
wpa_passphrase "アクセスポイントのSSID" "パスワード"
とコマンドを実行すると
/etc/wpa_supplicant/wpa_supplicant.conf
に追記する内容が出力されるので、viで開いて追記します。
sudo vi /etc/wpa_supplicant/wpa_supplicant.conf
追記したらWi-Fiのインタフェース wlan0
を稼働させます。
sudo ifconfig wlan0 up
これによってWi-FiのIPアドレスが振られているか ifconfig
を使って確認します。
ifconfig
IPの固定化
ネットワークに接続するたびにIPが変わってしまうと不便なので固定化します。DHCPの範囲外のIPを指定します。
sudo vi /etc/dhcpcd.conf
/etc/dhcpcd.conf
の該当箇所を下記のように編集します(あくまで例です)。ご自身のネットワーク環境に合わせて内容を変えてください。
interface wlan0
static ip_address=192.168.0.20/24
static routers=192.168.0.1
static domain_name_servers=192.168.0.1
SDカードの故障対策
Raspberry Piを使っていてよく聞くトラブルとしてSDカードの故障があります。SDカードに使われているNANDフラッシュメモリの素子は書き込み回数に上限があります。 そこで、書き込み回数を減らすなど、SDカードの寿命を伸ばせるだろう手法をいくつか試しました。(実際寿命が延びたかどうかは壊れる期間をみないとわかりません)
スワップの無効化
sudo swapoff --all
sudo apt-get remove dphys-swapfile
F2FS (Flash-Friendly File System) の利用
サムスン電子が中心となって開発されたファイルシステム、F2FS (Flash-Friendly File System) を利用することでSDカードにおけるランダムライト性能向上、ガベージコレクションのオーバーヘッドを低減させる工夫がされているようです。
詳しくはこちらのサイトで解説されています。
F2FS(Flash-Friendly File System) を試してみる。 https://syucream.hatenablog.jp/entry/2013/12/19/221559
Raspberry PiのルートパーティションをF2FSに変更する手順
SDカードのパーティションをマウントして作業するため、Ubuntuマシンを用意します。macOSにインストールしたVirtualBox上のUbuntuでも大丈夫です(VirtualBoxとUbuntuをセットアップする手順は割愛します)。
Raspberry Pi側での作業
Raspberry Pi側でF2FSのパッケージをインストールします。これを忘れると、F2FSにした後に起動できません。
sudo apt-get install f2fs-tools
Ubuntu側での作業
Ubuntuマシン側でもF2FSのパッケージをインストールします。
sudo apt-get install f2fs-tools
SDカードマウント用のディレクトリを作成し、SDカードをマウントします。
sudo mkdir /mnt/boot
sudo mkdir /mnt/rootfs
sudo mount /dev/sdc1 /mnt/boot
sudo mount /dev/sdc2 /mnt/rootfs
マウントしたrootfs側のファイル一式をいったんUbuntu側にtarballにします。
cd /mnt/rootfs
sudo tar cvzf ~/rootfs.tar.gz .
rootfsをアンマウントして、F2FSでファイルシステムを作成します。
cd ..
sudo umount /mnt/rootfs
sudo mkfs.f2fs -f -l rootfs /dev/sdc2
マウントして、先ほど作成したtarballを展開します。
sudo mount /dev/sdc2 /mnt/rootfs
cd /mnt/rootfs
sudo tar xzvpf ~/rootfs.tar.gz
fstabに書かれたファイルシステムをf2fsに変更します。/
のファイルシステムを f2fs
に書き換えます。
sudo vi /mnt/rootfs/etc/fstab
bootパーティションにある設定ファイルを書き換えます。rootfstype
を f2fs
に書き換えます。
sudo vi /mnt/boot/cmdline.txt
最後にアンマウントします。
sudo umount /mnt/boot
sudo umount /mnt/rootfs
SDカードを抜き、Raspberry Piに差し、電源を入れ、無事起動されることを確認します。
起動後に df -T
などのコマンドで f2fs
として認識されていることを確認しておくと良さそうです。
ログの抑制
/etc/rsyslog.conf
の以下の箇所をコメントにします。
#cron.* /var/log/cron.log
#daemon.* -/var/log/daemon.log
#kern.* -/var/log/kern.log
#lpr.* -/var/log/lpr.log
#mail.* -/var/log/mail.log
#user.* -/var/log/user.log
#mail.info -/var/log/mail.info
#mail.warn -/var/log/mail.warn
#mail.err /var/log/mail.err
さらにログローテーションの頻度を低くします。
/etc/logrotate.d
にある各設定ファイルの rotate
を 1
に、ローテーション頻度である daily
や weekly
と書かれた箇所を monthly
にします。
log2ramの導入
https://github.com/azlux/log2ram
を導入し、/var/log
をRAMディスクに書き込むように変更します。これによってさらにSDカードへの書き込みを減らすことができます。
echo "deb http://packages.azlux.fr/debian/ buster main" | sudo tee /etc/apt/sources.list.d/azlux.list
wget -qO - https://azlux.fr/repo.gpg.key | sudo apt-key add -
sudo apt update
sudo apt install log2ram
/etc/log2ram.conf
の USE_RSYNC=true
にします。
ここでまた reboot
しておくと安心です。
FFmpegでH.264のハードウェアエンコードができるようにする
Raspberry PiにはBroadcom社のVideoCoreというGPUが搭載されています。Raspberry Pi 4にはVideoCore VIが採用されています。
LinuxからH.264のハードウェアエンコードをおこなうには、このGPUとLinux Kernel間をつなぐコマンドインタフェース /dev/vchiq
にアクセスする必要があります。このデバイスのパーミッションを変更することで、FFmpegで h264_omx
を使ったH.264ハードウェアエンコードができるようになります。
以下のudevのルールを追加することでOS起動時にデバイスが使えるようになります。
echo 'SUBSYSTEM=="vchiq",GROUP="video",MODE="0666"' | sudo tee /etc/udev/rules.d/10-vchiq-permissions.rules
PX-S1UD V2.0 チューナーのドライバインストール
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/
Dockerのインストール
curl -sSL https://get.docker.com | sh
Docker Composeのインストール
sudo apt -y install docker-compose
外付けHDDをUSBポートに接続する
この後セットアップするMirakurunとEPGStationのインストール先や、録画データの保存先に外付けハードディスクを使います。
USBタイプのハードディスクをRaspberry Piに接続して、ファイルシステムを作成します。ここではファイルシステムに ext4
、マウント先として /data
を使います。ファイルシステムのタイプやディレクトリは好みに合わせて変更してください。また、必要に応じて fdisk
などでパーティションを作成してください。
/dev/sda1
が外付けハードディスクのパーティションの場合、以下のコマンドでファイルシステムとディレクトリを作成し、マウントします。
sudo mkfs.ext4 /dev/sda1
sudo mkdir /data
sudo mount /dev/sda1 /data
/etc/fstab
で起動時にマウントさせるため、外付けハードディスクのパーティションのIDを調べます。
sudo blkid /dev/sda1
実行結果の PARTUUID
をコピーしておきます。
/etc/fstab
に追記します。
PARTUUID=調べたID /data ext4 defaults,nofail 0 0
一度 reboot して、問題なくマウントされることを確認しておくとよいでしょう。
MirakurunとEPGStationのセットアップ
http://github.com/ykym/docker-mirakurun-epgstation-rpi.git
を使って、Docker ComposeでMirakurunとEPGStationをセットアップします。
先にgit clone先のディレクトリを pi
ユーザーの権限で作っておきます。
cd /data
sudo mkdir docker-mirakurun-epgstation-rpi
sudo chown 1000:1000 docker-mirakurun-epgstation-rpi
git cloneします。もしgitが入っていなかったら sudo apt install -y git
してください。
git clone http://github.com/ykym/docker-mirakurun-epgstation-rpi.git
cd docker-mirakurun-epgstation-rpi
docker-compose.yml
の録画データのマウント先を /data/recorded
に変更しておきます。
- /data/recorded:/usr/local/EPGStation/recorded
Dockerコンテナ内では /usr/local/EPGStation/recorded
、ホスト側では /data/recorded
に録画データを保存するという意味になります。
Dockerコンテナをビルドします。それなりに時間がかかります(数十分)。
cd docker-mirakurun-epgstation-rpi
sudo docker-compose build
ビルドが終わったら起動します。
sudo docker-compose up -d
Sambaのセットアップ
録画データの保存先を他のPCからネットワーク越しにアクセスできるように、Sambaを使って共有します。
まず、docker-compose.ymlを格納するディレクトリを作ります。
sudo mkdir /data/docker-samba
sudo chown 1000:1000 /data/docker-samba
そのディレクトリの中に docker-compose.yml
を以下の内容で作成します。
viで開きます。
vi /data/docker-samba/docker-compose.yml
内容(例)
version: '3.4'
services:
samba:
image: dperson/samba:armhf
environment:
USERID: 1000
GROUPID: 1000
TZ: 'Asia/Tokyo'
networks:
- default
ports:
- "137:137/udp"
- "138:138/udp"
- "139:139/tcp"
- "445:445/tcp"
tmpfs:
- /tmp
volumes:
- /data/recorded:/mnt
command: '-s "recorded;/mnt;yes;no;no;USERNAME” -u “USERNAME;PASSWORD” -p'
networks:
default:
USERNAME
と PASSWORD
のところは好きなものに置き換えてください。ここでのパスワードは平文でしか書けなそうなのでご注意ください。
ファイルが用意できたら起動します。
cd /data/docker-samba
docker-compose up -d
macOSのFinderで Cmd + k
をして smb://Raspberry PiのIPアドレス
を入力し、先に設定したユーザー名、パスワードでアクセスできることを確認します。
H.264のハードウェアエンコードのパフォーマンスについて
ざっくり調べた結果ですが、番組を1分間tsファイルに録画し、FFmpegで2Mbpsのビットレートでエンコードした場合(veryfastプリセット)、だいたい2分くらいかかりました。実時間に対して2倍というところ。エンコード中のCPU利用率は40〜50%程度。 保存先のディスク性能やFFmpegのいろんなパラメーターで試したら結果は違うと思います。
さいごに
Dockerを活用してRaspberry Pi 4で地デジの録画サーバーを作る手順を紹介しました。 あとから記述した手順もあるため、一部誤りがあるかもしれませんがご了承ください。 作業にあたり、以下のサイト、コードには大変助けられました。ありがとうございました。
- Raspberry Pi 4 で構築する録画マシン
- docker-mirakurun-epgstation-rpi
- Raspberry Pi 3+Chinachuで地デジ録画サーバー構築
- Raspberry Pi 4 で録画サーバーを作った (Mirakurun + EPGStation)
今後は頃合いをみて以下のMirakurunクローンの導入も検討したいと思っています。