0
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

めんどい太郎のAdvent Calendar 2023

Day 12

SpotifyのAPIを使ってみる

Last updated at Posted at 2023-12-11

本記事は、めんどい太郎の Advent Calendar 2023 12日目の記事です。

はじめに

この記事は初心者が書いています。

皆さんはSpotify、使ってますか?

私は以前Spotifyを使っていました。

今回はSpotifyのAPIを使ってみようと思います。

Spotifyもドキュメントがわかりやすいので、読むのをおすすめします。

なんなら、ここで試すこともできます。

この記事で紹介するコードは不完全であり、テストのためにセキュリティ面を考慮してない実装があります。

SpotifyのAPI

SpotifyのAPIでは楽曲の検索やプレイヤーの操作など様々なことができます。

個人的にはプレイヤーの操作が気になります。

それでは早速使ってみましょう。

試す

アプリの登録とClient ID,secretの取得

Spotifyはデベロッパー向けサイトがあります。

まずはそこにアクセスし、APIキーなどを取得します。

Home | Spotify for Developers

右上にログインボタンがあるので押してログインします。

image.png

ログインすると、先程のボタンがユーザー名に変わるのでクリックしダッシュボードを開きます。

image.png

Create Appをクリックし、アプリを作成します。

image.png

アプリの名前や概要、サイトのURLなどを入力します。

そして、リダイレクトURIと使用する予定のAPI/SDKを選択します。

今回はWeb APIだけを選択します。

image.png

(自分のWebサイトにSpotifyのプレイヤーを実装できちゃうんですね...便利。)

Saveを押してアプリを作成すると、アプリのホームに移動します。

image.png

ホームでアプリの利用者数などの様々な情報を見ることができます。

右上のSettingsを押して、設定に移動します。

ここで表示されるClient IDClient secretをメモしておきます。

(Client secretはView Client secretを押すことで表示されます。)

image.png

トークン取得

それでは早速APIを使ってみます。

SpotifyのAPIではまずClient IDClient secretを用いてトークンを取得する必要があります。

トークンの取得はhttps://accounts.spotify.com/api/tokenにPOSTを送ります。

curlでやってみましょう。

curl -X POST "https://accounts.spotify.com/api/token" -H "Content-Type: application/x-www-form-urlencoded" -d "grant_type=client_credentials&client_id={Client id}&client_secret={Client secret}"

こんな感じで行います。

ヘッダーにContent-Type: application/x-www-form-urlencodedを指定し、送るデータにgrant_typeclient_idclient_secretを指定します。

実行するとトークンが返ってきます。

以下はドキュメント記載のサンプルです。

{
  "access_token": "BQDBKJ5eo5jxbtpWjVOj7ryS84khybFpP_lTqzV7uV-T_m0cTfwvdn5BnBSKPxKgEb11",
  "token_type": "Bearer",
  "expires_in": 3600
}

これでトークンの取得ができました。

トークンは1時間有効です。

検索

検索に使用するURLはhttps://api.spotify.com/v1/searchです。

先程入手したトークンを使います。

curl "https://api.spotify.com/v1/searchq={search_text}&type={album,track,artist}&market=JP&limit={contents_limit}" -H "Authorization: Bearer {Token}"

こんな感じです。

GETリクエストを送信します。

ヘッダーにAuthorization: Bearer でトークンを送ります。

データは下の図に載せます。

項目名 概要
q 検索文字列 URLエンコードする必要あり。
type 検索する対象の種類 album,track,artistなど
market 検索する対象の国 JPなど
limit 返してもらう検索結果の数

このように指定します。

それでは実際にやってみます。

