# How I Spent 40 Hours Building a Serverless 8K Video Downloader on Android by Embedding CPython and FFmpeg

> Source: <https://dev.to/rajan_prasailayadav_7366/how-i-spent-40-hours-building-a-serverless-8k-video-downloader-on-android-by-embedding-cpython-and-219h>
> Published: 2026-10-28 23:06:38+00:00

Building a mobile YouTube downloader seems straightforward at first glance—until you actually try to build one that runs **100% on-device**, downloads in **4K and 8K**, requires **zero servers**, and costs **₹0**.

Over the last 40 hours of continuous research, day-and-night testing, and hundreds of failed experiments, I went down the deepest rabbit hole of mobile systems engineering I’ve ever experienced.

Here is the story of how I bypassed the infamous "360p ceiling," why free cloud hosting failed, and how I ended up embedding a full **CPython 3.11 runtime** and an **ARM64 FFmpeg binary** directly inside a modern **Kotlin + Jetpack Compose** Android app.

My original goal was simple: write a lightweight client using cross-platform tooling (Flutter + Dart) to download videos directly to mobile storage.

I quickly hit three massive walls:

YouTube stopped serving combined video-and-audio files for high resolutions years ago. If you want 720p, 1080p, 1440p, 4K, or 8K, YouTube serves them via **DASH (Dynamic Adaptive Streaming over HTTP)**—meaning the video track and the audio track are two completely separate network streams. 

To get a playable `.mp4`, you **must** have a multiplexer (` muxer`) like FFmpeg running locally to combine them. Without an on-device muxer, pure mobile scrapers are permanently locked to legacy **360p** (`itag 18`).

When downloading direct HTTP stream chunks, downloads would start at full speed, hit around 5 MB, and suddenly choke to 0 KB/s before failing. YouTube's CDN actively rate-limits and drops TCP sockets if the client does not continuously solve and send valid player tokens.

Direct scraping triggered YouTube’s bot detection systems: `HTTP 403 Forbidden` and `"Sign in to confirm you're not a bot"`.

Thinking the mobile device’s network or CPU was the issue, I moved the extraction engine to free cloud hosting platforms:

Every single cloud host failed. Why? **Datacenter IP reputation**. 

YouTube maintains real-time blacklists of known cloud provider IP CIDR blocks (AWS, Google Cloud, Fastly, Cloudflare). The moment a request comes from a cloud datacenter IP, YouTube demands a CAPTCHA or blocks the connection outright. 

A remote cloud server was not going to work. The only way to guarantee longevity was to make the app **run entirely locally on the user's phone IP**.

I stepped back and built a standalone Python desktop script using `Tkinter`, `yt-dlp`, and native `ffmpeg`. 

On my PC, it worked flawlessly:

That led to the ultimate question:

*"If a local CPython engine and FFmpeg can download 8K videos without any server, why can't we bundle that entire engine inside an Android APK?"*

I started a clean native Android project built with **Kotlin 2.0**, **Jetpack Compose**, and **Media3 ExoPlayer**. 

Here are the key technical challenges I had to overcome to embed CPython on Android:

Modern Android (API 29+) forbids executing binaries from external storage or normal cache partitions (`noexec` mount flag).

`assets/` into the app's private internal storage (`/data/user/0/<package>/files/runtime/`).

```
  android.system.Os.chmod(binaryFile.absolutePath, 493) // 0755 rwxr-xr-x
```

`PYTHONHOME`, `PYTHONPATH`, and `LD_LIBRARY_PATH`) are mapped dynamically so Python can load shared cryptographic libraries (`libcrypto.so`, `libssl.so`).
YouTube uses dynamic JavaScript challenges (`n-sig` transformations) to throttle download speeds. Rather than bundling a bulky Node.js binary, I embedded **QuickJS** (`libqjs.so`), a tiny, lightweight C-based JavaScript engine that allows `yt-dlp` to evaluate cipher challenges in milliseconds directly on mobile.

High-resolution 4K/8K multiplexing consumes CPU cycles. When the user turned off the screen, Android's battery manager would kill the child process mid-stream.

`FOREGROUND_SERVICE_TYPE_DATA_SYNC` and a `PARTIAL_WAKE_LOCK`. Real-time `stdout` from the child process is parsed into an ongoing notification progress bar with download speed (MB/s) and ETA.
Under Android 11–15 Scoped Storage, child processes cannot write directly to `/storage/emulated/0/Download/`.

`context.cacheDir/staging/`). Once FFmpeg finishes merging, a native Kotlin worker commits the file directly into `MediaStore.Video` or `MediaStore.Audio` using Android's `ContentResolver`. The files immediately appear in the user's Gallery, VLC, and MX Player.
Downloading high-quality media is only half the experience; playing it is the other half. I built a native player powered by **Media3 ExoPlayer** featuring:

`FIT TO SCREEN`, `STRETCH`, `CROP`, and `100%` (unscaled 1:1 pixel rendering with borders all around) complete with centered bold HUD overlays.`+Xs / -Xs (MM:SS)` HUD.`awaitPointerEvent()`) only fire when the finger 

```
  val holdJob = coroutineScope.launch {
      delay(1800L)
      if (!hasDragged && !isMultiTouch) {
          player?.setPlaybackSpeed(2.0f)
      }
  }
```

`0.25x` to `2.0x` that persist across all video and audio tracks globally.
After 40 hours of focused development:

The project is completely open source under the MIT License. You can check out the source code, architecture diagrams, and download the pre-compiled APK directly:

👉 **GitHub Repository**: [https://github.com/Rajan7013/YtMax](https://github.com/Rajan7013/YtMax)

📦 **Direct v1.0.0 APK**: [Download from GitHub Releases](https://github.com/Rajan7013/YtMax/releases/tag/v1.0.0)
