π§ A modern local music player with an Apple Music-inspired UI. (macOS, Windows, Linux, Android) - NO ELECTRON
See the code
![]() Home | ![]() Tracks | ![]() Tracks (compact mode) |
![]() Albums | ![]() Album | ![]() Artists |
![]() Genres | ![]() Playlists | ![]() Playlist |
![]() Fullscreen player | ![]() Mini player | ![]() Search |
![]() Remote control | ![]() Mobile app |
.lrc, then .txt), embedded lyrics, then online lyrics from LRCLIB and Kugou. Search and pick lyrics manually, optionally saving the result as a .lrc file (dedicated lyrics folder, subfolder next to the track, or next to the track itself, in that order).artist.jpg/.jpeg/.webp files from your music folders (in the artist folder or beside the songs), or set your own custom image per artist. Toggle "Online Artist Artwork" to use Deezer images instead; turn it off to use your local files.Airmedy Mobile is an Android-first companion app, built with native Jetpack Compose for Android 12 and newer. It is independently usable and pairs with Airmedy Desktop when you want your library on the go.
Ctrl on Windows/Linux, Cmd on macOS. Ignored while typing in an input/textarea.
| Shortcut | Action |
|---|---|
Space | Play / pause |
Ctrl/Cmd + β | Next track |
Ctrl/Cmd + Alt + β | Fast forward |
Ctrl/Cmd + β | Previous track |
Ctrl/Cmd + Alt + β | Rewind |
Ctrl/Cmd + β | Volume up |
Ctrl/Cmd + β | Volume down |
Ctrl/Cmd + Alt + β | Mute toggle |
Ctrl/Cmd + S | Shuffle toggle |
Ctrl/Cmd + R | Cycle repeat mode |
Ctrl/Cmd + F | Go to search |
Ctrl + Cmd + F (macOS), Ctrl + Alt + F (Windows) | Toggle fullscreen |
Ctrl/Cmd + , | Open settings |
Every format plays on macOS Β· Windows Β· Linux.
| Format | Extensions |
|---|---|
| MP3 | .mp3 |
| AAC / ALAC | .m4a .aac .mp4 |
| FLAC | .flac |
| WAV / AIFF | .wav .aiff |
| Ogg Vorbis | .ogg |
| Opus | .opus |
| APE (Monkey's Audio) | .ape |
| WavPack | .wv |
| DSD | .dsf .dff |
On macOS, playback runs through SFBAudioEngine β a powerful, high-performance audio engine that provides native support for almost every format without needing FFmpeg. On Windows and Linux, miniaudio provides high-performance audio output, while FFmpeg serves as the universal decoding backend for all supported formats, ensuring consistent and robust playback across the entire library.
flowchart TB
subgraph Core["Airmedy Core"]
subgraph macOS["macOS Path"]
SFB["SFBAudioEngine<br/>(All Formats)"]
end
subgraph WinLinux["Windows / Linux Path"]
FF["FFmpeg Decoder<br/>(All Formats)"] --> MA["miniaudio<br/>(output engine)"]
end
SFB --> Stream
MA --> Stream["Consistent Audio Stream<br/>(Float32 PCM)"]
end
The FFmpeg libraries are statically compiled and bundled inside internal/infra/audio/ffmpeg_libs/. No system FFmpeg installation is ever required.
| Layer | Technology |
|---|---|
| Backend runtime | Go 1.25, Wails v3 |
| Dependency injection | uber-go/fx |
| Database | SQLite via golang-migrate |
| Search index | Bleve |
| Audio (macOS) | SFBAudioEngine + CGo |
| Audio (Win/Linux) | miniaudio + FFmpeg (CGo) |
| Metadata | go-taglib |
| Frontend framework | Vue 3 (Composition API) |
| State management | Pinia 3 |
| UI components | Radix Vue + Tailwind CSS v4 |
| Monorepo | pnpm workspaces + Turbo |
| UI package | @airmedy/ui (packages/ui) |
| Utils package | @airmedy/utils (packages/utils) |
| Lyrics | Local .lrc/.txt, embedded tags, LRCLIB + Kugou |
| Layer | Technology |
|---|---|
| Platform | Kotlin Multiplatform, Android 12+ |
| UI | Jetpack Compose |
| Local storage | Room + DataStore |
| Audio | FFmpeg + AAudio |
| Shared logic | sharedLogic (models, use cases, ports) |
Airmedy follows a Hexagonal / Ports & Adapters pattern:
main.go # Entry point
internal/
βββ domain/ # Business logic, interfaces, DTOs
βββ app/ # Application services (use cases)
βββ infra/
βββ audio/ # SFBAudioEngine / miniaudio / FFmpeg adapters
βββ db/ # SQLite migrations and queries
βββ search/ # Bleve index adapter
βββ wails/ # Thin Wails bindings (frontend β app)
frontend/ # Main desktop UI (Vue 3)
βββ src/
β βββ components/ # Feature components (AlbumCard, TrackTableβ¦)
β βββ views/ # Route-level pages
β βββ stores/ # Pinia stores
β βββ composables/ # Shared logic
β βββ locales/ # i18n locale files
packages/
βββ ui/ # @airmedy/ui β stateless UI primitives (Slider, Inputβ¦)
βββ utils/ # @airmedy/utils β shared utilities (logger, utils)
remote/ # Browser-based remote control SPA (Vue 3)
βββ src/
βββ components/ # Remote UI components
βββ stores/ # Pinia stores (player state over WS)
βββ locales/ # i18n locale files
mobile/ # Android-first Kotlin Multiplatform app
βββ androidApp/ # Compose UI, ViewModels, Android adapters
βββ sharedLogic/ # Platform-neutral models, use cases, and ports
Dependencies always point inward β infra depends on app, app depends on domain, never the reverse.
| Tool | Version |
|---|---|
| Go | β₯ 1.25 |
| Node.js | β₯ 20 |
| pnpm | β₯ 9 |
| Task | taskfile.dev |
| Wails CLI v3 | go install github.com/wailsapp/wails/v3/cmd/wails@latest |
| JDK | 11 (mobile builds) |
| Android SDK | Platform 36 (mobile builds) |
| Android NDK | 30.0.15729638 (mobile audio builds) |
No system FFmpeg required. FFmpeg is the decode backend on Windows/Linux only β macOS uses SFBAudioEngine and ships no FFmpeg. Pre-built static libraries for
windows/amd64,windows/arm64,linux/amd64, andlinux/arm64are bundled ininternal/infra/audio/ffmpeg_libs/.To rebuild them:
scripts/build-ffmpeg-linux.shandscripts/build-ffmpeg-windows.sh(the latter cross-compilesamd64+arm64from Linux viagcc-mingw-w64).scripts/build-ffmpeg-windows-msys2.shbuilds Windowsamd64natively inside an MSYS2 MINGW64 shell. All produce minimal static.alibs (FFmpeg 8.1.2, decoders only).
git clone https://github.com/misa198/airmedy.git
cd airmedy
# Run in development mode
wails3 dev
# Build production binary
wails3 build
wails3 task verify # runs all Go unit tests + Vue component tests + linters
# Mobile shared-logic tests
./mobile/gradlew :sharedLogic:testAndroidHostTest
wails3 task {task_name}
Build the Android FFmpeg libraries once, then assemble either installable variant:
bash scripts/build-ffmpeg-android.sh arm64-v8a
./mobile/gradlew :androidApp:assembleDevDebug
./mobile/gradlew :androidApp:assembleProdDebug
dev and prod use separate application IDs, so both can be installed on one device. Android requires API 31 (Android 12) or newer.
commit-msg hook (wails3 task setup:hooks)masterGPL-3.0 Β© misa198. Third-party licenses in NOTICES.
Kotlin
37.9%
Go
29.3%
Vue
15.9%
TypeScript
8.7%
Shell
2.2%
C
2.0%
C++
1.7%
π§ A modern local music player with an Apple Music-inspired UI. (macOS, Windows, Linux, Android) - NO ELECTRON
See the code
![]() Home | ![]() Tracks | ![]() Tracks (compact mode) |
![]() Albums | ![]() Album | ![]() Artists |
![]() Genres | ![]() Playlists | ![]() Playlist |
![]() Fullscreen player | ![]() Mini player | ![]() Search |
![]() Remote control | ![]() Mobile app |
.lrc, then .txt), embedded lyrics, then online lyrics from LRCLIB and Kugou. Search and pick lyrics manually, optionally saving the result as a .lrc file (dedicated lyrics folder, subfolder next to the track, or next to the track itself, in that order).artist.jpg/.jpeg/.webp files from your music folders (in the artist folder or beside the songs), or set your own custom image per artist. Toggle "Online Artist Artwork" to use Deezer images instead; turn it off to use your local files.Airmedy Mobile is an Android-first companion app, built with native Jetpack Compose for Android 12 and newer. It is independently usable and pairs with Airmedy Desktop when you want your library on the go.
Ctrl on Windows/Linux, Cmd on macOS. Ignored while typing in an input/textarea.
| Shortcut | Action |
|---|---|
Space | Play / pause |
Ctrl/Cmd + β | Next track |
Ctrl/Cmd + Alt + β | Fast forward |
Ctrl/Cmd + β | Previous track |
Ctrl/Cmd + Alt + β | Rewind |
Ctrl/Cmd + β | Volume up |
Ctrl/Cmd + β | Volume down |
Ctrl/Cmd + Alt + β | Mute toggle |
Ctrl/Cmd + S | Shuffle toggle |
Ctrl/Cmd + R | Cycle repeat mode |
Ctrl/Cmd + F | Go to search |
Ctrl + Cmd + F (macOS), Ctrl + Alt + F (Windows) | Toggle fullscreen |
Ctrl/Cmd + , | Open settings |
Every format plays on macOS Β· Windows Β· Linux.
| Format | Extensions |
|---|---|
| MP3 | .mp3 |
| AAC / ALAC | .m4a .aac .mp4 |
| FLAC | .flac |
| WAV / AIFF | .wav .aiff |
| Ogg Vorbis | .ogg |
| Opus | .opus |
| APE (Monkey's Audio) | .ape |
| WavPack | .wv |
| DSD | .dsf .dff |
On macOS, playback runs through SFBAudioEngine β a powerful, high-performance audio engine that provides native support for almost every format without needing FFmpeg. On Windows and Linux, miniaudio provides high-performance audio output, while FFmpeg serves as the universal decoding backend for all supported formats, ensuring consistent and robust playback across the entire library.
flowchart TB
subgraph Core["Airmedy Core"]
subgraph macOS["macOS Path"]
SFB["SFBAudioEngine<br/>(All Formats)"]
end
subgraph WinLinux["Windows / Linux Path"]
FF["FFmpeg Decoder<br/>(All Formats)"] --> MA["miniaudio<br/>(output engine)"]
end
SFB --> Stream
MA --> Stream["Consistent Audio Stream<br/>(Float32 PCM)"]
end
The FFmpeg libraries are statically compiled and bundled inside internal/infra/audio/ffmpeg_libs/. No system FFmpeg installation is ever required.
| Layer | Technology |
|---|---|
| Backend runtime | Go 1.25, Wails v3 |
| Dependency injection | uber-go/fx |
| Database | SQLite via golang-migrate |
| Search index | Bleve |
| Audio (macOS) | SFBAudioEngine + CGo |
| Audio (Win/Linux) | miniaudio + FFmpeg (CGo) |
| Metadata | go-taglib |
| Frontend framework | Vue 3 (Composition API) |
| State management | Pinia 3 |
| UI components | Radix Vue + Tailwind CSS v4 |
| Monorepo | pnpm workspaces + Turbo |
| UI package | @airmedy/ui (packages/ui) |
| Utils package | @airmedy/utils (packages/utils) |
| Lyrics | Local .lrc/.txt, embedded tags, LRCLIB + Kugou |
| Layer | Technology |
|---|---|
| Platform | Kotlin Multiplatform, Android 12+ |
| UI | Jetpack Compose |
| Local storage | Room + DataStore |
| Audio | FFmpeg + AAudio |
| Shared logic | sharedLogic (models, use cases, ports) |
Airmedy follows a Hexagonal / Ports & Adapters pattern:
main.go # Entry point
internal/
βββ domain/ # Business logic, interfaces, DTOs
βββ app/ # Application services (use cases)
βββ infra/
βββ audio/ # SFBAudioEngine / miniaudio / FFmpeg adapters
βββ db/ # SQLite migrations and queries
βββ search/ # Bleve index adapter
βββ wails/ # Thin Wails bindings (frontend β app)
frontend/ # Main desktop UI (Vue 3)
βββ src/
β βββ components/ # Feature components (AlbumCard, TrackTableβ¦)
β βββ views/ # Route-level pages
β βββ stores/ # Pinia stores
β βββ composables/ # Shared logic
β βββ locales/ # i18n locale files
packages/
βββ ui/ # @airmedy/ui β stateless UI primitives (Slider, Inputβ¦)
βββ utils/ # @airmedy/utils β shared utilities (logger, utils)
remote/ # Browser-based remote control SPA (Vue 3)
βββ src/
βββ components/ # Remote UI components
βββ stores/ # Pinia stores (player state over WS)
βββ locales/ # i18n locale files
mobile/ # Android-first Kotlin Multiplatform app
βββ androidApp/ # Compose UI, ViewModels, Android adapters
βββ sharedLogic/ # Platform-neutral models, use cases, and ports
Dependencies always point inward β infra depends on app, app depends on domain, never the reverse.
| Tool | Version |
|---|---|
| Go | β₯ 1.25 |
| Node.js | β₯ 20 |
| pnpm | β₯ 9 |
| Task | taskfile.dev |
| Wails CLI v3 | go install github.com/wailsapp/wails/v3/cmd/wails@latest |
| JDK | 11 (mobile builds) |
| Android SDK | Platform 36 (mobile builds) |
| Android NDK | 30.0.15729638 (mobile audio builds) |
No system FFmpeg required. FFmpeg is the decode backend on Windows/Linux only β macOS uses SFBAudioEngine and ships no FFmpeg. Pre-built static libraries for
windows/amd64,windows/arm64,linux/amd64, andlinux/arm64are bundled ininternal/infra/audio/ffmpeg_libs/.To rebuild them:
scripts/build-ffmpeg-linux.shandscripts/build-ffmpeg-windows.sh(the latter cross-compilesamd64+arm64from Linux viagcc-mingw-w64).scripts/build-ffmpeg-windows-msys2.shbuilds Windowsamd64natively inside an MSYS2 MINGW64 shell. All produce minimal static.alibs (FFmpeg 8.1.2, decoders only).
git clone https://github.com/misa198/airmedy.git
cd airmedy
# Run in development mode
wails3 dev
# Build production binary
wails3 build
wails3 task verify # runs all Go unit tests + Vue component tests + linters
# Mobile shared-logic tests
./mobile/gradlew :sharedLogic:testAndroidHostTest
wails3 task {task_name}
Build the Android FFmpeg libraries once, then assemble either installable variant:
bash scripts/build-ffmpeg-android.sh arm64-v8a
./mobile/gradlew :androidApp:assembleDevDebug
./mobile/gradlew :androidApp:assembleProdDebug
dev and prod use separate application IDs, so both can be installed on one device. Android requires API 31 (Android 12) or newer.
commit-msg hook (wails3 task setup:hooks)masterGPL-3.0 Β© misa198. Third-party licenses in NOTICES.
Kotlin
37.9%
Go
29.3%
Vue
15.9%
TypeScript
8.7%
Shell
2.2%
C
2.0%
C++
1.7%