preloader image
15.04.2024
Data Fun

Data Makes Music – Spotify writes Udio Pompts

01

Trending

The rise of the Music AI

In recent weeks, innovative music tools like Suno and udio entered the stage and captured significant attention. By simply inputting text prompts, users can generate amazingly dense, natural, and beautiful songs. Although these tools have drawn considerable criticism from artists concerning their opaque sources of training material, users have flocked to them to try out their services.

While early adopters were sharing their creations, I noticed a recurring theme: Non-musicians (like myself) often struggle to form their preferences into effective prompts. Consequently, many experiment with these powerful services are using absurd, quirky prompts such as “18th-century synthesizer techno about the Heisenberg phenomenon.” While they marvel at the novelty, they soon turn away.

In the course of this post, we will develop a Python script to transform the songs and styles you really like into data, and then into prompts. This creative exploration translates Spotify’s detailed audio metrics into highly descriptive tokens for udio.

02

Start here

Prerequisites

  • - A well curated Spotify account that reflects your listening habits.
  • - Optional: access to the openAI API to improve the lyric analysis and generation.
  • - Basic knowledge how to setup and run Python scripts on your computer

03

Basics

Spotify’s music data

In 2014, Spotify acquired the the music intelligence service “The Echo Nest”. By then, Echo Nest already had 10 years experience in sourcing music data and telling creative narratives around it. This laid the foundation for Spotify’s extensive music data expertise. Spotify not only stores title and artist information but also calculates detailed audio features for each track for analysis and recommendations. You can find out more in Spotify’s developer documentation — a set of helpful resources that explains which features are used and how you can build your own awesome projects on top of it.

For this exploration you will access your top track information from Spotify. You will get the audio features for each track to combine and translate them into a prompt. Acousticness, Danceability, Energy, Tempo and others are an awesome foundation for descriptive prompts. Moreover, you will need the genre information for the track’s artist.

04

Code

Authentication

We will use the spotipy library to connect to your Spotify account. This requires to set up a Spotify developer app. The workflow can be a little tricky. If you encounter problems, check out Ian Annase’s comprehensive walkthrough on Youtube. On your browser, head to the Spotify developer dashboard and click “Create app”.

Enter the information in the form:
App name: `promptmaker`
(or any app name you prefer)
Redirect URI: `http://www.google.com/`
(This can be any valid URL. Just make sure to put a forward slash at the end)
Click “settings” and copy the relevant information. Switch to your Terminal window and add the info as secrets to your environent. For each line, paste the information between the quotation marks and hit enter.

mkdir promptmaker
    cd promptmaker
    
    # setup to isolate the installation 
    virtualenv env
    
    # activate environment
    source env/bin/activate
    
    # install necessary libraries
    pip3 install spotipy openai

    export SPOTIPY_CLIENT_ID='your-spotify-client-id'
    export SPOTIPY_CLIENT_SECRET='your-spotify-client-secret'
    export SPOTIPY_REDIRECT_URI='your-app-redirect-url'
    # Again, make sure you have the forward slash at the end
    
    # If you want to analyze the song titles 
    # and have access to openAI API, enter the key
    export OPENAI_API_KEY='your-open-ai-api-key'

05

Code

Set up

Now let’s fire up a text editor or code editor and create a file prompt_maker.py. In the first part, set the imports, init some variables and instantiate the necessary objects.

import spotipy
    from spotipy.oauth2 import SpotifyOAuth
    from math import floor
    from collections import Counter
    from openai import OpenAI
    
    number_of_top_tracks = 10 # keep it between 3 and 50
    scope = 'user-top-read' # submitted to spotify for the authentication process
    
    sp = spotipy.Spotify(auth_manager=SpotifyOAuth(scope=scope))
    results = sp.current_user_top_tracks(limit=number_of_top_tracks,
                                            offset=0, 
                                            time_range='long_term')
    
    # helper function for prompt building
    def prompt_from_range(input_list, input_val):
        """returns the value matching the input on a range 0 to 1"""
        return_item = input_list[floor(input_val * len(input_list))]
        return f'{return_item}, '
    
    # init variables
    counter = 0
    acousticness_sum = 0
    danceability_sum = 0
    energy_sum = 0
    tempo_sum = 0
    valence_sum = 0
    instrumentalness_sum = 0
    liveness_sum = 0
    mode_sum = 0
    genre_list = []
    title_list = []

