[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"project-81213":3},{"id":4,"name":5,"fullName":6,"owner":7,"repo":5,"description":8,"homepage":9,"htmlUrl":9,"language":10,"languages":9,"totalLinesOfCode":9,"stars":11,"forks":12,"watchers":13,"openIssues":12,"contributorsCount":14,"subscribersCount":14,"size":14,"stars1d":12,"stars7d":15,"stars30d":15,"stars90d":14,"forks30d":14,"starsTrendScore":16,"compositeScore":17,"rankGlobal":9,"rankLanguage":9,"license":9,"archived":18,"fork":18,"defaultBranch":19,"hasWiki":20,"hasPages":18,"topics":21,"createdAt":9,"pushedAt":9,"updatedAt":30,"readmeContent":31,"aiSummary":32,"trendingCount":14,"starSnapshotCount":14,"syncStatus":15,"lastSyncTime":33,"discoverSource":34},81213,"untube","tomfriart\u002Funtube","tomfriart","Self-hosted YouTube channel downloader & viewer",null,"JavaScript",26,1,24,0,2,3,41.1,false,"main",true,[22,23,24,25,26,27,28,29],"docker","flask","home-server","media-server","react","self-hosted","youtube","yt-dlp","2026-06-12 04:01:32","# UnTube — Self-Hosted YouTube Channel Downloader & Viewer\n\n---\n\n### 🔒 For Local Network Use Only\n\n> **This application is not designed or intended to be run on a public-facing URL.**\n> There is no authentication, no user management, and no security hardening.\n> **Run it exclusively on your local network or behind a VPN. Do not expose it to the internet.**\n\n---\n\n### ⚠️ Disclaimer\n\nThis project was built **entirely through AI prompting** using [Claude](https:\u002F\u002Fclaude.ai) — no manual code was written by the author. AI can and does make mistakes, and this application is not perfect. **Bugs should be expected.**\n\nThe author does not take any credit for the features and technologies that make UnTube function — all credit goes to the open-source projects this app is built on: [yt-dlp](https:\u002F\u002Fgithub.com\u002Fyt-dlp\u002Fyt-dlp), [Flask](https:\u002F\u002Fflask.palletsprojects.com\u002F), [React](https:\u002F\u002Freact.dev\u002F), and others.\n\nYou are free to modify, improve, and adapt this project in any way you like. **Use at your own risk.**\n\n---\n\nA Docker-based web application that lets you follow YouTube channels, automatically download their videos, and watch them in a clean, ad-free interface — all on your own hardware.\n\n![UnTube feed](screenshots\u002Funtube%20feed.png) \u003Cimg src=\"screenshots\u002Funtube feed mobile.png\" width=\"200\"\u002F>\n\n[View all screenshots](screenshots\u002F)\n\n## Features\n\n- **Channel Management** — Add channels by URL, `@handle`, or channel ID\n- **Auto Downloads** — Background scheduler polls for new videos at a configurable interval\n- **Quality Control** — Per-channel quality overrides (360p to 4K or best available)\n- **Skip Shorts** — Optionally skip YouTube Shorts (videos under 60 seconds)\n- **Auto-Delete** — Automatically remove videos older than X days (global or per-channel)\n- **Built-in Player** — HTML5 video player with HLS\u002Ftranscoded stream support and CC subtitles\n- **Feed View** — All videos sorted by newest first, filterable by channel\n- **Push Notifications** — Optional Apprise-based notifications on new downloads\n- **Mobile-Friendly** — Responsive layout optimised for phone\u002Ftablet use\n- **Persistent Storage** — Everything saved to local Docker volumes\n\n## Quick Start\n\n### Prerequisites\n- Docker and Docker Compose\n\n### Option 1 — Pull from Docker Hub (fastest)\n\n```bash\ndocker pull tomfriart\u002Funtube:latest\n```\n\nThen create a `docker-compose.yml`:\n\n```yaml\nservices:\n  untube:\n    image: tomfriart\u002Funtube:latest\n    container_name: untube\n    ports:\n      - \"3987:80\"\n    volumes:\n      - .\u002Fdata:\u002Fapp\u002Fdata\n      - .\u002Fdownloads:\u002Fapp\u002Fdownloads\n    restart: unless-stopped\n```\n\n```bash\ndocker compose up -d\n\n# Open in your browser\nopen http:\u002F\u002Flocalhost:3987\n```\n\n### Option 2 — Build from source\n\n```bash\ngit clone https:\u002F\u002Fgithub.com\u002Ftomfriart\u002Funtube.git\ncd untube\n\ndocker compose up -d --build\n\n# Open in your browser\nopen http:\u002F\u002Flocalhost:3987\n```\n\n### Stop\n\n```bash\ndocker compose down\n```\n\n## Architecture\n\nUnTube runs as a **single Docker container** combining the frontend and backend, managed by supervisord.\n\n```\nuntube\u002F\n├── Dockerfile                  # Single image: React build → Python + nginx + supervisord\n├── nginx.conf                  # Serves frontend, proxies \u002Fapi\u002F* to Flask on localhost:5000\n├── supervisord.conf            # Runs Flask + nginx together in one container\n├── docker-compose.yml\n├── backend\u002F\n│   ├── requirements.txt\n│   └── app.py                  # Flask API + yt-dlp + APScheduler\n├── frontend\u002F\n│   ├── package.json\n│   ├── vite.config.js\n│   ├── index.html\n│   └── src\u002F\n│       ├── main.jsx\n│       ├── App.jsx\n│       ├── icons.jsx\n│       ├── styles.js\n│       ├── utils.js\n│       └── components\u002F\n├── data\u002F                       # Auto-created: SQLite database + thumb cache\n└── downloads\u002F                  # Auto-created: downloaded video files\n    ├── ChannelName1\u002F\n    │   ├── videoId1.mp4\n    │   └── videoId2.mp4\n    └── ChannelName2\u002F\n        └── videoId3.mp4\n```\n\n## Configuration\n\nAll settings are adjustable from the **Settings** panel in the UI:\n\n| Setting            | Default  | Description                                         |\n|--------------------|----------|-----------------------------------------------------|\n| Quality            | 720p     | Video download resolution (360p–4K or best)         |\n| Skip Shorts        | On       | Don't download videos under 60 seconds              |\n| Check Interval     | 180 min  | How often to poll channels for new uploads          |\n| Auto-Delete        | Off      | Remove videos older than N days                     |\n| Notifications      | Off      | Apprise URL for push notifications on new downloads |\n\nPer-channel overrides for quality and auto-delete are available from each channel's settings.\n\n## Custom Downloads Path\n\nBy default videos are saved to `.\u002Fdownloads\u002F` next to the `docker-compose.yml`. To point at an existing media library, edit the backend volume in `docker-compose.yml`:\n\n```yaml\nvolumes:\n  - \u002Fyour\u002Fmedia\u002Fpath:\u002Fapp\u002Fdownloads\n```\n\n## API Endpoints\n\n| Method | Endpoint                    | Description                        |\n|--------|-----------------------------|------------------------------------|\n| GET    | `\u002Fapi\u002Fchannels`             | List all followed channels         |\n| POST   | `\u002Fapi\u002Fchannels`             | Add a channel `{ url: \"...\" }`     |\n| DELETE | `\u002Fapi\u002Fchannels\u002F:id`         | Remove a channel + its videos      |\n| GET    | `\u002Fapi\u002Fvideos`               | List all videos (newest first)     |\n| GET    | `\u002Fapi\u002Fvideos?channel_id=X`  | Filter by channel                  |\n| GET    | `\u002Fapi\u002Fsettings`             | Get current settings               |\n| PUT    | `\u002Fapi\u002Fsettings`             | Update settings                    |\n| POST   | `\u002Fapi\u002Fcheck-now`            | Trigger immediate check            |\n| GET    | `\u002Fmedia\u002F:filepath`          | Serve a downloaded video file      |\n| GET    | `\u002Fapi\u002Fstream\u002F:video_id`     | HLS transcode stream               |\n\n## Troubleshooting\n\n- **Videos not downloading?** Check logs: `docker compose logs untube`\n- **yt-dlp errors?** YouTube frequently changes its internals, which breaks yt-dlp. This is the most common source of issues and is outside this project's control. When it happens, rebuild the image to get the latest yt-dlp: `docker compose build --no-cache` (or `docker pull tomfriart\u002Funtube:latest` if using Docker Hub). Expect this to be needed every few weeks.\n- **Disk space?** Monitor `.\u002Fdownloads\u002F` — higher quality = bigger files; enable auto-delete in Settings\n\n## Tech Stack\n\n- **Backend** — Python, Flask, yt-dlp, APScheduler, SQLite\n- **Frontend** — React 18, Vite, hls.js\n- **Serving** — nginx (reverse proxy + static files)\n- **Packaging** — Docker Compose\n\n## License\n\nMIT\n","UnTube 是一个自托管的 YouTube 频道下载器和播放器。该项目允许用户通过简单的界面管理并自动下载订阅频道中的视频，支持按频道设置下载质量、跳过短片及自动删除旧视频等功能，并提供了一个无广告的观看环境。技术上，UnTube 基于 Docker 容器运行，结合了 Flask 后端与 React 前端框架，使用 yt-dlp 作为核心下载工具。鉴于其设计初衷是为本地网络或通过 VPN 访问而设，且缺乏安全认证机制，因此推荐仅在私有网络内部署使用，非常适合那些希望离线保存喜爱内容同时避免在线观看时遇到广告干扰的家庭媒体服务器场景。","2026-06-11 04:03:55","CREATED_QUERY"]