Skip to content

Chaganti-Reddy/resonance

Repository files navigation

Resonance

A premium music streaming app built with Flutter, FastAPI, Redis, and Supabase. Stream from YouTube via Invidious, manage playlists, follow friends, and play your own local music library.


Quick Start

# 1. Clone
git clone https://github.com/Chaganti-Reddy/resonance.git
cd resonance

# 2. Run setup (requires Docker Desktop)
.\setup.ps1

# 3. Run the app
cd musicapp
flutter pub get
flutter run

Windows only: setup script requires PowerShell 5.1+ and Docker Desktop. See below for macOS/Linux.


Features

Streaming

  • YouTube audio via Invidious — no API key required, 7-instance fallback pool
  • Stream URLs cached in Redis (6h TTL) — minimal re-resolution
  • Local music files from ./music folder (MP3, FLAC, OGG, M4A, AAC, WAV, OPUS)
  • Background playback with lock-screen controls

Premium UI

  • Ambient color extraction — dominant color pulled from album art, animates as background tint across player and mini player (800ms smooth transition)
  • Swipe to skip — swipe left/right on album art in the full player
  • Floating mini player — ambient-tinted glass pill with progress bar
  • Immersive full-screen player — blurred album art backdrop, glow shadow
  • No dropdowns anywhere — everything uses bottom sheets or custom pickers

Onboarding

  • Visual genre grid selection
  • Artist search with Invidious autocomplete (~50ms), real-time grid filtering while typing
  • Country picker with flag emojis via bottom sheet (no dropdown)

Library

  • Like songs, create and manage playlists
  • Play history with play counts
  • Collaborative playlists

Social

  • Follow other users
  • Now Playing feed — see what friends are listening to in real time (Supabase Realtime)
  • Public playlists

Discovery

  • Multi-signal personalised recommendations:
    • Play history (30d) · liked songs · playlist songs · friend listening · onboarding prefs
    • Per-artist diversity cap (max 3 songs per artist)
    • Cold-start fallback for new users

Setup Guide

Prerequisites

Tool Version
Docker Desktop 24+
Flutter SDK 3.19+
Git any

1. Supabase

  1. Create project at supabase.com
  2. In SQL Editor, run supabase/schema.sql
  3. From Project Settings → API, copy your URL and keys

2. Configure .env

setup.ps1 copies .env.example.env. Fill in:

SUPABASE_URL=https://xxxxxxxxxxxx.supabase.co
SUPABASE_ANON_KEY=eyJhbGc...
SUPABASE_SERVICE_KEY=eyJhbGc...
SECRET_KEY=replace-with-a-long-random-string

3. Start the backend

docker compose up -d --build
docker compose ps
curl http://localhost:8000/health

This starts:

  • resonance_backend on port 8000
  • resonance_redis on port 6379

4. Configure Flutter

Set backend URL in musicapp/lib/core/constants/api_constants.dart:

// Android emulator
const kApiBaseUrl = 'http://10.0.2.2:8000';
// iOS simulator / web / desktop
const kApiBaseUrl = 'http://localhost:8000';

Set Supabase credentials in musicapp/lib/core/constants/app_constants.dart.


Architecture

┌─────────────────────────────────────────────────────────────────┐
│  Flutter App (musicapp/)                                        │
│  Riverpod · just_audio · audio_service · palette_generator     │
└────────────────────┬───────────────────────┬────────────────────┘
                     │ REST / HTTP            │ Realtime WebSocket
                     ▼                        ▼
┌──────────────────────────┐    ┌─────────────────────────────────┐
│  FastAPI Backend          │    │  Supabase                       │
│  (backend/)               │    │  - PostgreSQL database          │
│  - Invidious search       │    │  - Auth (email + OAuth)         │
│  - Stream URL resolution  │    │  - Row Level Security           │
│  - Lyrics (LRCLIB)        │    │  - Realtime (now_playing)       │
│  - Recommendations        │    └─────────────────────────────────┘
│  - Local music scanning   │
└──────────┬───────────────┘
           │
           ▼
┌──────────────────────────┐    ┌─────────────────────────────────┐
│  Redis                    │    │  Invidious (open-source YouTube) │
│  - Search cache (1h TTL)  │◄──│  - 7-instance fallback pool     │
│  - Stream URL cache (6h)  │    │  - Search + autocomplete        │
│  - Artist suggestions     │    │  - Audio stream extraction      │
└──────────────────────────┘    └─────────────────────────────────┘

