Proof of Concept Homemade MP3 Wrapped to Talk About Tech and Meno
January 21, 2026
-
Today I want to talk about my thoughts on technology, where it is today and why that is.
Then I want to discuss what it could be. I will demonstrate this by describing my own experience and thoughts combined with philosophy,
and finally how I've enacted this through my proof of concept, homemade MP3 Wrapped.
The philosophy will consider our place in technology, and how I think we have been put in a box, alienating us from our potential.
Just to put this out there for this homemade Wrapped project, like I just said, it is a proof of concept, and I hope to continue to work on it
throughout the year to realize my goal.
Intro
Hi, it's been a minute! Today I want to talk about my thoughts on technology, where it is today and why that is. Then I want to discuss what it could be. I will demonstrate this by describing my own experience and thoughts combined with philosophy, and finally how I've enacted this through my proof of concept, homemade MP3 Wrapped. The philosophy will consider our place in technology, and how I think we have been put in a box, alienating us from our potential. Just to put this out there for this homemade Wrapped project, like I just said, it is a proof of concept, and I hope to continue to work on it throughout the year to realize my goal.
Background
You may recall if you read my last blog post that I'm interested in what's happening in tech right now, and I'm not the biggest fan, yet I still have hope. Over this past year I have in way reunited with my interest in technology. Throughout my life, I was always interested in technology, and that is what made me think I wanted to be a computer science student. I then went to school to get a bachelors degree in computer science, and found that for the first two years it was a little miserable, and I quickly became jaded towards technology; I couldn't remember how I felt about technology before this. It wasn't until last year when I took a lot less comp sci, and a lot more philosophy that I started to feel better. I understood the world differently. There were multiple factors contributing to this change at the time, but I think this was a large factor. Starting this current school year, I was going into my last year and I had mostly comp sci courses with a little bit of philosophy. Despite this big change, and what did end up being and still is a lot of work, I definitely felt different about technology.
I started to understand why I used to be interested in technology as a kid, and I started to see why I hadn't been interested for a while. I think it mostly comes down to how we view it, and how it is interacting with our lives. In the current day, technology is something that we have to interact with, and there seemingly isn't much choice about it. You also aren't really involved in technology, it's more magic that we are aware certain people can harness, but we aren't those people, we just kneel at their feet and be grateful for their divine gifts. Even if you do understand technology, it feels a little unobtainable to do anything useful. We are also told what type of technology we need, and I think this makes all the difference. Technology, the way I see it can be viewed theoretically, philosophically, and as a trade. The trade of technology is something that I think feels impossible for most. Perhaps this is because the theory is treated as synonymous with the trade and as though only the most learned computer science students could possibly comprehend it. Then I think that the philosophical side is often disregarded or missed entirely.
If technology is something that you are told you need for X then you are going to get that piece of technology and be stuck there at the mercy of those who bestowed it to you. I'm not saying you must do things alone, but you should also be a factor in the process. You shouldn't be alienated from technology, we are not cattle. When the human becomes alienated from the means of production, they become like animals, not educating, not striving, just accepting, like cattle in a field, being told what to do, and where to go.
Why MP3?
Anyway, long story short, I think that technology can be a way to achieve your goals, and you should not be beholden to the technology, it should be beholden to you. I recently, and I mean very recently, got an MP3 player, because I was tired of Spotify. I was tired of their platform not recommending music, despite them telling me that was part of the service. I was tired of music feeling worthless and commodified. I was tired of buying and not owning. I could stream on Spotify for years and my listening to an artist wouldn't benefit them as much as one CD purchase could. I was tired of the AI slop they were trying to feed me. On a less personal level, I'm tired of them not paying their artists, and like I just mentioned, trying to replace them with AI. Surprisingly I also don't want my music streaming service to be investing in drones made for war.
So anyway, I switched to an MP3 player and it's great, I love speed and ease I have to accessing my music, that's another thing that bothered me about an app, because I have a slower phone, so any bloated app like the one mentioned in the last paragraph, makes listening hard. I love the physical buttons, and the scroll wheel, and I like that I was able to put open source firmware on it to customize it as my own. I ended up buying the HIFI Walker H2 and while I'm not endorsing them, I think it was a good fit. I had some amazon gift cards from Christmas making this a more justifiable purchase, because I will say it wasn't the cheapest one. I chose it for the reasons I gave above, physical buttons, ability to load open source firmware and plugins, good battery, and solid build. The firmware was the big thing, because the H2 is able to run rockbox, which allows you to upload custom plugins and track playback. I think there might be other ways to do this without rockbox, but I'm unsure.
Wrapped, technically and philosophically
So getting into the thing that kinda set my aspirations of getting an MP3 player into motion. As mentioned above I think you can do really cool things with technology to help you reach goals, improving your life. I had the goal of abandoning Spotify, but the one thing I actually really like about the service is wrapped. I wanted to take my aspirations of leaving Spotify, and use my skills to make it so that I was benefitting from leaving, and not losing anything. In the intro I was trying and potentially failing to say that you can do really cool stuff with your skills to make your life better. If you think about anything that people do, are they better off with nothing, or with tools, knowledge, and practice. The latter of course. Through our continued pursuit of virtue, we live. By allowing ourselves to be domesticated, we lie stagnant, and allow those who keep us in this state to benefit from it. This is like Plato's Meno; Meno eventually comes to the conclusion that because he cannot say what virtue is, therefore, there are no virtuous people. Instead, he missed the point that Socrates was trying to give him. Virtuous people become virtuous by searching and living. Meno wants to be given the answer to being virtuous like we do with our tech overlords, so that we can use the newest iPhone to solve all the problems in life.
- Anyway, off track again. So with my new MP3 player running rockbox (email me if you actually do this and get a H2 and want help), the first thing I did was enable logging
- you can do this by going to:
- Settings → Playback Settings → Logging → Yes
- This will start logging all playback in a file called
playback.logwhich you can find in your.rockboxfile on the sd card when you insert it into your computer and browse the sd card directory. So now you have started logging, and know where to find it when you want to. The next step is to wait, play some music, have fun, enjoy yourself. I didn't do this step because I wanted to see how it was going, and that's why you're reading this proof of concept blog post in January and not later in the year. So I've been listening to music on this thing for only about half a week, but I wanted to see if my idea was plausible so I took myplayback.logfile and wrote a little python script to see if this was even going to be possible. I would like to improve a couple things, like what I'm actually going to track, I might have to reference old Spotify wraps for this, and I also want to make a user interface so it looks pretty, and is just cooler. I'd also like to make it user friendly so that others could use it. Anyway this is just a proof of concept after a couple of days. I'll include the code after the output so that if you actually want to see the code you can, but if you're just here for the output, here it is.
Output
🎧 TOTAL LISTENING TIME (context only)
894.6 minutes
🎵 MOST LOVED TRACKS (Replay-Weighted)
plays ... score
artist track ...
Run The Jewels 02 - ooh la la (feat. Santa Fe Klan) (Mexican I... 4 ... 3.678302
DAngelo 01 - Playa Playa 4 ... 3.033279
Run The Jewels 01 - yankee y el valiente (TROOKO’s Versión) 3 ... 2.999897
DAngelo 04 - The Line 3 ... 2.932544
A$AP Rocky A$AP Rocky - WHISKEY (RELEASE ME) 3 ... 2.816019
Killer Mike 07 - Don't Die 3 ... 2.647636
Kendrick Lamar 09 - FEEL. 4 ... 2.545272
04 - XXX. 3 ... 2.313771
Lauryn Hill 04 - To Zion 2 ... 1.999968
DAngelo 05 - Send It On 2 ... 1.999966
[10 rows x 3 columns]
🔥 MOST LOVED ARTISTS (Replay-Weighted)
total_plays avg_completion score
artist
A$AP Rocky 25 0.994695 24.867380
DAngelo 25 0.936122 23.403043
Frank Ocean 22 0.999642 21.992123
Lauryn Hill 21 0.969550 20.360548
Kendrick Lamar 19 0.944439 17.944348
JPEG Mafia 15 0.993968 14.909516
Erykah Badu 14 0.992598 13.896371
Run The Jewels 13 0.988485 12.850303
DeLaSoul 13 0.949224 12.339908
Chappell Roan 12 0.925282 11.103388
💿 MOST RETURNED-TO ALBUMS (Normalized)
total_plays ... normalized_score
artist album ...
Run The Jewels RTJ CU4TRO 10 ... 2.500000
A$AP Rocky A$AP Rocky - Don't Be Dumb 25 ... 2.083333
DAngelo Voodoo 25 ... 1.923077
Stevie Wonder Innervisions 5 ... 1.666667
Kendrick Lamar DAMN. COLLECTORS EDITION# 19 ... 1.461538
Killer Mike R.A.P. Music 10 ... 1.428571
Lauryn Hill The Miseducation of Lauryn Hill 21 ... 1.312500
TylerTheCreator dont-tap-the-glass 5 ... 1.250000
Inside (The Songs) [2021] CD1 6 ... 1.200000
DeLaSoul Cabin In The Sky 13 ... 1.181818
[10 rows x 3 columns]
🧠 STICKIEST TRACKS (Sought Out)
total_plays ... stickiness
artist track ...
DAngelo 01 - Playa Playa 4 ... 4.0
Run The Jewels 02 - ooh la la (feat. Santa Fe Klan) (Mexican I... 4 ... 4.0
Kendrick Lamar 09 - FEEL. 4 ... 4.0
DAngelo 04 - The Line 3 ... 3.0
DeLaSoul 12 - Different World 3 ... 3.0
Run The Jewels 01 - yankee y el valiente (TROOKO’s Versión) 3 ... 3.0
A$AP Rocky A$AP Rocky - WHISKEY (RELEASE ME) 3 ... 3.0
Kendrick Lamar 04 - XXX. 3 ... 3.0
Killer Mike 07 - Don't Die 3 ... 3.0
A$AP Rocky A$AP Rocky - AIR FORCE (BLACK DEMARCO) 2 ... 2.0
[10 rows x 3 columns]
⏰ LISTENING BY HOUR
hour
8 123.189583
7 111.663167
23 89.855450
20 56.294250
19 55.693167
6 54.289083
22 49.352850
9 45.970900
15 45.827750
12 36.709583
0 35.914150
16 27.062867
5 24.930950
21 22.466383
10 19.560100
11 14.817383
13 13.968050
2 9.343900
14 8.830483
3 7.598983
17 6.584700
4 5.081033
1 2.402400
Name: played_minutes, dtype: float64
📅 TOP LISTENING DAYS
date
2026-01-19 239.856217
2026-01-20 198.344200
2026-01-18 192.356283
2026-01-17 171.199450
2026-01-21 65.651017
Name: played_minutes, dtype: float64
✅ COMPLETION RATE SUMMARY
count 233.000000
mean 0.938677
std 0.149258
min 0.409539
25% 0.999683
50% 0.999940
75% 0.999975
max 0.999990
Name: completion, dtype: float64
wrapped.py
import pandas as pd
from pathlib import Path
from datetime import datetime
LOG_PATH = "playback.log"
rows = []
with open(LOG_PATH, "r", encoding="utf-8", errors="ignore") as f:
for line in f:
line = line.strip()
if not line or line.startswith("#"):
continue
try:
ts, played_ms, total_ms, path = line.split(":", 3)
ts = int(ts)
played_ms = int(played_ms)
total_ms = int(total_ms)
p = Path(path)
parts = p.parts
artist = parts[-3] if len(parts) >= 3 else "Unknown"
album = parts[-2] if len(parts) >= 2 else "Unknown"
track = p.stem
rows.append({
"timestamp": datetime.fromtimestamp(ts),
"played_ms": played_ms,
"total_ms": total_ms,
"completion": played_ms / total_ms if total_ms else 0,
"artist": artist.replace("_", " "),
"album": album.replace("_", " "),
"track": track.replace("_", " ")
})
except Exception:
continue
df = pd.DataFrame(rows)
# ---------- TIME FEATURES ----------
df["played_minutes"] = df["played_ms"] / 60000
df["hour"] = df["timestamp"].dt.hour
df["date"] = df["timestamp"].dt.date
# ---------- QUALIFIED PLAYS ----------
QUALIFIED = df[
(df["played_ms"] > 30_000) &
(df["completion"] > 0.4)
]
print("\n🎧 TOTAL LISTENING TIME (context only)")
print(f"{df['played_minutes'].sum():.1f} minutes")
# ---------- TOP TRACKS (REPLAY-BASED) ----------
track_scores = (
QUALIFIED
.groupby(["artist", "track"])
.agg(
plays=("track", "count"),
avg_completion=("completion", "mean")
)
)
track_scores["score"] = track_scores["plays"] * track_scores["avg_completion"]
track_scores = track_scores.sort_values("score", ascending=False)
print("\n🎵 MOST LOVED TRACKS (Replay-Weighted)")
print(track_scores.head(10))
# ---------- TOP ARTISTS ----------
artist_scores = (
track_scores
.groupby("artist")
.agg(
total_plays=("plays", "sum"),
avg_completion=("avg_completion", "mean")
)
)
artist_scores["score"] = (
artist_scores["total_plays"] * artist_scores["avg_completion"]
)
artist_scores = artist_scores.sort_values("score", ascending=False)
print("\n🔥 MOST LOVED ARTISTS (Replay-Weighted)")
print(artist_scores.head(10))
# ---------- ALBUM NORMALIZATION ----------
album_scores = (
QUALIFIED
.groupby(["artist", "album"])
.agg(
total_plays=("track", "count"),
unique_tracks=("track", "nunique")
)
)
album_scores["normalized_score"] = (
album_scores["total_plays"] / album_scores["unique_tracks"]
)
album_scores = album_scores.sort_values("normalized_score", ascending=False)
print("\n💿 MOST RETURNED-TO ALBUMS (Normalized)")
print(album_scores.head(10))
# ---------- STICKINESS ----------
stickiness = (
QUALIFIED
.groupby(["artist", "track"])
.agg(
total_plays=("track", "count"),
albums=("album", "nunique")
)
)
stickiness["stickiness"] = stickiness["total_plays"] / stickiness["albums"]
stickiness = stickiness.sort_values("stickiness", ascending=False)
print("\n🧠 STICKIEST TRACKS (Sought Out)")
print(stickiness.head(10))
# ---------- TIME OF DAY ----------
print("\n⏰ LISTENING BY HOUR")
print(
QUALIFIED
.groupby("hour")["played_minutes"]
.sum()
.sort_values(ascending=False)
)
# ---------- TOP LISTENING DAYS ----------
print("\n📅 TOP LISTENING DAYS")
print(
QUALIFIED
.groupby("date")["played_minutes"]
.sum()
.sort_values(ascending=False)
.head(10)
)
# ---------- COMPLETION INSIGHT ----------
print("\n✅ COMPLETION RATE SUMMARY")
print(QUALIFIED["completion"].describe())