먼저 API에 조금은 생소한 분들은 전에 작성한 두개 포스트를 보시면 이어서 아래 내용도 무리없이 이해하실 수 있을 것 같습니다.

 

Spotify Open API 사용하기 (1)
Spotify Open API 사용하기 (2)

 

Spotify에서는 Open API를 제공하고 가수및 앨범과 노래들에 대한 다양한 정보를 얻을 수 있습니다.
그리고 그 중 조금은 주목할만한 기능이 두가지 있습니다.

  • audio_analysis
  • audio_features

audio_analysis는 노래 그자체의 frequency같은 원초적인 데이터를 그대로 보여줍니다만 여기까지 이용하는 것은 아직은 아니라고 생각합니다만 다음 기회에 다뤄보려 합니다. 그리고 audio_features가 이번 포스트에 다뤄볼 주제입니다.

audio_features는 각 노래의 특징들을 수치화하여 보여주는 기능입니다.

일단 각설하고 파이썬 코딩을 작성해 보겠습니다.

import spotipy
from spotipy.oauth2 import SpotifyClientCredentials
import pprint

class Spotify_audio_features:
    def __init__(self):
        # initial setting
        cid = '부여받은 id'
        secret = '부여받은 비밀키'

        client_credentials_manager = SpotifyClientCredentials(client_id=cid, client_secret=secret)
        self.sp = spotipy.Spotify(client_credentials_manager=client_credentials_manager)

스포티파이 개발자 페이지에서 부여받은 아이디와 비번을 기지고 위와 같이 작성합니다.
이제 self.sp 함수를 가지고 각 정보를 얻어내 봅시다.

    def get_features(self, song):
        # get track id information
        track_info = self.sp.search(q=song, type='track', market='JP')
        track_id = track_info["tracks"]["items"][0]["id"]

        # get audio_feature
        features = self.sp.audio_features(tracks=[track_id])
        acousticness = features[0]["acousticness"]
        danceability = features[0]["danceability"]
        energy = features[0]["energy"]
        liveness = features[0]["liveness"]
        loudness = features[0]["loudness"]
        valence = features[0]["valence"]
        mode = features[0]["mode"]

        result = {"acousticness" : acousticness,
                    "danceability" : danceability,
                    "energy" : energy,
                    "liveness" : liveness,
                    "loudness" : loudness,
                    "valence" : valence,
                    "mode" : mode}

        return result

이어서 get_features(self, song): 함수를 만들고 이때 인자는 노래 곡명입니다. search를 이용하여 이 때 쿼리q=는 노래명, type=은 'track'으로 진행합니다.(market=은 사실 필요없습니다.)

 

그리고 이에 대한 결과는 많은 정보들이 들어가 있습니다.(앨범정보, 가수정보, 사진, 길이, 인기도 등) 하지만 이경우 같은 제목의 노래들이 여러개 검색되기 때문에 가수 이름도 함께 확인하여 내가 원하는 트랙을 정확히 확인하도록 합니다.

 

그리고 track_id라는 변수를 만들어 track의 id정보를 빼 옵니다. 위의 [0]은 첫번째 곡을 의미합니다.

 

이제 track_id를 가지고 audio_features를 사용합니다.


결과를 features에 저장하였고 함수의 각 특징들을 최종 딕셔너리 형태로 return하도록 하여 코드를 마칩니다.

위의 코드 예제는 없지만 pprint를 이용해서 한번 출력해봅니다.


참고로 노래는 BTS의 Dynamite 입니다.😂

[{'acousticness': 0.0112,
  'analysis_url': 'https://api.spotify.com/v1/audio-analysis/4saklk6nie3yiGePpBwUoc',
  'danceability': 0.746,
  'duration_ms': 199054,
  'energy': 0.765,
  'id': '4saklk6nie3yiGePpBwUoc',
  'instrumentalness': 0,
  'key': 6,
  'liveness': 0.0936,
  'loudness': -4.41,
  'mode': 0,
  'speechiness': 0.0993,
  'tempo': 114.044,
  'time_signature': 4,
  'track_href': 'https://api.spotify.com/v1/tracks/4saklk6nie3yiGePpBwUoc',
  'type': 'audio_features',
  'uri': 'spotify:track:4saklk6nie3yiGePpBwUoc',
  'valence': 0.737}]

