帰宅するとSpotifyのプレイリストをランダムで自動再生するシステムを構築してみる
Pythonを用いてSpotifyのプレイリストを作成&再生してみるの続き。
前回は、Spotifyのプレイリストを自動で作成&再生するプログラムを作りました。 しかしながら、プレイリスト再生の度にPCを起動して、そこからプログラムを実行するのは面倒です。 そこで今回は
これらの2つのサービスを利用して、帰宅すると自動的に音楽を再生システム を実現します。
事前準備
先に、以下の2つのサービスのアカウント作成を済ませておきましょう。
- AWSアカウントの作成
- IFTTTアカウントの作成
AWSの利用にはクレジットカード情報の登録が必要です。 登録後12ヶ月間は無料であれこれ使うことができますが、期間を過ぎるとサービス利用料が発生します。 料金の仕組みは色々あって自分も混乱していますが、
- 通信量
- 関数の呼び出し回数
などによって決まるみたいです。 今回の場合は、通信量も呼び出し回数も非常に少ないため、多くても数十円/月ぐらいだと思います。 心配な方はAWSの料金について調べておきましょう。
AWSの設定
AWSでは、LambdaとAPIGatewayの2種類のサービスを用います。各サービスは、ざっくり言うと以下の役割を持ちます。
APIGatewayの設定
まずAWSのコンソールにアクセスし、検索ボックスからLambdaを検索します。
画面から、「新しい関数を作成」ボタンを押します。
関数名、ロールを設定すると次の画面へ遷移します。
左のタブから、APIGateWayを選択し、Lambda関数のトリガーにセットします。 セットが完了すると、Lambda関数へのエンドポイントが作成されます。 このURLを外部サービスから叩くことによって、関数が実行するような仕組みです。
このエンドポイントは後に使用するので、どこかに控えておきましょう。
Lambdaの設定
次に、Lambda関数の中身をアップロードしていきます。 今回は、自分がSpotifyに登録しているプレイリストの中から、ランダムに1つ選んで再生するプログラムです。大まかな内容は前回と同じですが、ソースコードが見辛かったのと、Lambda用に改変する部分があったので修正しています。
まず、作業ディレクトリを作成します。
mkdir workspace cd workspace
次に、以下のプログラムをlambda_function.py
という名前で保存します。
import spotipy import spotipy.util as util import random import subprocess import requests import json import os from datetime import datetime class PlaySpofity: def __init__(self, username, scope): self.username = username self.scope = scope self.token = util.prompt_for_user_token(self.username, self.scope) self.spotipy = spotipy.Spotify(auth=self.token) self.header = {'Authorization': 'Bearer {}'.format(self.token)} self.device_id = self.get_deviceid() self.playlist_id = None def get_deviceid(self): res = requests.get( "https://api.spotify.com/v1/me/player/devices",headers=self.header) devices = res.json() try: device_id = devices["devices"][0]['id'] except IndexError: print("IndexError: Device did not found") exit() return device_id def generate_playlist(self, playlistname): playlist = self.spotipy.user_playlist_create(self.username, playlistname) playlist_id = playlist['id'] return playlist_id def make_playlist(self, search_artist, playlistname="default"): self.make_playlist = self.generate_playlist(playlistname) artist_id_map = {} print (playlistname) if search_str == None: raise TypeError('Favorite artist is None') result = self.spotipy.search(q='artist:'+search_artist, limit=1) artist_id = result['tracks']['items'][0]['artists'][0]['id'] print(result['tracks']['items'][0]['id']) artist_related_artists = self.spotipy.artist_related_artists(artist_id) track_ids = [] for artist_list in artist_related_artists['artists']: result = self.spotipy.search(q='artist:'+artist_list['name'], limit=50) if len(result['tracks']['items']) > 1: track_ids.append(random.choice( result['tracks']['items'])['id']) self.spotipy.user_playlist_add_tracks(username, self.playlist_id, track_ids) def random_select_playlist(self): current_playlists = self.spotipy.current_user_playlists(limit=50) playlist = random.choice(current_playlists['items']) return playlist def play_playlist(self, playlist_id): param = {'device_id': self.device_id, 'context_uri': 'spotify:playlist:%s' % playlist_id} res = requests.put("https://api.spotify.com/v1/me/player/play", data=json.dumps(param), headers=self.header) def logging(errorLv, lambdaName, errorMsg): loggingDateStr=(datetime.now()).strftime('%Y/%m/%d %H:%M:%S') print(loggingDateStr + " " + lambdaName + " [" + errorLv + "] " + errorMsg) return def lambda_handler(event, context): username = os.getenv('SPOTIFY_USERNAME') scope = os.getenv('SCOPE') sp = PlaySpofity(username, scope) playlist = sp.random_select_playlist() sp.play_playlist(playlist['id']) return { 'isBase64Encoded': False, 'statusCode': 200, 'headers': {}, 'body': '{"message": "PlaySpofity was executed"}' } if __name__ == '__main__': username = os.getenv('SPOTIFY_USERNAME') scope = os.getenv('SCOPE') sp = PlaySpofity(username, scope) playlist = sp.random_select_playlist() sp.play_playlist(playlist['id'])
次に、Lambdaの中でspotipy
とrequests
ライブラリを使用するために、作業ディレクトリ内にライブラリを配置します。
pip install spotipy requests -t
次に、bashrcに以下の項目をセットしましょう
$ vi ~/.bash_profile export SPOTIPY_CLIENT_ID='XXXX' export SPOTIPY_CLIENT_SECRET='XXXX' export SPOTIPY_REDIRECT_URI='http://example.com' export SPOTIFY_USERNAME='XXXXXXXXX' export SCOPE='user-read-playback-state,playlist-read-private,user-modify-playback-state,playlist-modify-public'
Lambdaにアップロードする前に、ローカルでプログラムを実行します。
python lambda_function.py
実行すると、http://example.comがブラウザで開かれます。このURLを丸ごとコピーして、 コンソールに貼り付けます。 この手順を踏むことで、Spotifyの認証に必要な情報(access_token等)が、
.cache-XXXXXX
としてlambda.pyと同じディレクトリに保存されます。 隠しファイルのままではlambdaにアップロード出来ないので、
mv ./.cache-XXXXXX cache-XXXXXX
とします。
また、
spottily/util.py
内の50行目を
cache_path=".cache-"....
cache_path="cache-"
と変更します。
プログラムが無事実行されると、Spotifyのプレイリストが紐づいているデバイス上で再生されます。
ディレクトリ内をzipファイルにまとめます。
zip -r lambda.zip *
このzipファイルを、Lambdaにアップロードします。
コードエントリータイプから.zipファイルをアップロードを選択し、先ほどのLambda.zipをアップロードします。
最後に、Lambdaにもbash_profileと同じ環境変数をセットしましょう。
キー | 値 |
---|---|
SPOTIPY_CLIENT_ID | 'XXXX' |
SPOTIPY_CLIENT_SECRET | 'XXXX' |
SPOTIPY_REDIRECT_URI | 'http://example.com' |
SPOTIFY_USERNAME | 'XXXX' |
SCOPE | 'user-read-playback-state,playlist-read-private,user-modify-playback-state,playlist-modify-public' |
これでLambdaの設定は完了です。
IFTTTの設定
次に、作成したLambda関数のエンドポイントを叩くために、IFTTT
と呼ばれるWebサービスを用います。
IFTTTは、「If This Then That」の頭文字を撮ったもので、系統の異なるWebサービスやデバイスを繋げて、システムを作ることができます。
今回は、
- 入力:スマートフォンの位置情報
- 出力:webhook(Lambda関数のエンドポイントを叩く)
となるようなシステムを作ります。
まず、IFTTTにアクセスします。
左上のMyApplet
をクリックし、リンク先の右上にあるNewApplet
をクリックします。
+this
を選択し、検索ボックスにlocationを打ち込み、選択します。
You enter an area
を選択すると、次のようなページに移動するので、ここで自宅の場所を選択します。
この選択した場所に入ることが、システムの入力となります。
選択後、下のCreate Trigger
をクリック、次に+then
の設定へと進んでいきます。
検索ボックスから、Webhook
を選択します。
Make a Web Request
を選択すると、次のページに移ります。
- URL : APIGateway設定の際に控えたURL
- Method : GET
- Content type : 適当
設定の方はこれで完了です。あとはIFTTTのスマートフォンアプリをDLし、ログインをしておくことで実行可能になります。
Point
構築したシステムの動作を確かめる場合、スマートフォンを持って自宅付近をうろつき回るのは面倒です。
その場合、Location
の代わりにbutton widjet
を選択することで、
スマートフォンのボタンウィジェットにIFTTTのボタンを作成することができます。
まとめ
今回は、帰宅するとSpotifyのプレイリストを自動再生するためのシステムを作りました。