Skip to content

Latest commit

Β 

History

History
563 lines (456 loc) Β· 12.6 KB

File metadata and controls

563 lines (456 loc) Β· 12.6 KB

🎬 VideoEditorAPI

AI-powered video processing API with subtitle generation, karaoke effects, and editing tools.

⚑ Quick Start

Option 1: Digital Ocean App Platform (Easiest)

Deploy to DO

Option 2: One-Click Droplet Deploy

curl -fsSL https://raw.githubusercontent.com/jdportugal/VideoEditorAPI/main/install-ghcr.sh | sudo bash

Option 2: Local Development

git clone https://github.com/jdportugal/VideoEditorAPI.git
cd VideoEditorAPI
docker-compose up -d

Option 3: Manual Docker

docker run -d -p 8080:8080 ghcr.io/jdportugal/videoeditorapi:latest

🎯 Features

  • 🎀 AI Subtitles - Whisper-powered speech recognition
  • 🌟 Karaoke Effects - Word-by-word highlighting
  • βœ‚οΈ Video Editing - Split, join, trim videos
  • 🎡 Audio Mixing - Add background music
  • πŸ“Š Job Tracking - Real-time processing status

πŸ“‹ System Requirements

  • CPU: 2+ vCPUs (4+ recommended for faster processing)
  • RAM: 4GB minimum (8GB+ for large videos)
  • Storage: 25GB+ SSD
  • OS: Ubuntu 20.04+, Docker installed

πŸ› οΈ API Endpoints

Health Check

GET /health
curl http://localhost:8080/health

Response:

{"status": "healthy", "timestamp": "2024-01-01T12:00:00"}

Add Subtitles with Karaoke Effect

POST /add-subtitles
curl -X POST http://localhost:8080/add-subtitles \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://example.com/video.mp4",
    "settings": {
      "font-size": 120,
      "normal-color": "#FFF4E9"
    }
  }'

Parameters:

  • url (required): Video URL or Google Drive link
  • language (optional): Language code (default: "en")
  • settings (optional): Subtitle styling options

Styling Options:

{
  "font-size": 120,
  "font-family": "Luckiest Guy", 
  "normal-color": "#FFFFFF",
  "outline-width": 10,
  "position": "bottom-center"
}

Response:

{
  "job_id": "uuid-here",
  "status": "pending", 
  "message": "Subtitle processing started"
}

Split Video by Time

POST /split-video
curl -X POST http://localhost:8080/split-video \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://example.com/video.mp4",
    "start_time": "00:00:10,000",
    "end_time": "00:01:30,500"
  }'

Job Chaining - Split Previous Output:

curl -X POST http://localhost:8080/split-video \
  -H "Content-Type: application/json" \
  -d '{
    "job_id": "previous-job-uuid",
    "start_time": "00:00:05,000",
    "end_time": "00:00:15,000"
  }'

Parameters:

  • url OR job_id (required): Video URL or previous job ID to split
  • start_time (required): Start time for split
  • end_time (required): End time for split

Time Formats Supported:

  • "00:01:30,500" (HH:MM:SS,mmm)
  • "90.5" (seconds as string)
  • 90.5 (numeric seconds)

Join Multiple Videos

POST /join-videos
curl -X POST http://localhost:8080/join-videos \
  -H "Content-Type: application/json" \
  -d '{
    "urls": [
      "https://example.com/video1.mp4",
      "https://example.com/video2.mp4"
    ]
  }'

Add Background Music

POST /add-music
curl -X POST http://localhost:8080/add-music \
  -H "Content-Type: application/json" \
  -d '{
    "video_url": "https://example.com/video.mp4",
    "music_url": "https://example.com/music.mp3",
    "settings": {
      "volume": 0.3,
      "fade_in": 2,
      "fade_out": 3,
      "loop_music": true
    }
  }'

Music Settings:

  • volume: 0.0 to 1.0 (default: 0.5)
  • fade_in: Fade in duration in seconds
  • fade_out: Fade out duration in seconds
  • loop_music: Loop music to match video length

Check Job Status

GET /job-status/<job_id>
curl http://localhost:8080/job-status/your-job-id

Response:

{
  "job_id": "uuid-here",
  "status": "completed",
  "progress": 100,
  "video_download_url": "/download/uuid-here",
  "subtitle_download_url": "/download-subtitles/uuid-here"
}

