Help us understand the problem. What is going on with this article?

【2019年12月版】ラズパイ4をNode-RED+SpotifyでDJ-Botにしてみよう!

株式会社ピーアールオー(あったらいいな!を作ります) Advent Calendar 2019 の24日目メリークリスマスイブ〜!の夜にお届けする、筆者がクリスマスパーティーに添えたい最高にあったらいいな!の記事です。

パーティーを最高に盛り上げるBGMを pi4 からお届け!

今夜は🎄クリスマス🎄ということで、手元のラズパイをDJ-Bot🔊に変身させてみたいと思います!
当然、ただ単にSpotify Connectで繋ぐだけじゃ面白くないので、Node-RED から WebAPI 経由でのSpotify再生にチャレンジいたします!!

用意するもの

  • Spotify プレミアム (3ヶ月無料のうちにアカウントゲット!!)
  • Raspberry Pi 4
  • Raspbian Lite
  • SSH 接続

リスト再生、停止などのPlayerを直接、操作するAPIはプレミアムアカウントでないとできない?模様です。

今回も引き続きRaspbian Liteでデスクトップなしで、SSHからの操作だけで行ってみます。

1. Spotify クライアントをインストール

まずは、Spotify から 普通に音楽を再生できる 環境を整えます。
ラズパイ用 Spotify Connectクライアントは "Raspotify" というものがありますので、これをインストールします。

上記のサイトを参考に、以下のコマンドでいけました。

$ curl -sSL https://dtcooper.github.io/raspotify/key.asc | sudo apt-key add -v -
$ echo 'deb https://dtcooper.github.io/raspotify raspotify main' | sudo tee /etc/apt/sources.list.d/raspotify.list
$ sudo apt update
$ sudo apt install raspotify

apt にキーとリスト追加して、インストール、のいつもの流れでOKです。

今回は設定をいじって、

/etc/default/raspotify
...
DEVICE_NAME="raspotify-1"
...

機器の名前を raspotify-1に変えてみました。

設定ファイルを保存して、respotifyのサービスを再起動します。

$ sudo systemctl restart raspotify

スピーカーの設定はまた別の記事で取り上げますが、なんとか音が出るように調整してください。(これも結構、大変だったりする。)

これでSpotifyのプレイヤーにはデバイスとして以下のようにrespotify-1 が表示されてるようになると思います。

SpotifyPlayerデバイスリスト.png

これでまず、Spotifyからの配信がラズパイで受け取れるようになりました。

2. Spotify Developer ログイン

続いて、Developerサイトにてログインしてアクセスキーなどを取得します。
手順は以下のサイトにて詳しく載っています。

この記事の内容で、ほぼ問題なかったので、ここでは詳細な説明を割愛させていただきます。

以下のSpotify開発者のサイトでログインして…

ダッシュボードにクライアントを登録して、クライアントIDとクライアントキーを取得してください。

My Dashboard アプリ詳細.png

この画面の Client IDClient Secretをコピペしておいてください。

3. Spotify の APIを叩いてみる

アクセスキーが入手できたので、Node-REDでの実装に移りたいところですが、実際にAPI呼び出す際には然るべき"scope"が付与されたOAuth2.0のトークンが必要になります。
この"scope"がAPIごとに異なるので、事前に使いたい機能(API)をチェックするのは必須です。
また、Node-REDで使用するのAPIの"ラッパー"になりますので実際のAPIの使い方とラッパーの実装、両方知っておく必要もあります。

そんなわけで、例えば肝心の 再生する 箇所のAPIを見てみましょう。

https://developer.spotify.com/documentation/web-api/reference/player/start-a-users-playback/

"Authorization"の欄に必要な"Scope"が明記してあります。このAPIはuser-modify-playback-stateというスコープが必要です。

APIの定義と引数のリストを眺めていると…?

Start Resume a User s Playback  _Try_it  Spotify for Developers.png

"TRY IT" のボタンを発見いたしました。クリックしてみると…

Start Resume a User s Playback   Spotify for Developers.png

実際に、APIを叩いて試せるフォームが用意されています。また、URLも見れますね。
ついでに、このフォームからOAuth2トークンも取得できるので、試してみます。

