Since the rise of digital storage and the internet, the recorded music industry can - at best - be described as a mess. At first thought, it would seem that these technological advancements would make the industry better since they come with many potential benefits for artists and listeners alike. For example, a person's entire music collection can fit on a micro sd card and artists can quickly send their music to whoever they like and can cheaply produce and store massive amounts of recordings. However, the ability to cheaply and perfectly copy recorded music has flipped the supply/demand ratio that the recorded music industry depended on. There is now a theoretically infinite supply of any musical recording so long as it has been released once. Because of this, the streaming services that most people use today spend most of their time and effort making it hard or inconvenient to copy and share music OUTSIDE of their platforms which undermines many of the benefits of digital audio technology.
Whenever you stream (or download to stream later) any music from these services, the actual audio data is often encrypted with invasive and annoying DRM technology so that the user cannot play said music in another program. Imagine if you bought a CD and kept it in your house, but every time you wanted to play that CD you had to make a phone call to the manufacturer to get permission to play it. This is effectively what happens on most major streaming services.
Now, both artists and listners are left with a poor experience. Listeners have to deal with anti-consumer DRM software and connot have full ownership of ANY of their music. Artists, on the other hand, must rely on these streaming services because they supply the digital infrastructure to distribute music to their listeners and provide a trustworthy source of truth for artists' discographies (although many streaming services are hardly capable of fulfilling the latter). Even with all of this restricive infrastructure, artists' streaming revenue is often so small that most artists would not care if their music was pirated so long as they got proper attribution.
WavePin is a specification for storing and distributing music on IPFS that seeks to fix the issues described in the last section. Rather than making an attempt to artificially impose a profitable supply/demand ratio, WavePin embraces the infinite supply of music and seeks only to make digital recordings of music MORE available (thus obviating anti-consumer DRM practices) while enabling artists to both define a source of truth for their music and prove ownership of their works without a single 3rd party.
By the nature of the IPFS network, artists can upload their music and have full control of the online storage of their works while maintaining the same levels of availability and reliability of streaming services. Wavepin defines a strict format for music and metadata so that individuals, applications, and online services can all equally access this content. Therefore, a service or application that provides WavePin content can only provide value to a listener by curating, organizing, or playing music - NOT by being a sole provider of that music. This ensures the market for music streaming/playing software remains competetive and beneficial to users.
When artsits "upload" their music "to" WavePin, their entire discography can be represented as a single IPFS CID which is a ~46 character long identifier. By nature of IPFS, this CID (and this CID alone) references the discography and can act as a source of truth since it is a mathematical hash of the entire discography and the artist can place this CID in a website, social media account, blockchain token, or any other source of trust. Smaller pieces of content (tracks, albums, etc.) are also represented as CIDs and artists can generate this identifier BEFORE releasing their a particular work so that they can mathematically prove authorship AFTER releasing it.
Since wavepin is just a specification, nobody can own or control it.
WavePin is built entirely on top of IPFS. It stores music files directly on the IPFS network and metadata as JSON objects which are also stored directly on the IPFS network as plain text. An album for example, will simply be a JSON object containing metadata and a list of tracks which are just CID strings that make reference to track JSON objects with CID references to actual audio files, artwork, etc.
Audio files must be stored as WAV files. The highest quality possible is recommended. Encoding to smaller or lossy formats should be left up to applications and users. WavePin should be seen as the source of truth only.
Tracks are stored as JSON objects which contain their metadata and reference their assets.
Here is the format of a track object represented as a JSON Schema:
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://wavepin.xyz/schemas/0.3.0/track.schema.json",
"name": "Track",
"description": "The track type is used to describe a track.",
"type": "object",
"properties": {
"contentType": {
"name": "Content Type",
"description": "Describes the type of wavepin object that this is. for tracks, this must be 'track'.",
"type": "string",
"pattern": "track"
},
"wavepinVersion":{
"name": "Wavepin Version",
"description": "Identifies the version of wavepin that this object conforms to.",
"type": "string"
},
"version":{
"name": "Version",
"version": "A version identifier for this piece of content.",
"type": "string"
},
"versionDate":{
"name": "Version Date",
"description": "The date that this version of this content was released.",
"type": "string"
},
"title":{
"name": "Title",
"description": "The title of the track.",
"type": "string"
},
"displayName":{
"name": "Display Name",
"description": "the entire track name if displayed on one line. This typically includes artist names and version info. The artist can choose how to format this however he/she pleases. For example: 'flutttr - make believe [extended mix]'",
"type": "string"
},
"description":{
"name": "Description",
"description": "a description of the track.",
"type": "string"
},
"notes":{
"name": "Notes",
"description": "Notes about this piece of content.",
"type": "string"
},
"artists":{
"name": "Artists",
"description": "A list of artists who contributed to this track including original artists, sampled artists, remix artists, etc.",
"type":"array",
"items":{
"type":"object",
"properties": {
"name":{
"name": "Name",
"description": "The name of the artist.",
"type": "string"
},
"wavepinArtistUrl":{
"name": "Wavepin Artist URL",
"description": "A url that returns a string (and only a string) that is the CID of this artist's discography on wavepin (a wavepin artist object).",
"type": "string"
},
"role":{
"name": "Role",
"description": "the role(s) of the artist. For example: 'primary artist', 'producer', 'featured artist', 'original artist', etc.",
"type": "string"
}
},
"required": ["name","role"]
}
},
"recording":{
"name": "Recording",
"description": "the main recording of the track.",
"type": "object",
"properties": {
"fileName":{
"name": "File Name",
"description": "The name of the audio file if it is downloaded or shared.",
"type": "string"
},
"cid":{
"name": "CID",
"description": "The actual cid for the PCM audio file on the IPFS network.",
"type": "string"
}
},
"required": ["fileName","cid"]
},
"alternateLinks":{
"name": "Alternate Links",
"description": "A list of links to THIS track on other stores or streaming services.",
"type":"array",
"items":{
"type":"object",
"properties": {
"name":{
"name": "Name",
"description": "The name of the service or store. For example, SoundCloud, Spotify, BandCamp.",
"type": "string"
},
"url":{
"name": "URL",
"description": "The url to the track on the service named in the name field.",
"type": "string"
}
},
"required": ["name","url"]
}
},
"artwork": {
"name": "Artwork",
"description": "The cover image for this track.",
"type": "object",
"properties": {
"cid": {
"name": "CID",
"type": "string",
"description": "the actual IPFS CID of the image"
},
"width":{
"name": "Width",
"type": "integer",
"description": "The width in pixels of the file if applicable. Note: vector images should not require this."
},
"height":{
"name": "Height",
"type": "integer",
"description": "the height in pixels of the file if applicable. Note: vector images should not require this."
},
"format":{
"name": "Format",
"type": "string",
"description": "the format of the image file. For example: 'png', 'jpeg', 'svg', etc."
}
}
},
"extraData":{
"name": "Extra Data",
"description": "A JSON object with no specification. This can be used for any purpose.",
"type": "object"
}
},
"required":["contentType","wavepinVersion","title","displayName"]
}
Collections are lists of mixed content and can be used for playlists, albums, discographies, etc. Collections can hold other collections and can therefor be used for defining artist discographies, personal music collections or anything else. (note: colored text refers to information specific to a collection):
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://wavepin.xyz/schemas/0.3.0/collection.schema.json",
"name": "Collection",
"description": "The collection data type is used to describe a collection. A collection can be a playlist, album, or even a set of other collections.",
"type": "object",
"properties": {
"contentType": {
"name": "Content Type",
"description": "Describes the type of wavepin object that this is. for colections, this must be 'collection'.",
"type": "string",
"pattern": "collection"
},
"wavepinVersion":{
"name": "Wavepin Version",
"description": "Identifies the version of wavepin that this object conforms to.",
"type": "string"
},
"version":{
"name": "Version",
"version": "A version identifier for this piece of content.",
"type": "string"
},
"versionDate":{
"name": "Version Date",
"description": "The date that this version of this content was released.",
"type": "string"
},
"title":{
"name": "Title",
"description": "The name of the collection.",
"type": "string"
},
"description":{
"name": "Description",
"description": "A description of the collection.",
"type": "string"
},
"notes":{
"name": "Notes",
"description": "Notes about this piece of content.",
"type": "string"
},
"items":{
"name": "Items",
"description": "A list of IPFS cids referring to the objects within the collection. Note: these cids do NOT refer to audio files.",
"type": "array",
"items":{
"type":"string"
}
},
"artwork": {
"name": "Artwork",
"description": "The cover image for this collection.",
"type": "object",
"properties": {
"cid": {
"name": "CID",
"type": "string",
"description": "the actual IPFS CID of the image"
},
"width":{
"name": "Width",
"type": "integer",
"description": "The width in pixels of the file if applicable. Note: vector images should not require this."
},
"height":{
"name": "Height",
"type": "integer",
"description": "the height in pixels of the file if applicable. Note: vector images should not require this."
},
"format":{
"name": "Format",
"type": "string",
"description": "the format of the image file. For example: 'png', 'jpeg', 'svg', etc."
}
}
},
"extraData":{
"name": "Extra Data",
"description": "A JSON object with no specification. This can be used for any purpose.",
"type": "object"
}
},
"required":["contentType","wavepinVersion","title"]
}
The artist data type is used to describe an artist. Typically an artist should register a domain and have the domain point to an artist object which can in turn point to all of that artist's music on WavePin.
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://wavepin.xyz/schemas/0.3.0/artist.schema.json",
"name": "Artist",
"description": "The artist data type is used to describe an artist. Typically an artist should register a domain and have the domain point to an artist object which can in turn point to all of that artist's music on wavepin.",
"type": "object",
"properties": {
"contentType": {
"name": "Content Type",
"description": "Describes the type of wavepin object that this is. for artists, this must be 'artist'.",
"type": "string",
"pattern": "artist"
},
"wavepinVersion":{
"name": "Wavepin Version",
"description": "Identifies the version of wavepin that this object conforms to.",
"type": "string"
},
"version":{
"name": "Version",
"version": "A version identifier for this piece of content.",
"type": "string"
},
"versionDate":{
"name": "Version Date",
"description": "The date that this version of this content was released.",
"type": "string"
},
"name":{
"name": "Name",
"description": "The name of the artist.",
"type": "string"
},
"bio":{
"name": "Bio",
"description": "A bio/description of the artist.",
"type": "string"
},
"notes":{
"name": "Notes",
"description": "Notes about this piece of content.",
"type": "string"
},
"works":{
"name": "Works",
"description": "A list of IPFS cids referring to wavepin tracks or collectiosn that this artist contributed to. Note: these cids do NOT refer to audio files.",
"type": "array",
"items":{
"type":"string"
}
},
"profileImage": {
"name": "Profile Image",
"description": "The artist's profile image file on the IPFS network.",
"type": "object",
"properties": {
"cid": {
"name": "CID",
"type": "string",
"description": "the actual IPFS CID of the image"
},
"width":{
"name": "Width",
"type": "integer",
"description": "The width in pixels of the file if applicable. Note: vector images should not require this."
},
"height":{
"name": "Height",
"type": "integer",
"description": "the height in pixels of the file if applicable. Note: vector images should not require this."
},
"format":{
"name": "Format",
"type": "string",
"description": "the format of the image file. For example: 'png', 'jpeg', 'svg', etc."
}
}
},
"extraData":{
"name": "Extra Data",
"description": "A JSON object with no specification. This can be used for any purpose.",
"type": "object"
}
},
"required":["contentType","wavepinVersion","name"]
}
Music players and other applications that intend to read music from WavePin under the WavePin should be able to handle any property missing
This specification was written by flutttr
September 2026