vidrip/CLAUDE.md

4.0 KiB

CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

Development Commands

# Install dependencies
npm run install:all

# Development (run in separate terminals)
npm run dev:backend    # Starts on :3001 with tsx watch
npm run dev:frontend   # Starts on :3000 with Vite HMR

# Within backend/ directory
cd backend
npm run dev      # Development with tsx watch
npm run build    # TypeScript compilation
npm start        # Run compiled version

# Within frontend/ directory
cd frontend
npm run dev      # Vite dev server
npm run build    # TypeScript + Vite build
npm run preview  # Preview production build

Architecture Overview

VidRip is a monorepo with separate backend (Express/SQLite) and frontend (React) apps.

Core Scheduler Logic

The scheduler in backend/src/services/scheduler.ts operates on two separate timers:

  1. Channel Checker: Cron job (0 * * * *) runs every hour to check active channels for new videos
  2. Download Cycle: Self-scheduling recursive setTimeout that:
    • Downloads one pending video
    • Calculates next run: intervalHours * 60 ± random(varianceMinutes)
    • Schedules itself again with the calculated delay

The variance prevents predictable download patterns. The scheduler uses a single global isDownloading flag to prevent concurrent downloads.

Database Layer

SQLite database (backend/data.db) with three tables managed via better-sqlite3:

  • channels: YouTube channels to monitor
  • videos: Individual videos with status tracking (pending/downloading/completed/failed)
  • config: Key-value store for app settings

All database operations are in backend/src/db/database.ts using synchronous better-sqlite3 API. The database auto-initializes on first run.

yt-dlp Integration

backend/src/services/ytdlp.ts wraps the yt-dlp CLI (must be installed on system):

  • Uses child_process.spawn to call yt-dlp
  • --dump-json extracts metadata without downloading
  • --flat-playlist lists channel videos efficiently
  • Progress tracking via stdout parsing (looks for percentage patterns)
  • Downloads merge best video+audio to MP4 format

Frontend Proxy Setup

Vite development server (port 3000) proxies to backend (port 3001):

  • /api/* → Backend API endpoints
  • /downloads/* → Static video files

This is configured in frontend/vite.config.ts. Production deployments need a reverse proxy (nginx, etc.).

API Structure

Routes are split by domain:

  • backend/src/routes/channels.ts: Channel CRUD + refresh
  • backend/src/routes/videos.ts: Video CRUD + retry
  • backend/src/routes/config.ts: Settings + scheduler control

Video files are served statically from backend/downloads/ directory.

Key Constraints

  • Only 1 concurrent download supported (hardcoded in scheduler)
  • Download progress is ephemeral (not persisted to DB, only in-memory)
  • No authentication/authorization
  • yt-dlp must be in PATH (external dependency)
  • Database uses WAL mode by default for better concurrency

Important Implementation Notes

Scheduler Restart Behavior

When config changes (e.g., interval or variance), call restartScheduler() from backend/src/services/scheduler.ts. This stops the cron task and clears the setTimeout chain, then restarts with new settings.

Video Status State Machine

Videos progress through states: pending → downloading → completed/failed

  • Retry functionality resets failed back to pending
  • Deleting a channel cascades to delete all its videos and files

Channel Refresh

Adding a channel fetches ALL videos from that channel using yt-dlp's --flat-playlist. Large channels (1000+ videos) may take time. Videos are created in pending state and downloaded according to the schedule.

File Locations

  • Database: backend/data.db
  • Downloaded videos: backend/downloads/{videoId}.mp4
  • Environment: Optional backend/.env (PORT, NODE_ENV)

System Requirements

  • Node.js 18+
  • yt-dlp installed and in PATH (pip install yt-dlp or brew install yt-dlp)