Tonne of debugging - getting ready for the production builds

This commit is contained in:
2026-02-16 10:44:18 -07:00
parent a77306fac2
commit 7895ce683e
1367 changed files with 404191 additions and 2005 deletions

View File

@@ -0,0 +1,358 @@
# Media Manager
The Media Manager provides a complete video library system with upload, metadata extraction, public gallery, reaction system, and job queue monitoring. Built as a separate Fastify microservice with Drizzle ORM.
## Overview
The Media Manager consists of four integrated components:
1. **[Video Library](video-library.md)** - Admin video management
2. **[Upload System](upload.md)** - Video upload with metadata extraction
3. **[Public Gallery](public-gallery.md)** - Public video sharing
4. **[Job Queue](jobs.md)** - Background job monitoring
## Features
### Video Library
- Video CRUD operations
- Metadata editing (title, description, tags)
- Lock/unlock videos
- Bulk operations (delete, lock, share)
- Search and filtering
- Thumbnail generation (future)
### Upload System
- Drag-and-drop upload
- Single and batch upload
- Progress tracking
- **Automatic metadata extraction** (FFprobe)
- Duration
- Dimensions (width x height)
- Orientation (landscape/portrait/square)
- Quality (resolution-based: 4K, 1080p, 720p, etc.)
- Audio detection
- File validation (type, size)
- Supported formats: MP4, MOV, AVI, MKV, WebM, M4V, FLV
- Max file size: 10GB
### Public Gallery
- Shared videos display
- Category filtering
- Reaction system (6 emojis)
- Video cards with thumbnails
- Lock/unlock control
- Visitor reactions
### Reaction System
Six emoji reactions:
- Like (👍)
- Love (❤️)
- Laugh (😂)
- Wow (😮)
- Sad (😢)
- Angry (😡)
## Architecture
### Dual API Design
**Express API** (Port 4000)
- Main V2 features
- Prisma ORM
- PostgreSQL
**Fastify Media API** (Port 4100)
- Media-specific operations
- Drizzle ORM
- Same PostgreSQL database
- Optimized for file uploads
### Backend Components
**Media API:**
- `api/src/media-server.ts` - Fastify entry point
- `api/src/modules/media/routes/` - Video, upload, shared, reactions, jobs
- `api/src/modules/media/services/` - FFprobe, video service
- `api/src/modules/media/db/schema.ts` - Drizzle schema
**Database Tables:**
- `videos` - Video metadata (Drizzle)
- `shared_media` - Public gallery (Drizzle)
- `media_reactions` - Reaction tracking (Drizzle)
- `media_jobs` - Job queue (Drizzle)
### Frontend Components
**Admin Pages:**
- `admin/src/pages/media/LibraryPage.tsx` - Video library management
- `admin/src/pages/media/SharedMediaPage.tsx` - Public gallery admin
- `admin/src/pages/media/MediaJobsPage.tsx` - Job queue monitoring
**Public Pages:**
- `admin/src/pages/public/MediaGalleryPage.tsx` - Public video gallery
- `admin/src/pages/public/MediaViewerPage.tsx` - Video detail page
**Components:**
- `admin/src/components/media/VideoCard.tsx` - Video display card
- `admin/src/components/media/BulkActions.tsx` - Batch operations
- `admin/src/components/media/UploadVideoModal.tsx` - Upload interface
**API Clients:**
- `admin/src/lib/media-api.ts` - Authenticated media API client
- `admin/src/lib/media-public-api.ts` - Public media API client
## Configuration
### Environment Variables
```bash
# Enable media features
ENABLE_MEDIA_FEATURES=true
# Media API port
MEDIA_API_PORT=4100
# Media storage
MEDIA_LIBRARY_PATH=/media/local/library # Read-only library
MEDIA_INBOX_PATH=/media/local/inbox # Read-write inbox
```
### Docker Volumes
```yaml
volumes:
# Library (read-only)
- /path/to/library:/media/local/library:ro
# Inbox (read-write for uploads)
- /path/to/inbox:/media/local/inbox:rw
```
## Upload System
### Upload Flow
1. **Select Files**
- Drag-and-drop or file picker
- Multiple file selection
- File type validation
2. **Upload to Inbox**
- Stream to `/media/local/inbox`
- UUID filename (prevents conflicts)
- Progress tracking
3. **Extract Metadata**
- FFprobe analysis (30s timeout)
- Duration, dimensions, orientation
- Quality calculation
- Audio detection
4. **Create Database Record**
- Store metadata
- Set initial status
- Link to user
5. **Process Video** (Future)
- Generate thumbnail
- Transcode formats
- Move to library
### FFprobe Metadata Extraction
Automatically extracts:
```typescript
interface VideoMetadata {
duration: number; // Seconds (e.g., 125.5)
width: number; // Pixels (e.g., 1920)
height: number; // Pixels (e.g., 1080)
orientation: string; // 'landscape' | 'portrait' | 'square'
quality: string; // '4K' | '1080p' | '720p' | 'SD'
hasAudio: boolean; // Audio stream detected
}
```
**Quality Calculation:**
- 4K: ≥2160p (3840x2160)
- 1080p: ≥1080p (1920x1080)
- 720p: ≥720p (1280x720)
- SD: <720p
**Orientation:**
- Landscape: width > height
- Portrait: height > width
- Square: width ≈ height (within 10%)
### Supported Formats
- **MP4** - H.264/H.265 video
- **MOV** - QuickTime
- **AVI** - Audio Video Interleave
- **MKV** - Matroska
- **WebM** - Web-optimized
- **M4V** - iTunes video
- **FLV** - Flash video
## Public Gallery
### Sharing System
Videos can be shared publicly:
1. **Lock/Unlock** - Control public visibility
2. **Category Assignment** - Organize by category
3. **Public Access** - View at `/media`
4. **Reactions** - Emoji reactions from visitors
### Categories
Predefined categories:
- Events
- Testimonials
- Tutorials
- Announcements
- Behind the Scenes
- Custom categories
## Reaction System
### Reaction Tracking
```typescript
interface MediaReaction {
id: number;
videoId: number;
reactionType: string; // 'like' | 'love' | 'laugh' | 'wow' | 'sad' | 'angry'
sessionId: string; // Unique session identifier
createdAt: Date;
}
```
### Session-Based Reactions
- One reaction per video per session
- Session ID in localStorage
- Update reaction (change type)
- Remove reaction (click again)
## Job Queue
Background jobs for:
- Video processing
- Thumbnail generation
- Format transcoding
- Metadata extraction
- File cleanup
### Job Monitoring
Admin can:
- View job status
- Monitor progress
- Retry failed jobs
- View error logs
## Database Schema (Drizzle)
### Videos Table
```typescript
export const videos = pgTable('videos', {
id: serial('id').primaryKey(),
title: varchar('title', { length: 255 }).notNull(),
description: text('description'),
filename: varchar('filename', { length: 255 }).notNull(),
filepath: varchar('filepath', { length: 500 }).notNull(),
duration: integer('duration'), // Seconds
width: integer('width'), // Pixels
height: integer('height'), // Pixels
orientation: varchar('orientation', { length: 20 }), // 'landscape' | 'portrait' | 'square'
quality: varchar('quality', { length: 20 }), // '4K' | '1080p' | '720p' | 'SD'
hasAudio: boolean('has_audio'),
tags: json('tags').$type<string[]>(),
locked: boolean('locked').default(false),
uploadedBy: integer('uploaded_by'),
createdAt: timestamp('created_at').defaultNow(),
updatedAt: timestamp('updated_at').defaultNow(),
});
```
## API Endpoints
### Admin Endpoints (Media API - Port 4100)
```
GET /media-api/videos # List videos
POST /media-api/videos # Create video (manual)
GET /media-api/videos/:id # Get video
PATCH /media-api/videos/:id # Update video
DELETE /media-api/videos/:id # Delete video
POST /media-api/upload # Upload single video
POST /media-api/upload/batch # Upload multiple videos
GET /media-api/shared # List shared videos
POST /media-api/shared # Share video
DELETE /media-api/shared/:id # Unshare video
GET /media-api/jobs # List jobs
```
### Public Endpoints
```
GET /media-api/public/videos # List public videos
GET /media-api/public/videos/:id # Get public video
POST /media-api/reactions # Add/update reaction
DELETE /media-api/reactions/:id # Remove reaction
```
## Security
### File Validation
- MIME type checking
- File extension validation
- File size limits (10GB max)
- Path traversal prevention
- Null byte detection
### Access Control
- Admin-only uploads
- Lock/unlock controls
- Public visibility flags
- Session-based reactions
## Performance
### Upload Optimization
- Streaming uploads (no memory buffering)
- UUID filenames (no collisions)
- Async metadata extraction
- Progress tracking
### Gallery Optimization
- Lazy loading
- Thumbnail caching (future)
- Paginated results
- Infinite scroll
## Related Documentation
- [Video Library](video-library.md)
- [Upload System](upload.md)
- [Public Gallery](public-gallery.md)
- [Job Queue](jobs.md)
- [Backend Media Module](../../backend/modules/media.md)
- [Library Page](../../frontend/pages/admin/library-page.md)
- [Upload Modal Component](../../frontend/components/index.md)
- [FFprobe Service](../../backend/services/index.md)

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff