android app

Zmusic

A music player that streams straight from YouTube — no downloads, no wasted storage.

No official APINo trackingBuilt solo, on a phone
Zmusic home screen

Overview

Zmusic is an Android music player that streams straight from YouTube with no official API — just NewPipeExtractor scraping the web frontend. It behaves like a real music app: search, library, Daily Mix, mood-based playlists, gapless playback, synced lyrics, and offline downloads, without a paid subscription or storing every song locally.

Engineering highlights

01

Streams from YouTube with no official API — pure web scraping via NewPipeExtractor, with a documented fallback path for when YouTube enforces SABR/poToken and audio streams disappear.

02

Spotify-level gapless playback: the next track is pre-queued and playback errors are attributed to the correct song by media ID, instead of a naive setMediaItem call.

03

A WebView-based poToken engine standing by as a fallback, bridged through a mutex with an hourly expiry — defensive engineering built around a data source it doesn't control.

04

Hardened release build: R8 + scoped StringFog, ProGuard rules tuned for Hilt/Room/Media3, shipped via dual CI — debug on every push, signed release with a mapping file on tag.

Tech stack

Language & UI
Kotlin 2.0.21Compose · Material3Sora + Space Grotesk
Architecture & DI
Hilt 2.51MVVM + RepositoryCoroutines · StateFlow
Media
Media3 / ExoPlayer 1.4.1MediaSessionServiceCustom equalizer + visualizer
Data source
NewPipeExtractor 0.26.5Room 2.6.1OkHttp · Coil

Architecture

tree — com.zaaam.Zmusic
com/zaaam/Zmusic/
├── ui/player/PlayerScreen.kt      # ~1,100 lines — the largest screen
├── service/MusicService.kt        # MediaSessionService + ExoPlayer
├── data/MusicRepository.kt        # search() / getStreamUrl() — the core
├── util/QueueManager.kt           # @Singleton, source of truth for the queue
├── util/DailyMixGenerator.kt      # 40% familiar + 40% mood + 20% discovery
└── di/AppModule.kt                # Hilt bindings

Compose UI → per-screen ViewModel (Hilt) → QueueManager / MusicRepository → MusicService (ExoPlayer).

Features

  • Search and stream any track on YouTube, with gapless playback
  • Daily Mix, 6 mood-based playlists, Smart Playlists, and a Wrapped recap
  • Dynamic UI accent color pulled from the track's cover art
  • Synced LRC lyrics, 5-band equalizer, sleep timer with fade-out
  • Offline downloads, floating bubble player, home-screen widget

Development process

Solo build, developed and tested entirely on-device via Termux/proot Ubuntu — no laptop involved. Went through a full UI redesign into the current "Dark Plum" system, and the lyrics provider was swapped out after the original got blocked on Indonesian networks.

Challenges

Staying playable when the data source is scraped rather than official: YouTube's SABR/poToken rollout killed audio streams outright, so the app needed a logcat decision tree — and a fallback muxed stream — just to stay functional across backend changes.

What I learned

How much of a "real" streaming app — gapless playback, offline downloads, a recommendation engine — can be built solo from a phone, and how to design defensively around a data source you don't control.

← Chasly Ztube →