A sleek, lightweight Flutter music player β play your local library, discover trending tracks, and download songs straight to your device.
- π¦ Overview
- β¨ Features
- π₯ Download
- πΌοΈ Screens
- π Project Structure
- π Getting Started
- π§ How It Works
- π οΈ Architecture
- π¦ Dependencies
- π€ Contributing
- π License
Noir Player is a small, focused Flutter app that:
- Loads your local audio files from the device library.
- Shows them in a tabbed library (
Songs,Albums,Artists,Playlists). - Runs a background audio service, so playback keeps going when the app is backgrounded or the screen is locked β with media controls on the notification, lock screen and dynamic island.
- Discovers new music β browse trending tracks and search by name via the Last.fm API.
- Streams & downloads β preview tracks and save them as MP3 to your device's music folder.
- Tailors playback β sleep timer, playback speed, resumeβafterβaβcall and more, all in a sectioned Settings page reached from the side drawer.
| Feature | Where | How it works |
|---|---|---|
| πΌ Tabbed Library | library_screen.dart |
Songs / Albums / Artists / Playlists via on_audio_query |
player_screen.dart |
Reactive UI bound to audioHandler.mediaItem & playbackState |
|
| π Background Playback | audio_handler.dart |
audio_service + just_audio with notification / lockβscreen / dynamicβisland controls and artwork |
| π§ Discover | discover_screen.dart |
Trending + search powered by Last.fm, with album art |
| β¬οΈ Download | music_discovery_service.dart |
Resolves YouTube β MP3 (RapidAPI) and saves via media_store_plus, with duplicateβdownload protection |
| β±οΈ Sleep Timer | sleep_timer_service.dart |
Autoβpause after a chosen duration, with a live countdown |
| β© Playback Speed | audio_handler.dart |
0.5Γβ2Γ without pitch change, persisted |
| π Call / interruption handling | audio_handler.dart |
Resume after a call via audio_session |
| βοΈ Persistent Settings | settings_service.dart |
Theme, playback and notification options saved with shared_preferences |
Grab the latest signed APK from the Releases page
(NoirPlayer-vX.Y.Z.apk) and install it on Android 6.0+. You may need to allow installing from unknown sources.
| Version | Notes |
|---|---|
| v1.1.1 | Native equalizer (bands + presets) |
| v1.1.0 | Musicβfolder tab, repeat/shuffle, Discover plays in the main player, playlist/favourites fixes, immersive UI + animations |
| v1.0.0 | Online discovery, downloads, media controls and full playback settings |
| v0.2.0 | Firebase authentication (experimental, preβrelease) |
| v0.1.0 | Initial local music player |
A 4βtab bottom bar plus a hamburger drawer for everything else:
| Destination | Where | Description |
|---|---|---|
| π Library | bottom bar | Your local songs, albums, artists |
| π΅ Player | bottom bar | The full "Now Playing" view (with speed & sleepβtimer actions) |
| πΆ Playlists | bottom bar | Create and browse playlists |
| π§ Discover | bottom bar | Trending tracks, search, stream & download |
| βοΈ Settings | drawer | Appearance, playback, notification & timer options |
| β±οΈ Sleep Timer | drawer | Start / cancel the autoβstop timer |
| βΉοΈ About | drawer | App info |
lib/
βββ main.dart # App entry β loads .env + settings, inits audio service
βββ core/
β βββ models/
β β βββ playlist_model.dart
β β βββ discovered_track.dart # Discover/download track model
β βββ services/
β β βββ audio_handler.dart # Background audio, media controls, interruptions
β β βββ music_discovery_service.dart # Last.fm + YouTube + MP3 download
β β βββ settings_service.dart # Persisted user preferences
β β βββ sleep_timer_service.dart # Autoβstop timer
β βββ theme/
β βββ app_theme.dart
βββ screens/
β βββ home/home_screen.dart # Bottom nav + hamburger drawer shell
β βββ library/ # Library + tabs (songs/albums/artists/playlists)
β βββ player/player_screen.dart
β βββ playlists/
β βββ albums/ artist/
β βββ discover/discover_screen.dart # Discover + download UI
β βββ settings/settings_screen.dart # Sectioned settings
β βββ about/about_screen.dart
βββ widgets/
βββ playback_menus.dart # Sleepβtimer & playbackβspeed bottom sheets
| Requirement | Version |
|---|---|
| Flutter SDK | β₯ 3.9 |
| Dart SDK | β₯ 3.9 |
| Android | 6.0 (API 23)+ |
flutter --versiongit clone https://github.com/Abdullah-Masood-05/NoirPlayer.git
cd NoirPlayer
flutter pub getThe Discover / download module needs API keys. They are loaded at runtime from a
.env file (via flutter_dotenv) and are
never committed β .env is in .gitignore.
-
Copy the template:
cp .env.example .env
-
Fill in your keys in
.env:LASTFM_API_KEY=your_lastfm_key YOUTUBE_API_KEY=your_youtube_data_api_v3_key RAPIDAPI_KEY=your_rapidapi_key
Key Get it from LASTFM_API_KEYhttps://www.last.fm/api/account/create YOUTUBE_API_KEYhttps://console.cloud.google.com/apis/credentials RAPIDAPI_KEYhttps://rapidapi.com/ (subscribe to the youtube-mp36 API)
π‘ Without keys, the rest of the app (local library + playback) still works β only the Discover tab needs them.
flutter run -d androidOn first launch the app requests permission to read your music library and to download files. Grant them and the library populates automatically.
βββββββββββββββββββββββ init ββββββββββββββββββββββββ
β main.dart β ββββββββββββΆ β AudioHandler β
β (loads .env + audio) β β (audio_service) β
ββββββββββββ¬βββββββββββ ββββββββββββββββββββββββ
β
βΌ
βββββββββββββββββββββββ bottom nav ββββββββββββββββββββββββ
β HomeScreen β ββββββββββββββΆ β Library / Player / β
β (5-tab shell) β β Playlists / Discover β
βββββββββββββββββββββββ ββββββββββββ¬ββββββββββββ
β Discover
βΌ
ββββββββββββββββββββββββββββββββ
β MusicDiscoveryService β
β Last.fm β YouTube β MP3 β save β
ββββββββββββββββββββββββββββββββ
Download flow: pick a track β look up its YouTube video ID β resolve an MP3 URL
(RapidAPI) β stream-download with dio (with progress) β save to the device's Music
folder via media_store_plus.
| File | Responsibility |
|---|---|
main.dart |
Loads .env, initialises the audio service, sets up theming & routes |
audio_handler.dart |
Wraps audio_service + just_audio for background playback and notifications |
library_screen.dart |
Tabbed local library using on_audio_query |
discover_screen.dart |
Discover UI β search, trending, preview-play, and per-track download progress |
music_discovery_service.dart |
Last.fm metadata, YouTube lookup, RapidAPI MP3 resolution, and file saving |
player_screen.dart |
Reactive "Now Playing" bound to the audio service streams |
| Package | Purpose |
|---|---|
just_audio |
Audio playback (queue, speed, seeking) |
audio_service |
Background playback + notification / lockβscreen controls |
audio_session |
Audio focus & call/headset interruptions |
on_audio_query |
Read the device's music library & artwork |
permission_handler |
Runtime permissions |
provider Β· shared_preferences |
State & persistence |
http Β· dio |
Networking & file download |
media_store_plus Β· path_provider |
Saving downloads to device storage |
flutter_dotenv |
Loading API keys from .env |
Run
flutter pub getto install everything declared inpubspec.yaml.
Pull requests are welcome! For major changes, please open an issue first to discuss what you'd like to change.
- Fork the repo
- Create a feature branch (
git checkout -b feature/amazing-thing) - Commit your changes
- Open a PR π
Distributed under the MIT License. See LICENSE for details.
π§ Enjoy the music with Noir Player!