ラズパイをAirPlay化！RPiPlayの使い方

最近のおうち時間の有効活用ということで、家にあるラズパイがAirPlayサーバーになって大きな画面で映画とか見られたらいいな〜、と思ったのがきっかけでやってみた。

思っていたよりも簡単だった。
## 概要
[RPiPlay - GitHub](https://github.com/FD-/RPiPlay)

- iOS9以上、および最近のmacOSに対応
- 画面ミラーリングやオーディオの再生ができる
- YouTubeやNetflix等のアプリからのストリーミングはできない（後述）
- Raspberry Pi Zeroでも動く

## セットアップ
### ダウンロード
まずはGitHubからcloneしてくる。

```
git clone https://github.com/FD-/RPiPlay.git
cd RPiPlay
```

### 必要パッケージのインストール

- cmake …ビルドするのに使う
- libavahi-compat-libdnssd-dev …bonjourに登録するため
- libssl-dev …暗号化のため

```
sudo apt-get install cmake
sudo apt-get install libavahi-compat-libdnssd-dev
sudo apt-get install libssl-dev
```

### ビルド
インストールしたcmakeを使ってビルドする。

```
mkdir build
cd build
cmake ..
make
```
`cmake ..`は`cmake --DCMAKE_CXX_FLAGS="-O3" --DCMAKE_C_FLAGS="-O3" ..`でも良い。

## 実行
実行ファイルを起動するだけ。

```
./rpiplay
>> Initialized server socket(s)
>> *** WARNING *** The program 'rpiplay' uses the Apple Bonjour compatibility layer of Avahi.
>> *** WARNING *** Please fix your application to use the native API of Avahi!
>> *** WARNING *** For more information see <http://0pointer.de/blog/projects/avahi-compat.html>
```

### パラメータ
| key | value | 説明 |
|:-:|:-:|:-:|
| -n | 任意の名前 | クライアントに表示される名前 |
| -b | on, auto or off | 黒背景を常に表示する, 接続アクティブ時のみ or 常に表示しない |
| -r | 90, 180 or 270 | 画面の回転 |
| -l |   | 低遅延モードを有効にする |
| -a | hdmi, analog or off | 音声の出力先 |
| -d |   | デバッグログを有効化。コンソール出力が重くなるため再生が不安定になる |
| -v/-h |   | ヘルプ |

#### 低遅延モードについて
低遅延モードはタイムスタンプを無視して、効率的に音声とビデオフレームをレンダリングするモード。副作用として、再生が不安定になり音声と動画の明らかに同期されなくなる。

#### 音声が出力されない？ (on RPi 4)
Raspberry Pi 4ではHDMIの出力が2つある。初期設定ではHDMI0（USB Type-Cの隣）のみにしか出力されない。HDMI1に出力するには手動で設定する必要がある（未検証）。
参考：[Problem with start #39](https://github.com/FD-/RPiPlay/issues/39#issuecomment-586410411)

HDMIポートを差し替えた場合は再起動をかける必要がある。ラズパイの仕様で、起動時に出力先が認識されるため。

## 自動実行する方法
AirPlayする度にコマンドは打つのは面倒だよね。service化してみる。
参考：[Autostart RPiPlay #77](https://github.com/FD-/RPiPlay/issues/77)

```
sudo nano /etc/systemd/system/rpiplay.service
```
```:rpiplay.service
[Unit]
Description=RPi Play
After=network.target
StartLimitIntervalSec=30

[Service]
Type=simple
Restart=always
RestartSec=10
User=pi
ExecStart=/home/pi/RPiPlay/build/rpiplay -b auto
StandardOutput=inherit
StandardError=journal

[Install]
WantedBy=multi-user.target
```
```
sudo systemctl daemon-reload
sudo systemctl enable rpiplay
sudo systemctl start rpiplay
```

これでラズパイが起動される度に自動実行される。

## 注意点
### RPiPlayが使用しているプロトコルは将来的にサポート外となりうる
AirPlayのプロトコルは何度か変更されてきたが、RPiPlayが使用しているプロトコルは2015年にiOS9のリリースとともに更新されたバージョンで、iOS12でもレガシーモードとして残されている（筆者注：iOS13でも問題なし）。
2017年、tvOS 10.2がリリースされるとサードパーティのAirPlayレシーバーの多くは使えなくなった。理由は（以前は義務ではなかった）ピンによるデバイス検証が義務化されたため。
2018年、iOS11.4にAirPlay2が追加された。ただ、プロトコルに関してAppleがどのような変更を加えたのかはわかっていない。iOS 12.2とAppleTV（tvOS 12.2.1）との通信のログを見ると最初のハンドシェイク以降の通信は暗号化されているようであり、これは理論的にはAirPlay 2の一部である。同じデバイスをAppleTV第3世代に繋ぐと、**通信は平文のままであり、AppleはiOS9から使われているこの平文のプロトコルをレガシーなプロトコルだと考えているとわかる**。それを踏まえると将来的にはこのプロトコルは完全に削除されると思われ、サードパーティのAirPlayレシーバーはいずれは完全に暗号化されたプロトコルにアップデートされる必要がある。
RPiPlay作者によると、今のところ対応の見通しは立っていないようだ。
[RPiPlayのGithubページ内のAirPlay protocol versions](https://github.com/FD-/RPiPlay#airplay-protocol-versions)を抜粋して訳した。

### YouTubeやNetflixなどのストリーミングができない問題
画面のミラーリングは問題なく使えるが、iOSデバイスからYouTubeやNetflix、Amazonプライムビデオなどの動画のストリーミングをしようとすると、うまく再生できない問題がある。
これはミラーリングとストリーミングという言葉の違いから分かるように、**LANの中で映像を送受信する「ミラーリング」**と、**デバイスはあくまでリモコンとして用い、映像はインターネットから直接ダウンロードする「ストリーミング」**の違いで、RPiPlayは前者のプロトコルにのみ対応している。
これはGithubでIssueとして上がっているので、詳しくは[Casting videos doesn’t work #7](https://github.com/FD-/RPiPlay/issues/7)を参照。


## おわり
インストールして実行するだけで簡単に使えるのでぜひお試しを！