Status Values:

  • pending - Job queued for processing
  • processing - Currently being processed
  • completed - Successfully completed
  • failed - Processing failed (check error field)

Admin Cleanup

POST /admin/cleanup
curl -X POST http://localhost:8080/admin/cleanup \
  -H "Content-Type: application/json"

Purpose: Comprehensive cleanup of all jobs and files (completed, failed, pending)

Removes:

  • All job files (jobs directory)
  • All temporary files (temp directory)
  • All uploaded files (uploads directory)
  • All static files (static directory)

Response:

{
  "status": "success",
  "message": "Comprehensive cleanup completed",
  "timestamp": "2025-11-15T11:59:04.888763",
  "cleanup_stats": {
    "jobs_removed": 10,
    "temp_files_removed": 18,
    "upload_files_removed": 1,
    "static_files_removed": 1,
    "total_size_freed": 322308966,
    "total_size_freed_formatted": "307.38 MB",
    "directories_cleaned": ["jobs", "temp", "uploads", "static"]
  }
}

⚠️ Warning: This operation is irreversible and removes ALL files regardless of status.


Download Processed Video

GET /download/<job_id>
curl http://localhost:8080/download/your-job-id -o result.mp4

Download Subtitle File

GET /download-subtitles/<job_id>  
curl http://localhost:8080/download-subtitles/your-job-id -o subtitles.srt

🎨 Subtitle Customization

Font Styles

  • font-family: "Luckiest Guy" (default), "Arial", "DejaVu-Sans-Bold"
  • font-size: 80-200 pixels (default: 120)
  • normal-color: Any hex color (default: "#FFFFFF")
  • outline-width: 0-20 pixels (default: 10)

Positioning

  • top-left, top-center, top-right
  • center-left, center-center, center-right
  • bottom-left, bottom-center, bottom-right

Karaoke Modes

  • karaoke (default): Word-by-word highlighting
  • off: Traditional sentence subtitles
  • popup: Individual word pop-ups
  • typewriter: Accumulating word display

πŸ“Š Usage Examples

Basic Subtitle Addition

curl -X POST http://localhost:8080/add-subtitles \
  -H "Content-Type: application/json" \
  -d '{"url": "https://example.com/video.mp4"}'

Custom Styling

curl -X POST http://localhost:8080/add-subtitles \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://example.com/video.mp4", 
    "settings": {
      "font-size": 140,
      "normal-color": "#FFD700",
      "outline-width": 8,
      "position": "top-center"
    }
  }'

Job Chaining Workflow

# 1. Add subtitles to original video
SUBTITLE_JOB=$(curl -s -X POST http://localhost:8080/add-subtitles \
  -H "Content-Type: application/json" \
  -d '{"url": "https://example.com/video.mp4"}' | jq -r '.job_id')

# 2. Wait for completion and get status
curl http://localhost:8080/job-status/$SUBTITLE_JOB

# 3. Split the subtitled video using job chaining
SPLIT_JOB=$(curl -s -X POST http://localhost:8080/split-video \
  -H "Content-Type: application/json" \
  -d "{\"job_id\": \"$SUBTITLE_JOB\", \"start_time\": \"00:00:10,000\", \"end_time\": \"00:00:30,000\"}" | jq -r '.job_id')

# 4. Download the final result
curl http://localhost:8080/download/$SPLIT_JOB -o final_video.mp4

Split & Process Workflow

# 1. Split video to extract segment
curl -X POST http://localhost:8080/split-video \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://example.com/long-video.mp4",
    "start_time": "00:02:00,000", 
    "end_time": "00:03:30,000"
  }'

# 2. Get job ID from response, check status
curl http://localhost:8080/job-status/JOB_ID

# 3. Download split video
curl http://localhost:8080/download/JOB_ID -o segment.mp4

# 4. Add subtitles to segment
curl -X POST http://localhost:8080/add-subtitles \
  -H "Content-Type: application/json" \
  -d '{"url": "https://yourdomain.com/segment.mp4"}'

πŸš€ Deployment Options

Digital Ocean (Recommended)

  1. Create droplet (4GB+ RAM, Ubuntu 20.04+)
  2. Run installer:
curl -fsSL https://raw.githubusercontent.com/jdportugal/VideoEditorAPI/main/install-ghcr.sh | sudo bash

Local Development

git clone https://github.com/jdportugal/VideoEditorAPI.git
cd VideoEditorAPI
docker-compose up -d

