🎵 Elegant music app to play & manage music library. YouTube Music client.
[work-in-progress] [report-bugs-or-request-features] [patreon] [primary-guide] [youtube-music-guide]
Enjoy that 🧈 buttery experience.
video.mp4
- Features
- Limitations
- Guide
- Acknowledgements
- Compiling
- License
- Third-Party Credits
- Discord
- Patreon
- Controversies
Supports Windows 7 or later.
On Windows, setup is recommended as it automatically links with files & file explorer context menus.
Linux [beta]
Any modern Linux distribution.
On Debian or Ubuntu based distros, you need to install mpv
& libmpv-dev
to be able to install & run the app.
sudo apt install mpv libmpv-dev
sudo dpkg -i harmonoid-linux-x86_64.deb
Similar instructions can be followed on your favorite distro.
- Powerful music library management based on metadata tags. Indexes music into group of albums & artists.
- Capable of indexing 20 files/second (on Windows) & saves cache for future app start-ups.
- Cross-platform (currently aiming Windows, Linux & Android).
- mpv based music playback for strong format support (on Linux & Windows) using
dart:ffi
. - Taskbar & System Media Transport Controls for Windows.
- Small installer (< 25 MB) & low RAM usage (< 120 MB) (tested on Windows, still see limitations).
- Lyrics for all your music.
- Very strictly follows Material Design guidelines for UI & animations.
- Ability to create persistent or "Now playing" playlists.
- Context menu integrations & file associations (exclusive to setup version).
- Discord RPC integration.
- Portable (if you wish).
- Does not use electron.js.
- D-Bus MPRIS controls for Linux.
- Gapless playback.
- Music visualizations.
- Time-synced lyrics.
- Equalizer.
- Details editor.
- Re-ordering "Now Playing" list.
- Mini-window mode.
- Minimization to system tray.
- Last.fm scrobbling.
- Plugin API.
- Windows 11
IExplorerCommand
integration. - Publishing to Microsoft Store & other places.
- YOU Tell 😄.
[hopefully these will be resolved over time]
A lot of time has went into making this project possible using Flutter & nearly everything has been written from ground-up (from low-level C/C++ plugins to UI & business-logic in Flutter/Dart).
Flutter is quite new at the time for desktop & every new (even basic) functionality in the app is a research itself.
Nothing at the time is very stable & every new feature is a new discovery. Just have fun, learn & share your knowledge!
Few issues regarding memory usage alone can be:
In most cases as of now (Windows & Linux), memory usage will be really low at fresh start of the application & will continue to rise (although slowly) overtime with no specific reason.
- Space: Play or pause.
- Alt + N: Next song.
- Alt + B: Previous song.
- Alt + M: mute or un-mute.
- Alt + V: Volume increase.
- Alt + C: Volume decrease.
- Alt + X: Seek forwards.
- Alt + Z: Seek backwards.
To show your local music inside Harmonoid, you can go to the settings & click "ADD NEW FOLDER". This will show a new window, where you can select a folder where all your music is stored. After selecting the folder, your music collection inside the application will start building.
Your music will be categorized into albums, artists etc. & you'll be able to freely browse music album-wise or artist-wise etc. while being able to sort it alphabetically or year-wise etc.
As of now, you can still browse/play your music while it is being indexed.
Next time when you start the app, your music collection will be retrieved from the cache.
To remove a folder from your music collection, just click on "REMOVE" next to the folder you might wanna remove in the settings page.
Just tap the circular "refresh" button in bottom-right of the application, it'll look for new files & remove the deleted ones from your library.
If you wish to completely re-build your music library (from scratch), go to Settings & press "REINDEX" under "Collection" section.
By default, the app will attempt to play the song that you click on, while adding songs after it to the queue. To add more songs to the queue, simply right click on the new song & click "Add to now playing".
You can also configure to automatically play other songs from your collection when the queue is finished.
To create a new playlist, you need to go the the "PLAYLISTS" tab & click "CREATE NEW PLAYLIST". This will ask you a name for your new shiny playlist. After its creation, you can click on your favorite song to add it to the required playlist. This can help you greatly organize your music collection.
You can add both local music & music from web URLs to these playlists.
Click on the "earth icon" in top-right of the application, select "YT Music".
Currently, YouTube Music support works well in terms of performance & features. Right now, you can:
- Play songs.
- Play songs from URL.
- Search for songs, videos, albums, artists & playlists.
- Browse albums, artists & playlists.
- Get recommendations.
- Get suggestions.
- Save to playlists (still streamed over the internet).
You can play music directly from file explorer if you installed Harmonoid using the setup installer or from Microsoft Store.
You can also right click a folder to "Add to Harmonoid's Playlist".
If you're playing a song from YouTube Music & want to hear it on website instead, you can simply go to the "Now Playing Screen" by an arrow in the bottom-right corner of the application. Hovering over the album art, you'll see an icon hinting to open the song in your web-browser. Click on it & you're on YouTube Music website.
Click on the "earth icon" in top-right of the application, select "Play URL".
If you encounter some problem like you're unable to start the app or see an error screen, you can try to delete the .Harmonoid
folder in your home directory.
WARNING: This will also delete your music indexing cache & playlists. Best decision can be to report us at our Discord.
If you wish to really configure properties of the app which are not available in the UI yet, you may edit the .JSON
files in ~/.Harmonoid
directory.
An incomplete list of people who are working (or worked) on the project in past:
-
Hitesh Kumar Saini
- Lead developer. Deals with playback & indexing of media. Writes UI, state management & lifecycle code. Manages native plugins.
-
Yehuda Kremer
- UI & animation improvements. Application persistence & other important features. MSIX package for the store publishing.
-
Denis
- Major bug-fixes & Windows installer. Russian translation.
-
Mitja Ševerkar
- WinGet package. Backward Windows compatiblity checks. Bug reports. CI. Slovenian translation.
-
Prateek Sunal
- RPM package. Bug reports. Hindi translation.
-
Bruno D'Luka
- User interface & design. Portuguese translation.
-
Gaetan Jonathan BAKARY
- Linux related bug-fixes. French translation.
-
Tamim Arafat
- User interface & design. Bug reports.
-
Leon
- User interface fixes, app persistence improvements. Dutch translation.
-
Bluebell
- Artwork & iconography used in the application.
-
Sombian
- Testing & bug reports.
-
SleepDaemon
- Testing & bug reports.
-
ilopX
- Testing & bug reports.
-
Ankit Rana
- Testing & bug reports.
-
Fodor Benedek
- Hungarian translation.
-
Max Haureus
- Swedish translation.
-
Lars
- Dutch translation.
-
CanbiZ
- German translation.
-
stonegate
- Mandarin translation & bug reports.
-
さぶうぇい
- Japanese translation.
-
Yusuf Kamil Turan
- Turkish translation.
-
yulog
- Update Japanese translation.
-
ejacquemoud
- Update French translation.
-
Maison
- Update Portuguese translation.
-
mi875
- Update Japanese translation.
-
Lucifer25x
- Add Azerbaijani & update Turkish translation.
-
0xj0hn
- Add Persian translation.
-
Feelogil
- Update Russian translation.
-
Takeshi
- Add Indonesian translation.
Ensure that you have Flutter SDK & the required toolchain e.g. Visual Studio for Windows, Android Studio for Android installed.
git clone https://github.com/harmonoid/harmonoid.git --single-branch --recursive --branch master
cd harmonoid
flutter build windows
flutter build linux
...
As of now, if you wish to gain access to all the private packages (and other source code within GitHub organization) used in Harmonoid, you may become a Patreon & support the development.
You can compile Harmonoid yourself by removing references to following private plugins & replacing them with my following other already publicly available packages:
Private package | Open-source alternative | Notes |
---|---|---|
libmpv.dart | dart_vlc & flutter_media_metadata | All features may not work, performance may not be as tuned. The resultant bundle size may be larger in size. |
smtc-win32 | libwinmedia | libwinmedia was used in earlier versions of application for media playback & still available under MIT license. |
mpris_service.dart | - | No alternatives available. |
harmonoid_visual_assets | - | Contains iconography & pictures used within the project. You can simply disable. |
The source-code in this repository and official releases/binaries are distributed under our End-User License Agreement for Harmonoid (EULA).
-
Harmonoid is (for the most part) written in Dart programming language using Flutter SDK. Refrences to all the other external "plugins" & "packages" used at the time of building application can be found here.
-
Harmonoid uses a modified version of libmpv for media playback capabilities on desktop. The compilation setup & other information (for Microsoft Windows) can be found here. The application bundles a minimal & LGPL compilant version of mpv shared library (for Microsoft Windows) (
mpv-2.dll
). Users are free to update/change to their own preferred libmpv by replacing thempv-2.dll
file present in Harmonoid's application directory. -
Harmonoid also depends upon some of the awesome packages available on pub.dev. A complete list of those can be found here.
-
YouTube & YouTube Music is owned by Google LLC. Playback of videos & music is governed by YouTube Terms of Service. The application does not store any music/video streams locally, neither saves files on the disk. The content is shown in a manner similar to how a normal web-browser functions. This is not a "core" functionality of the application and just something application supports for the sake of completion.
A lot of things were (are still) inexistent for Flutter Desktop or had to be made on-my-own for this project specifically. Thus, few of the things are written with a compromise.
Few of the common arguments can be:
- You are using singletons in the project.
- Stop saving cache in JSON.
- Don't use Provider, use Riverpod.
- No tests?
- Platform specific design
Answers:
- Singletons might be "bad", but here the application internally requires reference to these singleton objects/
ChangeNotifier
s outsideWidget
tree quite often (withoutBuildContext
) (possibly usingget_it
like dependency-injection at some point will be good idea). e.g. few situtations like:
- Triggering seekbar re-draw whenever position-update is sent from native code.
- A file is opened from file explorer & app should open the clicked file within same instance.
- Showing media-buffering state.
- Indexing a
File
(retreving its tags) & showing progress update in UI. - System media control button(s) are clicked, the playback should be paused & UI re-draws should be triggered.
- Some
TextField
is focused, keyboard shortcuts should be prevented. - Music files are being indexed, progress updates should be shown while saving metadata/tags to cache. And we can't make UI redraw for every single file that is parsed, but rather in a definite period interval (so that everything stays usable).
-
Saving cache as JSON isn't a problem since there are no performance drawbacks (think of it as a NoSQL database). All that is happening at the end is serialization-deserialization & file read-write, either it be a sqlite3, hive, JSON or something else. Now a lot of good cross-platform databases are available like
hive
orisar
for Flutter on Desktop, which can be used for caching the music-library/metadata-tags. However, the same wasn't applicable before. -
I fear I don't have time for that-much refactor now. I will prefer switching to BLoC instead, if any refactor ever happens. Why would I use a state-management solution that encourages to create global-variables ;)
-
We need to write those. It's becoming a struggle with time. But I fear tests in Flutter aren't "capable" enough, the app highly depends upon C-interop & if something wrong happens or memory error takes place, Dart VM itself will die. I need tests to check actual functionality, audio output, correct audio-tagging, file explorer associations etc. NOT to measure/match position of
Widget
s on screen or compare Dart sided data-types with fake native-calls. In that case, only a human can do the job & look for possible regressions. And, since I am the only one who regularly commits changes or works on features, I don't feel that urgency to setup a pull-request test suite for public-contributions. -
No. Never. It's not "smart" to run a full-blown Skia renderer (from Flutter) & make it show a bland "native looking" UI design. One of the biggest advantage Flutter provides is that it's pixel-by-pixel painted, which means it is highly customisable in terms of what one can render visually. And I don't wanna put that advantage to no use, by following same boring design as other "native looking" apps (which will actually perform better in terms of graphical performance, for obvious reasons). I really like Material Design & current design is highly inspired by this video & I've made efforts to keep it CONSISTENT, FLUID & ADAPTIVE across all the platforms. I will add support for Material You at some point, but will be optional to users inside the Settings.
If you disagree with any of the answers or want to correct my knowledge, please open a new issue or discussion.
Well you've scrolled this down... How about seeing more ✨ colorful ✨ stuff.