LoginSignup
2
2

More than 5 years have passed since last update.

Spotifyで現在再生中の曲をAWS IoTボタンでプレイリストに追加する

Last updated at Posted at 2018-12-15

この記事は、ケーシーエスキャロット Advent Calendar 2018 の16日目の記事です。

音楽を聴きながら仕事をしていると、ふと気になる曲が流れることがありますよね。
私はSpotifyを使用しているのですが、曲名を確認する程度ならSpotMenuが便利ですが、
プレイリストに登録する作業は、毎回Spotifyアプリを開いてポチポチしなければなりません。
仕事中には結構な手間ですし、集中が途切れる要因になります。

概要

そこで、AWS Lambdaを使って現在再生中の曲をプレイリストに追加するコードを書き、
IoTボタンと組み合わせて、1プッシュで実行出来るようにしたいと思います。
Spotifyのアカウントは取得済みを前提とします。
また、ローカルの開発端末はmacを想定としていますので、それ以外の方は適宜読み替えてください。

SpotifyのAPIについて

SpotifyのAPIは、検索やトラック情報取得といったグローバルなAPIは
Client IDとClient Secretを使ってトークンを取得するだけで使用出来るのですが、
自分が今再生している曲を取得するようなプライベートな情報を扱うAPIは、OAuth認証が必要です。
つまり、インタラクティブな処理が必要ということになります。

どう実現するか

SpotifyのAuthorization Code Flowを見ると、
GET https://accounts.spotify.com/authorizeで返却されたログイン画面に、
ユーザー名とパスワードでログインし、リダイレクト先URLのパラメータの値を取得する必要があります。
ここの部分をLambdaで実現するために、Lambda上でseleniumを使い、headless chromeを動かすことにします。

手順

  • Client IDとClient Secretの取得
  • Redirect URIsの設定
  • 登録先プレイリストの作成とIDの取得
  • Lambdaの設定
    • serverless-chromiumのインストール
    • chromedriverのインストール
    • Redirect URIsの設定
    • 登録先プレイリストの作成とIDの取得
    • lambda_function.pyの作成

Client IDとClient Secretの取得

Spotify for Developersからログインし、DashboardページにあるCREATE A CLIENT IDから、必要な情報を入力して作成します。

  • App or Hardware Name
    • 適当で大丈夫です
  • App or Hardware Description
    • 適当で大丈夫です
  • What are you building?
    • 適当で大丈夫です、I don't knowにでもチェック付けておきましょう

次ページで3つのチェックボックスにチェックをつけ、SUBMITをクリックすると、
作成したアプリケーションのページに遷移します。

SHOW CLIENT SECRETをクリックし、Client IDとClient Secretを控えておきましょう。

Redirect URIsの設定

先ほどのアプリケーション画面にあるEDIT SETTINGSを開き、
Redirect URIshttp://localhostを記載し、ADDしてからSAVEしましょう。
ここに登録されたuriのみが、後ほど出てくる認証時のリダイレクト先のパラメータで指定出来ます。

登録先プレイリストの作成とIDの取得

Lambda実行時に登録するプレイリストをアプリなどから作成します。
IDの取得方法については、以下の通りです。
途中ログイン画面が入った場合は適宜ログインしてください。

  1. Spotify for Developersのコンソールからプレイリスト取得APIを開く
  2. OAuth TokenのGET TOKENをクリック
  3. Required scopes for this endpoint:に記載されているplaylist-read-privateにチェック
  4. REQUEST TOKENをクリック
  5. TRY ITをクリック
  6. 出力された結果から、対象プレイリストの"id"の値を取得

Lambdaの設定

今回は最終的にデプロイパッケージのサイズが50MB程になるため、コンソールからはソースが編集出来ません。
なので、ローカルでソースを編集し、zipファイルにしてS3にアップロードしたファイルを使用します。
Lambdaでheadless chromeを使用する方法については、AWS Lambda上のheadless chromeをPythonで動かすを参考にさせて頂きましたので、そちらをご参照ください。
こちらでは引用して記載します。

serverless-chromiumのインストール

mkdir -p bin/
curl -SL https://github.com/adieuadieu/serverless-chrome/releases/download/v1.0.0-37/stable-headless-chromium-amazonlinux-2017-03.zip > headless-chromium.zip
unzip headless-chromium.zip -d bin/
rm headless-chromium.zip

chromedriverのインストール

