sync&sweat

A workout music recommender built on people's own Spotify, Strava and heart-rate data, taken from data collection and analysis to recommendation logic and a mobile prototype.

My role
Data analysis, recommendation logic, product design & prototype
Context
Data-Centric Design, TU Delft, 2026
Team
With Hao Lin and Sebastiaan Schulte
Methods
Data donation, correlation analysis, participatory data interviews
Why this playlist? screen explaining the recommendation with the user's own BPM cluster Post-workout feedback screen asking whether the beat matched the effort Live session screen showing 147 BPM heart rate in Zone 3

Summary

Problem

Workout music is rarely personal. Playlists don't know your training, your heart rate or how hard the session feels.

Insight

Track tempo barely tracked heart rate (r = +0.05 across 232 track–workout pairs). Music drove motivation instead.

Strategy

From “control your heart rate” to matching music to your state and your own habits.

Product

Follow the Beat: upload, state detection, recommendation, feedback, using zone playlists from your own library.

What I did

4 contributions
  • Multi-source data analysis

    Built the Spotify + Strava collection flow and the dataset: time-series matching, cleaning, audio features and correlation analysis.

    Data
  • Data-led strategy shift

    Showed that tempo didn't track heart rate, combined that with interviews, and moved the goal from heart-rate control to state matching.

    Insight
  • Recommendation logic & prototype

    Designed the zone + personal-history logic with BPM clustering, and the Follow the Beat mobile prototype.

    Logic
  • Validation & iteration

    Ran participatory data interviews with each person's own charts, and turned what the data missed into the next model inputs.

    Validation

PythonStreamlitPlotlyPandasSciPyVADERHTML/JSSpotify Web APIGitHub

Product decisions & metrics

Prototype with 3 participants
  1. Decision 01Match the session, don’t steer heart rate.

    Tempo barely tracked heart rate (r = +0.05), so promising control would have overclaimed. Trade-off: a less striking pitch, but one the data supports.

  2. Decision 02Build playlists from people’s own libraries.

    Familiar tracks are the ones people keep playing, and their history solves the cold start. Trade-off: less discovery of new music.

  3. Decision 03Ask the activity type every session.

    Training alone or with friends changes what music is for, and the data can’t tell the difference. Trade-off: one extra tap before each workout.

North starSessions rated as a match

Share of workouts where the check-in says the beat matched the effort.

Supporting
  • Skips per workout
  • Weekly sessions started with the app
Guardrail
  • Consent withdrawals and upload drop-off
  • Share of tracks running on an estimated tempo

Proposed for a longer field test. The study itself covered 3 people and 13 sessions.

Workout music knows your taste, but not your workout.

Streaming apps recommend by genre and mood. None of them look at the session itself: what you're doing, how hard your heart is working, how tired you feel.

We asked how a connected product could use people's own music and training data to suggest music that either pushes them into a higher heart-rate zone or helps them recover.

Two sub-questions guided the work: do heart-rate zones line up with the energy and valence of the music played, and do people choose high-energy music on purpose, or does music shift heart rate without them noticing?

Design question

How can a connected product create music suggestions that push a user into a higher heart-rate zone or guide them into recovery?

I built one dataset out of two personal histories.

Spotify knows what you played and when. Strava knows when you trained and how hard. Neither knows about the other, so every track had to be matched to the workout it was played in.

Participants exported their own data and uploaded it through a donation platform we built, where they could review everything before sharing it. Tracks were enriched with audio features from the Spotify API and aligned to workout windows by timestamp.

01 · CollectDonation platform 02 · ProcessEnrich & align 03 · StoreData Foundry 04 · AnalyseResearcher dashboard Spotify historyStreamingHistory.json Strava activitiesactivities.csv + heart rate Audio featuresSpotify API: BPM, energy, valence Timestamp alignmentTracks matched to workout windows Thematic codingWorkout notes and reflections audio_features.csvPer track activity.csvPer workout, with zones master_aligned.csvOne dataset per participant
From raw exports to one time-aligned, feature-enriched dataset per participant.

The dataset

After cleaning
  • 3
    Participants

    People who donated their own Spotify listening history and Strava workout history.

  • 13
    Workout sessions

    Sessions with heart-rate data that could be analysed across the three participants.

  • 232
    Track–workout pairs

    Each pair is one song matched to the workout it was played in. This is the unit behind every correlation on this page.

  • 49 / 112
    Matches with tempo data, first participant

    Only 49 of the first participant's 112 matched tracks had a BPM value.

We didn't fill the 112 → 49 gap in. We asked the participant why it was there: he played music on the bike, but rarely in the gym. The gap was behaviour, not noise, and it pointed to activity type as something the model had to account for.

Donation platform

Participant side
Step 1 of the donation platform: Spotify upload with total hours listened and top 10 tracks
Step 1, Spotify. Upload the listening history and see it right away: hours listened and most-played tracks.
Step 2 of the donation platform: Strava upload with total activities, distance and activities by type
Step 2, Strava. Upload workouts and review activity counts and types before anything is shared.

Tempo didn't move heart rate, so I changed what the product aims for.

Track BPM ↔ heart rate r = +0.05

No meaningful link across all 232 track–workout pairs. Heart rate clustered by type of workout, not by the tempo of the music.

Scatter plot of track BPM against workout heart rate, forming four clusters by activity type
One participant's tracks formed four clusters by activity. On the bike, he stayed around 100–120 BPM whatever his heart rate.
Track BPM ↔ workout duration r = +0.24

