Skip to main content

Find Similar Tracks

The Cyanite.ai API offers the functionality to find similar tracks based on a input track.

You can search for similar tracks for any library or spotify track and retreive results from either your Library (LibraryTrack), a Crate (LibraryTrack) or Spotify (SpotifyTrack).

Additionally, it is possible to specify a search criteria, e.g. only return tracks whose BPM is the range of the input track or tracks whose genre matches a specified genre.

The functionalilty is exposed via the Track.similarTracks field.

tip

We assume that you already have a basic understanding GraphQL interfaces and unions. If you are new with GraphQL in general we recommend starting with the official learning resource.

Example Query

Search on
and find
query SimilarTracksQuery($trackId: ID!) {
libraryTrack(id: $trackId) {
__typename
... on Error {
message
}
... on Track {
id
similarTracks(target: { spotify: {} }) {
__typename
... on SimilarTracksError {
code
message
}
... on SimilarTracksConnection {
edges {
node {
id
}
}
}
}
}
}
}
Example response
{
"data": {
"libraryTrack": {
"__typename": "LibraryTrack",
"id": "test-id-1",
"similarTracks": {
"__typename": "SimilarTracksConnection",
"edges": [
{
"node": {
"id": "5P8KKoAiwhzZkwcBuyhdUi"
}
},
{
"node": {
"id": "6tnnuZ3pgO83D65xIRgEaG"
}
},
{
"node": {
"id": "6q64fAbMqCU92HOJcDKm34"
}
}
]
}
}
}
}

Specifying a Target

The Track.similarTracks field has one required parameter which is the Track.similarTracks(target:) argument of the SimilarTracksTarget! input type.

This argument specifies what kind of search results we want. Currently, it is possible to get results from the library, a crate or spotify.

TargetTrack.similarTracks(target:) value
library{ library: {} }
crate{ crate: { crateId: "$crateId" } }
spotify{ spotify: {} }
caution

It is only possible to specify one target. Mixing options e.g. { library: {}, spotify: {} } might result in an error.

Specifying the Search Mode

There different methods available for finding similar tracks. By default the segment of the track that is categorized as the most-representative one of the track will be used. In addition it is possible to choose two additional modes via the Track.similarTracks(searchMode:) argument of the SimilarTracksSearchMode type.

Example Document: Specifying a Search Mode

fragment TrackSimilarTracksFragment on Track {
similarTracks(target: { library: {} }, searchMode: { complete: {} }) {
__typename
... on SimilarTracksError {
code
message
}
... on SimilarTracksConnection {
edges {
node {
id
}
}
}
}
}
InputDescriptionTrack.similarTracks(searchMode:) value
mostRepresentativeUse most representative part of the track.{ mostRepresentative: {} }
completeUse the complete track.{ complete: {} }
intervalUse a custom part of the track.{ interval: { start: 10, end: 20 } }

Applying Search Filters

caution

The search filter API is subjected to change and is not fully stable yet.

By default no additional filters will be applied and all similar sounding tracks will be returned. Additionally, it is possible to apply filters for narrowing down the selection of returned tracks.

The filters are applied via the Track.similarTracks(experimental_filter:) argument of the experimental_SimilarTracksFilter input type.

Example filters:

FilterDescriptionExample Track.similarTracks(experimental_filter:) value
BPMFilter track by BPM (in range of track){ bpm: { input: {} } }
GenreFilter track by genre{ genre: { input: {} } }
KeyFilter track by key{ key: { input: {} } }

The above filters would result only returning tracks which match the BPM, genre and key of the input track. But, it is also possible to specify custom ranges.

All the filters can be mixed, so it is possible to filter by bpm and additionally also filter by genre or key.

Example Document: BPM and Key Filter

fragment TrackSimilarTracksFragment on Track {
similarTracks(
target: { library: {} }
experimental_filter: {
bpm: { range: { start: 160, end: 200 } }
key: { input: {} }
}
) {
__typename
... on SimilarTracksError {
code
message
}
... on SimilarTracksConnection {
edges {
node {
id
}
}
}
}
}

BPM filter

The experimental_SimilarTracksFilter.bpm field of the input type experimental_SimilarTracksFilterBpm describes a bpm filter.

It is possible to either filter for the bpm of the input track or a custom range:

FilterExample Track.similarTracks(experimental_filter:) value
BPM (input track){ bpm: { input: {} } }
BPM (custom range){ bpm: { range: { start: 60, end: 140 } } }

Genre filter

The experimental_SimilarTracksFilter.genre field of the input type experimental_SimilarTracksFilterGenre describes a genre filter.

It is possible to either filter for the genre of the input track or a list of specified genres.

FilterExample Track.similarTracks(experimental_filter:) value
Genre (input track){ genre: { input: {} } }
Genre (custom list){ genre: { list: ["country", "folk"] }

The possible genres are described by the MusicalGenre enum type.

Key filter

The experimental_SimilarTracksFilter.key field of the input type experimental_SimilarTracksFilterKey describes a key filter.

It is possible to either filter for a specific key (input track or list of keys) or via the camelot method.

FilterExample Track.similarTracks(experimental_filter:) value
Key (input track){ key: { matching: { input: {} } } }
Key (custom list){ key: { matching: { list: ["cMajor"] } }
Camelot (input track){ key: { camelot: { input: {} } } }
Camelot (custom list){ key: { camelot: { key: "cMajor" } } }

The possible keys are described by the MusicalKey enum type.

Specify the amount of edges to fetch

By default the Track.similarTracks field will return up to 10 tracks, given they match all the specified filters and there are enough available. It is possible to fetch up to 100 songs by specifying the Track.similarTracks(first:) argument of the Int type.

Example Document: Fetch 100 items

fragment TrackSimilarTracksFragment on Track {
similarTracks(target: { library: {} }, first: 100) {
__typename
... on SimilarTracksError {
code
message
}
... on SimilarTracksConnection {
edges {
node {
id
}
}
}
}
}