curl -SL https://chromedriver.storage.googleapis.com/2.37/chromedriver_linux64.zip > chromedriver.zip
unzip chromedriver.zip -d bin/
rm chromedriver.zip

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

現状、pip install spotipy -t ./でインストールすると、
current_user_playing_track()がないため以下のようにインストールします。

pip install --upgrade git+https://github.com/plamere/spotipy.git -t ./
pip install selenium -t ./

lambda_function.pyの作成

いよいよ本題です。
seleniumを使ってログイン処理をし、authorization_codeを取得した後、
それを使ってAPIからアクセストークンを取得し、現在再生中の曲をプレイリストに入れる処理になります。

from spotipy import Spotify
from spotipy.oauth2 import SpotifyOAuth
from urllib.parse import urlencode, urlparse, parse_qs, quote
from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By

AUTHORIZE_URL = 'https://accounts.spotify.com/authorize'
CLIENT_ID = 'xxxxxxxxxxxxxxxxxxxxxxx'
CLIENT_SECRET = 'xxxxxxxxxxxxxxxxxxxxxxx'
LOGIN_USERNAME = 'xxxxxxxxxxxxxxxxxxxxxxx'
LOGIN_PASSWORD = 'xxxxxxxxxxxxxxxxxxxxxxx'
PLAYLIST_ID = 'xxxxxxxxxxxxxxxxxxxxxxx'
SCOPE = 'user-read-currently-playing playlist-modify-public playlist-modify-private'
LOCALHOST = 'http://localhost'

def lambda_handler(event, context):

    options = webdriver.ChromeOptions()
    options.binary_location = './bin/headless-chromium'

    # headlessで動かすために必要なオプション
    options.add_argument('--headless')
    options.add_argument('--disable-gpu')
    options.add_argument('--window-size=1280x1696')
    options.add_argument('--disable-application-cache')
    options.add_argument('--disable-infobars')
    options.add_argument('--no-sandbox')
    options.add_argument('--hide-scrollbars')
    options.add_argument('--enable-logging')
    options.add_argument('--log-level=0')
    options.add_argument('--single-process')
    options.add_argument('--ignore-certificate-errors')
    options.add_argument('--homedir=/tmp')
    driver = webdriver.Chrome('./bin/chromedriver', chrome_options=options)

    params = {
        'client_id': CLIENT_ID,
        'response_type': 'code',
        'redirect_uri': LOCALHOST,
        'scope': SCOPE
    }

    # ヘッドレスブラウザでログイン処理をし、アクセストークン生成に必要なcodeの値を取得する
    driver.get('{}?{}'.format(AUTHORIZE_URL, urlencode(params, quote_via=quote)))
    WebDriverWait(driver, 5).until(EC.presence_of_element_located((By.ID, 'login-username')))
    driver.find_element_by_id('login-username').send_keys(LOGIN_USERNAME)
    driver.find_element_by_id('login-password').send_keys(LOGIN_PASSWORD)
    driver.find_element_by_id('login-button').click()
    code = parse_qs(urlparse(driver.current_url).query).get('code')[0]

    # アクセストークンの取得
    so = SpotifyOAuth(client_id=CLIENT_ID, client_secret=CLIENT_SECRET, redirect_uri=LOCALHOST, scope=SCOPE)
    res_token = so.get_access_token(code=code)
    access_token = res_token['access_token']

    # 現在再生中の曲を取得してプレイリストに登録する
    sp = Spotify(auth=access_token)
    track_info = sp.current_user_playing_track()
    if track_info is None:
        return 'No music is being played.'
    response = sp.user_playlist_add_tracks(LOGIN_USERNAME, PLAYLIST_ID, [track_info['item']['uri']])

    return response

あとは作成したリソースをzipファイルにし、S3に配置したURLをLambdaで指定して実行するだけです。
なお、AWS IoTボタンとの連携はこちらを参考に実施しました。

実行してみる

処理時間を計ってみると、スムーズに終わって約20秒弱かかったので、Lambdaのタイムアウト値を1分程度に設定しておくのが良さそうです。
また、メモリも128MBだと少々心許ないので192MBに設定しておくことをオススメします。

最後に

曲のラストで「この曲いい!」と思ってポチッと実行しても、登録が間に合わない可能性があるのがネックですが、それは今後の課題として改善出来たらなと思っています。
少しざっくりとした説明になってしまったところもあるので、質問等があればコメントお願いします。
それでは皆さま職場での良き音楽ライフをお過ごしください!

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2