Spotify Web APIでデバイスから指定した音楽を再生してみる

2018.03.25

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

先日個人的にSpotifyを契約し、こちらでSpotify Web APIの使い方を読んだ後なんとなく公式のドキュメントを見ていたところ、情報の取得や更新に限らず音楽の再生ができるとのことでした。

本記事では、APIを実行する準備を行い、以下のようなシナリオでAPIを実行してみます。

  1. 接続されたデバイスの一覧を取得
  2. 自分のプレイリスト一覧の取得
  3. プレイリストに登録されたトラック一覧の取得
  4. デバイスを指定して、取得したトラックを再生

注意

一部ベータ版のAPIを呼び出しています。これらは予告なしに挙動が変わる可能性があるとのことです。 参考:New Endpoints (Beta): Web API Connect

前提条件

  • Spotify Premiumに登録済みであること(Premiumユーザに生成されたトークンでしか実行できないエンドポイントがあります。)
  • Spotifyでなんらかのプレイリストを登録していること
  • aurlがインストール済みであること

やってみる

アプリケーションの登録

SpotifyにAPIを呼び出すアプリケーションを登録する必要があります。 ダッシュボードにログインし、CREATE A CLIENT IDからアプリケーションを登録します。

アプリケーションの概要を指定します。

登録後、Client IDおよびClient Secretが取得できるのでメモしておきます。

EDIT SETTINGSから設定を開き、Redirect URLsを指定します。今回はコマンドラインからAPIを実行するだけなので、とりあえずhttp://example.comとしておきます。

Spotify側の準備はこれで整いました。

aurlの準備

Spotify Web APIでは、OAuth2.0のAuthorization Code、Client Credentials、Implicit Grantのフローがそれぞれサポートされていますが、このうちClient Credentialsでは特定のユーザのリソースへのアクセスができないため、Authorization Code Flowでのアクセスをします。 コマンドを簡易にするため、本記事ではaurlを利用します。

aurlにSpotifyから認可コードおよびトークンを得るためのエンドポイントと必要なスコープ、アプリケーションの登録時に取得したclient_id,client_secretを指定します。

$ vi ~/.aurl/profiles
[spotify]
grant_type = authorization_code
client_id = {$取得したCLIENT ID}
client_secret = {$取得したCLIENT SECRET}
auth_server_auth_endpoint = https://accounts.spotify.com/authorize
auth_server_token_endpoint = https://accounts.spotify.com/api/token
redirect = http://example.com
scopes = user-read-playback-state,playlist-read-private,user-modify-playback-state

スコープはアプリケーションでやりたいことに合わせて指定する必要があります。 リファレンスにはエンドポイントごとに必要なスコープが記載されています。

APIの呼び出し

アクセストークンの取得とデバイス一覧の取得

先ほど指定した設定でデバイス一覧取得のAPIにアクセスします。

$ aurl --profile spotify https://api.spotify.com/v1/me/player/devices

初回のアクセス時はSpotify側のリソースへのアクセス権限の許可を求める画面が開くので、OKをクリックします。

以下のようなURLにリダイレクトしますので、クエリパラメータのcodeの値を取得します。

http://example.com/?code=xxxxx&state=xxxxx

コンソールに戻ります。認可コードの入力を求められるので、取得したcodeを指定します。