A small but consistent signal, in the same direction for every participant: faster tracks went with longer sessions. Tempo related to sustained effort, not peak heart rate.

Scatter plot of workout duration against average track BPM
Workout duration against average track BPM, coloured by activity type.
Participant
Sometimes when I'm not that motivated, I try to find external motivation, either by working with someone else or by choosing my music.
All three participants described music as a way into the right headspace, not as something that changes their body.

Where the product belongs

Design principle
Socially-situated activity awareness

Training alone

Music is part of the workout. The system recommends.

Training with friends

Conversation replaces music, and the activity follows the group. The system steps back.

Strategy shift

Product goal
From

Control heart rate: prescribe tempo to push people into a target zone.

To

State matching: music that fits the current session and the person's own training habits.

  • InputActivity type

    Asked every session, because it changes with who you train with.

  • InputReal-time heart rate

    Locates the zone you are in right now.

  • InputMusic features

    BPM, energy and valence of each track.

  • InputYour Spotify library

    Familiar tracks are the ones people actually keep playing.

Five heart-rate zones, filled with the tracks you actually train to.

  1. 1

    Set a goal

    Push, maintain or recover sets the target zone for the session.

  2. 2

    Cluster by BPM

    Every track from your workout history goes into one of five tempo bands.

  3. 3

    Rank by habit

    Within a band, tracks are ranked by how long you played them during workouts.

  4. 4

    Play and explain

    The zone playlist plays, with a “Why this playlist?” view one tap away.

Tempo bands

Track BPM per zone
  1. Zone 1 · Recovery< 110 BPM
  2. Zone 2 · Endurance110–130 BPM
  3. Zone 3 · Tempo131–150 BPM
  4. Zone 4 · Threshold151–170 BPM
  5. Zone 5 · Max> 170 BPM

When Spotify had no BPM for a track, the pipeline fell back to other sources (SongBPM, Deezer, then an estimate from genre) and kept the source visible, so a guessed tempo never looked like a measured one.

Five zone playlists generated from one participant's own Spotify listening history
Zone playlists. Generated from one participant's own workout listening history, shown back to them in the donation platform.

Follow the Beat, a mobile prototype that lived on participants' phones.

Built as a web app and added to the home screen, so it opened full-screen like a native app. All file parsing happened on the phone.

Upload State detection Recommendation Feedback

Watch it run

A screen recording on a participant's phone: connecting Spotify and Strava, starting a solo session, opening “Why this playlist?”, and rating the session afterwards.

  1. Set upConnect your sound, sync your sweat
  2. SessionLive zone and the zone playlist
  3. ReasoningWhy this playlist?
  4. AfterDid the beat match your sweat?

Set up

Three screens, one time. Your history becomes the baseline.

Welcome screen: Follow the Beat, music that meets your heart rate where it is
WelcomeThree promises up front: your real Spotify history, your Strava zones, playlists for solo sessions.
Connect your sound: upload the Spotify export
Connect your soundDrop in the Spotify export. The app reads BPM, energy and valence of what you actually train to.
Sync your sweat: upload the Strava export and see heart-rate zones
Sync your sweatAdd Strava workouts. Heart-rate zones, activity types and durations become your baseline.

During the workout

Live zone, the music, and the reasoning behind it.

Live session: 147 BPM in Zone 3 during a solo tempo ride, with the next track queued
Live zoneHeart rate places you in a zone. When it drifts low, higher-energy tracks queue up next.
Now playing: Follow the Beat playlist at a target tempo of 142 BPM, Zone 3
Now playingA zone playlist built from your own tracks, with the target tempo on screen.
Why this playlist? Three signals from the user's own data
Why this playlist?Three signals from your own data in plain language, including how weak the BPM–heart-rate link is.

After the workout

One quick check-in closes the loop.

Feedback: did the beat match your sweat? Thumbs, energy match slider and tags
Did the beat match your sweat?Thumbs, an energy-match slider and quick tags feed tomorrow's playlist.

Tools behind it

Built in Streamlit
  • Data donation platform

    Consent, upload, review and a first look at your own music–workout history. It also became the basis for the interviews.

  • Researcher dashboard

    Cohort overview, music × heart rate, duration × effort, text sentiment (VADER), and a recommendation simulator for testing the logic before building it.

I used people's own data as the interview prompt.

Each participant saw their own BPM–heart-rate chart and their zone playlists, then took the playlists into their workouts on Spotify.

Instead of judging an abstract concept, they confirmed or contested patterns in their own data. We coded the interviews with reflexive thematic analysis.

Participants recognised most of the recommended tracks, but weren't sure the tracks would give them the same feeling mid-workout.

What the interviews showed

3 themes
  • Music is a motivational tool

    Used to get into the right headspace, and shaped by the type of activity.

  • Choice is habitual and mood-driven

    Genre playlists picked by mood (techno, or “darker rap, more aggressive”), not matched to a zone.

  • Audio features miss what matters

    Lyrics, emotion and memories shape the experience, and BPM can't see any of them.

Participant
Maybe the song lyrics are very depressing, but you want something that pumps you up and also switches things up.
The gap between recommendation and experience pointed to what the model needs next.

Next iteration

Model inputs
Finding

Lyric emotion and personal memories shape music choice, and audio features miss both.

Proposed

Add emotion tags and a hype check-in before and after each session, and learn which tracks consistently motivate each person.

Exploratory study · 3 participants · 13 sessions · 232 track–workout pairs