Custom Docker

docker run -d \
  --name videoeditor \
  -p 5000:5000 \
  -v ./temp:/app/temp \
  -v ./uploads:/app/uploads \
  ghcr.io/jdportugal/videoeditorapi:latest

βš™οΈ Configuration

Environment Variables

# Optional customization
FLASK_ENV=production
MAX_CONCURRENT_JOBS=4
VIDEO_MAX_DURATION=1800
WHISPER_MODEL=base
LOG_LEVEL=INFO

Volume Mounts

  • /app/temp - Temporary processing files
  • /app/uploads - User uploaded files
  • /app/jobs - Job status tracking
  • /app/logs - Application logs

πŸ”§ Troubleshooting

Check Service Status

# Docker Compose
docker-compose ps
docker-compose logs -f

# Direct Docker
docker ps
docker logs videoeditor

Common Issues

Port 8080 not accessible:

# Check firewall
sudo ufw allow 8080/tcp

# Check if service is running
curl http://localhost:8080/health

Out of disk space:

# Clean up temporary files
docker system prune -f
sudo rm -rf ./temp/*

Memory issues:

# Check resource usage
docker stats

# Increase droplet size or add swap

Job stuck in processing:

# Restart service
docker-compose restart

# Check logs for errors
docker-compose logs video-editor-api

πŸ“ˆ Performance

Processing Times (Approximate)

  • 1-minute video: 30-60 seconds
  • 5-minute video: 2-4 minutes
  • 10-minute video: 5-10 minutes

Optimization Tips

  1. Use CPU-optimized droplets for faster processing
  2. Keep videos under 500MB for best performance
  3. Ensure clear audio for better subtitle accuracy
  4. Use MP4 format for compatibility

πŸ”„ Updates & Maintenance

Auto-Updates (If using installer)

cd /opt/shortscreator
./update.sh

Manual Updates

docker-compose pull
docker-compose up -d

Health Monitoring

# Check API health
curl http://localhost:8080/health

# View recent logs
docker-compose logs --tail=50

# Monitor resources
docker stats

🌐 Integration Examples

Node.js

const axios = require('axios');

async function addSubtitles(videoUrl) {
  const response = await axios.post('http://localhost:8080/add-subtitles', {
    url: videoUrl,
    settings: {
      'font-size': 120,
      'normal-color': '#FFD700'
    }
  });
  
  return response.data.job_id;
}

async function checkJobStatus(jobId) {
  const response = await axios.get(`http://localhost:8080/job-status/${jobId}`);
  return response.data;
}

Python

import requests
import time

def add_subtitles(video_url):
    response = requests.post('http://localhost:8080/add-subtitles', json={
        'url': video_url,
        'settings': {
            'font-size': 120,
            'normal-color': '#FFD700'
        }
    })
    return response.json()['job_id']

def wait_for_completion(job_id):
    while True:
        response = requests.get(f'http://localhost:8080/job-status/{job_id}')
        status = response.json()
        
        if status['status'] == 'completed':
            return status
        elif status['status'] == 'failed':
            raise Exception(f"Job failed: {status.get('error')}")
        
        time.sleep(5)

cURL Scripts

#!/bin/bash
# process_video.sh

VIDEO_URL="$1"
API_URL="http://localhost:8080"

# Submit job
JOB_ID=$(curl -s -X POST "$API_URL/add-subtitles" \
  -H "Content-Type: application/json" \
  -d "{\"url\": \"$VIDEO_URL\"}" | jq -r '.job_id')

echo "Job ID: $JOB_ID"

# Wait for completion
while true; do
  STATUS=$(curl -s "$API_URL/job-status/$JOB_ID" | jq -r '.status')
  echo "Status: $STATUS"
  
  if [ "$STATUS" = "completed" ]; then
    echo "Downloading result..."
    curl -o "result.mp4" "$API_URL/download/$JOB_ID"
    curl -o "subtitles.srt" "$API_URL/download-subtitles/$JOB_ID" 
    break
  elif [ "$STATUS" = "failed" ]; then
    echo "Job failed!"
    exit 1
  fi
  
  sleep 5
done

πŸ“ž Support

πŸ“„ License

MIT License - Feel free to use in personal and commercial projects.


⭐ Star this repository if it helped you!

Built with Python, Flask, Whisper AI, and MoviePy.