그리고 주요 특징들은 다음과 같습니다.

  • danceability : 춤 추기에 적합한가? 0.0 - 1.0 범위이며 값이 클 수록 춤추기 좋음.
  • energy : 말그대로 에너지의 정도라고 받아들이면 될 것 같습니다. 0.0 - 1.0 번위이며 빠르고 화려하고 노이즈가 많은 음악일수록 값이 큽니다.
  • instrumentlness : 노래에 보컬이 있는 정도입니다.(0.0 - 1.0)
  • liveness : 노래의 라이브 정도를 나타냅니다. 라이브 음원일수록 값이 높겠지요?
  • loudness : 소리의 화려함/큼 정도를 보여줍니다.(데시벨 값으로 보여준다고 하네요.)
  • mode : major(장조) = 1, minor(단조) = 0 입니다.
  • speechiness : 말하는 정도를 보여줍니다. 스포티파이에서는 팟캐스트를 통해 토크쇼나 오디오북 등도 제공하는데 노래와 비교해서 값이 높겠지요?
  • tempo : 템포, beats per minute(BPM) 입니다.
  • valence : 음원의 밝음 정도를 나타내줍니다. 밝고 행복하고 기쁘면 값이 높고 반대로 슬프고 화나고 우울하면 값이 낮다고 하는데 가장 흥미로운 요소인 듯 합니다.😏

 

이제 위의 각 요소에 대한 설명을 보고 노래의 특징을 보겠지만 역시 꽤 불편합니다. 문득 떠오른 생각은 아래와 같은 그래프로 한눈에 곡의 특징을 알아보면 가장 좋을 것 같습니다.

 

찾아보니 위와 같은 그래프를 레이더 그래프 또는 스파이더 그래프라고 하더군요.(방사형) 그리고 위의 코딩은 아래 블로그를 통해 배우고 코드도 거의 그대로 가져다 썼습니다. (감사합니다.😁)
https://zephyrus1111.tistory.com/63

 

Matplotlib을 이용하여 레이더 차트(Radar chart) 그리기!

안녕하세요~ 꽁냥이에요. 보통 게임 속 캐릭터의 능력치를 나타낼 때 레이더 차트(Radar chart)를 많이 사용합니다. 여러분들도 많이 보셨을 거예요. 레이더 차트는 스파이더 차트(Spider chart)라고도

zephyrus1111.tistory.com

일단 저 위에서 왜 노래를 구분지을 수 있는 특징들은 여럿 있는데 결국 danceability, energy, valence 셋만 쓴 이유는 각 특징들의 실용성에 있어서 굳이 구분지을 필요가 없어서 결국 빼게 되었습니다. 일반적인 노래라면 굳이 노래에 보컬이 어느정도 포함되어 있는지 또는 라이브 정도가 어느정도인지를 알 필요도 없고 안다고 하더라도 그 값이 갖는 의미 자체가 없는 것이지요.

 

이제 matplot 라이브러리를 이용한 시각화 코딩을 봅시다. 앞서 진행한 코드의 경우 main.py로 저장을 해놓고 이제 이 main.py는 하나의 모듈로 나중에 다른 목적으로 노래의 각 특징들을 알고 싶을 때 꺼내다 쓰도록 합니다.(main.py보다는 좀 더 그럴듯한 파일명이 낫겠네요..)

import matplotlib
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np

from math import pi
from matplotlib.path import Path
from matplotlib.spines import Spine
from matplotlib.transforms import Affine2D
from pandas.core import frame

from main import Spotify_audio_features

saf = Spotify_audio_features()
song_title = "dynamite"

feat = saf.get_features(song_title)
df = pd.DataFrame({
    'song': [song_title],
    'danceability': [feat['danceability']],
    'energy': [feat['energy']],
    'valence': [feat['valence']]
})
print(df)

matplotlib.rc('font', family='malgun gothic')
labels = df.columns[1:]
num_labels = len(labels)
print(num_labels)

