XSPF Extension¶
This document describes the mbzlists XML namespace, which is designed to extend the standard XSPF (XML Shareable Playlist Format) with rich, annotated block content. This allows a playlist to be more than just a list of tracks; it can be a narrative, a curated mix with commentary, or a photo album.
2.0 DRAFT¶
Warning
This is a draft spec and is under review.
The next version of the spec has the following requirements in mind:
- Support for audio or video media content along with
imageblobs. This could be used for, say, putting in audio recordings in the document. We could support any generic file, but not sure if that would be the right thing to do. - Support for non-linear flows. At times we need build a branching list instead of single linear one. This can be supported by adding id to elements and then providing internal links.
- Support sections or sub-lists. Right now there is no nesting under a heading. If enabled, this will allow logically grouping tracks together.
Proposed Changes¶
1. ID and internal references¶
Each mbzlists element under blocks has an optional id attribute that can be
referred by <a> in text blocks that allow HTML. For example, you could have a
paragraph linking to another like the following:
<mbzlists:paragraph>
Hey, if you don't like this, then try <a href="#some-id">this</a>, else <a href="#another-link">go here</a>
</mbzlists:paragraph>
<mbzlists:paragraph id="some-id">
Another paragraph
</mbzlists:paragraph>
This allows to implement natural language based non-linearity in navigating the list. Note that the focus is still to make a human-readable document where the reader decides to click one or other link and not run the playlist based on dynamic computation without a human-in-the-loop.
2. Section block¶
A new block that can hold other blocks like section, header, paragraph,
etc.
This allows to group contents together which can be referred to using a single ID.
3. Audio and Video blocks¶
Media blocks named <mbzlists:audio> and <mbzlists:video> with optional
caption attribute.
The main content is displayed using child elements that could be either of the
following, just like in the case of <mbzlists:image>:
1. <mbzlists:file> with url as the attribute specifying the full
download URL of the content.
2. <mbzlists:blob> with name attribute specifying the filename and base64
encoded data as content.
1.1¶
Pulls the track/reference model forward from the 2.0 draft and deprecates
<mbzlists:mbrecording> in its favor. This changes the recommended shape of
a recording rather than purely adding to it, so the namespace URI bumps to
http://docs.lepisma.xyz/mbzlists/ns/1.1/:
<playlist version="1" xmlns="http://xspf.org/ns/0/" xmlns:mbzlists="http://docs.lepisma.xyz/mbzlists/ns/1.1/">
Warning
<mbzlists:mbrecording> is deprecated as of 1.1 in favor of
<mbzlists:track>. Tools should stop writing new mbrecording blocks;
support for reading them will be removed in 2.0.
<mbzlists:track>¶
A general block for describing a track, replacing <mbzlists:mbrecording>.
Unlike mbrecording, it resolves against any source (YouTube, Spotify,
MusicBrainz, etc.) instead of only MusicBrainz, and can carry more than one
source at once.
Attributes:
length(optional) The length of the track in milliseconds.
Child elements:
<mbzlists:title>The title of the track.<mbzlists:artist>and<mbzlists:album>(optional). Both have a<mbzlists:name>child holding the name string, and one or more<mbzlists:ref>children (see below) for resolving that artist or album.- One or more
<mbzlists:ref>children directly under<mbzlists:track>, for resolving the track itself.
<mbzlists:ref>¶
Sits inside <mbzlists:track>, <mbzlists:artist>, or <mbzlists:album> and
helps the tool resolve that specific track, artist, or album. It carries no
metadata of its own.
Attributes:
kindAn arbitrary string identifying the source, used to interpretid. For examplemusicbrainz,spotify,youtube,url, etc.idThe identifier or URL string, interpreted according tokind.
A track, artist, or album can carry more than one <mbzlists:ref>, e.g. to
resolve the same recording via both MusicBrainz and YouTube.
<mbzlists:track length="212000">
<mbzlists:title>Never Gonna Give You Up</mbzlists:title>
<mbzlists:artist>
<mbzlists:name>Rick Astley</mbzlists:name>
<mbzlists:ref kind="musicbrainz" id="b13c8e7d-7575-4f5f-8a8e-2557d10ed348" />
</mbzlists:artist>
<mbzlists:album>
<mbzlists:name>Whenever You Need Somebody</mbzlists:name>
</mbzlists:album>
<mbzlists:ref kind="youtube" id="dQw4w9WgXcQ" />
</mbzlists:track>
The corresponding <track> entry in the XSPF tracklist gets its <location>
and <info> from one of the track's <mbzlists:ref> elements when more than
one is present. The spec imposes no semantics on which ref is picked.
1.0¶
Note
The current specification duplicates the track details in extension content
and the tracklist of the playlist.
Namespace Declaration¶
To use the mbzlists vocabulary, you must declare the namespace on the root
<playlist> element of your XSPF document. We will use the prefix mbzlists
for this.
<playlist version="1" xmlns="http://xspf.org/ns/0/" xmlns:mbzlists="http://docs.lepisma.xyz/mbzlists/ns/1.0/">
<!-- XSPF general content goes here -->
<extension application="https://docs.lepisma.xyz/mbzlists/ns/1.0/">
<!-- mbzlists playlist content goes here >
</extension>
<!-- continued XSPF content -->
</playlist>
Based on the XSPF guidelines, all extra mbzlists content goes inside an
<extension> tag as shown above. Next we specify content that can go inside the
<extension>.
1. Metadata: <mbzlists:metadata>¶
1.1. <mbzlists:lastModifiedOn>¶
Date time information about the last modification done for the playlist. The
format is similar to that of <date> tag in XSPF file.
2. Block Container: <mbzlists:blocks>¶
Each mbzlists playlist is represented as a list of blocks that can contain text
elements, images, or songs. The <mbzlists:blocks> element is the container for
all the individual content blocks within the list. The blocks currently
supported are specified next:
2.1. <mbzlists:header>¶
Text for the heading. It can contain inline HTML for formatting like <i> or
<a>. It contains the following attributes.
level. A value from 1 to 6 that specifies the heading level.
2.2. <mbzlists:paragraph>¶
A simple text block for commentary or descriptions. The text content of the
paragraph. It can contain inline HTML for formatting like <i> or <a>.
2.3. <mbzlists:image>¶
An image block with various display options as following attributes:
caption(optional) A caption to be displayed with the image.withBorderboolean (true or false) to indicate if the image should have a border.withBackgroundboolean to indicate if the image should have a background color.stretchedboolean to indicate if the image should stretch to fill the width.
The main content is displayed using child elements that could be either of the
following:
1. <mbzlists:file> with url as the attribute specifying the full
download URL of the image.
2. <mbzlists:blob> with name attribute specifying the filename and base64
encoded image data as content.
2.4. <mbzlists:mbrecording>¶
Warning
Deprecated as of 1.1 in favor of <mbzlists:track>
A block for a specific MusicBrainz recording. This is the core element identifying each track in the playlist.
Attributes:
mbidThe MusicBrainz recording ID.lengthThe length of the recording in milliseconds.
Child elements:
<mbzlists:title>The title of the recording<mbzlists:artist>Name of the music artist. This hasmbidas the attribute keeping the MusicBrainz artist ID.<mbzlists:release>Title of the release associated with this track. This hasmbidattribute identifying the MusicBrainz release ID, along withdatethat has string representation of the release date. Note that the date is optional, as well as, has no strict format as it can by just the year or a string like1985-11-23or something else.
2.5. <mbzlists:quote>¶
Element representing quoted text as its content. It has caption and
alignment (left, right, or center) as attributes.
2.6. <mbzlists:list>¶
Element containing text lists. Each list, including sublists, can only be of one type (ordered, unordered, etc.)
Attributes:
style, ordered, checklist, or unorderedcounterType(optional) numeric is the only value supported right now.
Child elements:
<mbzlists:listItem> represents a single item in the list with checked as
optional attribute present in checklist type lists. The text content is kept
inside <mbzlists:listContent> element. In case of nesting, another
<mbzlists:list> can go after <mbzlists:listContent>.
Complete Example (1.1)¶
Here is a complete example exported from the example list
here, updated
to the 1.1 namespace and using <mbzlists:track> instead of the deprecated
<mbzlists:mbrecording>:
<?xml version="1.0" encoding="UTF-8"?>
<playlist version="1" xmlns="http://xspf.org/ns/0" xmlns:mbzlists="http://docs.lepisma.xyz/mbzlists/ns/1.1/">
<title>Test playlist with annotation</title>
<creator>mbzlists</creator>
<info>https://mbzlists.com/list/8a07ff86-7406-45f6-9afc-cbdd97df7b02</info>
<date>2025-08-18T14:52:47.027Z</date>
<extension application="http://docs.lepisma.xyz/mbzlists/ns/1.1/">
<mbzlists:metadata>
<mbzlists:lastModifiedOn>2025-08-19T06:28:29.626Z</mbzlists:lastModifiedOn>
</mbzlists:metadata>
<mbzlists:blocks>
<mbzlists:paragraph>This is a test playlist to showcase all features of an mbzlists playlist.</mbzlists:paragraph>
<mbzlists:header level="2">This is a heading of level 2</mbzlists:header>
<mbzlists:paragraph>This is a paragraph. A paragraph could <b>have</b> <i>inline</i> styles. Also you can add links like <a href="https://xspf.org/">this</a>.</mbzlists:paragraph>
<mbzlists:header level="3">This is a level 3 heading</mbzlists:header>
<mbzlists:header level="4">This is a level 4 heading</mbzlists:header>
<mbzlists:paragraph>Let's add a few songs:</mbzlists:paragraph>
<mbzlists:track length="566466">
<mbzlists:title>In Your Room</mbzlists:title>
<mbzlists:artist>
<mbzlists:name>Airiel</mbzlists:name>
<mbzlists:ref kind="musicbrainz" id="a6bf1276-9150-40fc-a94e-6b14f377fe3d" />
</mbzlists:artist>
<mbzlists:album>
<mbzlists:name>Winks & Kisses: 20th Anniversary Deluxe Edition</mbzlists:name>
<mbzlists:ref kind="musicbrainz" id="3c05be8d-1783-42f5-8207-645fc741bc0d" />
</mbzlists:album>
<mbzlists:ref kind="musicbrainz" id="7b54cad3-7542-4edf-8d0e-fd423c9b8166" />
</mbzlists:track>
<mbzlists:paragraph>You can also add text lists.</mbzlists:paragraph>
<mbzlists:list style="ordered" counterType="numeric">
<mbzlists:listItem>
<mbzlists:listContent>One</mbzlists:listContent>
</mbzlists:listItem>
<mbzlists:listItem>
<mbzlists:listContent>Two</mbzlists:listContent>
</mbzlists:listItem>
<mbzlists:listItem>
<mbzlists:listContent>Three, only numeric bullets are supported in ordered lists</mbzlists:listContent>
</mbzlists:listItem>
</mbzlists:list>
<mbzlists:paragraph>The lists can be of unordered type too, and also checkboxes.</mbzlists:paragraph>
<mbzlists:list style="unordered">
<mbzlists:listItem>
<mbzlists:listContent>A list without order</mbzlists:listContent>
</mbzlists:listItem>
<mbzlists:listItem>
<mbzlists:listContent>Another element</mbzlists:listContent>
<mbzlists:list style="unordered">
<mbzlists:listItem>
<mbzlists:listContent>Nesting is allowed, but only with the same list type.</mbzlists:listContent>
</mbzlists:listItem>
</mbzlists:list>
</mbzlists:listItem>
</mbzlists:list>
<mbzlists:list style="checklist">
<mbzlists:listItem>
<mbzlists:listContent>Check lists are also supported</mbzlists:listContent>
</mbzlists:listItem>
<mbzlists:listItem checked="true">
<mbzlists:listContent>This is a done item</mbzlists:listContent>
</mbzlists:listItem>
</mbzlists:list>
<mbzlists:paragraph>Let's add a few more songs.</mbzlists:paragraph>
<mbzlists:track length="237000">
<mbzlists:title>kisses</mbzlists:title>
<mbzlists:artist>
<mbzlists:name>Slowdive</mbzlists:name>
<mbzlists:ref kind="musicbrainz" id="a16371b9-7d36-497a-a9d4-42b0a0440c5e" />
</mbzlists:artist>
<mbzlists:album>
<mbzlists:name>Kisses (Remixes)</mbzlists:name>
<mbzlists:ref kind="musicbrainz" id="318f59fe-dabf-4023-9817-25cb30769777" />
</mbzlists:album>
<mbzlists:ref kind="musicbrainz" id="ea346317-7114-42a8-b16d-dd41d5f70bd4" />
</mbzlists:track>
<mbzlists:track length="231600">
<mbzlists:title>Time Baby III</mbzlists:title>
<mbzlists:artist>
<mbzlists:name>Medicine</mbzlists:name>
<mbzlists:ref kind="musicbrainz" id="0f24bcb0-8d37-409d-aed1-92bd4e5337ed" />
</mbzlists:artist>
<mbzlists:album>
<mbzlists:name>Sounds of Medicine: Stripped and Reformed Sounds</mbzlists:name>
<mbzlists:ref kind="musicbrainz" id="28fbf6ac-7056-4009-aad4-6620970b8ee1" />
</mbzlists:album>
<mbzlists:ref kind="musicbrainz" id="3be1e03e-376f-49fd-a0e3-2b372c6bfecd" />
</mbzlists:track>
<mbzlists:paragraph>Of course images are supported,</mbzlists:paragraph>
<mbzlists:image caption="" withBorder="false" withBackground="false" stretched="true">
<mbzlists:file url="https://mbzlists.com/api/image/e5b6845b-a9b6-4870-99aa-cf3d3ed1ba07/"/>
</mbzlists:image>
<mbzlists:quote caption="Here is the caption for the quote" alignment="left">Quoted texts show up like this. Lorem ipsum (/ˌlɔː.rəm ˈɪp.səm/ LOR-əm IP-səm) is a dummy or placeholder text
commonly used in graphic design, publishing, and web development. Its
purpose is to permit a page layout to be designed, independently of the copy that will subsequently populate it, or to demonstrate various fonts of a typeface without meaningful text that could be distracting.</mbzlists:quote>
</mbzlists:blocks>
</extension>
<tracklist>
<track>
<title>In Your Room</title>
<creator>Airiel</creator>
<album>Winks & Kisses: 20th Anniversary Deluxe Edition</album>
<info>https://musicbrainz.org/recording/7b54cad3-7542-4edf-8d0e-fd423c9b8166</info>
<location>https://musicbrainz.org/recording/7b54cad3-7542-4edf-8d0e-fd423c9b8166</location>
</track>
<track>
<title>kisses</title>
<creator>Slowdive</creator>
<album>Kisses (Remixes)</album>
<info>https://musicbrainz.org/recording/ea346317-7114-42a8-b16d-dd41d5f70bd4</info>
<location>https://musicbrainz.org/recording/ea346317-7114-42a8-b16d-dd41d5f70bd4</location>
</track>
<track>
<title>Time Baby III</title>
<creator>Medicine</creator>
<album>Sounds of Medicine: Stripped and Reformed Sounds</album>
<info>https://musicbrainz.org/recording/3be1e03e-376f-49fd-a0e3-2b372c6bfecd</info>
<location>https://musicbrainz.org/recording/3be1e03e-376f-49fd-a0e3-2b372c6bfecd</location>
</track>
</tracklist>
</playlist>