Music Genre Classification Annotation
Build a music tagging task in Potato with audio playback, track metadata on screen, multi-label genre tagging, and Likert scales for energy and danceability.
Genre labels are what recommendation systems, auto-generated playlists, and music discovery features run on. This post builds genre-tagging interfaces in Potato, with audio previews and the track metadata an annotator needs to judge what they are hearing.
Playing the track and asking the question
Potato keeps content and questions apart. instance_display says what the annotator sees and hears, and annotation_schemes says what they answer. For a tagging task the audio is a display field, not an annotation scheme:
annotation_task_name: "Music Genre Classification"
task_dir: "."
data_files:
- data/tracks.json
item_properties:
id_key: track_id
text_key: audio_preview
instance_display:
fields:
- key: artist
type: text
label: "Artist"
- key: title
type: text
label: "Track"
- key: audio_preview
type: audio
label: "Preview"
display_options:
controls: true
show_waveform: true
annotation_schemes:
- annotation_type: radio
name: primary_genre
description: "Select the primary genre"
labels:
- Rock
- Pop
- Hip-Hop
- Electronic
- Jazz
- Classical
- R&B
- Country
- Metal
- Folk
sequential_key_binding: true
output_annotation_dir: annotation_output/
export_annotation_format: jsonlitem_properties takes id_key and text_key only. There is no audio_path or metadata_fields key, and a config that uses them gets a player that never appears and metadata the annotator never sees. Anything the annotator should read is a field in instance_display.
The audio_annotation type is for marking regions of the waveform. A whole-track judgment is a radio, a multiselect, or a likert.
A two-level genre taxonomy
Potato has no conditional label tree, so a two-level taxonomy is two schemes, and the second needs every subgenre it might have to cover:
annotation_schemes:
- annotation_type: radio
name: genre
description: "Primary genre"
labels:
- Rock
- Electronic
- Hip-Hop
- Pop
- Jazz
- Classical
- annotation_type: radio
name: subgenre
description: "Subgenre within the primary genre"
labels:
- Indie Rock
- Punk
- Metal
- House
- Techno
- Drum & Bass
- Boom Bap
- Trap
- Synth-pop
- Bebop
- Baroque
- Romantic
- OtherWhere that list gets unwieldy, hierarchical_multiselect collapses both levels into one widget instead.
Multi-label tagging
Plenty of tracks sit in more than one genre:
annotation_schemes:
- annotation_type: multiselect
name: genres
description: "Select every genre that applies, up to three"
labels:
- Rock
- Pop
- Electronic
- Hip-Hop
- R&B
- Jazz
- Classical
- Country
- Folk
- Metal
- Punk
- Indie
- World
- Latin
- annotation_type: radio
name: primary_genre
description: "Which of the genres you selected is the primary one?"
labels:
- Rock
- Pop
- Electronic
- Hip-Hop
- R&B
- Jazz
- Classical
- Country
- Folk
- Metal
- Punk
- Indie
- World
- LatinNothing enforces the "up to three" or checks that the primary genre is one of the selected ones. Both are worth stating in the instructions and checking in the export.
Complete configuration
annotation_task_name: "Music Tagging and Classification"
task_dir: "."
data_files:
- data/music_library.json
item_properties:
id_key: track_id
text_key: preview_url
instance_display:
layout:
direction: vertical
gap: 12px
fields:
- key: artist
type: text
label: "Artist"
- key: title
type: text
label: "Track"
- key: album
type: text
label: "Album"
- key: year
type: text
label: "Year"
- key: preview_url
type: audio
label: "Preview"
display_options:
controls: true
show_waveform: true
annotation_schemes:
- annotation_type: multiselect
name: genres
description: "Select all applicable genres"
labels:
- Rock
- Pop
- Electronic/Dance
- Hip-Hop/Rap
- R&B/Soul
- Jazz
- Classical
- Country
- Folk/Acoustic
- Metal
- Punk
- Indie
- World/International
- Latin
- Blues
- Reggae
- annotation_type: multiselect
name: mood
description: "Select the mood or moods of this track"
labels:
- Happy/Uplifting
- Sad/Melancholic
- Energetic
- Calm/Relaxing
- Aggressive
- Romantic
- Dark/Moody
- Nostalgic
- Motivational
- annotation_type: likert
name: energy
description: "Energy level"
size: 5
min_label: "Very low energy"
max_label: "Very high energy"
- annotation_type: likert
name: danceability
description: "How danceable is this track?"
size: 5
min_label: "Not danceable"
max_label: "Very danceable"
- annotation_type: radio
name: vocals
description: "Vocal content"
labels:
- Instrumental only
- Mostly instrumental
- Balanced
- Mostly vocals
- Vocals dominant
- annotation_type: radio
name: era
description: "Musical era or style"
labels:
- Pre-1970s
- 1970s
- 1980s
- 1990s
- 2000s
- 2010s
- 2020s
- annotation_type: multiselect
name: flags
description: "Special flags, if any apply"
labels:
- Explicit content
- Live recording
- Remix or cover
- Holiday/Seasonal
- Soundtrack
- Spoken word sections
label_requirement:
required: false
- annotation_type: likert
name: confidence
description: "Confidence in your genre classification"
size: 5
min_label: "Uncertain"
max_label: "Very confident"
annotation_instructions: |
## Music Tagging Guidelines
### Genre selection
Choose one to three genres that describe the track. Prefer the most
specific genre that fits, and fall back to a broader one when unsure.
### Mood
Judge the overall emotional tone. A track can carry several moods.
### Energy and danceability
Energy is tempo, intensity, and power. Danceability is rhythm, beat
clarity, and groove. A slow track can be highly danceable.
### Listening
Listen to at least 30 seconds, and listen past the intro. Drops and
transitions are where the genre often becomes clear.
output_annotation_dir: annotation_output/
export_annotation_format: jsonl
user_config:
allow_all_users: trueWhat the output contains
Each scheme stores its answer under its own name:
{
"genres": ["Rock", "Pop"],
"mood": ["Happy/Uplifting", "Nostalgic"],
"energy": "3",
"danceability": "2",
"vocals": "Balanced",
"era": "Pre-1970s",
"flags": [],
"confidence": "5"
}Likert answers come back as strings. Convert them before averaging.
Tips for music annotation
Good headphones matter, because laptop speakers hide the low end that separates several of these genres. Keep the volume steady rather than adjusting per track, which tires ears faster than the listening does. Listen far enough into each preview to catch the changes. Brush up on what each genre label means for your project before starting, since genre boundaries are exactly where annotators disagree. And take breaks, because tired ears make worse calls and the drift is gradual enough that nobody notices it happening.
Where to go next
- Add audio event detection for picking out instruments
- Set up crowdsourcing to get a wider range of ears on the data
- Learn about agreement metrics for music
For the full set of audio annotation options, see the source documentation.
Full audio documentation at Audio Annotation.