MusicBrainz (musicbrainz v0.1.0)

Copy Markdown View Source

The music of a film or a show, from MusicBrainz: the soundtrack albums named after the title, and their tracks.

{:ok, albums} = MusicBrainz.albums("Heat", year: 1995)
#=> [%{id: "…", title: "Heat (Music From the Motion Picture)", year: 1995,
#      artist: "Various Artists"}, %{title: "Heat: The Score", …}]

{:ok, tracks} = MusicBrainz.tracks(hd(albums).id)
#=> [%{n: 1, title: "Heat", artist: "Elliot Goldenthal feat. Kronos Quartet", secs: 461}, …]

MusicBrainz.youtube([hd(tracks).artist, hd(tracks).title, "Heat"])
#=> "https://www.youtube.com/results?search_query=Elliot+Goldenthal+feat.+Kronos+Quartet+Heat"

MusicBrainz is asked for release groups of secondary type soundtrack whose name begins with the title's words (a search also matches on one word: Body Heat is not Heat's), for a film within a year of its release (:year), oldest first — the original album before its expanded editions, a show's seasons in order. An album's tracks are those of its fullest official release, numbered through its discs; an artist credited only in kana is named by the Latin sort name ("Kanno, Yoko" → "Yoko Kanno"), so a search finds the song.

Being a good client

MusicBrainz is free and keyless, and asks two things: a user agent that names your application with a way to reach you, and one request a second. Set the first:

config :musicbrainz, user_agent: "MyApp/1.0 (https://example.com)"

and keep the second yourself: cache what comes back (albums for a month, tracks for a year — they do not change) and do not ask in a loop. Nothing here plays music and no YouTube key is needed: youtube/1 is a search link.

Every request merges :req_options (per call or config :musicbrainz, :req_options), so the client can be pointed at Req.Test.

Summary

Types

A release group: year is its first release's, artist the credit as printed.

A track of the album's fullest release, numbered through its discs; secs its length.

Functions

The soundtrack albums named after name, best first: {:ok, [album]} ({:ok, []} when MusicBrainz lists none) or {:error, reason}.

The tracks of the fullest of these releases, numbered through its discs.

The release groups of a search answer whose name begins with name's words, as albums: albums and EPs with a search score of 50 or more, oldest first, limit at most.

The Lucene query albums/2 sends: the name as a release-group title, soundtracks only, and with :year a first release within a year of it.

The tracks of the album (a release-group id): those of its fullest official release, :limit at most (default 60). {:ok, []} for a group with no release listed.

A YouTube search for these words (blanks dropped, a word said twice once).

Types

album()

@type album() :: %{
  id: String.t(),
  title: String.t(),
  year: integer() | nil,
  artist: String.t() | nil
}

A release group: year is its first release's, artist the credit as printed.

track()

@type track() :: %{
  n: pos_integer(),
  title: String.t(),
  artist: String.t() | nil,
  secs: integer() | nil
}

A track of the album's fullest release, numbered through its discs; secs its length.

Functions

albums(name, opts \\ [])

@spec albums(String.t(), keyword()) :: {:ok, [album()]} | {:error, term()}

The soundtrack albums named after name, best first: {:ok, [album]} ({:ok, []} when MusicBrainz lists none) or {:error, reason}.

Options:

  • :year — the film's release year: only albums first released within a year of it. Leave it out for a show, whose albums span its seasons.
  • :names — other names to try when the first finds nothing (the original title, say); the first name with albums wins.
  • :limit — albums at most (default 8).
  • :req_options — merged into the request.

parse_tracks(releases, limit \\ 60)

@spec parse_tracks(term(), pos_integer()) :: [track()]

The tracks of the fullest of these releases, numbered through its discs.

pick_albums(groups, name, limit \\ 8)

@spec pick_albums(term(), String.t(), pos_integer()) :: [album()]

The release groups of a search answer whose name begins with name's words, as albums: albums and EPs with a search score of 50 or more, oldest first, limit at most.

query(name, opts \\ [])

@spec query(String.t(), keyword()) :: String.t()

The Lucene query albums/2 sends: the name as a release-group title, soundtracks only, and with :year a first release within a year of it.

tracks(mbid, opts \\ [])

@spec tracks(String.t(), keyword()) :: {:ok, [track()]} | {:error, term()}

The tracks of the album (a release-group id): those of its fullest official release, :limit at most (default 60). {:ok, []} for a group with no release listed.

youtube(words)

@spec youtube([String.t() | nil]) :: String.t()

A YouTube search for these words (blanks dropped, a word said twice once).