Overview
Ztube is a YouTube client for Android with no account and no official Google API — video and stream data come from scraping via NewPipeExtractor. It covers a home feed, full search, a full-featured player (quality/track selection, PiP, background play), and a TikTok-style Shorts feed powered by a locally-run recommendation engine. A personal/educational project, not distributed on the Play Store.
Engineering highlights
Survived YouTube's SABR/poToken rollout by manually merging video-only and audio streams (MergingMediaSource) instead of depending on a single muxed stream.
A local-only "For You" / Shorts recommendation engine, adapted from a 2016 YouTube candidate-generation paper — parallel candidate generation, epsilon-greedy exploration, per-channel diversification — all running client-side, no backend.
Two ExoPlayer instances with clearly separated roles: one singleton for continuity, background playback and PiP; a second dedicated to the vertical Shorts pager.
A denormalized Room schema with no JOINs, tuned specifically for a low-RAM mid-range device.
Tech stack
Language & UI
Architecture & DI
Media
Data source
Architecture
com/zaaam/Ztube/ ├── data/VideoRepository.kt # 674 lines — search, streams, FYP ├── service/PlaybackService.kt # MediaSessionService, main ExoPlayer ├── ui/shorts/ # VerticalPager, its own ExoPlayer ├── ui/player/PlayerScreen.kt # quality/track selection, PiP ├── data/FypFilters.kt # pure recommendation-filtering logic └── data/local/ # Room v3, denormalized, no JOINs
Repository fetches via NewPipeExtractor → Room cache → Compose screens (per-screen ViewModel).
Features
- Home feed, search, and trending — no Google API involved
- Full player: quality/audio-track selection, fullscreen, PiP, background play
- Shorts feed with a client-side "For You" recommendation engine
- Offline-first library: history, saved, liked, playlists
- Local subscriptions, channel pages, and an incognito mode
Development process
Built solo in Kotlin and Compose, developed on-device via Termux/proot Ubuntu with LADB for debugging and GitHub Actions for CI. Shares its NewPipeExtractor integration patterns with Zmusic, documented in a reusable internal reference.
Challenges
Rendering a dense, high-scroll feed UI in Compose while keeping it smooth on a mid-range Snapdragon 680 device. The Shorts recommendation scoring also needed a rework — an early version was biased toward long videos until it switched from watch-ratio to absolute dwell-time scoring.
What I learned
How to profile and tune list performance in Compose, and how to adapt an industry recommendation-system paper into something that runs entirely client-side, with no backend at all.
