YouTube-like video platform with HLS streaming, subscriptions, watch history, comments, and PWA. Go backend + Next.js. Dockerized for Synology NAS
  • TypeScript 63.9%
  • Go 21.4%
  • CSS 6.2%
  • Shell 5.9%
  • JavaScript 1.4%
  • Other 1.2%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
2026-08-01 11:13:55 +07:00
backend perf(backend): add singleflight dedup, comments caching, reduce yt-dlp concurrency to prevent CPU saturation 2026-08-01 11:13:55 +07:00
doc feat: rich channel pages, view counts, lazy avatars, themed loading, consistent icons 2026-07-11 21:29:40 +07:00
frontend style(branding): simplify logo and app icon to a clean, minimal red play emblem 2026-08-01 08:39:06 +07:00
releases Release: fullscreen overlay mode without rotation 2026-07-22 19:56:52 +07:00
.dockerignore feat: background playback via self-hosted player + MediaSession + PiP 2026-07-13 07:35:52 +07:00
.env.example fix: prevent CPU hogging from zombie yt-dlp processes 2026-07-24 14:56:47 +07:00
.gitignore perf: reduce CPU usage on NAS - cache video/playback info, pre-compute subscription feed, reduce retries 2026-07-23 10:11:08 +07:00
AGENTS.md feat: add Android native app with Kotlin/Jetpack Compose 2026-07-20 21:40:09 +07:00
CHANGELOG.md feat(android): v4.4.0 — fix downloads, share button, channel pages, download progress UI 2026-07-21 17:47:39 +07:00
cookies.example.txt chore: add cookies.example.txt, update docker-compose for staging 2026-07-23 11:10:34 +07:00
docker-compose.yml fix: add global yt-dlp concurrency cap (5 processes) to reduce CPU on NAS 2026-07-25 07:21:59 +07:00
Dockerfile fix: use relative /api URLs through Next.js proxy instead of direct backend URL 2026-05-14 17:59:50 +07:00
Dockerfile.diag Add Synology-compatible Dockerfile and docker-compose (v4.0.8) 2026-03-24 22:57:30 +07:00
get-docker.sh feat: server-side yt-dlp downloads with SSE progress and temp cache (v4.2.1) 2026-07-20 12:42:30 +07:00
launch.sh feat: rich channel pages, view counts, lazy avatars, themed loading, consistent icons 2026-07-11 21:29:40 +07:00
LICENSE docs: add MIT license 2026-05-14 14:31:01 +07:00
README.md feat(android): v4.4.0 — fix downloads, share button, channel pages, download progress UI 2026-07-21 17:47:39 +07:00
restart.sh feat: rich channel pages, view counts, lazy avatars, themed loading, consistent icons 2026-07-11 21:29:40 +07:00
SECURITY.md Create SECURITY.md for security policy 2026-05-14 14:12:57 +07:00
start.sh feat: rich channel pages, view counts, lazy avatars, themed loading, consistent icons 2026-07-11 21:29:40 +07:00
stop.sh feat: rich channel pages, view counts, lazy avatars, themed loading, consistent icons 2026-07-11 21:29:40 +07:00
supervisord.conf fix: security hardening - remove secrets, fix CORS, add non-root user, add Secure flag 2026-05-14 14:24:14 +07:00

🎬 KV-Tube

Your personal YouTube · Self-hosted, private, lightweight

License Go Next.js Docker SQLite PWA Android Kotlin Jetpack Compose

GitHub Forgejo

FeaturesQuick StartWhy KV-Tube?DeploymentDevelopmentContributing


Watch, search, and subscribe — just like YouTube, but fully under your control.

Features

🎞️ Video Playback

HLS streaming with adaptive quality — from 144p to 4K.

📜 Watch History

Automatically tracked. Always in sync. Never lose your place.

🔔 Subscriptions

Follow any YouTube channel. Get updates instantly.

🔍 Search

Full-text search across videos, channels, and history.

🎵 Background Audio

Keep listening with the screen locked — perfect for music.

📱 PWA

Install as a native app. Works offline. Full-screen experience.

🌍 Region Tuning

Tailor content and recommendations to any region.

🌓 Themes

Light, dark, and system-following themes out of the box.

📺 Rich Channel Pages

Banner, avatar, description, subscriber & view counts, and infinite-scrolling videos.

Fast & Resilient

Aggressive caching, multi-client yt-dlp fallback, and lazy metadata hydration.

📥 Server-side Downloads

Download any video straight to your device as an MP4. The server fetches it with yt-dlp and streams a live progress bar — no ads, no client-side hacks. Pick from three quality tiers: Low (≤360p), Recommended (≤1080p), or Best.

🧹 Self-cleaning Cache

Downloaded files live in a temp server cache (30-minute TTL) and are purged automatically — nothing piles up on your disk.

📱 Android App

