8.7 KiB
8.7 KiB
VidRip - Project Context
Project Overview
VidRip is a respectful YouTube video drip downloader that slowly downloads videos from channels over time to avoid aggressive scraping. Videos are downloaded at configurable intervals with random variance to make the pattern less predictable.
Architecture
Tech Stack
- Backend: Node.js, Express, TypeScript, SQLite (better-sqlite3), node-cron
- Frontend: React, TypeScript, Vite, Tailwind CSS, React Router
- External: yt-dlp (must be installed on system)
Project Structure
vidrip/
├── backend/
│ ├── src/
│ │ ├── db/
│ │ │ └── database.ts # SQLite operations, schema, CRUD
│ │ ├── routes/
│ │ │ ├── channels.ts # Channel management endpoints
│ │ │ ├── videos.ts # Video management endpoints
│ │ │ └── config.ts # Settings & scheduler status
│ │ ├── services/
│ │ │ ├── ytdlp.ts # yt-dlp wrapper for downloads
│ │ │ └── scheduler.ts # Download scheduler logic
│ │ ├── types/
│ │ │ └── index.ts # TypeScript interfaces
│ │ └── server.ts # Express app entry point
│ ├── downloads/ # Downloaded video storage
│ ├── data.db # SQLite database (auto-created)
│ └── package.json
├── frontend/
│ ├── src/
│ │ ├── components/ # (empty - components in pages)
│ │ ├── pages/
│ │ │ ├── VideosPage.tsx # List/add/filter videos
│ │ │ ├── ChannelsPage.tsx # Manage channels
│ │ │ ├── SettingsPage.tsx # Configure scheduler
│ │ │ └── VideoPlayerPage.tsx # Watch videos
│ │ ├── services/
│ │ │ └── api.ts # API client functions
│ │ ├── types/
│ │ │ └── index.ts # TypeScript interfaces
│ │ ├── App.tsx # Router & navigation
│ │ ├── main.tsx # React entry point
│ │ └── index.css # Tailwind imports
│ ├── index.html
│ ├── vite.config.ts # Proxy to backend
│ └── package.json
└── README.md
Database Schema
Tables
-
channels
- id, url, name, channelId, addedAt, lastChecked, active
- Stores YouTube channels to monitor
-
videos
- id, channelId, videoId, title, url, duration, thumbnail, uploadDate
- status (pending/downloading/completed/failed), filePath, fileSize
- addedAt, downloadedAt, error
- Stores individual videos and download status
-
config
- id, key, value
- Stores app configuration (intervalHours, varianceMinutes, enabled, etc.)
Key Flows
Download Scheduler (backend/src/services/scheduler.ts)
- Channel Checking: Runs every hour via cron to check channels for new videos
- Download Cycle:
- Picks next pending video
- Downloads with progress tracking
- Marks completed or failed
- Schedules next download using:
intervalHours ± random(varianceMinutes)
- Restartable: Can be stopped/restarted when config changes
Adding a Channel
- User enters YouTube channel URL in frontend
- Backend calls
getChannelInfo()to fetch channel metadata - Backend calls
getChannelVideos()to get all videos (flat playlist) - Creates channel record and all video records with status='pending'
- Scheduler will pick them up based on configuration
Video Download
- Scheduler picks next pending video
- Calls yt-dlp with progress callbacks
- Downloads to
backend/downloads/{videoId}.mp4 - Updates database with file path, size, status
API Endpoints
Channels
GET /api/channels- List all channelsGET /api/channels/:id- Get channel detailsGET /api/channels/:id/videos- Get channel's videosPOST /api/channels- Add new channel (body: {url})PATCH /api/channels/:id- Update channel (body: {active})DELETE /api/channels/:id- Delete channel & videosPOST /api/channels/:id/refresh- Check for new videos
Videos
GET /api/videos- List all videos (optional ?status=)GET /api/videos/:id- Get video detailsPOST /api/videos- Add single video (body: {url})DELETE /api/videos/:id- Delete video & filePOST /api/videos/:id/retry- Retry failed video
Config
GET /api/config- Get all settingsPATCH /api/config- Update settings (body: {key: value})GET /api/config/scheduler/status- Get scheduler status & progress
Static
/downloads/{videoId}.mp4- Serve downloaded videos
Configuration Options
Default values in database:
intervalHours: "3" - Average hours between downloadsvarianceMinutes: "30" - Random ± minutes to addmaxConcurrentDownloads: "1" - Simultaneous downloads (currently only 1 supported)enabled: "true" - Whether scheduler is active
Important Implementation Details
yt-dlp Integration
- Uses spawn to call yt-dlp CLI (must be in PATH)
--dump-jsonfor metadata extraction--flat-playlistfor channel video lists- Progress parsing via stdout line parsing
- Downloads as MP4 (merges best video+audio)
Scheduler Variance
- Prevents predictable download patterns
- Calculates:
baseMinutes = intervalHours * 60 - Adds random:
variance = random(-varianceMinutes, +varianceMinutes) - Uses
setTimeoutfor next download, not fixed cron
Frontend Proxy
- Vite proxies
/apiand/downloadsto backend (port 3001) - Allows development without CORS issues
- Production would need reverse proxy (nginx/etc)
Known Limitations & Future Enhancements
Current Limitations
- Only 1 concurrent download supported (hardcoded in scheduler)
- No authentication/authorization
- No video queue reordering
- No bandwidth limiting
- No retry limit for failed videos
- No disk space checking
- No video preview before download
- Progress tracking only works during active download (not persisted)
Potential Enhancements
- User authentication
- Video quality selection
- Download queue prioritization
- Bandwidth throttling
- Automatic old video cleanup
- Video search/filtering by title
- Channel categorization/tagging
- Download history/statistics
- Webhook notifications
- Docker containerization
- Multiple download quality profiles
- Subtitle downloading
Development Commands
# Install all dependencies
npm run install:all
# Development (run in separate terminals)
npm run dev:backend # Backend on :3001
npm run dev:frontend # Frontend on :3000
# Production build
npm run build:backend
npm run build:frontend
# Production run
npm run start:backend
npm run start:frontend
Dependencies to Install
System Requirements
- Node.js 18+
- yt-dlp (via pip, brew, or binary)
Installation
# yt-dlp
pip install yt-dlp
# or
brew install yt-dlp
# Node dependencies
npm run install:all
Troubleshooting
Common Issues
- "yt-dlp not found": Ensure yt-dlp is in PATH
- Database locked: Only one backend instance should run
- Video won't play: Check file exists in
backend/downloads/ - Scheduler not running: Check settings page, ensure enabled=true
- Channel refresh fails: YouTube may be rate limiting, wait and retry
File Locations
- Database:
backend/data.db - Videos:
backend/downloads/{videoId}.mp4 - Logs: Console output (not persisted to file currently)
Security Considerations
- No authentication - anyone with access can manage downloads
- Videos stored unencrypted on filesystem
- No rate limiting on API endpoints
- YouTube URLs not validated before passing to yt-dlp
- Consider running behind reverse proxy with auth in production
Code Entry Points
To understand the codebase quickly:
- Start with
backend/src/server.ts- see how routes connect - Read
backend/src/services/scheduler.ts- core business logic - Check
frontend/src/App.tsx- understand page routing - Review
backend/src/db/database.ts- database schema & operations
Testing
Currently no automated tests. Manual testing checklist:
- Add channel and verify videos appear
- Add individual video by URL
- Watch completed video
- Change settings and verify scheduler restarts
- Delete channel and verify cascade delete
- Retry failed video
- Refresh channel for new videos
Environment Variables
Backend supports (optional):
PORT- Server port (default: 3001)NODE_ENV- Environment (development/production)
Currently no .env file required - uses defaults.