Artists and credits
Every credit in the output is an Artist:
{ name: string; role: "primary" | "featured" | "producer" | "remixer"; joiner: string | null; source: "artist" | "title" | "version" }Artist(name: str, role: ArtistRole, joiner: Optional[str], source: ArtistSource)# role: "primary" | "featured" | "producer" | "remixer"; source: "artist" | "title" | "version"role says what the person did. joiner is the text that introduced the name, exactly as written
("&", ",", "ft.", "prod. by"), and null for the first name of a list. source says where
the credit was found: left of the dash (artist), right of it (title), or inside a version
(version).
Remixers live inside versions, not in artists. Use allArtists(track)
(all_artists in Python) when you want everyone in one list.
Joiners
Section titled “Joiners”&, x, vs., ,, ;, +, / and and separate names. They're joiners, not roles: every name
they produce is still primary.
parse("Skrillex & Diplo x Justin Bieber - Where Are Ü Now").artists;// Skrillex (joiner null), Diplo (joiner '&'), Justin Bieber (joiner 'x'), all primary
parse("Kanye West vs. Daft Punk - Stronger").artists.map((a) => a.name);// [ 'Kanye West', 'Daft Punk' ]parse("Skrillex & Diplo x Justin Bieber - Where Are Ü Now").artists# Skrillex (joiner None), Diplo (joiner '&'), Justin Bieber (joiner 'x'), all primary
[a.name for a in parse("Kanye West vs. Daft Punk - Stronger").artists]# ['Kanye West', 'Daft Punk']Some things look like joiners and aren't:
- An unspaced
/,&or+never splits.AC/DCandDrum&Bassstay whole. xonly splits in lowercase, soMalcolm Xkeeps its X.& Sons,& Co.,& His Orchestraand a few others never start a new artist. The list is inno-split-before.json.- A comma between two digits (
1,000) is part of the name.
and is special
Section titled “and is special”and is common inside band names, so by default it only splits after a comma has already split the
same list:
parse("Simon and Garfunkel - The Boxer").artists.map((a) => a.name);// [ 'Simon and Garfunkel' ]
parseArtists("Crosby, Stills, Nash and Young").map((a) => a.name);// [ 'Crosby', 'Stills', 'Nash', 'Young' ][a.name for a in parse("Simon and Garfunkel - The Boxer").artists]# ['Simon and Garfunkel']
[a.name for a in parse_artists("Crosby, Stills, Nash and Young")]# ['Crosby', 'Stills', 'Nash', 'Young']Set splitAnd (Python: split_and) to "always" or "never" to change that.
Features
Section titled “Features”feat., ft. and featuring work on either side of the dash and in brackets. with and w/
only count at the start of a bracket, since "with" turns up in plenty of titles. All of these give
the second name the role featured:
parse("Noisia feat. Foreign Beggars - Shellshock"); // source 'artist'parse("Noisia - Shellshock ft. Foreign Beggars"); // source 'title'parse("Silk City - Electricity (with Dua Lipa)"); // source 'title'parse("Noisia feat. Foreign Beggars - Shellshock") # source 'artist'parse("Noisia - Shellshock ft. Foreign Beggars") # source 'title'parse("Silk City - Electricity (with Dua Lipa)") # source 'title'If the same person is credited twice, they appear once:
parse("Noisia feat. Foreign Beggars - Shellshock (feat. Foreign Beggars)").artists.map((a) => a.name);// [ 'Noisia', 'Foreign Beggars' ][a.name for a in parse("Noisia feat. Foreign Beggars - Shellshock (feat. Foreign Beggars)").artists]# ['Noisia', 'Foreign Beggars']Names are compared with full Unicode case folding and accents removed, so Sigur Rós and
SIGUR ROS count as the same artist.
Producers
Section titled “Producers”const t = parse("Future - Mask Off (prod. by Metro Boomin)");t.artists[1]; // { name: 'Metro Boomin', role: 'producer', joiner: 'prod. by', source: 'title' }t.title; // 'Mask Off't = parse("Future - Mask Off (prod. by Metro Boomin)")t.artists[1] # Artist(name='Metro Boomin', role='producer', joiner='prod. by', source='title')t.title # 'Mask Off'knownArtists
Section titled “knownArtists”(Python: known_artists)
trackparse has no artist database, and that's deliberate. A built-in list would be wrong for half its users and impossible to keep current. Instead you tell it the names you care about:
parse("Chase & Status - Baddadan").artists.map((a) => a.name);// [ 'Chase', 'Status' ]
parse("Chase & Status - Baddadan", { knownArtists: ["Chase & Status"] }).artists.map((a) => a.name);// [ 'Chase & Status' ][a.name for a in parse("Chase & Status - Baddadan").artists]# ['Chase', 'Status']
[a.name for a in parse("Chase & Status - Baddadan", known_artists=["Chase & Status"]).artists]# ['Chase & Status']A known name is matched case- and accent-insensitively wherever a credit list starts. It also
protects names that begin with digits from being read as a track number (3 Doors Down). If you
parse a lot of strings with the same names, put them in createParser (create_parser).
Unknown artists
Section titled “Unknown artists”ID (and Unknown, Untitled, ?, ???) means the track hasn't been announced yet. It doesn't become a name.
The track gets flags.unknownArtist: true (flags.unknown_artist in Python) instead, and the same goes for titles:
const t = parse("ID - ID (ID Remix)");t.artists; // []t.flags.unknownArtist; // truet.flags.unknownTitle; // truet.versions[0].unknownArtist; // truet = parse("ID - ID (ID Remix)")t.artists # ()t.flags.unknown_artist # Truet.flags.unknown_title # Truet.versions[0].unknown_artist # True