File size: 4,518 Bytes
6d39409
fca73a6
db7246b
 
fca73a6
 
 
 
 
db7246b
 
 
 
 
 
5554bdf
 
db7246b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
import os

import numpy as np
import pandas as pd
import requests
import spotipy
import streamlit as st
from PIL import Image
from spotipy.oauth2 import SpotifyClientCredentials

st.set_page_config(
    page_title="Find Songs Similar to Yours🎤", page_icon="🎤", layout="wide"
)

# Spotify API
SPOTIPY_CLIENT_ID = os.environ["CLIENT_ID"]
SPOTIPY_CLIENT_SECRET = os.environ["CLIENT_SECRET"]

sp = spotipy.Spotify(
    auth_manager=SpotifyClientCredentials(
        client_id=SPOTIPY_CLIENT_ID, client_secret=SPOTIPY_CLIENT_SECRET
    )
)

"""
# Analyze Song and Get Recommendations🎤

Input a song title and the app will return recommendations as well as the features of the song.

Data is obtained using the Python library [Spotipy](https://spotipy.readthedocs.io/en/2.18.0/) that uses [Spotify Web API.](https://developer.spotify.com/documentation/web-api/)
"""
song = st.text_input("Enter a song title", value="Somebody Else")
search = sp.search(q="track:" + song, type="track")


class GetSongInfo:
    def __init__(self, search):
        self.search = search

    def song_id(self):
        song_id = search["tracks"]["items"][0]["id"]  # -gets song id
        return song_id

    def song_album(self):
        song_album = search["tracks"]["items"][0]["album"][
            "name"
        ]  # -gets song album name
        return song_album

    def song_image(self):
        song_image = search["tracks"]["items"][0]["album"]["images"][0][
            "url"
        ]  # -gets song image URL
        return song_image

    def song_artist_name(self):
        song_artist_name = search["tracks"]["items"][0]["artists"][0][
            "name"
        ]  # -gets artist for song
        return song_artist_name

    def song_name(self):
        song_name = search["tracks"]["items"][0]["name"]  # -gets song name
        return song_name

    def song_preview(self):
        song_preview = search["tracks"]["items"][0]["preview_url"]
        return song_preview


songs = GetSongInfo(song)

###


def url(song):
    url_to_song = "https://open.spotify.com/track/" + songs.song_id()
    st.write(
        f"Link to stream '{songs.song_name()}' by {songs.song_artist_name()} on Spotify: {url_to_song}"
    )


# Set up two-column layout for Streamlit app
image, stats = st.columns(2)

with image:
    try:
        url(song)
        r = requests.get(songs.song_image())
        open("img/" + songs.song_id() + ".jpg", "w+b").write(r.content)
        image_album = Image.open("img/" + songs.song_id() + ".jpg")
        st.image(
            image_album,
            caption=f"{songs.song_artist_name()} - {songs.song_album()}",
            use_column_width="auto",
        )

        feat = sp.audio_features(tracks=[songs.song_id()])
        features = feat[0]
        p = pd.Series(features).to_frame()
        data_feat = p.loc[
            [
                "acousticness",
                "danceability",
                "energy",
                "liveness",
                "speechiness",
                "valence",
            ]
        ]
        bpm = p.loc[["tempo"]]
        values = bpm.values[0]
        bpms = values.item()
        ticks = np.linspace(0, 1, 11)

        plot = data_feat.plot.barh(
            xticks=ticks, legend=False, color="limegreen"
        )  # Use Pandas plot
        plot.set_xlabel("Value")
        plot.set_ylabel("Parameters")
        plot.set_title(f"Analysing '{songs.song_name()}' by {songs.song_artist_name()}")
        plot.invert_yaxis()
        st.pyplot(plot.figure)
        st.subheader(f"BPM (Beats Per Minute): {bpms}")

        st.warning(
            "Note: Audio previews may have very high default volume and will reset after page refresh"
        )
        st.audio(songs.song_preview(), format="audio/wav")

    except IndexError or NameError:
        st.error(
            "This error is possibly due to the API being unable to find the song. Maybe try to retype it using the song title followed by artist without any hyphens (e.g. In my Blood Shawn Mendes)"
        )

# Recommendations
with stats:
    st.subheader("You might also like")

    reco = sp.recommendations(
        seed_artists=None, seed_tracks=[songs.song_id()], seed_genres=[], limit=10
    )

    for i in reco["tracks"]:
        st.write(f"\"{i['name']}\" - {i['artists'][0]['name']}")
        image_reco = requests.get(i["album"]["images"][2]["url"])
        open("img/" + i["id"] + ".jpg", "w+b").write(image_reco.content)
        st.image(Image.open("img/" + i["id"] + ".jpg"))