オタクの落書き(改)

オタクがぶつぶつ言うだけ

spotifyのAPIで遊ぶ:その3

someone34o2.hatenablog.com

マダアキテナイヨ。

ひっそりと裏でグラフ化して遊ぶところまでは進めていたのだが、なかなか数値が偏りがちで面白い感じにならないな~~とここに投げておくほどじゃねえかと放置していた。

が、今日はせっかくギルキスの2ndライブなので、Aqoursのユニットごとに傾向が出たら面白いな~~と思っていくつか出力してみたので載せていきます。適宜拡大して見てください(他力本願)。ちなみにすべて範囲はtempo以外0.0~1.0の値ですが、グラフの範囲はその限りではないので注意してください。

  • danceability-energy f:id:someone34o2:20210925121851p:plain

Danceability分かり味が深い、よくわかってる。でもFarewell partyはもう少し高くても良くない?ストトラが最低値なのは意外っちゃ意外だけどまあ踊る曲じゃねえかと言う気持ち。

縦軸はめんどくて全部energyにしておいた。大体納得の結果。ぎるとしゃろは上に固まってて一部低めのものがあるという感じだけど、あぜは比較的散っている気もする。ちゃんと分散を計算しなさ~~~い!!!ごめんなさい。

  • valence-energy f:id:someone34o2:20210925121847p:plain

valenceは曲のポジティブさを表すらしい。大方合っているような気はするが最高値近辺は結構怪しそう。P.S.って結構曲だけでも寂しさ溢れてない?先入観かもしれない。その辺がしゃろの売りというか良さなのかもしれない(適当)

  • acousticness-energy f:id:someone34o2:20210925121859p:plain

あのさあ……。まあそりゃクラシックとかも含めることを考えればそうなるんでしょうが。とはいえ結構納得の結果。

  • tempo-energy f:id:someone34o2:20210925123920p:plain

それを最初に出さんかい!!という意見が聞こえてきそうだが精度が怪しかったので。単位はいわゆるBPMだと思う。一部のテンポが速い/遅い曲がそれぞれ0.5/2倍として捉えられてしまっていそうなものが見受けられる。コワレヤスキが半分に見られるのはまあ分かるけど、Shooting Start Warriorは言うほどか?Deep Sea Cocoonと逆と言われても納得する。コドク・テレポートは「テレポ」で拍取るとまあそうなるんかな。あと2サビ後の3拍子のせいもありそうで分かる。CHANGELESSが180なのは流石に草生える。とは言え大体は順に曲名を眺めていくとなるほど~~~となるのでなんだかんだ分かりやすいとは思う。

まあこんなもんでしょうか。キーとかMajor/Minorでユニットごとの集計したりってのも面白いかもしれないけどとりあえずここまで。しゃろの頃にやる気になったら何かするかもしれない。


おまけのコード。これいる?そもそも普通github貼って終わりだよね?

json形式で出力するように改造。後から魔改造するからめちゃくちゃになってくるやつ。

from io import FileIO
import sys
import re
import json
import datetime
import spotipy
from spotipy.oauth2 import SpotifyClientCredentials
import codecs

# 見せられないよ
client_id = 
client_secrtet =

credential = SpotifyClientCredentials(client_id, client_secrtet)

spotify = spotipy.Spotify(client_credentials_manager = credential)

# メイン関数
def main_func(_share_link):
    (kind, target_uri) = uri_getter(_share_link)
    _name_list, _id_list = get_track_id_list(kind, target_uri)

    ret = {}
    cnt = 0
    for _track_id in _id_list:
        try:
            track_features = spotify.audio_features(_track_id)
            # track_analysys = spotify.audio_analysis(_track_id)
        except Exception as ex:
            print(ex)
            continue
        # ret[_name_list[cnt]] = {'features': track_features, 'analysys':track_analysys}
        ret[_name_list[cnt]] = track_features
        cnt = cnt + 1

    _datetime = datetime.datetime.now()
    _file_name = 'track_feature_{}.json'.format(_datetime.strftime('%Y%m%d%H%M%S'))

    # json出力
    with codecs.open(_file_name, 'w', encoding='utf-8') as f:
        json.dump(ret, f, ensure_ascii=False, indent=4)

# 対象リンクごとに対象とする曲の名前とidのリストを生成
def get_track_id_list(kind, uri):
    _uri_list = []
    _name_list = []
    if kind == 'playlist':
        targets = spotify.playlist_tracks(uri)
        for element in targets['items']:
            _uri_list.append(element['track']['id'])
            _name_list.append(element['track']['name'])
    elif kind == 'artist':
        targets = spotify.artist_top_tracks(uri)
        for element in targets['tracks']:
            _uri_list.append(element['id'])
            _name_list.append(element['name'])
    elif kind == 'track':
        target = spotify.track(uri)
        _uri_list.append(target['id'])
        _name_list.append(target['name'])
    elif kind == 'album':
        targets = spotify.album_tracks(uri)
        for element in targets['items']:
            _uri_list.append(element['id'])
            _name_list.append(element['name'])
    else:
        print('{} content is not suported.'.format(kind))

    return (_name_list, _uri_list)

# リンクからuriを生成する
def uri_getter(share_link):
    _link = re.split('[/?]', share_link)
    # [0] = https, [1] = '', [2] = open.spotify.com
    _kind = _link[3]
    _link[2] = 'spotify'
    return (_link[3], ':'.join(_link[2:5]))



if __name__ == '__main__':
    _arg_list = sys.argv

    if len(_arg_list) == 1:
        print('input share link of spotify content')
        exit()

    main_func(_arg_list[1])

文字コード類で結構こけた。

上で吐き出したjsonからプロット出力。これもまた日本語文字コード指定周りがめんどかった。人類早くエスペラント語で統一せんか?まあある意味プログラミング言語は国籍を問わない言語ですが(統一できているとは言っていない)

こっちも色々キメラ化していて、そこから一部を切って張り付けたのでそのままじゃこけるかもしれない。どうせ誰も使わんからヨシ!(最低)

import sys
import json
import os.path
import matplotlib
from matplotlib import font_manager
import matplotlib.pyplot as plt

X_AXE = 'acousticness'
Y_AXE = 'energy'


# おもしろそう
# energy, danceability, acousticness, valence
# あんまり関係なさそう
# speechiness, instrumentalness
# 尺度が違う
# key:C = 0?
# loudness:-の値で大きいほどやかましいはず
# mode:0=minor, 1=major
# tempo:テンポ


def compare(json_path_list):
    color_list = ['orange', 'pink', 'purple']
    for _color, _json in zip(color_list, json_path_list):
        with open(_json, mode='r', encoding='utf-8') as f:
            _dict = json.load(f)

            _track_list = list(_dict.items())
            x_axes = []
            y_axes = []
            for _name, _track in _track_list:
                print(_name)
                x_axes.append(_track[0][X_AXE])
                y_axes.append(_track[0][Y_AXE])

            plt.rcParams['font.family'] = 'MS Gothic'
            plt.scatter(x_axes, y_axes, marker = 'o', linestyle = 'None', color = _color)

            for _name, _track in _track_list:
                _info = _track[0]
                plt.annotate(_name, xy = (_info[X_AXE], _info[Y_AXE]))

    plt.title('Aqours unit compare')
    plt.xlabel(X_AXE)
    plt.ylabel(Y_AXE)
    plt.show()


if __name__ == '__main__':
    compare(sys.argv[1:4])
    exit()

アルバム読み込ませて、名前伏せて曲を当てるゲームも面白いかもしれない。そういうの作れたらおもろいんだけどね、将来の目標にしておきます。