angles = [x/float(num_labels)*(2*pi) for x in range(num_labels)]
angles += angles[:1]
print(angles)

# color depending on the mode (major or minor)
if feat['mode'] == 1: color = "steelblue"
else: color = "mediumseagreen"

fig = plt.figure(figsize=(5,5)) # Window size, figsize-tuple x 100 pixel...
fig.set_facecolor('white') # background color

for i, row in df.iterrows():
    print(i)
    print(row)
    data = df.iloc[i].drop('song').tolist()
    data += data[:1]
    print(data)

    # generate graphs
    ax = plt.subplot(1,1,i+1, polar=True) #args : nrows, ncols, index, **kwargs
    ax.set_theta_offset(pi / 2) 
    ax.set_theta_direction(-1)

    plt.xticks(angles[:-1], labels, fontsize=13)
    ax.tick_params(axis='x', which='major', pad=15)

    ax.set_rlabel_position(0)
    plt.yticks([0,0.2,0.4,0.6,0.8,1], ['0','0.2','0.4','0.6','0.8','1'], fontsize=8)
    plt.ylim(0,1)

    ax.plot(angles, data, color=color, linewidth=2, linestyle='solid')
    ax.fill(angles, data, color=color, alpha=0.4)

    plt.title(row.song, size=20)

plt.tight_layout(pad=5)
plt.show()

먼저 관련 라이브러리/모듈을 임포트 합니다. 보통 matplot을 사용할 경우 pandasnumpy는 따라오게 마련이고 matplot안의 여러 모듈들을 불러왔습니다. (앞서 언급한 블로그에서 그대로 복붙 했습니다.😅) 그리고 마지막에 저희가 앞서 만든 Spotify_audio_features 모듈도 불러왔습니다.

 

이어서 "dynamite" 노래를 Spotify_audio_features를 이용하여 분석하고 그 값을 df란 이름의 DataFrame으로 저장합니다.


그리고 그래프 선의 색을 노래의 장/단조 차이에 따라 구분하였습니다.(결국 4가지 특징을 보여주는 것이지요.)

위의 코드에서 가장 중요한 코드는 angles값을 정하는 코드와 plt.subplot의 파라미터 polar=True로 설정해주는 것이 일반 그래프가 아닌 방사형 그래프를 만들어 주는 핵심 포인트입니다.

 

사실 matplot을 그렇게 사용해보지 않고 수학에도 약해서 더이상 설명을 못 드리겠습니다. 하지만 잘 몰라도 배우고 하면 늦습니다. 그냥 하면서 배우면 됩니다.😎

 

 

사실 처음에 기대한 여러 특징들 중 결국 쓸만한 건 danceability, energy, valence, mode 정도밖에 없어 조금은 실망입니다.


하지만 이대로 포스트를 끝내지 않고 실제 결과들이 우리가 직접 느끼는 것과 얼마나 비슷할 지 테스트해 봅시다.


사실 이러한 기준들도 human들이 차이를 느끼는 기준에 따라 분류한 것이겠지만요.🤓

Dynamite - BTS

100점 만점 중 75점수준으로 큰 정삼각형을 보여주고 있습니다. 밝고 에너지 넘치는 춤추기에도 좋은 곡입니다. 그런데 그래프 선이 mediumseagreen으로 키가 마이너(단조)입니다? 악보를 안봤지만...

Celebrity - 아이유

마지막처럼 - 블랙핑크

역시 밝고 에너지 넘치는 K-Pop입니다. 그렇다면 정반대의 느낌을 가진, 슬프고 우울하고 기분나쁜 느낌일 듯한 곡들은 어떨까요?

Saddest Thing - Melanie

Mad World - Gary Jules

Gloomy Sunday - Billie Holiday

이 노래들을 모르셔도 제목들만 보고 곡의 느낌을 예상하실 수 있습니다. 결과도 역시나... 

(궁금하신 분들은 유튜브에서 들어보세요.)

 

아무튼 재밌지만 뭔가 응용하여 사용하기엔 좀 더 고민을 해봐야 겠습니다.😁

+ Recent posts