Current section
Files
Jump to
Current section
Files
lib/shazam_kit.ex
defmodule ShazamKit do
@moduledoc """
Elixir client for the [ShazamKit API](https://developer.apple.com/documentation/shazamkit).
ShazamKit allows you to match audio signatures against Shazam's vast music catalog.
Use it to:
- Identify songs from audio fingerprints
- Build custom audio recognition features
- Match user-generated audio against the Shazam database
## Quick Start
# Match a pre-generated audio signature
ShazamKit.match_signature(signature_data)
# Search Shazam catalog by ISRC
ShazamKit.search_by_isrc("USUG12002836")
## Configuration
config :shazam_kit,
team_id: System.get_env("APPLE_TEAM_ID"),
key_id: System.get_env("SHAZAM_KEY_ID"),
private_key: System.get_env("SHAZAM_PRIVATE_KEY"),
base_url: "https://api.shazam.com"
## Audio Signatures
Audio signatures (fingerprints) must be generated on the client side using:
- iOS: `SHSignatureGenerator` from ShazamKit framework
- Android: Shazam SDK
- Custom implementation following Shazam's signature format
The signature is a binary blob that ShazamKit uses to match against its catalog.
"""
alias ShazamKit.{Client, Token}
@type opts :: keyword()
@type response :: {:ok, map()} | {:error, term()}
@doc "Return a cached ShazamKit **access token** (after JWT generation)."
@spec token(opts) :: {:ok, String.t()} | {:error, term()}
def token(opts \\ []), do: Token.access_token(opts)
@doc """
Match an audio signature against the Shazam catalog.
## Parameters
- `signature`: Audio signature data (base64 encoded string or binary)
- `opts`:
- `:raw_audio` - Set to true if signature is raw audio data (signature will be generated server-side)
- `:limit` - Maximum results (default 1)
## Returns
- `{:ok, %{"matches" => [%{"track" => track_data}]}}` - Match found
- `{:ok, %{"matches" => []}}` - No match found
- `{:error, %ShazamKit.Error{}}` - API error
## Examples
signature = "AQAsFU4eASQ..." # base64 encoded signature from iOS ShazamKit
ShazamKit.match_signature(signature)
## Notes
Audio signatures should be generated using Apple's ShazamKit framework on iOS,
or the Shazam SDK on other platforms. The signature format is proprietary to Shazam.
"""
@spec match_signature(String.t() | binary(), opts) :: response
def match_signature(signature, opts \\ []) when is_binary(signature) do
# Check if signature is base64 encoded or raw binary
body =
if Keyword.get(opts, :raw_audio, false) do
%{
audio: Base.encode64(signature),
raw: true
}
else
%{
signature: signature
}
end
body = if limit = Keyword.get(opts, :limit), do: Map.put(body, :limit, limit), else: body
Client.post("/v1/signature/match", body, opts)
end
@doc """
Search the Shazam catalog by ISRC (International Standard Recording Code).
## Parameters
- `isrc`: ISRC code (e.g., "USUG12002836")
## Examples
ShazamKit.search_by_isrc("USUG12002836")
"""
@spec search_by_isrc(String.t(), opts) :: response
def search_by_isrc(isrc, opts \\ []) when is_binary(isrc) do
Client.get("/v1/catalog/search", Keyword.put(opts, :isrc, isrc))
end
@doc """
Get detailed information about a track by its Shazam ID.
## Parameters
- `track_id`: Shazam track identifier
## Examples
ShazamKit.get_track("548587123")
"""
@spec get_track(String.t(), opts) :: response
def get_track(track_id, opts \\ []) when is_binary(track_id) do
Client.get("/v1/catalog/tracks/#{track_id}", opts)
end
@doc """
Search for tracks by artist and title.
## Parameters
- `query`: Search query (artist name, track title, or both)
- `opts`:
- `:limit` - Maximum results (1-50, default 10)
- `:offset` - Pagination offset
## Examples
ShazamKit.search_tracks("The Beatles Yesterday")
ShazamKit.search_tracks("Billie Eilish", limit: 5)
"""
@spec search_tracks(String.t(), opts) :: response
def search_tracks(query, opts \\ []) when is_binary(query) do
params = [
term: query,
limit: Keyword.get(opts, :limit, 10),
offset: Keyword.get(opts, :offset, 0)
]
Client.get("/v1/catalog/search", Keyword.put(opts, :params, Enum.into(params, %{})))
end
@doc """
Get the Shazam chart (most popular tracks).
## Parameters
- `opts`:
- `:city_id` - City ID for local charts (optional)
- `:limit` - Maximum results (default 10)
## Examples
ShazamKit.get_chart()
ShazamKit.get_chart(city_id: "12345", limit: 20)
"""
@spec get_chart(opts) :: response
def get_chart(opts \\ []) do
endpoint =
if city_id = Keyword.get(opts, :city_id) do
"/v1/charts/cities/#{city_id}"
else
"/v1/charts/world"
end
Client.get(endpoint, opts)
end
@doc """
List available chart cities.
## Examples
ShazamKit.list_cities()
"""
@spec list_cities(opts) :: response
def list_cities(opts \\ []) do
Client.get("/v1/charts/cities", opts)
end
@doc """
Validate if a signature format is valid (basic validation).
## Examples
ShazamKit.valid_signature?("AQAsFU4eASQ...")
"""
@spec valid_signature?(String.t()) :: boolean()
def valid_signature?(signature) when is_binary(signature) do
# Basic validation: signatures are typically base64 and have minimum length
try do
decoded = Base.decode64!(signature)
# Shazam signatures have a specific header format
byte_size(decoded) >= 16
rescue
_ -> false
end
end
def valid_signature?(_), do: false
end