Streaming flow:

  1. Flutter sends GET /api/stream?external_id=...&source=youtube
  2. FastAPI checks Redis (6h TTL)
  3. On miss — Invidious resolves direct audio CDN URL across 7 instances
  4. URL cached, returned to Flutter
  5. just_audio streams directly from CDN
  6. Flutter upserts now_playing to Supabase → Realtime pushes to followers

Tech Stack

Layer Technology
Mobile / Desktop / Web Flutter 3 (Dart)
State management Riverpod
Audio engine just_audio + audio_service
Ambient color palette_generator + CachedNetworkImage
Backend API Python 3.11, FastAPI, Uvicorn
Audio source Invidious (open-source YouTube frontend)
Lyrics LRCLIB API
Cache Redis 7
Database PostgreSQL via Supabase
Auth Supabase Auth (email + Google OAuth)
Realtime Supabase Realtime
Containerisation Docker, Docker Compose

Project Structure

resonance/
├── backend/
│   ├── main.py                    FastAPI app factory
│   ├── requirements.txt
│   ├── Dockerfile
│   └── app/
│       ├── config.py              Settings (Pydantic)
│       ├── middleware/auth.py     Supabase JWT verification
│       ├── models/                Pydantic response models
│       ├── routers/               API route modules
│       └── services/              Business logic
│           ├── invidious_service  YouTube search + stream resolution
│           ├── music_orchestrator Search aggregation
│           ├── cache_service      Redis wrapper
│           ├── lyrics_service     LRCLIB integration
│           ├── radio_service      Related tracks
│           └── recommendations_service  Multi-signal personalisation
├── musicapp/
│   └── lib/
│       ├── main.dart
│       ├── app.dart               Router + ProviderScope
│       ├── core/
│       │   ├── constants/         API URLs, app config
│       │   ├── navigation/        GoRouter setup
│       │   ├── theme/             Colors, text styles, theme
│       │   └── utils/             Extensions, formatters
│       ├── features/
│       │   ├── auth/              Login + signup
│       │   ├── onboarding/        Genre/artist/country selection
│       │   ├── home/              Feed, genres, now-playing hero
│       │   ├── player/            Full-screen player + lyrics + queue
│       │   ├── search/            Search screen
│       │   ├── library/           Liked songs + history
│       │   ├── playlist/          Playlist CRUD
│       │   ├── social/            Following feed + profiles
│       │   ├── artist/            Artist detail
│       │   ├── album/             Album detail
│       │   ├── podcasts/          Podcast browser + episodes
│       │   └── settings/          App settings + equalizer
│       └── shared/
│           ├── models/            Dart data classes
│           ├── providers/         Riverpod providers (player, auth, library, ambient color)
│           ├── services/          API client, audio, Supabase, cache
│           └── widgets/           Mini player, song tile, glass widgets
├── supabase/schema.sql            DB schema + RLS policies
├── docker-compose.yml
├── setup.ps1                      One-command Windows setup
└── .env.example

API Reference

Swagger UI: http://localhost:8000/docs

GET  /health                                    Redis + app health
GET  /api/search?q=...&source=all&limit=20      Search songs
GET  /api/search/suggestions?q=...              Autocomplete (Invidious)
GET  /api/stream?external_id=...&source=youtube Stream URL
GET  /api/artists?genre=...&country=...         Artist suggestions
GET  /api/lyrics?title=...&artist=...           Lyrics (LRCLIB)
GET  /api/radio?external_id=...                 Related tracks
GET  /api/recommendations                       Personalised feed
POST /api/library/history                       Record play event
GET  /api/library/liked                         Liked songs
POST /api/library/like                          Like a song

Local Music

Drop files into ./music/ at the project root. Mounted into the container at /music.

resonance/
  music/
    artist - track.mp3
    album/
      01.flac

Docker Commands

docker compose logs -f backend       # live backend logs
docker compose restart backend       # restart after .env changes
docker compose down                  # stop all
docker compose down -v               # stop + delete Redis data
docker compose exec backend bash     # shell into backend
docker compose exec redis redis-cli keys "*"   # inspect cache

License

MIT © Chaganti-Reddy

About

Flutter music app with FastAPI backend. YouTube streaming via Invidious, ambient color player UI, Supabase auth + social, Redis caching. No API keys required.

Resources

License

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors