MiniMedia Sonic Server
June 6, 2026 ยท View on GitHub
A work in progress Subsonic music server with as backend database, postgres
There is a lot of work to be done still, but the basics work (playing a track, seeing the artists/albums/tracks)
My main goal is to come as close as possible to a real service, so that means performance, features they provide (covers, similar tracks etc)
Roadmap
This roadmap will be ongoing as the project keeps going
- Support for all OpenSubsonic API's
- Support for all Navidrome API's
- Legacy Subsonic authentication (needs to be improved still)
- Token-based Subsonic authentication
- Get similar tracks from Tidal
- Redis caching
- Support for Navidrome's Smart Playlist (nsp) format
Tested Working Android/iPhone Apps
- Android: Symfonium https://www.symfonium.app
- iPhone: Arpeggi
- iPhone: Narjo https://narjomusic.com
- iPhone/Android: Substreamer https://substreamer.org
- iPhone: Armperfy
Tested working projects
If a app/project was not mentioned in the list it does not mean it won't work, it simply means I personally did not verify it working
Docker Compose
services:
main_app:
container_name: MiniMediaSonicServer
deploy:
resources:
limits:
memory: 256M
hostname: MiniMediaSonicServer
image: musicmovearr/minimediasonicserver:latest
ports:
- target: 8080
published: "8080"
protocol: tcp
restart: always
volumes:
- type: bind
source: /DATA/AppData/MiniMediaSonicServer/appsettings.json
target: /app/appsettings.json
- ~/Music:~/Music:ro
Example Configuration
It's important you bind this file to /app/appsettings.json as above in the docker example
Change the connectionstring to your own postgres database
Change the "aaaaaaa" with a random 64character string, for example on linux you can run, openssl rand -hex 32
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*",
"DatabaseConfiguration":{
"ConnectionString": "Host=192.168.1.1;Username=postgres;Password=postgres;Database=minimedia;Pooling=true;MinPoolSize=5;MaxPoolSize=100;"
},
"EncryptionKeys": {
"UserPasswordKey": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
},
"tls": {
"Certificate":
{
"CertificateFile": "",
"KeyFile": "",
"Password": ""
}
},
"Shares": {
"BaseUrl": "http://192.168.1.2:8080"
},
"Redis": {
"ConnectionString": "",
"Expiry": "72:00:00",
"SlidingExpiration": "72:00:00"
},
"MusicCache": {
"Path": "/cache",
"DirectoryFormat": "{CleanArtistUpper:substr(0,1)}/{CleanArtistUpper:substr(1,1)}/{CleanArtist}/{Album}",
"DirectorySeparator": "_",
"FileFormat": "{CleanArtist} - {Album} - {DiscNumber:cond:<=1?{TrackNumber:00}|{DiscNumber:00}-{TrackNumber:00}} - {Title}",
"MaxCacheSize": 1000000000,
"MaxFileSize": 50000000,
"ExposeCachedFilePath": false
},
"Jobs": {
"PlaylistImportCron": "0 0 0 * * ?",
"NavidromeSmartPlaylistRefreshCron": "0 0 0 * * ?",
"PlaylistFixTracksCron": "0 0 0 * * ?",
"PlayHistoryFixTracksCron": "0 0 0 * * ?",
"ReIndexSearchCron": "0 0 0 * * ?",
"ImportLastFmScrobblesCron": "0 0 0 * * ?",
"AutoLikeCron": "0 0 0 * * ?",
"ScrobblerCron": "0 0/15 * * * ?"
}
}
Shares
After sharing your url with another user, you'll get to see this retro webplayer
Webjobs (Scheduled Tasks)
By default the following jobs are scheduled hourly which can be changed in the appsettings.json
- Playlist Import: Will look into the "/playlists" folder looking for .m3u files to import
- Playlist Fix Tracks: will look for playlist track files that were replaced (e.g. mp3 > flac) so files don't exist anymore but are in your playlists, it will search & replace that track with another with 99% accuracy match
- ReIndex Search: Keeping the search up-to-date whenever new tracks were added/remove/updated
- AutoLike: Per user configurable, when listening an artist e.g. +100x, automatically favorite the artist. later I will implement it as well for albums. User properties available (AutoLike_Artists_Enabled, AutoLike_Artists_DaysRecent, AutoLike_Artists_ListenCount)
- AutoRate: Per user configurable, when you've rated tracks in a album by e.g. >50% and minimum rating comes out as 4/5 stars. rate the album 4 or 5 stars automatically. User properties available (AutoRate_Albums_Enabled, AutoRate_Albums_MinimumRating, AutoRate_Albums_TracksRatedPercentage)
- AutoRate: Per user configurable, When you've rated a track from an album/single(etc), rate all other duplicate with +99% accuracy based on Acoustid Fingerprint tracks with the same rating. When matching based on Acoustid Fingerprint, this is an cpu intense task using multiple cpu cores. User properties available (AutoRate_DuplicateTracks_Enabled)
- Scrobbler: Scrobbles pending scrobbles to services like ListenBrainz, LibreFm, Maloja
Implemented API's
A lot of Not yet/Partially but on iPhone the Arpeggi/Narjo/SubStreamer apps are usable, mind you with missing API implementations
| API | Implemented | Status |
|---|---|---|
| AddChatMessage | Not yet | |
| ChangePassword | Not yet | |
| CreateBookmark | Working | |
| CreateInternetRadioStation | Not yet | |
| CreatePlaylist | Working | |
| CreatePodcastChannel | Not yet | |
| CreateShare | Working | |
| CreateUser | Working | |
| DeleteBookmark | Working | |
| DeleteInternetRadioStation | Not yet | |
| DeletePlaylist | Working | |
| DeletePodcastChannel | Not yet | |
| DeletePodcastEpisode | Not yet | |
| DeleteShare | Working | |
| DeleteUser | Working | |
| Download | Working | |
| DownloadPodcastEpisode | Not yet | |
| GetAlbum | Working | |
| GetAlbumList2 | Working | |
| GetAlbumList | Working | |
| GetArtist | Working | |
| GetArtistInfo2 | Working | |
| GetArtistInfo | Working | |
| GetArtists | Working | |
| GetAvatar | Not yet | |
| GetBookmarks | Working | |
| GetCaptions | Not yet | |
| GetChatMessages | Not yet | |
| GetCoverArt | Working | |
| GetGenres | Working | |
| GetIndexes | Not yet | |
| GetInternetRadioStations | Not yet | |
| GetLicense | Not yet | |
| GetLyricsBySongId | Not yet | |
| GetLyrics | Not yet | |
| GetMusicDirectory | Not yet | |
| GetMusicFolders | Partially | |
| GetNewestPodcasts | Not yet | |
| GetNowPlaying | Not yet | |
| GetOpenSubsonicExtensions | Working | |
| GetPlaylist | Working | |
| GetPlaylists | Working | |
| GetPlayQueueByIndex | Working | |
| GetPlayQueue | Working | |
| GetPodcastEpisode | Not yet | |
| GetPodcasts | Not yet | |
| GetRandomSongs | Working | |
| GetScanStatus | Not yet | |
| GetShares | Working | |
| GetSimilarSongs2 | Working | |
| GetSimilarSongs | Working | |
| GetSong | Working | |
| GetSongsByGenre | Working | |
| GetStarred2 | Working | |
| GetStarred | Working | |
| GetTopSongs | Working | |
| GetTranscodeDecision | Not yet | |
| GetTranscodeStream | Not yet | |
| GetUser | Working | |
| GetUsers | Working | |
| GetVideoInfo | Not yet | |
| GetVideos | Not yet | |
| HLS | Not yet | |
| JukeboxControl | Not yet | |
| Ping | Working | |
| RefreshPodcasts | Not yet | |
| SavePlayQueueByIndex | Working | |
| SavePlayQueue | Working | |
| Scrobble | Working | History via database and scrobbling ListenBrainz, Maloja work |
| Search2 | Not yet | |
| Search3 | Working | |
| Search | Not yet | |
| SetRating | Working | |
| Star | Working | |
| StartScan | Not yet | |
| Stream | Working | |
| TokenInfo | Not yet | |
| Unstar | Working | |
| UpdateInternetRadioStation | Not yet | |
| UpdatePlaylist | Working | |
| UpdateShare | Working | |
| UpdateUser | Working |