2020年1月1日水曜日

ラズベリーパイでradikoラジオをつくる: その9 AirPlay楽曲情報取得

AirPlayのメタデータを取得

この記事は、Show Artist & Song Metadata Using Airplay on Raspberry Piを参考にしました。AirPlayのメタデータを取得するには、shairport-sync の作者Mike Brady氏が作成された shairport-sync-metadata-reader を使います。(感謝!)
事前準備として、前記事の通りshairport-syncを --with-metadata --with-dbus-interface --with-mpris-interfaceオプション付きでビルドしておく必要があります。そしてshairport-sync.conf のmetadataに関する設定を有効にしてメタデータを出力させます。
$ sudo nano /etc/shairport-sync.conf
metadata =
{
enabled = "yes"; // set this to yes to get Shairport Sync to solicit metadata from the source and to pass it on via a pipe
include_cover_art = "yes"; // set to "yes" to get Shairport Sync to solicit cover art from the source and pass it via the pipe. You must also set "enabled" to "yes".
cover_art_cache_directory = "/tmp/shairport-sync/.cache/coverart"; // artwork will be  stored in this directory if the dbus or MPRIS interfaces are enabled or if the MQTT client is in use. Set it to "" to prevent caching, which may be useful on some systems
pipe_name = "/tmp/shairport-sync-metadata";
pipe_timeout = 5000; // wait for this number of milliseconds for a blocked pipe to unblock before giving up
};
shairport-syncサービスを再起動します。
$ sudo systemctl restart shairport-sync
メタデータを表示してみます。次のコマンドを実行し、iTunesから何か音楽を再生すると、どばっとXMLデータが表示されます。でも、何が何だかわからんですね。
$ cat /tmp/shairport-sync-metadata

shairport-sync-metadata-reader

XMLデータの解析ツールshairport-sync-metadata-readerをインストールします
$ cd ~
$ git clone https://github.com/mikebrady/shairport-sync-metadata-reader.git
$ cd shairport-sync-metadata-reader
$ autoreconf -i -f
$ ./configure
$ make
$ sudo make install
AirPlayが接続済みであれば再接続します。そして、次のコマンドを実行しiTunesから音楽を再生してみます。
$ shairport-sync-metadata-reader < /tmp/shairport-sync-metadata

今度は、少しわかりやすく表示されました。
冒頭に音源の情報が羅列されています。snuaは"user agent"、acreはActive-Remoteトークン、daidはDACP-IDです。スピーカ側からiTunesを制御?するときに使うようです。スピーカのボリューム変更がiTuneにも反映されるようにするとかですかね、よくわかりません。pendは再生ストリームの終了、pbegは再生ストリームの開始、pvolは音量、dapoはソース側のポート番号でiTunesは3689です。
次いでAlbum NameArtistTitleの情報が取得できています。
そして、mdstはメタデータのシーケンス開始、mdenは終了、数値はRTPタイムスタンプを表します。Shairport Syncの説明によると、32ビットの符号なし整数で1秒あたり44,100フレームのオーディオフレームのインデックス番号であるとのこと。
pcstは画像の送信開始、pcenは送信終了です。Picture received, length 240192 bytes.とあるとおりディスク・ジャケット画像が受信されshairport-sync.confで指定したフォルダに保存されます。この画像は、shairport-syncが受信しており、画像が変わる度に新たな名前で更新され、前の画像は削除されるようです。なお、ジャケット画像を含まない音楽ファイルでは更新されず、前の画像が残ったままになるようです。


prgr(progress)は、再生シーケンス開始、現在の再生ポイント、再生シーケンス終了のRTPタイムスタンプを表しています。
再生を一時停止すると次のようになります。flsrは、停止位置のRTSPタイムスタンプのようです。pflsは再生ストリームが無くなったことを示しています。


そのまま待っていると、10秒ほどで"ssnc" "pend"が2回繰り返しそのままとなります。pendは再生ストリームの終了を示しています。また、再生を再開するときは、再生開始と同じメッセージが出ました。


スライダーで再生位置を変更。


曲の再生が終わり、次の曲に移るとき。


iTunesには音量調整のスライダーがあります。音量最大、中間、最小に変更すると、1回ずつpvolが出ます。音量値の単位はdBで、-144.00はミュートを表すそうです。
shairport-sync.confでignore_volume_control = "yes"としていなければ、音量が変わるはずです。


メタデータの利用

曲名等とアルバム・ジャケット画像の表示のために、次のメタデータ情報を使います。prgrは再生開始、pflsは一時停止、pendは再生停止と解釈してみることにします。
Album Name: "Opus".
Artist: "山下達郎".
Title: "Down Town".
Picture received, length 240192 bytes.
"ssnc" "prgr": "3268798776/3268811064/3283215360".
"ssnc" "pfls": "".
"ssnc" "pend": "".
次に、shairport-sync-metadata-readerの出力を受け取り、楽曲情報・再生状態・アルバム・ジャケット画像ファイル名を表示するスクリプトを作成してみました。


Pythonスクリプトを以下に示します。標準出力の受け取り方がわからず困惑しましたが、Webに投稿された例を参考にしました。

#!/usr/bin/python
# -*- coding: utf-8 -*-

import subprocess
import os

class airplay_metadata:
    def __init__(self):
        self.artist = ""
        self.album = ""
        self.title = ""
        self.status = ""
        self.coverart_path = '/tmp/shairport-sync/.cache/coverart'
        self.coverart_filename = ""

    def read(self):
        cmd = "shairport-sync-metadata-reader < /tmp/shairport-sync-metadata"
        proc = subprocess.Popen(cmd,stdout=subprocess.PIPE,shell=True)