curl "https://api.spotify.com/v1/search?q=FutureBase&type=track&market=JP&limit=1" -H "Authorization: Bearer {Token}"
{
  "tracks" : {
    "href" : "https://api.spotify.com/v1/search?query=FutureBase&type=track&market=JP&offset=0&limit=1",
    "items" : [ {
      "album" : {
        "album_type" : "single",
        "artists" : [ {
          "external_urls" : {
            "spotify" : "https://open.spotify.com/artist/2nKGmC5Mc13ct02xAY8ccS"
          },
          "href" : "https://api.spotify.com/v1/artists/2nKGmC5Mc13ct02xAY8ccS",
          "id" : "2nKGmC5Mc13ct02xAY8ccS",
          "name" : "Kizuna AI",
          "type" : "artist",
          "uri" : "spotify:artist:2nKGmC5Mc13ct02xAY8ccS"
        } ],
        "external_urls" : {
          "spotify" : "https://open.spotify.com/album/4EXNitbM0G8ligJXUodkGE"
        },
        "href" : "https://api.spotify.com/v1/albums/4EXNitbM0G8ligJXUodkGE",
        "id" : "4EXNitbM0G8ligJXUodkGE",
        "images" : [ {
          "height" : 640,
          "url" : "https://i.scdn.co/image/ab67616d0000b27375c00310c13c39dfcc103044",
          "width" : 640
        }, {
          "height" : 300,
          "url" : "https://i.scdn.co/image/ab67616d00001e0275c00310c13c39dfcc103044",
          "width" : 300
        }, {
          "height" : 64,
          "url" : "https://i.scdn.co/image/ab67616d0000485175c00310c13c39dfcc103044",
          "width" : 64
        } ],
        "is_playable" : true,
        "name" : "future base",
        "release_date" : "2018-10-26",
        "release_date_precision" : "day",
        "total_tracks" : 1,
        "type" : "album",
        "uri" : "spotify:album:4EXNitbM0G8ligJXUodkGE"
      },
      "artists" : [ {
        "external_urls" : {
          "spotify" : "https://open.spotify.com/artist/2nKGmC5Mc13ct02xAY8ccS"
        },
        "href" : "https://api.spotify.com/v1/artists/2nKGmC5Mc13ct02xAY8ccS",
        "id" : "2nKGmC5Mc13ct02xAY8ccS",
        "name" : "Kizuna AI",
        "type" : "artist",
        "uri" : "spotify:artist:2nKGmC5Mc13ct02xAY8ccS"
      } ],
      "disc_number" : 1,
      "duration_ms" : 183500,
      "explicit" : false,
      "external_ids" : {
        "isrc" : "TCJPI1801999"
      },
      "external_urls" : {
        "spotify" : "https://open.spotify.com/track/6n6Kf8A4uKIpRNCm68yYBw"
      },
      "href" : "https://api.spotify.com/v1/tracks/6n6Kf8A4uKIpRNCm68yYBw",
      "id" : "6n6Kf8A4uKIpRNCm68yYBw",
      "is_local" : false,
      "is_playable" : true,
      "linked_from" : {
        "external_urls" : {
          "spotify" : "https://open.spotify.com/track/4NtdvYIPuCu7rGVryVgTWG"
        },
        "href" : "https://api.spotify.com/v1/tracks/4NtdvYIPuCu7rGVryVgTWG",
        "id" : "4NtdvYIPuCu7rGVryVgTWG",
        "type" : "track",
        "uri" : "spotify:track:4NtdvYIPuCu7rGVryVgTWG"
      },
      "name" : "future base",
      "popularity" : 24,
      "preview_url" : "https://p.scdn.co/mp3-preview/f85c348040c1072b3832a0fccb5c81d34dfefcfb?cid=44c653a8530b4cd387663a68dac0fde0",
      "track_number" : 1,
      "type" : "track",
      "uri" : "spotify:track:6n6Kf8A4uKIpRNCm68yYBw"
    } ],
    "limit" : 1,
    "next" : "https://api.spotify.com/v1/search?query=FutureBase&type=track&market=JP&offset=1&limit=1",
    "offset" : 0,
    "previous" : null,
    "total" : 860
  }
}

こんな感じで返ってきました。

様々な情報が返ってきました。

SpotifyのAPIでは取得することのできる情報が非常に多いです。

ですので今回は詳しく解説しません()

確実にドキュメント見たほうがわかりやすいです。

ですので、一部だけ紹介します。

preview_urlは視聴用音声へのリンクです。

audioとかでこのURLを指定してあげると、視聴用音声が聞けちゃいます。

便利。

imagesはアルバムアートやアーティスト画像なのですが、サイズが大きいです。

そのため比較的きれいな画像が取得できます。

認可コード

プレイヤーの操作をする前に、認可コードを取得する必要があります。

Spotifyへのログインが求められますので、PHPでやってみます。

といってもLINEログインとほぼ同じようです。

とゆことで10日の記事からほぼほぼ持ってきます。

<?php
function rand_str_gene($length) {
    return substr(str_shuffle("ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnpqrstuvwxyz0123456789"), 0, $length);
}

$client_id = '';//メモしたClient ID
$redirect_uri = 'https://example.com/callback/';
$redirect_uri = urlencode($redirect_uri);
$state = rand_str_gene(32);
$scope = urlencode('user-read-currently-playing user-read-playback-state user-modify-playback-state');

