Skip to content

afkcodes/sunoh-api

Repository files navigation

Sunoh API 🎵

Version Tech Stack License: MIT

The high-performance core for the Sunoh Music App, delivering a unified music discovery experience by orchestrating data from multiple industry-leading providers.


🚀 Overview

Sunoh API is a modern, TypeScript-based middleware designed to bridge the gap between various music sources. It provides a homogeneous data structure, allowing client applications to interact with many providers through a single, consistent interface.

Key Features

  • 🌪️ Unified Search & Home: Intelligent result merging and interleaving from Saavn and Gaana.
  • 📻 Universal Radio: Coordinated radio stations across providers with infinite playback support.
  • Multi-Tier Caching: Robust Redis-backed caching system with granular TTL policies.
  • 🎼 Provider-Agnostic Interface: One API for Songs, Albums, Playlists, and Artists regardless of the source.
  • 🎤 LRC/Synced Lyrics: High-quality sync lyrics integration via specialized providers.
  • 🟢 Gaana Integration Plus: Native support for stream decryption, curated occasions, and radio stations.
  • 🐋 Docker Ready: Fully containerized environment for seamless deployment and development.

🛠️ Technology Stack

  • Runtime: Node.js (v20+)
  • Framework: Fastify (High performance, low overhead)
  • Language: TypeScript (Type-safe codebase)
  • Database/Cache: Redis (High-speed data persistence)
  • Containerization: Docker & Docker Compose
  • Deployment: Optimized for Vercel Serverless and Standalone Docker.

🏛️ Architecture

Unified Search Engine

The API implements a sophisticated merging algorithm that prioritizes data quality and relevancy. When a search is performed:

  1. It queries multiple providers (Saavn, Gaana) in parallel using Promise.allSettled.
  2. It deduplicates results based on internal IDs and normalized titles.
  3. It cleans "dirty" metadata (e.g., placeholder titles like "Untitled" or "None").
  4. It prioritizes the highest resolution imagery available (atw format).

Universal Radio Stations

The API coordinates radio stations from Saavn and Gaana into a single stream. It supports creation of stations from artists or specific songs and provides a server-side cursor for endless music.

Data Homogenization

All source data is mapped to a strictly typed internal schema before returning. This means your frontend doesn't need to know if a song came from Saavn or Gaana; it always receives the exact same JSON structure.


🚦 Getting Started

Environment Setup

Create a .env file in the root directory:

PORT=3600
REDIS_HOST=redis
REDIS_PORT=6379
# PROVIDER TOKENS
LYRICS_TOKEN=your_token
MEDIA_USER_TOKEN=your_token

1. Using Docker (Recommended)

The fastest way to get up and running:

# Start API and Redis containers
npm run docker:up -- --build

The API will be available at http://localhost:3600.

2. Local Development

# Install dependencies
npm install

# Start development server with auto-reload
npm run dev

📖 API Documentation

Detailed endpoint specifications can be found in api-endpoints.json.

Core Endpoints

Path Method Description
/music/home GET Unified home screen with interleaved charts and releases.
/music/search GET Merged search results for songs, albums, and playlists.
/music/recommend GET Get similar songs based on a search query (q).
/music/radio GET Browse featured radio stations from all providers.
/music/artist/radio GET Start an artist-based radio station via query (q).
/music/song/:id GET Full song metadata and streaming URLs.
/music/occasions GET Browse curated moods and genres (Gaana focused).
/lyrics/:name GET Get LRC/Synced lyrics for a specific track.

📻 Universal Radio & Recommendations

The API provides a set of high-level endpoints to drive a "Discovery" experience.

1. Smart Recommendations

Fetch a list of similar songs and a coordinated radio station using just a song name.

  • Endpoint: GET /music/recommend?q=Song Name
  • Response: Returns a list of songs and a stationId.

2. Artist Radio

Start a personalized stream for any artist.

  • Endpoint: GET /music/artist/radio?q=Artist Name
  • Response: Returns a stationId and the first 20 tracks.

4. Universal Radio Wrapper (Unified)

The API provides a seamless, provider-agnostic way to handle infinite radio playback.

Step 1: Initialize Session Call this when the user clicks "Start Radio" on an entity.

  • Endpoint: GET /music/radio/session
  • Params:
    • id: Entity ID (Song/Artist ID)
    • type: song | artist | featured
    • provider: saavn | gaana
    • name: (Optional) Name for Featured/Artist stations
  • Response: Returns a unified stationId (e.g., saavn_PID123, gaana_12345).

Step 2: Fetch Songs / Infinite Playback Use the returned stationId to fetch songs. Supports pagination.

  • Endpoint: GET /music/radio/:stationId
  • Params:
    • k: Number of songs (default 20)
    • next: Page number (default 1)
  • Response: Returns a list of standardized Song objects ready for playback.

Legacy Radio Endpoints (Optional)

Direct access to specific provider radio logic is still available via:

  • /saavn/station/create
  • /gaana/radio/:id

💾 Caching Policy

We employ a tiered caching strategy to ensure minimal latency:

  • Playlists & Albums: 2 Hours (Tailored for discoverability).
  • Home & Occasions: 3 Hours (Optimized for performance).
  • Fast-Changing Data: No cache (e.g., real-time streams).

🚢 Deployment

Docker Deployment

# Production build and run
docker compose up -d --build

Vercel Serverless

The API is pre-configured for Vercel.

npm run deploy:prod

🤝 Contributing & Support

This project is the backbone of the Sunoh ecosystem. While we welcome community contributions, our priority is maintaining stability for the Sunoh Music App.

  • Found a bug? Open a GitHub issue.
  • Want to add a provider? Please open a discussion first to align on data mapping.
  • Support Sunoh: Visit www.sunoh.online.

Built with ❤️ by the Sunoh Team 🎵

About

fastify backend powering sunoh

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published