Native Android client built with Kotlin & Jetpack Compose. Material 3 design, ExoPlayer video playback, on-device NewPipeExtractor downloads, share to any app, download progress with badge indicator, dark/light themes, and auto-updates via GitHub/Forgejo releases.

⬇️ On-device Downloads

Download videos directly on your Android device using NewPipeExtractor stream extraction. Three quality tiers (Low 360p, Recommended 1080p, Best) with background download via WorkManager. Search, rename, sort, and delete downloaded files from the Downloads tab.

🚀 Quick Start

Pull the pre-built image and run it — no local build needed:

mkdir -p kv-tube/data && cd kv-tube
curl -O https://raw.githubusercontent.com/vndangkhoa/kv-tube/main/docker-compose.yml
docker compose up -d

Prefer building from source?

git clone https://github.com/vndangkhoa/kv-tube.git
cd kv-tube
mkdir -p data
docker build -t kv-tube:latest .
docker compose up -d

Frontend: http://localhost:5011  •  API: http://localhost:8981

📥 Container Images

Pre-built images are published to three registries:

Registry Image
Docker Hub vndangkhoa/kv-tube:latest
GitHub Container Registry ghcr.io/vndangkhoa/kv-tube:latest
Forgejo git.khoavo.myds.me/vndangkhoa/kv-tube:latest

🌐 Source Repositories

The project is mirrored on GitHub and Forgejo — both stay in sync:


🤔 Why KV-Tube?

YouTube is incredible — but it's also ad-ridden, tracks everything, and sometimes removes the videos you love.

KV-Tube gives you:

  • Privacy — No tracking, no algorithms manipulating you. Your watch history stays on your machine.
  • Permanence — Videos you subscribe to stay available. No takedowns, no region blocks.
  • Ownership — Run it on your NAS, your VPS, or a Raspberry Pi. It's yours.
  • Simplicity — One container. One command. Zero configuration.

📖 Backstory

I built KV-Tube because I wanted a way to watch YouTube content without the YouTube baggage — ads, recommendation rabbit holes, and the feeling that the product was me, not the video player.

What started as a simple Go API to proxy video streams evolved into a full-featured frontend with subscriptions, search, PWA support, and a clean, YouTube-like interface. It runs on my Synology NAS at home, and I use it daily.

If that resonates, give it a star — it helps others find the project.


🏗️ Architecture

KV-Tube ships as a single Docker image. Everything runs in one container, managed by supervisord.

Layer Tech Port Role
Backend Go + Gin 8080 REST API, video fetching, yt-dlp orchestration
Frontend Next.js 16 3000 SSR, PWA, responsive UI
Process Manager supervisord Keeps backend + frontend alive
Storage SQLite Watch history, subscriptions, metadata

📦 Deployment

Using the pre-built image from Docker Hub:

services:
  kv-tube:
    image: vndangkhoa/kv-tube:latest
    container_name: kv-tube
    platform: linux/amd64
    ports:
      - "5011:3000"
      - "8981:8080"
    volumes:
      - ./data:/app/data
    environment:
      - KVTUBE_DATA_DIR=/app/data
      - GIN_MODE=release
      - NODE_ENV=production
      - CORS_ALLOWED_ORIGINS=http://localhost:3000,http://localhost:5011
    restart: unless-stopped

Or pull from another registry — swap the image line:

    image: ghcr.io/vndangkhoa/kv-tube:latest
    # image: git.khoavo.myds.me/vndangkhoa/kv-tube:latest

Prefer building locally? Replace image: with build: ..

🖥️ Synology NAS (DSM 7.2+)

  1. Create folder /volume1/docker/kv-tube/data
  2. Upload docker-compose.yml, Dockerfile, supervisord.conf
  3. In Container ManagerProjectCreate, select the folder
  4. Done. The container builds and starts automatically.

🛠️ Multi-arch Build

docker buildx build --platform linux/amd64 -t kv-tube:latest --push .

⚙️ Configuration

Variable Default Description
KVTUBE_DATA_DIR /app/data Path for SQLite DB and data
GIN_MODE release Gin framework log mode
NODE_ENV production Node.js environment
CORS_ALLOWED_ORIGINS "" Comma-separated allowed origins
PORT 8080 Backend API listen port

💻 Development

# Frontend
cd frontend
npm install
npm run dev

# Backend
cd backend
go run main.go

# Android App
cd android
# Ensure JAVA_HOME points to JDK 17
./gradlew assembleDebug
# Install on emulator/device
adb install app/build/outputs/apk/debug/app-debug.apk

🤝 Contributing

Contributions are welcome! Here's how to help:

  1. Fork the repo
  2. Create a feature branch (git checkout -b feature/amazing)
  3. Commit your changes (git commit -m 'Add amazing feature')
  4. Push (git push origin feature/amazing)
  5. Open a Pull Request

Please make sure to follow existing code style and add tests when possible.


📄 License

Distributed under the MIT License. See LICENSE for more information.


If you find this project useful, please star it on GitHub.
Built with ❤️ by Khoa Vo