06

Code

Analyze your tracks

Here, we iterate over your favourite tracks and collect the features to calculate the average.

for i, track in enumerate(results['items']):
        print('---')
        title = track['name']
        artist_name = track['artists'][0]['name']
        print(f'{i} {title}{artist_name}')
    
        track_id = track['id']
        audio_features = sp.audio_features(track_id)
    
        speechiness = audio_features[0]['speechiness']
        if speechiness > 0.5:
            # ignore spoken content 
            print(f'speechiness: {speechiness} – ignoring as spoken content')
        else:
            counter += 1
            title_list.append(title)
    
            acousticness = audio_features[0]['acousticness']
            acousticness_sum += acousticness
    
            danceability = audio_features[0]['danceability']
            danceability_sum += danceability
            
            energy = audio_features[0]['energy']
            energy_sum += energy
    
            tempo = audio_features[0]['tempo']
            tempo_sum += tempo
    
            valence = audio_features[0]['valence']
            valence_sum += valence
    
            instrumentalness = audio_features[0]['instrumentalness']
            instrumentalness_sum += instrumentalness
            
            liveness = audio_features[0]['liveness']
            liveness_sum += liveness
    
            mode = audio_features[0]['mode']
            mode_sum += mode

            artist_id = track['artists'][0]['id']
            artist_info = sp.artist(artist_id)
            genres = artist_info.get('genres')
            print(f'Genres: {genres}')
            genre_list += genres #build a genre list

07

Code

Add genres

Let’s add the most popular and the most peculiar genres.

try:
        # get the most prominent genres
        genre_counts = Counter(genre_list) # creates a list of tuples  
        common_genres = genre_counts.most_common(3) # sort and limit 
        keys = [genre for genre, count in common_genres] 

        # find the longest genre description which is often the funniest
        max_length = max(len(genre) for genre in genre_list)
        peculiar_genre = [genre for genre in genre_list 
                            if len(genre) == max_length]
        peculiar_genre = peculiar_genre[0]

        genre_prompt = f'A {keys[0]} song with {keys[1]} and {keys[2]} elements.'
        genre_prompt += f'Spice it up with some {peculiar_genre}, '
    
        prompt = genre_prompt + prompt

    except Exception as e:
        # sometimes no genres are defined and the handling fails. 
        print(f'Error {e} while handling genres. Proceeding without genres.')

08

Code

Get topic with AI

Now let’s ask chatGPT to find a meta-topic in the first 10 track titles. If we don’t provide an openAI API key, the script will fall back to a simpler instruction.

try: 
        client = OpenAI()
        # chose the model: "gpt-3.5-turbo" (cheaper) or "gpt-4" (costier, better).
        model = "gpt-4"

        system_prompt = """You are a record company's portfolio 
            manager who analyzes 
            societal, behavioural, emotional topics in song titles.
            He considers several titles and transforms the most 
            striking meta-topic into brief for a lyricist that starts: 
            Write a song about [meta-topic]."""

        # Extrapolate the topic from your top 10 tracks 
        user_prompt = f"""Please have a look at these song titles {title_list[:10]} 
                            and turn them into a short single-sentence brief."""

        completion = client.chat.completions.create(
        model=model,
        messages=[  {"role": "system", "content": system_prompt},
                    {"role": "user", "content": user_prompt}])
        lyrics_prompt = completion.choices[0].message.content + " "

    except Exception as e:
        print(f'Error {e} while fetching lyrics. Proceeding with generic prompt')
        lyrics_prompt = f'A song about \'{title_list[0]}\' '
        lyrics_prompt += f'from someone who adores \'{title_list[1]}\' '
        lyrics_prompt += f'while thinking \'{title_list[2]}\'.'

    prompt = lyrics_prompt + prompt

    ### That’s all we need for the prompt. Print it to the Terminal:

    print('\n\nHere is the prompt generated from your data.')
    print('Copy and paste it into your song generation tool.')
    print('---')
    print(prompt)
    print('---')

Latest blog posts

Roblox Game

Strategic prototyping

Realize projects with rapid iterations

AI Experiment

Instant AI-fication

Flexible and fun image generation

Data Fun

Data Makes Music

Spotify writes Udio Pompts