$ aurl --profile spotify https://api.spotify.com/v1/me/player/devices
Open browser and get code from
https://accounts.spotify.com/authorize?client_id=xxxxx&redirect_uri=http%3A%2F%2Fexample.com&response_type=code&scope=user-read-playback-state&state=xxxxx
Enter code: XXXXXXXXXXXX
{
  "devices" : [ {
    "id" : "xxxxx",
    "is_active" : false,
    "is_restricted" : false,
    "name" : "JunのMacBook Pro",
    "type" : "Computer",
    "volume_percent" : 100
  }, {
    "id" : "xxxxx_google_home",
    "is_active" : true,
    "is_restricted" : false,
    "name" : "部屋",
    "type" : "CastAudio",
    "volume_percent" : null
  } ]

APIが実行され、登録済みのデバイス一覧が取得できました。今使っているPCと、部屋に置いてあるGoogle Homeが登録されています。(Google Homeに部屋という名前をつけています)

プレイリストの取得

登録済みのプレイリスト一覧を取得します。

$ aurl --profile spotify https://api.spotify.com/v1/me/playlists?limit=1
{
  "href" : "https://api.spotify.com/v1/users/xxxxx/playlists?offset=0&limit=1",
  "items" : [ {
    "collaborative" : false,
    "external_urls" : {
      "spotify" :
"https://open.spotify.com/user/xxxxx/playlist/xxxxx"
    },
    "href" : "https://api.spotify.com/v1/users/xxxxx/playlists/xxxxx",
    "id" : "xxxxx",
    "images" : [ {
      "height" : 640,
      "url" : "https://mosaic.scdn.co/640/4eb485bd0bdbf234199edc0572771a8fe730fa8e6b4b0822365b0bdbd3689028beceabc0afebdd81c5ea254b988b9a74b46dfc5aeb5cac0ed82a0ad7ef7b43e117090d33f2dd7364b9eedc2473595b81",
      "width" : 640
    }, {
      "height" : 300,
      "url" : "https://mosaic.scdn.co/300/4eb485bd0bdbf234199edc0572771a8fe730fa8e6b4b0822365b0bdbd3689028beceabc0afebdd81c5ea254b988b9a74b46dfc5aeb5cac0ed82a0ad7ef7b43e117090d33f2dd7364b9eedc2473595b81",
      "width" : 300
    }, {
      "height" : 60,
      "url" : "https://mosaic.scdn.co/60/4eb485bd0bdbf234199edc0572771a8fe730fa8e6b4b0822365b0bdbd3689028beceabc0afebdd81c5ea254b988b9a74b46dfc5aeb5cac0ed82a0ad7ef7b43e117090d33f2dd7364b9eedc2473595b81",
      "width" : 60
    } ],
    "name" : "Footwork-Jungle-Juke",
    "owner" : {
      "display_name" : "xxxxx",
      "external_urls" : {
        "spotify" : "https://open.spotify.com/user/xxxxx"
      },
      "href" : "https://api.spotify.com/v1/users/xxxxx",
      "id" : "xxxxx",
      "type" : "user",
      "uri" : "spotify:user:xxxxx"
    },
    "public" : false,
    "snapshot_id" :
"EhO8zMMM43/IsIAuTnNNN06ByyJTwsyW2upGErVE478dw/IH6P5ogZGEr9nm0wvv",
    "tracks" : {
      "href" : "https://api.spotify.com/v1/users/xxxxx/playlists/xxxxx/tracks",
      "total" : 87
    },
    "type" : "playlist",
    "uri" : "spotify:user:xxxxx:playlist:xxxxx"
  } ],
  "limit" : 1,
  "next" : "https://api.spotify.com/v1/users/xxxxx/playlists?offset=1&limit=1",
  "offset" : 0,
  "previous" : null,
  "total" : 8
}

プレイリスト内のトラックの取得

プレイリストに登録されているトラックを取得します。

$ aurl --profile spotify
https://api.spotify.com/v1/users/xxxxx/playlists/xxxxx/tracks?limit=1
{
  "href" : "https://api.spotify.com/v1/users/xxxxx/playlists/xxxxx/tracks?offset=0&limit=1",
  "items" : [ {
    "added_at" : "2016-04-21T07:14:13Z",
    "added_by" : {
      "external_urls" : {
        "spotify" : "https://open.spotify.com/user/xxxxx"
      },
      "href" : "https://api.spotify.com/v1/users/xxxxx",
      "id" : "xxxxx",
      "type" : "user",
      "uri" : "spotify:user:xxxxx"
    },
    "is_local" : false,
    "track" : {
      "album" : {
        "album_type" : "album",
        "artists" : [ {
          "external_urls" : {
            "spotify" : "https://open.spotify.com/artist/4zGBj9dI63YIWmZkPl3o7V"
          },
          "href" : "https://api.spotify.com/v1/artists/4zGBj9dI63YIWmZkPl3o7V",
          "id" : "4zGBj9dI63YIWmZkPl3o7V",f
          "name" : "DJ Rashad",
          "type" : "artist",
          "uri" : "spotify:artist:4zGBj9dI63YIWmZkPl3o7V"
        } ],
        "available_markets" : [ ],
        "external_urls" : {
          "spotify" : "https://open.spotify.com/album/4J7qkorMbPmJQy79SntDA8"
        },
        "href" : "https://api.spotify.com/v1/albums/4J7qkorMbPmJQy79SntDA8",
        "id" : "4J7qkorMbPmJQy79SntDA8",
        "images" : [ {
          "height" : 640,
          "url" :
"https://i.scdn.co/image/9cf0d76e58f1cdb75d209891a4ab66c653e3647a",
          "width" : 640
        }, {
          "height" : 300,
          "url" :
"https://i.scdn.co/image/fe38654a0e5a01772b3ba4c351b23ce2d687102b",
          "width" : 300
        }, {
          "height" : 64,
          "url" :
"https://i.scdn.co/image/d6c1a2d7c49bacba6f42d8138a99d41a17befb05",
          "width" : 64
        } ],
        "name" : "Double Cup",
        "release_date" : "2013-10-22",
        "release_date_precision" : "day",
        "type" : "album",
        "uri" : "spotify:album:4J7qkorMbPmJQy79SntDA8"
      },
      "artists" : [ {
        "external_urls" : {
          "spotify" : "https://open.spotify.com/artist/4zGBj9dI63YIWmZkPl3o7V"
        },
        "href" : "https://api.spotify.com/v1/artists/4zGBj9dI63YIWmZkPl3o7V",
        "id" : "4zGBj9dI63YIWmZkPl3o7V",
        "name" : "DJ Rashad",
        "type" : "artist",
        "uri" : "spotify:artist:4zGBj9dI63YIWmZkPl3o7V"
      }, {
        "external_urls" : {
          "spotify" : "https://open.spotify.com/artist/238R2QkXhYWy3YUIYlbtsc"
        },
        "href" : "https://api.spotify.com/v1/artists/238R2QkXhYWy3YUIYlbtsc",
        "id" : "238R2QkXhYWy3YUIYlbtsc",
        "name" : "Spinn",
        "type" : "artist",
        "uri" : "spotify:artist:238R2QkXhYWy3YUIYlbtsc"
      } ],
      "available_markets" : [ ],
      "disc_number" : 1,
      "duration_ms" : 270813,
      "explicit" : false,
      "external_ids" : {
        "isrc" : "GBLZC1300093"
      },
      "external_urls" : {
        "spotify" : "https://open.spotify.com/track/3Sb3FlaHxs5UYVukCy5oNW"
      },
      "href" : "https://api.spotify.com/v1/tracks/3Sb3FlaHxs5UYVukCy5oNW",
      "id" : "3Sb3FlaHxs5UYVukCy5oNW",
      "name" : "Feelin (feat. Spinn & Taso)",
      "popularity" : 24,
      "preview_url" : null,
      "track_number" : 1,
      "type" : "track",
      "uri" : "spotify:track:3Sb3FlaHxs5UYVukCy5oNW"
    }
  } ],
  "limit" : 1,
  "next" : "https://api.spotify.com/v1/users/xxxxx/playlists/xxxxx/tracks?offset=1&limit=1",
  "offset" : 0,
  "previous" : null,
  "total" : 87
}

取得できました。しかしこのトラックはSpotifyアプリのプレイリストには表示されず再生することもできません。

地域によってSpotifyで配信されている曲は異なるのですが、日本で設定されているアカウントはavailable_marketsにJPが含まれているものだけが再生可能です。

ページ送り

JPで再生可能なトラックを探してみます。

$ aurl --profile spotify
"https://api.spotify.com/v1/users/xxxxx/playlists/xxxxx/tracks?limit=1&offset=15"
{
  "href" : "https://api.spotify.com/v1/users/xxxxx/playlists/xxxxx/tracks?offset=15&limit=1",
  "items" : [ {
    "added_at" : "2016-04-21T07:35:39Z",
    "added_by" : {
      "external_urls" : {
        "spotify" : "https://open.spotify.com/user/xxxxx"
      },
      "href" : "https://api.spotify.com/v1/users/xxxxx",
      "id" : "xxxxx",
      "type" : "user",
      "uri" : "spotify:user:xxxxx"
    },
    "is_local" : false,
    "track" : {
      "album" : {
        "album_type" : "single",
        "artists" : [ {
          "external_urls" : {
            "spotify" : "https://open.spotify.com/artist/7DF6NrPDuqT69SYiqtWWcW"
          },
          "href" : "https://api.spotify.com/v1/artists/7DF6NrPDuqT69SYiqtWWcW",
          "id" : "7DF6NrPDuqT69SYiqtWWcW",
          "name" : "Stray",
          "type" : "artist",
          "uri" : "spotify:artist:7DF6NrPDuqT69SYiqtWWcW"
        } ],
        "available_markets" : [ "AD", "AR", "AT", "AU", "BE", "BG",
"BO", "BR", "CA", "CH", "CL", "CO", "CR", "CY", "CZ", "DE", "DK",
"DO", "EC", "EE", "ES", "FI", "FR", "GB", "GR", "GT", "HK", "HN",
"HU", "ID", "IE", "IL", "IS", "IT", "JP", "LI", "LT", "LU", "LV",
"MC", "MT", "MX", "MY", "NI", "NL", "NO", "NZ", "PA", "PE", "PH",
"PL", "PT", "PY", "RO", "SE", "SG", "SK", "SV", "TH", "TR", "TW",
"US", "UY", "VN", "ZA" ],
        "external_urls" : {
          "spotify" : "https://open.spotify.com/album/6FfCvbzYiemvMq3XhUs6S0"
        },
        "href" : "https://api.spotify.com/v1/albums/6FfCvbzYiemvMq3XhUs6S0",
        "id" : "6FfCvbzYiemvMq3XhUs6S0",
        "images" : [ {
          "height" : 640,
          "url" :
"https://i.scdn.co/image/1ce4d8afcc725e19b036870b38d6632275548221",
          "width" : 640
        }, {
          "height" : 300,
          "url" :
"https://i.scdn.co/image/4d04b1ba0e40bc695545739ae787f86693e293c7",
          "width" : 300
        }, {
          "height" : 64,
          "url" :
"https://i.scdn.co/image/32baf422c32ad7e5ec95e4a2088da3601d75b105",
          "width" : 64
        } ],
        "name" : "Paradise (Remixes)",
        "release_date" : "2015-07-31",
        "release_date_precision" : "day",
        "type" : "album",
        "uri" : "spotify:album:6FfCvbzYiemvMq3XhUs6S0"
      },
      "artists" : [ {
        "external_urls" : {
          "spotify" : "https://open.spotify.com/artist/7DF6NrPDuqT69SYiqtWWcW"
        },
        "href" : "https://api.spotify.com/v1/artists/7DF6NrPDuqT69SYiqtWWcW",
        "id" : "7DF6NrPDuqT69SYiqtWWcW",
        "name" : "Stray",
        "type" : "artist",
        "uri" : "spotify:artist:7DF6NrPDuqT69SYiqtWWcW"
      }, {
        "external_urls" : {
          "spotify" : "https://open.spotify.com/artist/06xa1OLBsMQJFXcl2tQkH4"
        },
        "href" : "https://api.spotify.com/v1/artists/06xa1OLBsMQJFXcl2tQkH4",
        "id" : "06xa1OLBsMQJFXcl2tQkH4",
        "name" : "Machinedrum",
        "type" : "artist",
        "uri" : "spotify:artist:06xa1OLBsMQJFXcl2tQkH4"
      } ],
      "available_markets" : [ "AD", "AR", "AT", "AU", "BE", "BG",
"BO", "BR", "CA", "CH", "CL", "CO", "CR", "CY", "CZ", "DE", "DK",
"DO", "EC", "EE", "ES", "FI", "FR", "GB", "GR", "GT", "HK", "HN",
"HU", "ID", "IE", "IL", "IS", "IT", "JP", "LI", "LT", "LU", "LV",
"MC", "MT", "MX", "MY", "NI", "NL", "NO", "NZ", "PA", "PE", "PH",
"PL", "PT", "PY", "RO", "SE", "SG", "SK", "SV", "TH", "TR", "TW",
"US", "UY", "VN", "ZA" ],
      "disc_number" : 1,
      "duration_ms" : 278120,
      "explicit" : false,
      "external_ids" : {
        "isrc" : "GBSZM1500364"
      },
      "external_urls" : {
        "spotify" : "https://open.spotify.com/track/0ipvRATjnKeAlIRNS5WqhN"
      },
      "href" : "https://api.spotify.com/v1/tracks/0ipvRATjnKeAlIRNS5WqhN",
      "id" : "0ipvRATjnKeAlIRNS5WqhN",
      "name" : "Movements - Machinedrum Remix",
      "popularity" : 10,
      "preview_url" :
"https://p.scdn.co/mp3-preview/7d31cf6f2685552ab64ad6d9151748e30a7cdeea?cid=866fa1fcd099495ea671e5d52b655dd7",
      "track_number" : 2,
      "type" : "track",
      "uri" : "spotify:track:0ipvRATjnKeAlIRNS5WqhN"
    }
  } ],
  "limit" : 1,
  "next" : "https://api.spotify.com/v1/users/xxxxx/playlists/xxxxx/tracks?offset=16&limit=1",
  "offset" : 15,
  "previous" : "https://api.spotify.com/v1/users/xxxxx/playlists/xxxxx/tracks?offset=14&limit=1",
  "total" : 87
}

こちらは再生可能なようです。Spotifyアプリ上にも表示されます。

再生する

以下のAPIで音楽を再生できます。 urisが配列なのは、次に再生する曲、さらに次に再生する曲、を指定できるためです。

aurl --profile spotify -X PUT
https://api.spotify.com/v1/me/player/play?device_id=xxxxx_google_home
-d '{"uris":["spotify:track:0ipvRATjnKeAlIRNS5WqhN",
"spotify:track:4TzkNDcjO1wiaRYs2HLXvA"]}'

Google Homeから音楽が再生されました。また、2番目に登録したトラックもPlay Queueに登録されています。

停止する

以下のAPIで再生中のトラックが停止します。

aurl --profile spotify -X PUT
https://api.spotify.com/v1/me/player/pause?device_id=xxxxx_google_home

まとめ

  • Spotify Web APIによって、以下の操作をしてみました。
    • 接続済みのデバイス一覧の取得
    • 登録済みのプレイリストの取得
    • プレイリスト内のトラック一覧の取得
    • 指定したトラックの再生と停止
  • 一部ベータ版のAPIを呼び出しています。これらは予告なしに挙動が変わる可能性があるとのことです。

とりあえず指定した時刻に指定したプレイリストからランダムで音楽が流れるアプリ(≒目覚めし時計)を作ってみようかなという気分です。

私からは以上です。

参考ページ