update readme and context
All checks were successful
Build Images and Deploy / Update-PROD-Stack (push) Successful in 1m11s
All checks were successful
Build Images and Deploy / Update-PROD-Stack (push) Successful in 1m11s
This commit is contained in:
426
PROJECT_CONTEXT.md
Normal file
426
PROJECT_CONTEXT.md
Normal file
@@ -0,0 +1,426 @@
|
||||
# 📘 Project Context for AI Assistants
|
||||
|
||||
This document provides technical context for AI assistants working on this video editor project. It covers architecture decisions, implementation patterns, and key code locations.
|
||||
|
||||
---
|
||||
|
||||
## 🏗️ Architecture Overview
|
||||
|
||||
### Tech Stack
|
||||
- **Backend**: Flask 3.0 (Python 3.11+)
|
||||
- **Video Engine**: FFmpeg with libx264 encoder
|
||||
- **Frontend**: Vanilla JavaScript (no frameworks)
|
||||
- **Deployment**: Python local / Docker / Docker Compose
|
||||
|
||||
### Request Flow
|
||||
```
|
||||
1. User uploads video → /upload endpoint
|
||||
2. Server assigns UUID, stores in uploads/ dir
|
||||
3. User edits via UI → sends params to /process
|
||||
4. FFmpeg processes with filters → outputs/ dir
|
||||
5. User downloads → /download/<file_id> endpoint
|
||||
6. Cleanup → /cleanup/<file_id> removes temp files
|
||||
```
|
||||
|
||||
### File Structure
|
||||
```
|
||||
c:\Projects\editor/
|
||||
├── app.py # Flask backend, FFmpeg integration
|
||||
├── templates/
|
||||
│ └── index.html # Single-page frontend app
|
||||
├── requirements.txt # Python dependencies
|
||||
├── uploads/ # Temporary uploaded files (created on first run)
|
||||
├── outputs/ # Processed video outputs (created on first run)
|
||||
├── Dockerfile # Container image definition
|
||||
├── docker-compose.yml # Local development compose
|
||||
├── prod-compose.yml # Production registry-pull compose
|
||||
├── .gitea/
|
||||
│ └── workflows/
|
||||
│ └── rebuild-prod.yaml # CI/CD build and deployment
|
||||
├── README.md # User documentation
|
||||
└── PROJECT_CONTEXT.md # This file (technical context)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🔑 Key Implementation Details
|
||||
|
||||
### 1. Video Processing (`app.py`)
|
||||
|
||||
#### FFmpeg Filter Chain
|
||||
The app builds a complex FFmpeg filter chain dynamically based on user selections:
|
||||
|
||||
```python
|
||||
# Base filters array
|
||||
filters = []
|
||||
|
||||
# Rotation (if not 0°)
|
||||
if rotate and rotate != '0':
|
||||
# transpose values: 1=90°CW, 2=90°CCW, 3=180° (using 2,2)
|
||||
if rotate == '90':
|
||||
filters.append('transpose=1')
|
||||
elif rotate == '180':
|
||||
filters.append('transpose=2,transpose=2')
|
||||
elif rotate == '270':
|
||||
filters.append('transpose=2')
|
||||
|
||||
# Crop (if specified)
|
||||
if crop_w and crop_h:
|
||||
filters.append(f'crop={crop_w}:{crop_h}:{crop_x}:{crop_y}')
|
||||
|
||||
# Scale with even dimension enforcement
|
||||
if scale_percentage < 100:
|
||||
# trunc(value/2)*2 ensures dimensions are divisible by 2 (H.264 requirement)
|
||||
filters.append(f'scale=trunc(iw*{scale_percentage/100}/2)*2:trunc(ih*{scale_percentage/100}/2)*2')
|
||||
|
||||
# Final filter string
|
||||
filter_str = ','.join(filters)
|
||||
```
|
||||
|
||||
**Critical**: The `trunc(iw*percentage/100/2)*2` pattern ensures output dimensions are always even numbers. H.264 encoder requires width and height divisible by 2.
|
||||
|
||||
#### File ID System
|
||||
- UUID4 generates unique IDs for each upload
|
||||
- `original_filenames` dict maps UUID → original filename
|
||||
- Downloads use: `{original_name}_processed_{timestamp}.mp4`
|
||||
- Timestamp format: `YYYYMMDD_HHMMSS` (e.g., `20240315_143022`)
|
||||
|
||||
#### CRF Quality Control
|
||||
- CRF (Constant Rate Factor) range: 18-32
|
||||
- Lower CRF = higher quality, larger file
|
||||
- Default: 23 (balanced)
|
||||
- Passed directly to FFmpeg: `-crf {quality}`
|
||||
|
||||
### 2. Visual Crop Selection (`index.html`)
|
||||
|
||||
#### Canvas Overlay Technique
|
||||
```javascript
|
||||
// Create canvas overlay matching video display size
|
||||
cropCanvas.width = video.offsetWidth;
|
||||
cropCanvas.height = video.offsetHeight;
|
||||
|
||||
// Calculate scale factors for actual video pixels
|
||||
const scaleX = video.videoWidth / video.offsetWidth;
|
||||
const scaleY = video.videoHeight / video.offsetHeight;
|
||||
|
||||
// Mouse drag draws rectangle on canvas
|
||||
// Convert canvas coordinates → actual video pixels
|
||||
const actualX = Math.round(rectX * scaleX);
|
||||
const actualY = Math.round(rectY * scaleY);
|
||||
const actualW = Math.round(rectW * scaleX);
|
||||
const actualH = Math.round(rectH * scaleY);
|
||||
```
|
||||
|
||||
**Why this works**: Video element display size ≠ actual video resolution. Scale factors convert screen pixels to video pixels for accurate crop commands.
|
||||
|
||||
#### Dynamic Button Creation
|
||||
The crop button is dynamically injected into video-info after video loads:
|
||||
|
||||
```javascript
|
||||
function setupCropButton(video, canvas) {
|
||||
const videoInfoDiv = document.getElementById('video-info');
|
||||
|
||||
// Create button HTML
|
||||
const cropButtonHtml = `
|
||||
<button id="draw-crop-btn" class="btn btn-primary">
|
||||
🎯 Click to Draw Crop Area
|
||||
</button>
|
||||
`;
|
||||
|
||||
// Inject after codec paragraph
|
||||
videoInfoDiv.innerHTML += cropButtonHtml;
|
||||
|
||||
// Add event listener to new button
|
||||
document.getElementById('draw-crop-btn').addEventListener('click', () => {
|
||||
enableCropDrawing(video, canvas);
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
**Caution**: Using `innerHTML +=` recreates all child elements. Event listeners must be re-attached after injection.
|
||||
|
||||
### 3. Trim Controls
|
||||
|
||||
#### Video Position Capture
|
||||
Instead of complex timeline scrubbing, uses simple current position capture:
|
||||
|
||||
```javascript
|
||||
// "Set Start Here" button
|
||||
video.currentTime // Gets current playback position in seconds
|
||||
|
||||
// Display position in real-time
|
||||
function formatTime(seconds) {
|
||||
const mins = Math.floor(seconds / 60);
|
||||
const secs = Math.floor(seconds % 60);
|
||||
const ms = Math.floor((seconds % 1) * 100);
|
||||
return `${mins}:${secs.toString().padStart(2, '0')}.${ms.toString().padStart(2, '0')}`;
|
||||
}
|
||||
```
|
||||
|
||||
**Design Decision**: Timeline scrubbers added complexity without improving UX. Position-based buttons are more intuitive.
|
||||
|
||||
### 4. Scale and Dimension Display
|
||||
|
||||
#### Live Output Resolution Preview
|
||||
```javascript
|
||||
// Calculate what output dimensions will be
|
||||
let outputW = videoWidth;
|
||||
let outputH = videoHeight;
|
||||
|
||||
// If cropped, use crop dimensions
|
||||
if (cropW && cropH) {
|
||||
outputW = cropW;
|
||||
outputH = cropH;
|
||||
}
|
||||
|
||||
// Apply scale percentage
|
||||
outputW = Math.round(outputW * (scalePercentage / 100));
|
||||
outputH = Math.round(outputH * (scalePercentage / 100));
|
||||
|
||||
// Force even dimensions (H.264 compatibility)
|
||||
if (outputW % 2 !== 0) outputW++;
|
||||
if (outputH % 2 !== 0) outputH++;
|
||||
|
||||
// Display to user
|
||||
document.getElementById('output-resolution').textContent = `${outputW}x${outputH}`;
|
||||
```
|
||||
|
||||
**Important**: Frontend preview must match backend FFMPEG logic exactly, or users see incorrect dimensions.
|
||||
|
||||
---
|
||||
|
||||
## 🎨 UI/UX Patterns
|
||||
|
||||
### Feature Ordering Logic
|
||||
Features are ordered by typical editing workflow:
|
||||
1. **Trim** - Select video segment (temporal)
|
||||
2. **Crop** - Select video area (spatial)
|
||||
3. **Output Scale** - Apply to trimmed/cropped result
|
||||
4. **Compression Quality** - Final output quality
|
||||
5. **Quick Actions** - Rotate/mute (can apply anytime)
|
||||
|
||||
### Reset Functionality
|
||||
Complete reset clears:
|
||||
- All input values (trim, crop, scale, quality)
|
||||
- Canvas drawings (crop rectangle)
|
||||
- Video preview (remove src)
|
||||
- Button states (rotate, mute)
|
||||
- Display texts (resolution, filename, time)
|
||||
- Section visibility (hide edit/download sections)
|
||||
|
||||
```javascript
|
||||
// Comprehensive reset
|
||||
video.src = '';
|
||||
cropCanvas.width = 0;
|
||||
cropCanvas.height = 0;
|
||||
document.querySelectorAll('input[type="number"]').forEach(input => input.value = '');
|
||||
document.getElementById('scale-slider').value = 100;
|
||||
document.getElementById('mute-audio').classList.remove('active');
|
||||
// ... etc
|
||||
```
|
||||
|
||||
### Button State Management
|
||||
Visual feedback for toggles:
|
||||
```javascript
|
||||
// Mute audio toggle
|
||||
muteBtn.classList.toggle('active');
|
||||
muteBtn.textContent = muted ? '🔇 Audio Muted' : '🔊 Mute Audio';
|
||||
|
||||
// Rotation state
|
||||
document.getElementById('rotation-display').textContent =
|
||||
rotationAngle === 0 ? '' : `Rotated ${rotationAngle}°`;
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🐳 Deployment Configurations
|
||||
|
||||
### Local Development
|
||||
```bash
|
||||
# Python
|
||||
python app.py # Runs on localhost:5000
|
||||
|
||||
# Docker
|
||||
docker-compose up --build
|
||||
```
|
||||
|
||||
### Production (CI/CD)
|
||||
`.gitea/workflows/rebuild-prod.yaml`:
|
||||
1. Triggered on push to main
|
||||
2. Builds Docker image with FFmpeg
|
||||
3. Pushes to `reg.dev.nervesocket.com/video-editor:latest`
|
||||
4. Calls Portainer API to redeploy container
|
||||
5. Uses production compose pulling from registry
|
||||
|
||||
**Registry**: Private registry at `reg.dev.nervesocket.com`
|
||||
**Deployment**: Portainer API with webhook ID `df5c509c-8002-463e-b009-3b05b8a1e2c3`
|
||||
|
||||
---
|
||||
|
||||
## 🧩 Common Extension Patterns
|
||||
|
||||
### Adding New FFmpeg Filter
|
||||
1. Add UI control in `index.html` (slider, button, input)
|
||||
2. Send parameter with form submission (line ~400)
|
||||
3. Extract in `app.py` process_video: `request.form.get('param_name')`
|
||||
4. Add filter to filters array: `filters.append('filter_name=value')`
|
||||
5. Ensure filter order is logical (crop before scale, etc.)
|
||||
|
||||
### Adding New Quick Action
|
||||
1. Create button in Quick Actions section
|
||||
2. Add click handler setting global variable
|
||||
3. Send parameter in POST to /process
|
||||
4. Handle in backend with FFmpeg flag or filter
|
||||
5. Add reset logic to resetApp()
|
||||
|
||||
### Handling New Video Codec Output
|
||||
Currently hardcoded to H.264/AAC. To add codec selection:
|
||||
1. Add codec dropdown in UI
|
||||
2. Pass codec parameter to backend
|
||||
3. Conditional FFmpeg args based on codec:
|
||||
```python
|
||||
if codec == 'h264':
|
||||
cmd.extend(['-c:v', 'libx264', '-crf', quality])
|
||||
elif codec == 'h265':
|
||||
cmd.extend(['-c:v', 'libx265', '-crf', quality])
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🔍 Debugging Tips
|
||||
|
||||
### FFmpeg Command Inspection
|
||||
The app prints full FFmpeg command to console:
|
||||
```python
|
||||
print("FFmpeg command:", ' '.join(cmd))
|
||||
subprocess.run(cmd, check=True)
|
||||
```
|
||||
Copy this command and run manually to debug encoding issues.
|
||||
|
||||
### Canvas Coordinate Debugging
|
||||
Add console logs in mouse handlers:
|
||||
```javascript
|
||||
console.log('Canvas coords:', x, y);
|
||||
console.log('Video coords:', Math.round(x * scaleX), Math.round(y * scaleY));
|
||||
```
|
||||
|
||||
### Processing Failures
|
||||
Common issues:
|
||||
- **Odd dimensions**: Backend now handles with trunc(), shouldn't occur
|
||||
- **Invalid crop**: Crop exceeds video bounds (validate in frontend)
|
||||
- **Missing FFmpeg**: Docker image includes it, but local Python needs manual install
|
||||
- **Unsupported format**: Check FFmpeg support with `ffmpeg -formats`
|
||||
|
||||
---
|
||||
|
||||
## 📦 Dependencies
|
||||
|
||||
### Python (requirements.txt)
|
||||
```
|
||||
Flask==3.0.0
|
||||
Werkzeug==3.0.1
|
||||
```
|
||||
|
||||
### System
|
||||
- **FFmpeg**: Must be installed and in PATH
|
||||
- On Debian/Ubuntu: `apt-get install ffmpeg`
|
||||
- On Windows: Download from ffmpeg.org
|
||||
- Docker: Installed in Dockerfile
|
||||
|
||||
### FFmpeg Codecs Used
|
||||
- **Video**: libx264 (H.264/AVC)
|
||||
- **Audio**: aac (AAC)
|
||||
- **Filters**: crop, scale, transpose
|
||||
|
||||
---
|
||||
|
||||
## 🚨 Critical Implementation Notes
|
||||
|
||||
### 1. H.264 Even Dimension Requirement
|
||||
**Must enforce**: Width and height divisible by 2
|
||||
- Backend: `trunc(iw*scale/2)*2`
|
||||
- Frontend: `if (dim % 2 !== 0) dim++;`
|
||||
- Violation causes FFmpeg error: "width not divisible by 2"
|
||||
|
||||
### 2. File Cleanup
|
||||
Currently, files are NOT auto-deleted. Manual cleanup endpoint exists but:
|
||||
- `/cleanup/<file_id>` removes files
|
||||
- Consider adding auto-cleanup timer (e.g., 1 hour after upload)
|
||||
- Or cron job to clean old files
|
||||
|
||||
### 3. Memory Usage
|
||||
`original_filenames` dict grows indefinitely in memory. For production:
|
||||
- Persist to Redis/database
|
||||
- Or tie to file existence (check disk, rebuild dict on startup)
|
||||
|
||||
### 4. Security Considerations
|
||||
Current implementation is for trusted users:
|
||||
- No file size limits (could DOS server)
|
||||
- No rate limiting
|
||||
- No authentication
|
||||
- FFmpeg runs with user permissions (subprocess)
|
||||
- For public deployment, add nginx upload limits, Flask rate limiting, user sessions
|
||||
|
||||
### 5. Browser Compatibility
|
||||
- **Canvas API**: IE not supported (use Chrome/Firefox/Edge)
|
||||
- **Video Preview**: Requires browser codec support (H.264 widely supported)
|
||||
- **File API**: Drag-and-drop requires modern browser
|
||||
|
||||
---
|
||||
|
||||
## 🎯 Design Philosophy Explained
|
||||
|
||||
### Why No Framework?
|
||||
- **Simplicity**: Single HTML file, no build process
|
||||
- **Learning**: Clear vanilla JS patterns
|
||||
- **Deployment**: No npm, no bundling, just Python + FFmpeg
|
||||
- **Performance**: No framework overhead for simple app
|
||||
|
||||
### Why Percentage-Based Scaling?
|
||||
- **Intuitive**: "50% smaller" clearer than "calculate dimensions"
|
||||
- **Flexible**: Works regardless of input resolution
|
||||
- **Safer**: Avoids invalid dimensions (too large/small)
|
||||
- **Chaining**: Works naturally after crop (scale the crop, not original)
|
||||
|
||||
### Why CRF Instead of Bitrate?
|
||||
- **Quality-based**: Maintains consistent quality across different content
|
||||
- **Simpler**: One slider, no need to understand bitrate implications
|
||||
- **Better results**: Variable bitrate adapts to video complexity
|
||||
- **Industry standard**: CRF 18-23 is professional range
|
||||
|
||||
---
|
||||
|
||||
## 🔮 Future Enhancement Considerations
|
||||
|
||||
If extending this project, consider:
|
||||
|
||||
1. **Multiple Video Support**: Concatenation, side-by-side
|
||||
2. **Audio Controls**: Volume adjustment, audio replacement
|
||||
3. **Filters**: Brightness, contrast, saturation, blur
|
||||
4. **Watermarks**: Text or image overlays
|
||||
5. **Format Selection**: WebM, GIF, HEVC output options
|
||||
6. **Batch Processing**: Queue multiple jobs
|
||||
7. **Progress Bar**: Real-time FFmpeg encoding progress (parse stderr)
|
||||
8. **Undo/Redo**: State management for edit history
|
||||
9. **Presets**: Save common settings as named presets
|
||||
10. **Cloud Storage**: S3/Azure integration for large files
|
||||
|
||||
---
|
||||
|
||||
## 📞 Getting Help
|
||||
|
||||
When asking for assistance:
|
||||
1. **Describe the feature**: User-facing behavior first
|
||||
2. **Specify location**: Which file/function needs changes
|
||||
3. **FFmpeg context**: If encoding-related, mention codec/format
|
||||
4. **Show errors**: Full error messages help diagnose issues
|
||||
5. **Test command**: If FFmpeg fails, what command would work manually?
|
||||
|
||||
Example good request:
|
||||
> "I want to add a brightness filter. Users should have a slider in the UI from -1.0 to 1.0. This should apply the FFmpeg `eq=brightness=X` filter before the scale filter. The parameter should be called 'brightness' and default to 0.0."
|
||||
|
||||
---
|
||||
|
||||
**Last Updated**: 2024-03-15 (after adding compression quality slider and filename preservation)
|
||||
|
||||
**Current Version**: Fully functional simple video editor with 7 main features (trim, crop, scale, quality, rotation, mute, visual controls)
|
||||
180
README.md
180
README.md
@@ -1,15 +1,52 @@
|
||||
# 🎬 Simple Video Editor
|
||||
|
||||
A lightweight, web-based video editor with an intuitive interface for basic video editing tasks. Built with Flask and FFmpeg, it allows you to trim, crop, resize, and convert videos to H.264 MP4 format.
|
||||
A lightweight, web-based video editor with an intuitive interface for basic video editing tasks. Built with Flask and FFmpeg, it allows you to trim, crop, scale, rotate, and convert videos to H.264 MP4 format with interactive visual controls.
|
||||
|
||||
## ✨ Features
|
||||
|
||||
### Video Input/Output
|
||||
- **📹 Video Upload**: Drag and drop or browse to upload videos (supports MP4, AVI, MOV, MKV, WMV, FLV, WebM)
|
||||
- **⏱️ Trim**: Cut videos by specifying start and end times
|
||||
- **✂️ Crop**: Crop videos by defining X/Y position and dimensions
|
||||
- **📐 Resize**: Change output resolution with preset options (4K, 1080p, 720p, 480p) or custom dimensions
|
||||
- **🎯 H.264 Export**: All videos are exported as H.264 MP4 with optimized settings
|
||||
- **🖥️ Intuitive UI**: Clean, modern interface with real-time video preview
|
||||
- **💾 Smart Filenames**: Downloads preserve original filename with "_processed" suffix and unique timestamp
|
||||
- **📊 Video Info**: Displays resolution, duration, codec details
|
||||
|
||||
### Editing Features
|
||||
|
||||
#### ⏱️ Trim Video
|
||||
- **Visual Time Selection**: Play video and click buttons to set trim points at current playback position
|
||||
- **Live Time Display**: Shows current video position in real-time (MM:SS.ms format)
|
||||
- **Manual Input**: Fine-tune start/end times with precise second inputs
|
||||
|
||||
#### ✂️ Crop Video
|
||||
- **Interactive Canvas Selection**: Click and draw directly on video to select crop area
|
||||
- **Visual Feedback**: Semi-transparent overlay shows what will be removed
|
||||
- **Real-time Dimensions**: Displays actual video pixel dimensions while dragging
|
||||
- **Manual Input**: Enter exact crop position (X/Y) and dimensions
|
||||
- **Automatic Adjustment**: Ensures even dimensions for H.264 compatibility
|
||||
|
||||
#### 📐 Output Scale
|
||||
- **Percentage-based Scaling**: Scale from 10% to 100% in 5% increments
|
||||
- **Preset Options**: Quick buttons for 100%, 75%, 50%, 25%
|
||||
- **Smart Cropping**: Scale applies to cropped area (if crop selected) or original video
|
||||
- **Live Preview**: Shows final output resolution with even dimensions
|
||||
|
||||
#### 💾 Compression Quality
|
||||
- **CRF Control**: Adjust H.264 quality from CRF 18 (best) to 32 (smallest)
|
||||
- **Smart Presets**: Best Quality, High, Balanced, Low, Smallest File
|
||||
- **Visual Feedback**: Shows quality label and CRF value in real-time
|
||||
- **File Size Control**: Balance between quality and file size
|
||||
|
||||
#### ⚡ Quick Actions
|
||||
- **🔇 Mute Audio**: Remove audio track completely
|
||||
- **🔄 Rotate**: Rotate video 90°, 180°, 270° or back to original
|
||||
- **Visual State**: Buttons show active state and rotation amount
|
||||
|
||||
### User Experience
|
||||
- **🖥️ Centered Video Preview**: Large, centered video display for easier editing
|
||||
- **📱 Responsive Design**: Clean, modern gradient interface
|
||||
- **🎨 Visual Feedback**: Button states, loading indicators, error messages
|
||||
- **🔄 Reset Controls**: Start over or process another video with clean state
|
||||
- **💡 Helpful Hints**: Contextual tips explain how each feature works
|
||||
|
||||
## 🚀 Quick Start
|
||||
|
||||
@@ -32,26 +69,41 @@ A lightweight, web-based video editor with an intuitive interface for basic vide
|
||||
```
|
||||
|
||||
3. **Run the Application**:
|
||||
```powershell
|
||||
python app.py
|
||||
```
|
||||
The editor provides features in logical order:
|
||||
|
||||
4. **Open in Browser**:
|
||||
Navigate to `http://localhost:5000`
|
||||
#### 1. Trim Video
|
||||
- **Play the video** and pause at desired point
|
||||
- Click **"⏮️ Set Start Here"** to mark the beginning
|
||||
- Play to the end point and click **"⏭️ Set End Here"**
|
||||
- Current video position shows in real-time above buttons
|
||||
- Fine-tune with manual second inputs if needed
|
||||
|
||||
### Option 2: Run with Docker
|
||||
#### 2. Crop Video
|
||||
- Click **"🎯 Click to Draw Crop Area"** button (under video info)
|
||||
- **Click and drag** on the video to select the area to keep
|
||||
- Purple rectangle shows selected area with pixel dimensions
|
||||
- Darkened area shows what will be removed
|
||||
- Release mouse to apply crop coordinates
|
||||
- Or manually enter X/Y position and width/height values
|
||||
|
||||
#### Prerequisites
|
||||
- Docker installed
|
||||
- Docker Compose installed
|
||||
#### 3. Output Scale
|
||||
- Use slider to scale from 10% to 100%
|
||||
- Click preset buttons for quick scaling (100%, 75%, 50%, 25%)
|
||||
- Scale applies to cropped area, or full video if no crop
|
||||
- Example: 200x400 crop at 50% = 100x200 output
|
||||
- Dimensions automatically rounded to even numbers for H.264
|
||||
|
||||
#### Steps
|
||||
|
||||
1. **Build and Run**:
|
||||
```bash
|
||||
docker-compose up --build
|
||||
```
|
||||
#### 4. Compression Quality
|
||||
- Adjust slider from CRF 18 (best quality) to 32 (smallest file)
|
||||
- Default is CRF 23 (balanced)
|
||||
- Lower CRF = larger files, better quality
|
||||
- Higher CRF = smaller files, more compression
|
||||
- Use presets: Best Quality, High, Balanced, Low, Smallest File
|
||||
|
||||
#### 5. Quick Actions
|
||||
- **Mute Audio**: Click to remove audio track entirely
|
||||
- **Rotate 90°**: Click repeatedly to rotate (90° → 180° → 270° → 0°)
|
||||
- Buttons show active state when applied
|
||||
2. **Open in Browser**:
|
||||
Navigate to `http://localhost:5000`
|
||||
|
||||
@@ -88,15 +140,19 @@ A lightweight, web-based video editor with an intuitive interface for basic vide
|
||||
- **Y Position**: Vertical starting point for crop (0 = top edge)
|
||||
- **Crop Width**: Width of the cropped area
|
||||
- **Crop Height**: Height of the cropped area
|
||||
- Leave empty to skip cropping
|
||||
|
||||
### Step 3: Process and Download
|
||||
- Click **"🎬 Process Video"** to start encoding
|
||||
- Wait for processing to complete (time depends on video length and settings)
|
||||
- Click **"⬇️ Download Video"** to save the processed file
|
||||
|
||||
## 🛠️ Technical Details
|
||||
- Leave eUser-adjustable (18-32, default 23)
|
||||
- Audio codec: AAC at 128kbps (unless muted)
|
||||
- Rotation: FFmpeg transpose filter
|
||||
- Even dimensions: Automatic rounding for H.264 compatibility
|
||||
- Fast start enabled for web streaming
|
||||
|
||||
### Frontend
|
||||
- Pure HTML, CSS, and JavaScript (no frameworks)
|
||||
- HTML5 Canvas for interactive crop selection
|
||||
- Real-time video metadata display
|
||||
- Responsive gradient design
|
||||
- Drag-and-drop file upload
|
||||
- Live updating scales and quality indicators
|
||||
### Backend
|
||||
- **Framework**: Flask 3.0
|
||||
- **Video Processing**: FFmpeg with libx264 encoder
|
||||
@@ -118,10 +174,17 @@ A lightweight, web-based video editor with an intuitive interface for basic vide
|
||||
```
|
||||
editor/
|
||||
├── app.py # Flask backend application
|
||||
├── templates/
|
||||
│ └── index.html # Frontend UI
|
||||
├── requirements.txt # Python dependencies
|
||||
├── Dockerfile # Docker image configuration
|
||||
The quality is now user-adjustable via the UI. Default backend settings in `app.py`:
|
||||
```python
|
||||
'-crf', str(quality), # User-selected CRF (18-32)
|
||||
'-preset', 'medium', # ultrafast, superfast, veryfast, faster, fast, medium, slow, slower, veryslow
|
||||
```
|
||||
|
||||
### Scaling and Dimensions
|
||||
Scale is percentage-based and ensures H.264 compatibility:
|
||||
```python
|
||||
# Force even dimensions
|
||||
scale_filter = f"scale=trunc(iw*{scale_percentage/100}/2)*2:trunc(ih*{scale_percentage/100}/2)*2"
|
||||
├── docker-compose.yml # Docker Compose configuration
|
||||
├── .gitignore # Git ignore rules
|
||||
├── uploads/ # Temporary upload storage (auto-created)
|
||||
@@ -131,6 +194,11 @@ editor/
|
||||
## 🔧 Configuration
|
||||
|
||||
### File Size Limit
|
||||
- Odd dimensions error: The app now auto-rounds to even dimensions
|
||||
|
||||
### Crop selection not accurate
|
||||
- The displayed dimensions while dragging show actual video pixels (not screen pixels)
|
||||
- Canvas automatically scales between display size and actual video resolution
|
||||
Edit in `app.py`:
|
||||
```python
|
||||
app.config['MAX_CONTENT_LENGTH'] = 500 * 1024 * 1024 # 500MB
|
||||
@@ -159,21 +227,40 @@ Edit in `app.py` (process_video function):
|
||||
- Check FFmpeg console output in the terminal
|
||||
|
||||
### Upload fails
|
||||
- Verify file size is under 500MB
|
||||
- Check file format is supported
|
||||
- Ensure `uploads/` folder has write permissions
|
||||
- Ve<56> Feature Workflow Examples
|
||||
|
||||
## 🔒 Security Considerations
|
||||
### Example 1: Create Social Media Clip
|
||||
1. Upload full-length video
|
||||
2. Play and set start/end to extract 15-second segment
|
||||
3. Draw crop to make it vertical (9:16)
|
||||
4. Scale to 50% for smaller file
|
||||
5. Set quality to "High" (CRF 21)
|
||||
6. Process and download
|
||||
|
||||
**Note**: This application is designed for local or self-hosted use. For production deployment:
|
||||
### Example 2: Fix Phone Video
|
||||
1. Upload sideways phone video
|
||||
2. Click "Rotate 90°" once or multiple times
|
||||
3. Optionally crop edges
|
||||
4. Keep scale at 100%
|
||||
5. Set quality to "Balanced" (CRF 23)
|
||||
6. Process and download
|
||||
|
||||
1. Add authentication/authorization
|
||||
2. Implement rate limiting
|
||||
3. Validate and sanitize all inputs
|
||||
4. Add HTTPS support
|
||||
5. Configure proper CORS policies
|
||||
6. Implement file cleanup routines
|
||||
7. Add virus scanning for uploaded files
|
||||
### Example 3: Create Silent GIF-style Video
|
||||
1. Upload video
|
||||
2. Trim to desired segment
|
||||
3. Click "Mute Audio"
|
||||
4. Scale to 25% for tiny file size
|
||||
5. Set quality to "Low" (CRF 26)
|
||||
6. Process for small, silent video
|
||||
|
||||
## 🎯 Design Philosophy
|
||||
|
||||
This editor prioritizes:
|
||||
- **Simplicity**: No complex timeline or multi-track editing
|
||||
- **Visual Feedback**: See exactly what you're doing with live previews
|
||||
- **Speed**: Quick single-video processing without render queues
|
||||
- **Accessibility**: No installation needed (web-based)
|
||||
- **Self-hosting**: Run locally or deploy privately with Docker
|
||||
|
||||
## 📝 License
|
||||
|
||||
@@ -181,6 +268,11 @@ This project is provided as-is for personal and educational use.
|
||||
|
||||
## 🤝 Contributing
|
||||
|
||||
Feel free to fork, modify, and submit pull requests for improvements!
|
||||
This project is provided as-is for personal and educational use.
|
||||
|
||||
## 🤝 Contributing
|
||||
|
||||
Feel free to fork, modify, and submit pull requests for improvements!
|
||||
|
||||
## 💡 Future Enhancements
|
||||
|
||||
Reference in New Issue
Block a user