🌃【後半】Spotify API を使ってBe:Firstの楽曲データや2023年度の世界トレンドを分析してみる!
【追加編集・アップデート:2024年1月4日】
このNote記事を最初に公開してからかなりコードの中身が変わりました。もっとグラフを追加したり、効率化アップを図りました。アップデートバージョンについてはまた新しくNote記事をアップしますのでお楽しみに。
前回からの続きです。詳しくはこちらのNoteから。
今回はいよいよBe:Firstのヒット曲【Mainstream】の楽曲データを取得して、今年Spotifyでグローバルで流行している曲との類似点などを分析してみようと思います。今年は流行っている曲と属性などの性質が似ているのなら、Mainstreamという楽曲も世界で流行するチャンスがあるかもしれません。
Spotify Web API
最初に、楽曲データにSpotify Web APIを通じてアクセスするにはSpotifyのデベロッパーアカウントに登録し、Web APIにアクセスする為の認証情報の取得をする必要があります。これはクライアントIDとクライアントシークレットと呼ばれるもので、いわゆるユーザーIDとパスワードと同じようなものです。これがないと楽曲データにはアクセスできません。
登録ページ https://www.spotify.com/jp/signup
詳しい手順がわかりやすく説明されたウェブサイトを見つけたのでシェアします。
Be:First (Mainstream)の楽曲データにアクセスする!
クライアントIDとクライアントシークレットを取得したらいよいよトラックデータの取得プロセスに入っていきます。
ここからは少しだけテクニカルな内容になりますが、Python言語を使って楽曲データにアクセスします。
色々なシナリオを想定するとコードを変化する必要がありますが、以下は調べたいアーティスト名と楽曲名がわかっている場合のコードです。
#------------ Import Libraries ------------
import requests
import json
# Set your Spotify API credentials
client_id = 'your_client_id'
client_secret = 'your_client_secret'
#------------ Get Access Token ---------------
# Define the endpoint for obtaining an access token
token_url = 'https://accounts.spotify.com/api/token'
# Define the data to be sent in the request
data = {
'grant_type': 'client_credentials',
'client_id': client_id,
'client_secret': client_secret,
}
# Request the access token
response = requests.post(token_url, data=data)
# Parse the JSON response
token_info = response.json()
# Obtain the access token
access_token = token_info['access_token']
#------------ Search for Track ---------------
# Define the artist and track names
artist_name = 'Be:First'
track_name = "Mainstream"
# Define the endpoint URL for track search
search_url = 'https://api.spotify.com/v1/search'
# Define the query parameters for track search
search_params = {
'q': f'artist:{artist_name} track:{track_name}',
'type': 'track',
'limit': 1,
}
# Set the Authorization header with the access token
headers = {
'Authorization': f'Bearer {access_token}',
}
# Make the API request for track saerch
search_response = requests.get(search_url, params=search_params,headers=headers)
# Check for successful response for the track search
if search_response.status_code == 200:
search_data = search_response.json()
# Extract the track ID from the search results
if 'tracks' in search_data and 'items' in search_data['tracks'] and search_data['tracks']['items']:
track_id = search_data['tracks']['items'][0]['id']
#--------------- Retrieve Audio Features --------------
# Define endpoint URL for audio features
audio_features_url = f'https://api.spotify.com/v1/audio-features/{track_id}'
# Make the API request for audio features
audio_features_response = requests.get(audio_features_url, headers=headers)
# Check for successful response for audio features
if audio_features_response.status_code == 200:
audio_features_data = audio_features_response.json()
# print(audio_features_data)
# Save the audio features data to JSON file or do further processing
with open('audio_features.json', 'w', encoding='utf-8') as json_file:
json.dump(audio_features_data, json_file, ensure_ascii=False, indent=4)
else:
print(f"Error fetching audio features: {audio_features_response.status_code}")
else:
print(f"No track found for '{track_name}' by '{artist_name}'")
else:
print(f"Error fetching track: {search_response.status_code}")
一番上の方にclient_id=と client_secret=がありますが、ここには取得したIDとシークレットをペーストします。
(追記・追加編集)この手法はハードコードと呼ばれて、実はあまり良くないプラクティスです。Githubなどでシェアした場合、シークレットが漏洩するからです。本来はあらかじめクライアントIDとシークレットをEnvファイルにセーブしてそのファイルをこのコード内で呼び込む方法を取りますが、その説明だけでも長いNote記事一本書けるくらいなので、これについては今回は省きます。
このコードを実行すると楽曲データが保存されたJSONファイルが作られます。ちなみに中身はこんな感じです。
これがBe:First "Mainstream" の楽曲データです。上部にはダンサビリティーやエネルギーなどの属性がリストアップされているのが見えるかと思います。これらのデータを使って今年の世界トレンド曲とどのくらい曲調が似ているのか、可視化していきたいと思います。
💡その前にPythonのワンポイント基礎知識。これらの属性は{}のなかにディクショナリー(辞書)というデータタイプで保存されています。ディクショナリーの特徴はキーとバリューのコンビネーションです。””の中にはキーを、そして:の右側にバリューを設定します。そうすることで辞書の役割つまり、キーを通じてバリューを引き出す事ができます。このディクショナリーはPython言語ではとても重要な役割を果たす事が多いので覚えておくと便利だと思います。
Be:FirstとSpotifyトレンド曲の比較ビジュアル
今回のアナリシスでは24個ある属性のうち、最も重要なものだけに絞って比較していきたいと思います。ピックアップした属性がこちら。
🕺🏽danceability (ダンスアビリティ)
全体的なテンポ、リズムの安定性、ビートの強さなどの要素を組み合わせて、その楽曲がダンスにどれ程適しているか示す数値。0が踊りにくく、1が最も踊りやすい。
🤗 valence (ヴァレンス)
楽曲の全体的な明るさ、ポジティブさを表す数値。1に近づくにつれて明るい曲。
⚡energy (エナジー)
エネルギッシュだったり激しさを表す数値。1に近づくにつれて激しさを増す。
🎸acounsticness (アコースティックネス)
音響であったり、生楽器系の度を表す数値。1に近づくほど生楽器性が強い曲。
🎻instrumentalness (インストルメンタルネス)
楽器のみ、ボーカルが入っていない度合を示す数値。1に近づくほどボーカルの占める割合が低い。通常のポップミュージックは大抵はこのインストルメンタルネスが0に近い場合が多い。
🎤liveness (ライブネス)
楽曲のライブ感の度合を示す数値。1に近づくほどライブ感が強い楽曲。
🗣️speechiness (スピーチネス)
スピーチ、話している感の度合を示す数値。ラップがベースの楽曲はこの数値が高くなる。通常の歌っている楽曲だとほとんどが0に近い事が多い。
レーダーチャートで比較
さあここからがメインのコードに入ります。
まずは今年Spotifyで良く聴かれている楽曲の属性(Attribute)と、Be:First "Mainstream"の属性の変数(Variable)を作ります。
att_list = ['danceability_%',
'valence_%',
'energy_%',
'acousticness_%',
'instrumentalness_%',
'liveness_%',
'speechiness_%'
]
# Target audio features (Be:First Mainstream)
audio_features = {
"danceability": 0.901,
"valence": 0.52,
"energy": 0.714,
"acousticness": 0.246,
"instrumentalness": 0,
"liveness": 0.0529,
"speechiness": 0.125
}
次に必要なライブラリーを呼び込みます。
import pandas as pd
import plotly.graph_objects as go
そしていよいよメインのコードでレーダーチャートを作ります。
# Calculate mean values for each attribute for the top 100 songs
mean_values_top_100 = df_sorted_100[att_list].mean()
# Create a radar chart for the top 100 songs
fig = go.Figure()
# Add traces for the top 100 songs
fig.add_trace(go.Scatterpolar(
r=mean_values_top_100,
theta=att_list,
fill='toself',
name='Top 100 Songs',
line=dict(color='blue'),
))
# Convert values to percentages for your favorite song
audio_feat_percent = {key: value * 100 for key, value in audio_features.items()}
# Add a trace for your favorite song
fig.add_trace(go.Scatterpolar(
r=list(audio_feat_percent.values()),
theta=att_list,
fill='toself',
name='Target Song (Mainstream)',
line=dict(color='red', dash='dot'),
))
# Update layout settings
fig.update_layout(
polar=dict(radialaxis=dict(visible=True, range=[0, 100])),
showlegend=True,
legend=dict(x=1, y=1, traceorder='normal', orientation='v'),
title='2023 Top 100 Songs Attribute Comparison (vs Be:First Mainstream)',
)
# Show the figure
fig.show()
コード内容を簡単に説明すると、
1.まず今年よく聴かれている曲の属性の平均値を計算し、新しい変数にセーブします。
2.そしてレーダーチャートを作るためのClass Functionのオブジェクトを作ります。(ちなみにこれはインスタンス化という作業でPythonのようなオブジェクト指向プログラミング言語には欠かせないステップです。オブジェクト指向についてはこれも長くなるのでまた今度の機会にNoteを書きます。)
3.それからレーダーチャート上に属性の平均値とBe:First の属性値をトレースしていきます。
コードを実行するとこのようなレーダーチャートが現れます。
青の線が今年最もストリーミングされているトップ10の楽曲から得られた属性データの平均値で、赤のエリアがBe:Firstの最新楽曲Mainstreamの属性データです。
赤と青いエリアがかなりマッチングしている事が分かるかと思います。2023年のトレンド曲とBe:Firstの曲の属性がかなり似ている事が可視化されています。
ダンスアビリティだけがBe:Firstはかなり高いですが、それ以外はほぼマッチングしてると言ってもいいと思います。
ちなみに以下のコードはBPM(テンポ)の比較です。
# Analyzing the distribution of Beats per Minute
plt.figure(figsize=(10,6))
sns.histplot(df_sorted_100['bpm'], bins=50, kde=True)
plt.axvline(x=df_sorted_100['bpm'].mean(), color='red', linestyle='dashed', linewidth=2, label="Mean BPM")
plt.axvline(x=100, color='green', linestyle='dashed', linewidth=2, label='Be:First')
plt.title('Distribution of Beats Per Minute (BPM)')
plt.xlabel('BPM')
plt.ylabel('Frequency')
plt.label('Distribution of Beats per Minute')
plt.legend()
plt.show()
赤い点線が今年度もっとも聴かれている楽曲の平均BPMで、緑の点線がBe:First (Mainstream) のBPMです。Be:First のテンポののほうが20以上も遅めなことがわかります。
【おまけ】じゃあIMP.の最新曲は?
先日、TOBE所属の7人組ボーイズグループであるIMP.が最新楽曲をリリースしました。彼らも同じ7人組でほぼ同世代、そして同じく世界を目指しているという事なので、おまけとしてIMP.も分析してみました。
属性比較の結果がこちらです。
上のレーダーチャートを見るとダンスアビリティはかなり近いですが、ヴァレンス、エネルギー、アコースティックネスについてはかなり違いがみられます。実際、赤と青のエリアがあまり一致していないのも一見して分かるかと思います。
BPMも比較してみました。IMP.のBPMが約130。トレンド曲の平均が約123なので、IMP.のほうがBPMのトレンドに近い値だったことがわかりました。
まとめ
属性(Attribute)はその楽曲の特徴を表す重要な数値です。Be:Firstの Mainstreamという最新楽曲を分析してみたところ、テンポはトレンド楽曲に比べてゆっくりめでしたが、その他の属性は今年頻繁にストリーミングされている楽曲の平均数値にかなり近い事が分かりました。
という事は、Be:First の曲はもしかしたら近い将来世界ランキングに食い込めるだけの素質は十分あると考えても良さそうです。
🚀 これからも疑問に思った事はデータ化して自分なりの答えを探していこうと思います。そしてその答えがどこかにいる誰かの為になる事を願っています。
この記事が気に入ったらサポートをしてみませんか?