J-POPソングは年々短くなっているのかーーpythonを用いた楽曲分析(最後まで無料で読めます)
レコードに針を落とす。
現代となってはもうマニアしかやらないであろうこの行為を、昔は皆が行なっていた。いまはそれが完全に指先一つに代替されつつある。
時代の潮流によって音楽は聴く人だけでなく、楽曲それ自体の性質も変化していくはずである。
ということで、今回はpythonを用いて通時的なJ-POPの分析を、楽曲の長さに絞って分析してみます。
結論だけ知りたい方は下の目次を参照して結論部分に飛んでください。
Spotify APIを使ってみる
今回は月額制音楽ストリーミングサービスであるSpotifyが提供しているAPIを用いて統計的な分析をおこなってみたいと思います。
SpotifyのAPIには、アーティストの検索や、楽曲の情報(アコースティック間)などさまざまなことができるので面白いです。
今回はその中でも楽曲の長さとその楽曲のリリース日を集計しました
最初はpython用のライブラリであるSpotipyを使おうと思ったのですが、アルバムやトラックを取得するリクエストがうまく送れなかったので、アーティストのidだけはSpotipyを用いて、楽曲情報の取得は仕方なくSpotifyのWeb APIを用いてリクエストのcurlコマンドを無理やりpythonのコードに変換することで実現しました。
[追記] 後日、試してみたところ、Spotipyがうまく動作しなかったのは、単純にリクエストが多すぎてリクエスト制限に達していたためだと分かりました。もうcurlコマンドで書いてしまいましたので、多くはそのまま実装しました。
しかし、curlコマンドではアーティストのidが必要ですが、アーティストのidを取得するcurlコマンドがなかったのでidの取得はSpotipyで実現しました。
(2024/01/30 時点)
集計するパラメータ
SpotifyのAPIでできることの紹介などは他の方々がすでになさっていますのでここでは割愛いたします。興味がある方は以下に参考させていただいたnoteの記事がございますのでぜひご参照ください。
以下note等をご参照ください。
今回は、このWebAPIを用いて日本のアーティスト414名から、それぞれ代表曲、top-tracksを10曲ほどとってきて、その曲がリリースされた日と、その楽曲の長さを集計して、各月毎に平均値を取ることによって分析してみたいと思います。
一番下に、参加いただいたアーティストの皆様は以下のjsonファイルにアーティスト名と、Spotify artist_idと一緒にまとめました。
command+Fやcontrol+Fで好きなアーティストが含まれているかを検索してみてください。
コードの全容
以下にコードの全容を貼り付けます。なお、本分ではないので、今回はコードの細かい説明は省きます。
import requests
from requests.exceptions import HTTPError
import pprint
import time
import pandas as pd
import json
# Spotify APIのクライアントIDとクライアントシークレット
client_id = '自分のid'
client_secret = '自分のシークレットコード'
def get_access_token(client_id,client_secret):
# Token取得のためのAPIエンドポイント
token_url = "https://accounts.spotify.com/api/token"
# リクエストボディのデータ
data = {
'grant_type': 'client_credentials',
'client_id': client_id,
'client_secret': client_secret
}
# リクエストヘッダー
headers = {
'Content-Type': 'application/x-www-form-urlencoded'
}
try:
# POSTリクエストを送信してトークンを取得
response_token = requests.post(token_url, data=data, headers=headers)
response_token.raise_for_status() # エラーチェック
# レスポンスのJSONを取得
token_data = response_token.json()
# Spotify APIアクセストークン
access_token = token_data["access_token"]
return access_token
except HTTPError as http_err:
print(f'Error getting access token: {http_err}')
return None
except Exception as err:
print(f'An error occurred: {err}')
return None
# アクセストークンを取得
access_token = get_access_token()
def get_top_tracks(access_token, artist_id):
api_url = f'https://api.spotify.com/v1/artists/{artist_id}/top-tracks'
# リクエストヘッダー
headers = {
'Authorization': f'Bearer {access_token}'
}
# GETリクエストを送信してトップトラック情報を取得
try:
response = requests.get(api_url, headers=headers, params={'market': 'JP'})
response.raise_for_status() # HTTPエラーレスポンスがあれば例外を発生させる
except requests.exceptions.HTTPError as errh:
print ("HTTP Error:", errh)
# ここでエラー処理を行う(例: ログ出力、エラーレスポンスの解析)
print(response)
return None
except requests.exceptions.ConnectionError as errc:
print ("Error Connecting:", errc)
return None
except requests.exceptions.Timeout as errt:
print ("Timeout Error:", errt)
return None
except requests.exceptions.RequestException as err:
print ("OOps: Something went wrong",err)
return None
# レスポンスのJSONを取得
top_tracks_data = response.json()
top_songs_data = []
for track in top_tracks_data["tracks"]:
pprint.pprint(track)
dic = {
"artist_name": track["artists"][-1]["name"],
"song_name": track["name"],
"release_date": track["album"]["release_date"],
"duration_ms": track["duration_ms"]
}
top_songs_data.append(dic)
return top_songs_data
df=pd.DataFrame(columns=["artist_name","song_name","release_date","duration_ms"])
def add_data_to_df(df ,data_list):
# concat関数を使用して複数の行を一気に追加
df = pd.concat([df, pd.DataFrame(data_list)], ignore_index=True)
return df
# JSONファイルから辞書を読み込む
with open('artist_id.json', 'r', encoding='utf-8') as json_file:
loaded_data = json.load(json_file)
for key,value in loaded_data.items():
df=add_data_to_df(df,get_top_tracks(access_token,key))
df=df.sort_values(by="release_date")
df.to_csv('songd_data.csv', index=False)
# release_date列を日付型に変換
df['release_date'] = pd.to_datetime(df['release_date'])
# 年と月の列を作成
df['year_month'] = df['release_date'].dt.to_period("M")
# 年ごとに月ごとの duration_ms 平均を計算
result = df.groupby(['year_month'])['duration_ms'].mean().reset_index()
# 列名を変更
result.columns = ['year_month', 'duration_ms_mean']
result.to_csv('change_of_duration.csv', index=False)
まだまだ不勉強ですので、汚いコードであることはお許しください。
ご参考までに、こちらも一番下に各アーティストの名前と代表楽曲、リリース日と楽曲の長さをまとめたcsvファイルと、それからリリース日の月毎に楽曲の長さの平均値をまとめたcsvファイルを添付いたします。
以下はそのデータから作ったグラフになります。
結論
まずはグラフを再掲します。
y軸の単位が[ms]なので少しわかりにくくなっていますが、400000[ms]は400[s]つまり6分40秒です。ちなみに楽曲の長さが一番長い月は1979年の6月で、この月は矢野顕子さんの「アイル・ビー・ゼア」ただ1曲でした。この曲は403306[ms]で6分43秒の楽曲でした。
お気持ちくらいかもしれませんが、全体的に短くなっているような気もします。1900年代の後半は月によって割とブレているのに対して、2000年代に入ってからはあまりブレがなくなっているのが現代の音楽トレンドとしての特徴を表していると考えられます。
かつてはお気に入りのレコードというものがあり、そのレコードが擦り切れるまで同じものを何度も、何度も聞いていたという時代がありました。
しかしいまとなっては、スマホの台頭により、レコードに針を落とすという行為は完全に指先一つに代替されつつある時代になりました。
さらに月額制で音楽を聴くサブスクが普及し、街を歩くが如く渉猟的に音楽を楽しむような時代になったため、退屈だと感じるような曲はすぐに指先一つで飛ばされてしまう。
レコードやCD 1つ1つという物質的な愛着も薄れている。これは抗えない時代の変化であるのかもしれない。(もちろん私もレコードに触れたことはないですが)
アーティストも、この流れに抗えずに消費者の好み、性質に合わせて曲を制作しようとすると考えると「短く終わる歌が多くなる」傾向にあるのかもしれません
近年では「イントロの長い曲は売れない」「バラードは売れない」などと言われているらしいです。これもサブスクの影響であると考えられます。最初の数秒で聞く人を惹きつけなければ、すぐに飛ばされてしまうという性質上、イントロの短い、BPMの速い曲を作るという方向に流れ、結果的に曲全体の長さが短くなる、という傾向になるのではないかと思います。
ただし現代の音楽についても例外はもちろんあると思います。例えばあいみょんはこのトレンドに逆張りしイントロの長いバラード曲である「裸の心」を2020年06月17日にリリースしています。
(彼女が意図して、あるいは明確な意思があってそういう曲を作ったのかは定かではないですが)
また私はロックバンドのヨルシカの大ファンなのですが、ヨルシカの楽曲には3番まである楽曲が多いと感じます。ヨルシカの作詞・作曲者であるn-bunaさんは2023年4月リリースのアルバム「幻燈」においてこのような現代の人々の音楽の聴き方の変化を憂いたりしています。(これについてはまた今度記事を書くかもしれません)
次回への課題
いかがだったでしょうか。
これからもプログラミングなどを絡めた自由研究ができればいいなと思います。音楽$${\times}$$プログラミングに関しては具体的には以下のようなものを研究してみたいと思いました。
押韻の研究(押韻論も踏まえたい)
個別のアーティスト単位での分析(いちアーティストに注目したコーパスとか)
音楽理論を踏まえた分析(私は全くの無学なのでこれはできるか分かりません)
また、音楽は話し言葉なのか、書き言葉なのかなど面白い疑問も浮かんできたので今後も気ままに調べられたらいいと思います。
最後まで読んでくださりどうもありがとうございました。
以下は今自由研究に使ったデータです。
ここから先は
¥ 100
この記事が気に入ったらサポートをしてみませんか?