Integrate Canvas
Into Your App

Use the Echo Music Canvas database to add beautiful looping motion visuals to your music player, website, or application. It's open, free, and community-driven.

Quick Start

How It Works

The Echo Music Canvas database is a single JSON file hosted on GitHub. It maps song + artist pairs to looping video URLs. You fetch the JSON, match songs by name, and play the corresponding video as a background visual.

1 Fetch canvas.json
2 Match song + artist
3 Play video canvas

API Reference

Canvas Database URL

The primary endpoint to fetch the complete canvas database:

ENDPOINT
https://canvas.echomusic.fun/canvas.json

This URL always serves the latest version from the main branch. Cache it on your server for performance.

Response Schema

The JSON file follows this structure:

JSON
{
  "items": [
    {
      "song": "Blinding Lights",
      "artist": "The Weeknd",
      "url": "https://canvas.echomusic.app/Song/20.m3u8"
    },
    {
      "song": "Dracula",
      "artist": "Tame Impala",
      "url": "https://canvas.echomusic.app/Song/1.mp4"
    }
  ]
}
FieldTypeDescription
itemsArrayThe list of all canvas entries
items[].songStringThe song title (case-sensitive as contributed)
items[].artistStringThe artist or band name
items[].urlStringDirect URL to the canvas video (.mp4 or .m3u8)

Integration Examples

JavaScript / Web

Fetch the database and find a canvas for a playing song:

JavaScript
const CANVAS_URL = 'https://canvas.echomusic.fun/canvas.json';

// Fetch and cache the canvas database
async function loadCanvasDB() {
  const res = await fetch(CANVAS_URL);
  const data = await res.json();
  return data.items || [];
}

// Find a canvas for a given song + artist
function findCanvas(items, songTitle, artistName) {
  const query = `${songTitle} ${artistName}`.toLowerCase();
  return items.find(item => {
    const entry = `${item.song} ${item.artist}`.toLowerCase();
    return entry === query;
  });
}

// Usage
const canvasDB = await loadCanvasDB();
const match = findCanvas(canvasDB, 'Blinding Lights', 'The Weeknd');

if (match) {
  const video = document.getElementById('canvas-player');
  video.src = match.url;
  video.loop = true;
  video.muted = true;
  video.play();
}

HTML Video Player

A minimal HTML structure to render a canvas behind your music player:

HTML
<div class="player-container" style="position: relative;">
  <!-- Canvas background -->
  <video id="canvas-player"
         loop muted playsinline
         style="position: absolute; inset: 0;
                width: 100%; height: 100%;
                object-fit: cover; z-index: 0;
                opacity: 0.85;">
  </video>

  <!-- Your player UI goes on top -->
  <div style="position: relative; z-index: 1;">
    <h2 id="song-title">Blinding Lights</h2>
    <p id="artist-name">The Weeknd</p>
    <!-- playback controls, progress bar, etc. -->
  </div>
</div>

Android / Kotlin

Use ExoPlayer to play canvas videos in your Android app:

Kotlin
// 1. Add ExoPlayer dependency in build.gradle
// implementation("androidx.media3:media3-exoplayer:1.3.0")
// implementation("androidx.media3:media3-ui:1.3.0")

// 2. Fetch canvas.json (using OkHttp / Retrofit)
suspend fun fetchCanvasDB(): List<CanvasEntry> {
    val response = httpClient.get(CANVAS_JSON_URL)
    val json = JSONObject(response.body.string())
    val items = json.getJSONArray("items")
    return (0 until items.length()).map { i ->
        val obj = items.getJSONObject(i)
        CanvasEntry(
            song = obj.getString("song"),
            artist = obj.getString("artist"),
            url = obj.getString("url")
        )
    }
}

// 3. Play the canvas video
fun playCanvas(url: String, playerView: PlayerView) {
    val player = ExoPlayer.Builder(context).build()
    playerView.player = player

    val mediaItem = MediaItem.fromUri(url)
    player.setMediaItem(mediaItem)
    player.repeatMode = Player.REPEAT_MODE_ONE
    player.volume = 0f  // muted background visual
    player.prepare()
    player.play()
}

iOS / Swift

Use AVPlayer to play canvas videos in your iOS app:

Swift
import AVKit

struct CanvasEntry: Codable {
    let song: String
    let artist: String
    let url: String
}

struct CanvasDB: Codable {
    let items: [CanvasEntry]
}

// Fetch the canvas database
func loadCanvasDB() async throws -> [CanvasEntry] {
    let url = URL(string: "https://canvas.echomusic.fun/canvas.json")!
    let (data, _) = try await URLSession.shared.data(from: url)
    let db = try JSONDecoder().decode(CanvasDB.self, from: data)
    return db.items
}

// Play canvas in a view
func playCanvas(urlString: String, in view: UIView) {
    guard let url = URL(string: urlString) else { return }
    let player = AVPlayer(url: url)
    player.isMuted = true

    let playerLayer = AVPlayerLayer(player: player)
    playerLayer.videoGravity = .resizeAspectFill
    playerLayer.frame = view.bounds
    view.layer.insertSublayer(playerLayer, at: 0)

    // Loop playback
    NotificationCenter.default.addObserver(
        forName: .AVPlayerItemDidPlayToEndTime,
        object: player.currentItem,
        queue: .main
    ) { _ in
        player.seek(to: .zero)
        player.play()
    }

    player.play()
}

Python (Backend / Bot)

Useful for Discord bots, Telegram bots, or backend services:

Python
import requests

CANVAS_URL = "https://canvas.echomusic.fun/canvas.json"

def load_canvas_db():
    """Fetch the full canvas database."""
    response = requests.get(CANVAS_URL)
    response.raise_for_status()
    return response.json().get("items", [])

def find_canvas(items, song_title, artist_name):
    """Find a matching canvas entry."""
    query = f"{song_title} {artist_name}".lower()
    for item in items:
        entry = f"{item['song']} {item['artist']}".lower()
        if entry == query:
            return item
    return None

# Example usage
db = load_canvas_db()
canvas = find_canvas(db, "Starboy (feat. Daft Punk)", "The Weeknd")
if canvas:
    print(f"Canvas URL: {canvas['url']}")

Best Practices

Cache the Database

Don't fetch canvas.json on every song change. Load it once on startup and cache it locally. Refresh periodically (e.g., every 30 minutes) to pick up new community contributions.

Fuzzy Matching

Song titles may not match exactly due to special characters, casing, or feat. tags. Use case-insensitive matching and strip common suffixes like (feat. …) for better hit rates.

Handle Both Formats

Canvas URLs can be .mp4 (direct video) or .m3u8 (HLS stream). On web, use hls.js for HLS. On mobile, most players support HLS natively.

Mute & Loop

Canvas videos are visual-only backgrounds. Always set them to muted and loop. This also enables autoplay on most browsers without user interaction.

Usage & Attribution

License & Fair Use

Open Source

The canvas database is GPL-3.0 licensed. You're free to use it in any project — commercial or personal.

Attribution

Please credit Echo Music Canvas in your app or website with a link back to canvas.echomusic.fun.

Rate Limits

The JSON is hosted on GitHub raw CDN. Avoid polling more than once per minute. For high-traffic apps, mirror the data on your own CDN.

Contribute Back

If your users discover new canvases, encourage them to submit via the Contribute Portal so the whole community benefits.