$login_url = 'https://accounts.spotify.com/authorize?response_type=code&client_id=' . $client_id . '&redirect_uri=' . $redirect_uri . '&state=' . $state . '&scope=' . $scope;

file_put_contents("csrf_token.txt", $state);

?>

スコープは (半角スペース)で区切るようです。

スコープは多すぎるのでドキュメントを見てください。

今回は後ほど必要なスコープを指定しています。

リダイレクト先の方もサクッと書きます

<?php

$client_id = '';//メモしたクライアントID
$redirect_uri = 'https://example.com/callback/';
$scope = urlencode('user-read-currently-playing user-read-playback-state user-modify-playback-state');
$client_secret = '';//メモしたクライアントシークレット

if(!empty($_GET['error'])) {
    $error_code = $_GET['error'];
} else {
    // GET_CODE
    $get_code = $_GET['code'];
    $get_state = $_GET['state'];
    // GET_GENERATE_TOKEN
    $contents = file("../csrf_token.txt");
    $before_login_gene_token = $contents[0];

    // GET_TOKEN
    // GET_Token(POST)
    $CURLERR = NULL;

    $data = array(
        'grant_type' => 'authorization_code',
        'code' => $get_code,
        'redirect_uri' => $redirect_uri,
        "client_id" => $client_id,
        "client_secret" => $client_secret
    );

    $headers = array(
        'Content-Type' => 'application/x-www-form-urlencoded',
    );

    $url = 'https://accounts.spotify.com/api/token';

    $ch = curl_init($url);

    curl_setopt($ch, CURLOPT_POST, TRUE);                            //POSTで送信
    curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
    curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data));    //データをセット
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);                    //受け取ったデータを変数に
    $token_response = curl_exec($ch);

    if(curl_errno($ch)){        //curlでエラー発生
        $CURLERR .= 'curl_errno:' . curl_errno($ch) . "\n";
        $CURLERR .= 'curl_error:' . curl_error($ch) . "\n";
        $CURLERR .= '▼curl_getinfo' . "\n";
        foreach(curl_getinfo($ch) as $key => $val){
            $CURLERR .= '■' . $key . ':' . $val . "\n";
        }
        echo nl2br($CURLERR);
    }
    curl_close($ch);

    //echo $token_response.'<br>';
    
    $json_token_response = json_decode($token_response, true);
    print_r($json_token_response);

    //Error Check
    if(!empty($json_token_response['error'])){
        echo 'Error: <br>';
        echo $json_token_response['error'] . '<br>';
        echo $json_token_response['error_description'] . '<br>';
        exit();
    }
}
?>

公式ドキュメントの方法でやるとうまく行かなかったので、少し方法を変えています。

がしかし、ほぼ同じです。

image.png

ログインURLへ行くと...

image.png

大丈夫そうですね。

そしてリダイレクト先にトークンが表示されます。OK!

プレイヤー操作

次はプレイヤーの操作をしてみます。

まずはテキトーにスマホなどのSpotifyで音楽を再生します。

そしたらなんの音楽を聞いているのかを取得してみたいと思います。

curl POST 'https://api.spotify.com/v1/me/player' --header 'Authorization: Bearer {Token}'

トークンは先程ログインして入手したものを用います。

レスポンスが返ってきましたが、詳細は念のため公開しないでおきます。

ここで、deviceidや再生中の音楽の詳細など様々な情報が入手できます。

それでは、曲を変えてみたいと思います。

curl POST 'https://api.spotify.com/v1/me/player/queue?uri={music_uri}&device_id={device_id}' --header 'Authorization: Bearer {Token}'

music_uriは楽曲情報を入手した際に記載されていたものです。

spotify:{track,album}:{id}といった形式のようです。

URLエンコード必須です。

device_idは先程入手したidを指定します。

それではやってみます。

{
  "error" : {
    "status" : 403,
    "message" : "Player command failed: Premium required",
    "reason" : "PREMIUM_REQUIRED"
  }
}

SpotifyPremiumが必要だよ!と怒られてしまいました。

おわり

Spotifyのプレイヤー関連はSpotifyPremiumに加入しないとだめなものが多いです。

残念ながらPremiumに加入する財力がないので試せません。残念。

まぁほかも同じようにすることでできるので大丈夫でしょう()

終わりに

SpotifyのAPIはできることが多く、非常に便利ですね。

ですが、APIを使うユーザーがPremiumに加入していないと色々制限されます。

SpotifyPremiumが必要だよ!と怒られたときの対処を考えないとですね。

また雑な記事になっちゃいました...

0
3
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
0
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?