diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..8a64454 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,263 @@ +# CLAUDE.md + +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. + +## Project Overview + +A video optimization tool for social media platforms that converts videos to platform-specific specifications (codec, bitrate, resolution) using FFmpeg. Built for L'Oréal creative optimization workflows based on CDMO Creative Optimization Documentation v1.1. + +**Key Capabilities:** +- 21 platform configurations across 8 social media platforms (Meta, Pinterest, Snapchat, TikTok, YouTube, YouTube CTV, Amazon Prime, Amazon Freevee) +- Automatic platform/aspect ratio detection from filename patterns +- Side-by-side video comparison with synchronized playback +- Admin panel for managing platform specifications +- Naming convention management + +## Architecture + +**Two-tier architecture:** + +### Backend (Python Flask REST API) +- **`backend/app.py`** - Main Flask server with REST endpoints and admin functionality + - Core endpoints: `/api/health`, `/api/platforms`, `/api/upload`, `/api/convert`, `/api/stream`, `/api/download`, `/api/cleanup` + - Admin endpoints: `/api/admin/platforms` (POST/PUT/DELETE), `/api/admin/export`, `/api/admin/import`, `/api/admin/reset-factory`, `/api/admin/naming-conventions` + - Factory defaults stored as deep copies at startup for reset functionality + - Persistent storage via JSON files (`platform_specs.json`, `naming_conventions.json`) + +- **`backend/video_processor.py`** - FFmpeg wrapper for video conversion + - Uses `ffmpeg-python` library + - Handles codec-specific parameters (H264: preset/crf/profile, H265: preset/crf, VP9: deadline/cpu-used/row-mt) + - Probes video metadata and calculates aspect ratios + +- **`backend/platform_specs.py`** - Platform specification definitions + - `PLATFORM_SPECS` dict: Contains all platform configurations with codecs, containers, and format arrays + - `FILENAME_PATTERNS` dict: Platform detection patterns (e.g., `_tiktok_`, `_meta_`, `_youtube_ctv_`) + - `ASPECT_RATIO_PATTERNS` dict: Aspect ratio detection patterns (e.g., `_16x9_`, `_9x16_`, `_1x1_`) + - Helper functions: `detect_platform_from_filename()`, `detect_aspect_ratio_from_filename()`, `get_platform_info()` + - Imported and modified by `app.py` for dynamic configuration + +### Frontend (Vanilla HTML/JS) +- **`frontend/index.html`** - Main user interface with drag-and-drop upload, platform selection, video comparison +- **`frontend/admin.html`** - Admin panel for platform management +- **`frontend/app.js`** - Main application logic (upload, conversion, comparison, mute controls) +- **`frontend/admin.js`** - Admin panel logic (CRUD operations, export/import, naming conventions) +- **`frontend/config.js`** - Configuration (API_BASE, MAX_FILE_SIZE) +- **`frontend/style.css` / `frontend/admin.css`** - Black (#000000) + Yellow (#FFC407) theme, Montserrat font + +## Common Commands + +### Development Setup +```bash +# First time setup +python3 -m venv venv +source venv/bin/activate # On Windows: venv\Scripts\activate +pip install -r backend/requirements.txt + +# Install FFmpeg (required) +brew install ffmpeg # macOS +sudo apt-get install ffmpeg # Ubuntu/Debian +``` + +### Running the Application +```bash +# Option 1: One-command start (starts both backend and frontend) +./start.sh + +# Option 2: Manual start (two terminals) +# Terminal 1 - Backend +cd backend +source ../venv/bin/activate +python app.py # Runs on http://localhost:5000 + +# Terminal 2 - Frontend +cd frontend +python3 -m http.server 8000 # Runs on http://localhost:8000 +``` + +### Testing +```bash +# Health check +curl http://localhost:5000/api/health + +# Get platforms +curl http://localhost:5000/api/platforms + +# Export specifications +curl http://localhost:5000/api/admin/export + +# Stop backend server (if port 5000 in use) +lsof -ti:5000 | xargs kill +``` + +### Admin Panel Access +- Standard setup: http://localhost:8000/admin.html +- MAMP setup: http://localhost:8888/admin.html + +## Key Implementation Details + +### File Storage +- **Uploads:** `backend/uploads/` - Original videos stored as `{uuid}.{extension}` +- **Outputs:** `backend/outputs/` - Converted videos stored as `{uuid}_optimized.{extension}` +- **Persistence:** `backend/platform_specs.json` and `backend/naming_conventions.json` (auto-generated, gitignored) +- Files are referenced by UUID throughout the conversion pipeline + +### Platform Detection Logic +Filename patterns are matched case-insensitively: +1. Check for platform patterns (e.g., `_tiktok_`, `_meta_`, `_youtube_ctv_`) +2. Check for aspect ratio patterns (e.g., `_16x9_`, `_9x16_`, `_1x1_`) +3. Return `None` if no match found + +**Example:** `summer_campaign_tiktok_9x16.mp4` → Auto-detects TikTok + 9:16 + +### Video Conversion Flow +1. Upload video → Store in `uploads/` → Return video info + detected platform/aspect ratio +2. User selects platform + aspect ratio (or uses auto-detected) +3. Backend looks up format spec from `PLATFORM_SPECS` +4. FFmpeg converts with platform-specific codec parameters +5. Output saved to `outputs/` → Return size reduction stats +6. Frontend streams both videos for side-by-side comparison + +### Codec-Specific Settings (in video_processor.py) +- **H264 (libx264):** `preset=medium`, `crf=23`, `profile:v=main`, `pix_fmt=yuv420p` +- **H265 (libx265):** `preset=medium`, `crf=28`, `pix_fmt=yuv420p` +- **VP9 (libvpx-vp9):** `deadline=good`, `cpu-used=2`, `row-mt=1` +- **Audio:** AAC (128k for mobile, 192k for CTV) or Opus (128-192k for VP9) + +### Admin Panel State Management +- Changes to `PLATFORM_SPECS`, `FILENAME_PATTERNS`, `ASPECT_RATIO_PATTERNS` are applied in-memory +- Automatically persisted to JSON files for reload on server restart +- Factory defaults stored as deep copies at app startup (`FACTORY_DEFAULTS`, `FACTORY_FILENAME_PATTERNS`, `FACTORY_ASPECT_RATIO_PATTERNS`) +- Reset to factory deletes JSON files and restores from deep copies + +### Frontend Video Comparison Features +- Side-by-side players with synchronized playback controls +- Independent mute/unmute buttons for each video +- Detailed specifications display (codec, bitrate, resolution, file size) +- Aspect ratio mismatch warnings (yellow on config page, red on comparison page) +- File size reduction percentage calculation + +## Adding New Platforms + +### Via Admin Panel (Recommended) +1. Navigate to `/admin.html` +2. Click "Add New Platform" +3. Fill in: platform key (lowercase, no spaces), name, codec (libx264/libx265/libvpx-vp9), container (mp4/webm) +4. Add format configurations: aspect ratio, resolution (WIDTHxHEIGHT), bitrate (e.g., 1500k), min/max bitrates, audio bitrate +5. Save → Automatically persisted to `platform_specs.json` + +### Via Code (backend/platform_specs.py) +Add to `PLATFORM_SPECS` dict: +```python +"platform_key": { + "name": "Platform Display Name", + "codec": "libx264", # or libx265, libvpx-vp9 + "container": "mp4", # or webm + "formats": [ + { + "ratio": "16:9", + "size": "1920x1080", + "bitrate": "1500k", + "bitrate_min": "1300k", + "bitrate_max": "1700k", + "audio": "128k", + "audio_codec": "aac", # optional: defaults to aac + "note": "Optional note" # optional + } + ] +} +``` + +Add filename detection patterns to `FILENAME_PATTERNS`: +```python +'platform_key': ['_pattern1_', '_pattern2_'] +``` + +### Naming Convention Management +Use Admin Panel → Naming Conventions tab to: +- Add/edit/remove platform detection patterns +- Add/edit/remove aspect ratio detection patterns +- Changes persist to `naming_conventions.json` + +## Supported Video Formats +**Input:** MP4, MOV, AVI, MKV, WEBM, FLV, WMV, M4V (max 500MB, configurable in `app.py`) +**Output:** MP4 (for H264/H265) or WebM (for VP9) + +## Configuration Changes + +### Change API Endpoint +Edit `frontend/config.js`: +```javascript +const CONFIG = { + API_BASE: 'http://localhost:5000/api', // Change this + MAX_FILE_SIZE: 500 * 1024 * 1024, + DEBUG: true +}; +``` + +### Change Max File Size +Edit `backend/app.py`: +```python +MAX_FILE_SIZE = 500 * 1024 * 1024 # Change this (bytes) +``` + +### Change Server Port +Edit `backend/app.py`: +```python +app.run(debug=True, host='0.0.0.0', port=5000) # Change port here +``` +Then update `frontend/config.js` to match. + +## CORS Configuration +CORS is enabled globally via `flask_cors.CORS(app)` in `app.py`. This allows frontend and backend to run on different ports/hosts for development. For production, restrict CORS to specific origins: +```python +CORS(app, origins=['https://yourdomain.com']) +``` + +## Production Deployment Notes +1. Use production WSGI server: `gunicorn -w 4 -b 0.0.0.0:5000 app:app` +2. Disable debug mode: `app.run(debug=False, ...)` +3. Set up reverse proxy (Nginx/Apache) with SSL +4. Implement authentication for admin endpoints +5. Set up file cleanup cron job for `uploads/` and `outputs/` +6. Configure proper CORS restrictions +7. Consider adding rate limiting for API endpoints + +## Important Constraints +- Platform keys are immutable after creation (delete and recreate to change) +- FFmpeg must be installed and accessible in PATH +- Backend must be running for frontend to function +- JSON files (`platform_specs.json`, `naming_conventions.json`) are auto-generated and gitignored +- Video files are stored on disk (not in database) +- No authentication on admin endpoints (local development only) + +## Troubleshooting + +### FFmpeg Not Found +```bash +# Verify installation +ffmpeg -version + +# Install if missing +brew install ffmpeg # macOS +sudo apt-get install ffmpeg # Ubuntu/Debian +``` + +### Port 5000 Already in Use +```bash +# Kill existing process +lsof -ti:5000 | xargs kill + +# Or use different port (update config.js) +python app.py --port 5001 +``` + +### Changes Not Appearing +1. Check backend logs for save errors +2. Verify JSON files were updated (`backend/platform_specs.json`) +3. Hard reload frontend (Cmd+Shift+R / Ctrl+Shift+R) +4. Use Admin Panel "Reload from Server" button + +## Design Theme +- **Colors:** Black (#000000) background + Yellow (#FFC407) accents +- **Font:** Montserrat (Google Fonts) +- **Style:** Dark UI with professional polish