android app

Ztube

YouTube, minus the ads. Same feed, same playback, none of the interruptions.

No account neededAd-freeClient-side recommendations
Ztube home feed

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

01

Survived YouTube's SABR/poToken rollout by manually merging video-only and audio streams (MergingMediaSource) instead of depending on a single muxed stream.

02

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.

03

Two ExoPlayer instances with clearly separated roles: one singleton for continuity, background playback and PiP; a second dedicated to the vertical Shorts pager.

04

A denormalized Room schema with no JOINs, tuned specifically for a low-RAM mid-range device.

Tech stack

Language & UI
Kotlin 2.0.21Compose · Material3Sora + Space Grotesk
Architecture & DI
Hilt 2.56.2MVVM per-screenRepository pattern
Media
Media3 / ExoPlayer 1.4.1Dual ExoPlayerMergingMediaSource
Data source
NewPipeExtractor 0.26.5Room 2.7.2OkHttp · Coil

Architecture

tree — com.zaaam.Ztube
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.

← Zmusic Chasly →