224 lines
7.8 KiB
Markdown
224 lines
7.8 KiB
Markdown
# Architecture Documentation
|
|
|
|
## Overview
|
|
Downlink is a Next.js application that provides a web interface for downloading YouTube videos and audio files. The application uses server-side processing with yt-dlp and provides a modern, responsive UI built with shadcn/ui.
|
|
|
|
## System Architecture
|
|
|
|
```
|
|
┌─────────────┐
|
|
│ Browser │
|
|
│ (Client) │
|
|
└──────┬──────┘
|
|
│ HTTP Requests
|
|
▼
|
|
┌─────────────────────────────────┐
|
|
│ Next.js App Router │
|
|
│ ┌───────────────────────────┐ │
|
|
│ │ UI Components (React) │ │
|
|
│ └───────────────────────────┘ │
|
|
│ ┌───────────────────────────┐ │
|
|
│ │ API Routes │ │
|
|
│ │ - /api/info │ │
|
|
│ │ - /api/download │ │
|
|
│ └───────────┬───────────────┘ │
|
|
└──────────────┼──────────────────┘
|
|
│
|
|
▼
|
|
┌─────────────────────────────────┐
|
|
│ Business Logic Layer │
|
|
│ ┌───────────────────────────┐ │
|
|
│ │ lib/youtube.ts │ │
|
|
│ │ - getVideoInfo() │ │
|
|
│ │ - downloadVideo() │ │
|
|
│ └───────────┬───────────────┘ │
|
|
└──────────────┼──────────────────┘
|
|
│
|
|
▼
|
|
┌─────────────────────────────────┐
|
|
│ External Tools │
|
|
│ ┌───────────────────────────┐ │
|
|
│ │ yt-dlp (Python) │ │
|
|
│ │ - Video download │ │
|
|
│ │ - Format conversion │ │
|
|
│ └───────────────────────────┘ │
|
|
│ ┌───────────────────────────┐ │
|
|
│ │ ffmpeg (via yt-dlp) │ │
|
|
│ │ - Audio transcoding │ │
|
|
│ └───────────────────────────┘ │
|
|
└─────────────────────────────────┘
|
|
```
|
|
|
|
## Component Structure
|
|
|
|
### Frontend Components
|
|
|
|
#### `app/page.tsx`
|
|
Main page component containing:
|
|
- URL input field
|
|
- Video information display
|
|
- Format selection (video/audio)
|
|
- Download button
|
|
- Error handling and success states
|
|
|
|
#### UI Components (`components/ui/`)
|
|
shadcn/ui components:
|
|
- `button.tsx`: Button component
|
|
- `input.tsx`: Input field component
|
|
- `card.tsx`: Card container component
|
|
- `label.tsx`: Form label component
|
|
- `select.tsx`: Dropdown select component
|
|
|
|
### Backend Components
|
|
|
|
#### API Routes
|
|
|
|
**`app/api/info/route.ts`**
|
|
- Handles POST requests for video information
|
|
- Validates YouTube URL
|
|
- Calls `getVideoInfo()` from `lib/youtube.ts`
|
|
- Returns video metadata
|
|
|
|
**`app/api/download/route.ts`**
|
|
- Handles POST requests for downloads
|
|
- Validates request body (url, format, formatType)
|
|
- Calls `downloadVideo()` from `lib/youtube.ts`
|
|
- Returns download URL and file information
|
|
|
|
#### Business Logic
|
|
|
|
**`lib/youtube.ts`**
|
|
Core functionality:
|
|
- `getVideoInfo(url)`: Fetches video metadata using yt-dlp
|
|
- `downloadVideo(request)`: Downloads and processes video/audio
|
|
- `ensureDirectories()`: Creates necessary directories
|
|
- `sanitizeFilename()`: Sanitizes filenames for safe storage
|
|
|
|
**`lib/types.ts`**
|
|
Centralized TypeScript type definitions:
|
|
- `VideoFormat`, `AudioFormat`: Format type unions
|
|
- `DownloadRequest`, `DownloadResponse`: API request/response types
|
|
- `VideoInfo`, `FormatOption`: Video metadata types
|
|
|
|
**`lib/utils.ts`**
|
|
Utility functions:
|
|
- `cn()`: Tailwind class name merger
|
|
- `isValidYouTubeUrl()`: URL validation
|
|
- `extractYouTubeId()`: Extract video ID from URL
|
|
|
|
## Data Flow
|
|
|
|
### Video Information Flow
|
|
1. User enters YouTube URL and clicks "Get Info"
|
|
2. Frontend sends POST request to `/api/info`
|
|
3. API route validates URL and calls `getVideoInfo()`
|
|
4. `getVideoInfo()` executes `yt-dlp --dump-json`
|
|
5. JSON response is parsed and formatted
|
|
6. Video info (title, thumbnail, duration) returned to frontend
|
|
7. Frontend displays video information
|
|
|
|
### Download Flow
|
|
1. User selects format and clicks "Download"
|
|
2. Frontend sends POST request to `/api/download`
|
|
3. API route validates request and calls `downloadVideo()`
|
|
4. `downloadVideo()`:
|
|
- Generates unique file ID
|
|
- Constructs yt-dlp command based on format
|
|
- Executes download command
|
|
- Moves file to `/public/downloads/`
|
|
- Returns download URL
|
|
5. Frontend receives download URL
|
|
6. User can download file via provided link
|
|
|
|
## File Storage
|
|
|
|
### Directory Structure
|
|
```
|
|
Downlink/
|
|
├── downloads/ # Temporary storage (gitignored)
|
|
│ └── [fileId].[ext] # Downloaded files before processing
|
|
├── public/
|
|
│ └── downloads/ # Public downloads (gitignored)
|
|
│ └── [fileId].[ext] # Final files served to users
|
|
```
|
|
|
|
### File Naming
|
|
- Format: `[timestamp]-[randomId].[extension]`
|
|
- Example: `1234567890-abc123.mp4`
|
|
- Prevents filename conflicts
|
|
- Timestamp enables cleanup of old files
|
|
|
|
## Dependencies
|
|
|
|
### Runtime Dependencies
|
|
- **next**: Next.js framework
|
|
- **react**: React library
|
|
- **react-dom**: React DOM rendering
|
|
- **lucide-react**: Icon library
|
|
- **@radix-ui/***: UI component primitives
|
|
- **tailwind-merge**: Tailwind class merging
|
|
- **clsx**: Conditional class names
|
|
|
|
### System Dependencies
|
|
- **yt-dlp**: Python-based YouTube downloader
|
|
- **ffmpeg**: Media conversion tool (used by yt-dlp)
|
|
|
|
### Development Dependencies
|
|
- **typescript**: TypeScript compiler
|
|
- **tailwindcss**: CSS framework
|
|
- **eslint**: Code linting
|
|
|
|
## Security Considerations
|
|
|
|
### Current Implementation
|
|
- URL validation to ensure YouTube URLs only
|
|
- Filename sanitization to prevent directory traversal
|
|
- Server-side processing (no client-side download logic)
|
|
|
|
### Recommended Enhancements
|
|
- Rate limiting to prevent abuse
|
|
- File size limits
|
|
- User authentication/authorization
|
|
- Download quotas per user/IP
|
|
- Automatic file cleanup
|
|
- CORS configuration
|
|
- Input sanitization for all user inputs
|
|
|
|
## Performance Considerations
|
|
|
|
### Current Limitations
|
|
- Synchronous file operations (could block for large files)
|
|
- No progress tracking during downloads
|
|
- Files stored in memory during copy operations
|
|
- No caching of video information
|
|
|
|
### Optimization Opportunities
|
|
- Stream large files instead of loading into memory
|
|
- Implement download progress tracking
|
|
- Cache video metadata
|
|
- Use background jobs for long-running downloads
|
|
- Implement CDN for file serving
|
|
- Add database for download history
|
|
|
|
## Deployment Considerations
|
|
|
|
### Requirements
|
|
- Node.js 18+ runtime
|
|
- Python 3.6+ (for yt-dlp)
|
|
- ffmpeg installed on server
|
|
- Sufficient disk space for downloads
|
|
- Network access to YouTube
|
|
|
|
### Environment Variables
|
|
Currently none required, but consider:
|
|
- `MAX_FILE_SIZE`: Maximum file size limit
|
|
- `CLEANUP_INTERVAL`: File cleanup schedule
|
|
- `ALLOWED_DOMAINS`: Allowed video platforms
|
|
- `STORAGE_PATH`: Custom storage location
|
|
|
|
### Scaling Considerations
|
|
- Stateless API design (can scale horizontally)
|
|
- File storage should be shared (S3, etc.) for multi-instance deployments
|
|
- Consider message queue for download processing
|
|
- Implement caching layer for video metadata
|