ポップアップダイアログが表示されて…

Start Resume a User s Playback  Scope Select Spotify for Developers.png

Scopeの選択ダイアログが表示されますが、ここでも必要なスコープを教えてくれます。
ここで取得したトークンで、APIが実際に叩けます。

... Spotify、すごい。

続いてデバイスの一覧も確認しておきます。
以下のページがデバイスの一覧が確認できるAPIです。

ここでも "TRY IT"をクリックしてAPIを叩いてみましょう。

Get a User s Available Devices   Spotify for Developers.png

raspotify-1が認識されていますね!このidは後ほど使用しますのでコピペしておきましょう。
というか・・・どうなってんの??

4. Node-RED のインストール

SpotifyのAPIについてだいたいわかりましたので、Node-REDからこれを叩いてみたいと思います。
まず、Node-REDのインストールです。
以下のサイトの手順を参考にしたいと思います。

$ bash <(curl -sL https://raw.githubusercontent.com/node-red/linux-installers/master/deb/update-nodejs-and-nodered)
...

だらだら〜っとインストールプロセスが進行していきまして…

All done.
  You can now start Node-RED with the command  node-red-start
  or using the icon under   Menu / Programming / Node-RED
  Then point your browser to localhost:1880 or http://{your_pi_ip-address}:1880

Started  Fri 20 Dec 09:48:18 GMT 2019  -  Finished  Fri 20 Dec 09:50:42 GMT 2019

はい、インストール完了いたしました。Node-REDは1880ポートなんですね〜。

ついでにチュートリアルに従って簡単なフローを作成してみました。

https://nodered.jp/docs/tutorials/first-flow

Node-REDで初めてのフロー実行.png

inejctノードでタイムスタンプを送信してdebugノードで中身を表示してみるってだけですが…デプロイして"inject"ノードクリックするとタイムスタンプがデバッグ窓に表示されました。
なんとなく雰囲気は掴めましたね!

と言うか・・・ラズパイの処理の機敏さにびっくりする。。。

5. Spotify ノードをインストール

続いて、Node-REDでSpotify APIを叩けるノード、"node-red-contrib-spotify" がありますのでそれをインストールいたします。
公式のヘルプは以下です。

まずパレットの設定画面を表示します。

Node-RED パレットの管理.png

"ノード追加"タブをクリックし、ここから Spotify を検索します。

Node-RED Add_node.png

node-red-contrib-spotify、ありました。
あとは ノードを追加をクリックするだけでインストール完了です。

6. OAuth トークンを取得

上記の "node-red-contrib-spotify" 公式ヘルプにはノードが"2つある"とありますが、Spotify Authのノードは見当たらず・・・

Spotifyノードを配置してみるとエラー?警告?のマークがついているのでダブルクリックします。

Node-RED _ spotify alert.png

プロパティが開かれて…

Node-RED Create_Token.png

ここからOAuthのトークンが取得できるようですね!編集のペンアイコンをクリックすると…クライアントIDとキー、スコープを指定するダイアログが表示されます。

Node-RED ADD_Token.png

先ほどのSpotify for Developersサイトで取得したIDとキーを入力し、"scope" には user-modify-playback-stateを指定します。

わかりにくいですが Start Authentication がボタン?リンク?担っておりますのでクリックすると認証画面が表示されます。

Spotifyの認証画面が表示されてトークンが取得できました。
これで準備完了です!

7. フローを作成

それでは、作りに入っていきましょう。個別に手順を解説すると大変なボリュームなので、まずは全体のフローを貼り付けてしまいます。

Node-RED_全体.png

左上のinejctノードから例えば、JR スキースキーという文字列を msg.payloadに入れて出力します。(例えば、ですよ!!)
続いて "function"ノードのbuild queryで検索API用の引数を作成いたします。

var query = msg.payload

msg.params = [
    query , { limit : 1, offset : 0 }
]

return msg;

payloadから値を持ってきて、paramsを作るのですが… ここで重要なのは node-red-contrib-spotify は Spotify APIのラッパーである、ということです。つまり、引数の作り方はSpotify APIじゃなくて、node-red-contrib-spotifyの実装をチェックする必要がある、ということです。
で、なにを見ればいいの?ということですが、公式のヘルプは…

Check out the API description for more information about available functions.

と、ご親切にもリンクが張ってあります。ですが、リンク先は…

・・・モロ実装やないかい!

はい、というわけで検索APIを叩くには、

spotify-web-api.js
...
  /**
   * Search for playlists.
   * @param {string} query The search query.
   * @param {Object} options The possible options.
   * @param {requestCallback} [callback] Optional callback method to be called instead of the promise.
   * @example searchPlaylists('workout', { limit : 1, offset : 0 }).then(...)
   * @returns {Promise|undefined} A promise that if successful, returns an object containing the
   *          search results. The result is paginated. If the promise is rejected,
   *          it contains an error object. Not returned if a callback is given.
   */
  searchPlaylists: function(query, options, callback) {
    return this.search(query, ['playlist'], options, callback);
  },
...

を参照してね、ということですか。。。こっ、こいつ。。。

この node-red-contrib-spotify のほんのり勝手が悪い点ですが、msg.params で渡すのは常に配列で、上記の callback 以外の引数 を渡す、という点が注意です。
これ第1引数がobjectで2番目がcallbackでも msg.params = [{ option: some }]みたいな渡し方が必要なのです。
ちょっと戸惑いましたね・・・

はい、それでは引き続いて次の"Spotify" ノードではAPIに"searchPlayList" を指定します。これで指定したキーワードで検索に引っかかったプレイリストが1件取得できます。

Node-RED spotify searchPlaylist.png

このAPIのレスポンスはデバッグとして出力させるものと次の再生APIに渡す用の二手に分かれます。
デバッグにはレスポンスのJSON出てますが、ちょっと長いので割愛します。。。

再生用の引数を作る"function"ノードsetPlayListではプレイリストの先頭の曲を流すようにいたします。
ここで先ほど取得したデバイス"raspotofy-1"のidを使用して、このラズパイで再生されるように指定します。

msg.params = [
    {
        device_id: "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
        context_uri: msg.payload.playlists.items[0].uri,
        offset: {"position":0}
    }]

return msg

payload.playlists.items[0].uriがプレイリストのURIとなります。
そしてこれを Spotify ノードの play APIに流せば再生開始です。

Node-RED Spotify Play.png

このままでは常に最初の曲しか流れないので、シャッフル再生させてみましょう、というのが次のspotifyノードです。
Spotifyはプレイリスト切り替えるとシャッフルがオフになって先頭から再生されるようなので、再生後に毎度、切り替える必要があるようです。(まぁ、そんなもんでしょう。局の順番は重要ですし。。)

"function"ノードsetShuffle:trueでシャッフルを有効にする引数を作ります。

msg.params = [
    {
        state: 'true'
    }
    ]
return msg;

この引数も spotify-web-api.js をよく見ないとなかなかアレですが…
で、これを"Spotify"ノードsetShuffleに投げます。

Node-RED spotify setShuffle.png

最後に"次の曲"を流す"Spotify"ノードnextを呼び出してシャッフル再生、完了です。

Node-RED Spotify SkipToNext.png

最後に右上の"デプロイ"をクリックして完了です。

実装(?)は以上です!

8. 実行!

まずは、Spotifyのアプリなどで他のプレイリストを再生しておきましょう。今回は Mac版のSpotifyアプリを使用しています。
ノリノリの EDM が流れているけど~

スクリーンショット 2019-12-24 1.09.55.png

Node-RED で injectノードをクリック!

スクリーンショット 2019-12-24 1 10 21.png

はい、Zoo キタ――(゚∀゚)――!!

Node-RED上でキーワードを"ドリカム"に修正して"デプロイ"→injectノードクリックしてみましょう。
スクリーンショット ドリ.png

はい!ドリカムに切り替わりました!
Node-RED上でキーワードを再度、"JR スキースキー"に戻して"デプロイ"→injectノードクリックしてみましょう。

スクリーンショットJR スキースキー2.png

プレイリストが戻っても別の曲が流れます。ランダム再生も効いている模様です!

これで今夜のクリスマスパーティーの🔊BGM🔊はバッチリですね〜!!
明日も、2回も続けてウザめにお送りいたします!!

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした