Visualizing Streaming Music Royalty Rates

Last week, T-Pain shared a fun graphic on Twitter (originally sourced from r/coolguides on Reddit) of how many streams are required to earn $1 across the biggest music streaming platforms.

The numbers are a little shocking - interesting enough that I thought it could be fun to call them out just a bit more!

The Tweet

Streams, Visualized

The first thing I wanted to do was to improve the visualization of the Streams/$1 image. While T-Pain’s table conveys the information directly and accurately, it doesn’t really reinforce how different the numbers are. Even something as simple as a bar chart immediately helps the data pop, which really aids my brain’s processing of the distinctions across platforms.

I’ve included a bit of commentary in the graphic itself - but want to call out again how crazy it is that Napster, of all things, has gone from music-pirate-mecca to artist’s dream.

Streams Required to Earn $1

Next, I re-scaled the volume of streams to show not just the number required to earn $1, but the number required to earn $100,000. In my mind, that helps serve as a proxy for a “normal” person’s income in a year - a useful landmark for contextualizing the number of streams.

With that done, we quickly learn that many millions of streams are required to hit $100k in earnings, starting with Napster on the low side at 2.6 million streams, and topping out with YouTube at 62.5 million streams required - which continues to seem like an insanely high figure for the relatively modest amount of earnings.

Streams Required to Earn $100,000

Anyone have ideas on the business reasons that let YouTube and Pandora get away with paying rates to artists that are so much lower than the rest of their competitors?! Would love to hear them.

Code for Reference

Build Dataframe and Compute Metrics

library(tidyverse)

platform <- c(
  "Amazon Music",
  "Apple Music",
  "Tidal Music",
  "Napster",
  "Deezer",
  "Pandora",
  "YouTube Music",
  "Spotify"
)

streams_1d <- c(
  249,
  128,
  78,
  53,
  156,
  752,
  1250,
  315
)

df <- data.frame(platform, streams_1d)

df <- df %>%
  mutate(
    dollars_per_stream = 1 / streams_1d,
    streams_100k = streams_1d * 50000,
    dollars_per_100m = (1 / streams_1d) * 100000000,
    cents_per_stream = (1 / streams_1d) * 100
  )

Build Streams per $1 Chart

library(scales)

ggplot(df, aes(x = reorder(platform, streams_1d), y = streams_1d, label = streams_1d)) + 
  geom_col(fill = '#444e86') +
  geom_text(size = 3, position = position_dodge(width = 1), hjust = 1.1, color = "white", fontface = "bold") + 
  scale_y_continuous(breaks = seq(0, 1400, 200)) + 
  coord_flip() +
  theme_minimal() + 
  theme(
    plot.title = element_text(size = 20, face = "bold"),
    plot.caption = element_text(colour = "grey60")
  ) +
  labs(
    x = '',
    y = '\n# of Streams to Earn $1',
    title = 'Streams Required to Earn $1',
    subtitle = 'In a hilarious historical twist, Napster ends up as the most lucrative platform for artists, while YouTube and Pandora have\nthe stingiest payout structures. Focusing on the two big platforms, streams pay 2.4x better on Apple Music than Spotify.',
    caption = 'conormclaughlin.net'
  )

ggsave("streams_to_earn_1_usd_by_platform.png", height = 5, width = 10, units = "in", dpi = 400)

Build Streams per $100,000 Chart

ggplot(df, aes(x = reorder(platform, -streams_100k), y = streams_100k, label = streams_100k)) + 
  geom_col(fill = '#a05195') +
  scale_y_continuous(
    breaks = seq(0, 70000000, by = 10000000),
    labels = label_number(suffix = " M", scale = 1e-6) # millions
  ) +
  geom_text(
    aes(label = paste(round(streams_100k / 1e6, 1), "M", sep = '')),
    size = 3, 
    position = position_dodge(width = 1), 
    hjust = 1.05, 
    color = "white", 
    fontface = "bold"
  ) + 
  coord_flip() +
  theme_minimal() + 
  theme(
    plot.title = element_text(size = 20, face = "bold"),
    plot.caption = element_text(colour = "grey60")
  ) +
  labs(
    x = '',
    y = '\n# of Streams to Earn $100,000',
    title = 'Streams Required to Earn $100,000',
    subtitle = 'It takes 24 times as many streams to make $100k on YouTube Music (62.5m) than it does on Napster (2.6m)',
    caption = 'conormclaughlin.net'
  )

ggsave("streams_to_earn_100k_usd_by_platform.png", height = 5, width = 10, units = "in", dpi = 400)