A FastAPI application for merging videos stored in MinIO S3 buckets and uploading videos to YouTube.
- Download videos from MinIO S3 buckets via URLs
- Merge multiple MP4 videos into a single video file
- Upload the merged video to a target S3 bucket
- NEW: Upload videos directly to YouTube via YouTube Data API v3
- Support for both MinIO and AWS S3
- Automatic cleanup of temporary files
- Comprehensive logging
- Request validation with Pydantic
- Health check endpoint
- Optional callback URLs for async processing
- Secure API Key Authentication
This API uses API key authentication to secure all endpoints (except health check). All requests must include a valid API key in the X-API-Key header.
- Using the generator script:
python generate_api_key.py- Using the API endpoint (one-time setup):
curl -X POST http://localhost:8000/generate-api-key- Set the API key as environment variable:
export API_KEY="your-generated-key-here"- Or add to .env file:
API_KEY=your-generated-key-hereInclude the API key in all requests:
curl -X POST http://localhost:8000/merge-videos \
-H "Content-Type: application/json" \
-H "X-API-Key: your-generated-key-here" \
-d '{"video_urls": ["http://..."], "output_filename": "merged.mp4"}'- Store API keys securely (environment variables, key management systems)
- Do not commit API keys to version control
- Regenerate API keys periodically
- Use HTTPS in production
- Consider implementing rate limiting for additional security
- Python 3.8+
- MinIO server or AWS S3 access
- FFmpeg (for video processing)
- Clone the repository:
git clone <repository-url>
cd vi-upper- Create and activate a virtual environment:
python -m venv .venv
source .venv/bin/activate # On Windows: .venv\Scripts\activate- Install dependencies:
pip install -r requirements.txt-
Install FFmpeg:
- macOS:
brew install ffmpeg - Ubuntu/Debian:
sudo apt update && sudo apt install ffmpeg - Windows: Download from https://ffmpeg.org/download.html
- macOS:
-
Create environment configuration:
cp .env.example .env- Edit
.envfile with your MinIO/S3 configuration:
# MinIO/S3 Configuration
MINIO_ENDPOINT=localhost:9000
MINIO_ACCESS_KEY=minioadmin
MINIO_SECRET_KEY=minioadmin
MINIO_SECURE=false
# Bucket Configuration
SOURCE_BUCKET=source-videos
TARGET_BUCKET=merged-videos
# Domain Configuration (optional)
SUBDOMAIN=your-subdomain
DOMAIN_NAME=your-domain.com
# Optional: AWS S3 Configuration (if using AWS instead of MinIO)
# AWS_ACCESS_KEY_ID=your_aws_access_key
# AWS_SECRET_ACCESS_KEY=your_aws_secret_key
# AWS_REGION=us-east-1
# Application Configuration
TEMP_DIR=./temp
LOG_LEVEL=INFO
# YouTube API Configuration
YOUTUBE_CLIENT_SECRETS_FILE=client_secrets.json
YOUTUBE_TOKEN_FILE=token.json
# API Key for Video Merger API
# Generate using: python generate_api_key.py
API_KEY=your-generated-api-key-here- Set up YouTube Data API v3 (for YouTube upload feature):
- Go to Google Cloud Console
- Create a new project or select existing one
- Enable YouTube Data API v3
- Create OAuth 2.0 Client ID credentials
- Download the credentials as
client_secrets.jsonin project root - The first API call will prompt for OAuth authorization
| Variable | Description | Default |
|---|---|---|
API_KEY |
API key for authentication | Required |
MINIO_ENDPOINT |
MinIO server endpoint | localhost:9000 |
MINIO_ACCESS_KEY |
MinIO access key | minioadmin |
MINIO_SECRET_KEY |
MinIO secret key | minioadmin |
MINIO_SECURE |
Use HTTPS for MinIO | false |
SOURCE_BUCKET |
Source bucket name | source-videos |
TARGET_BUCKET |
Target bucket name | merged-videos |
SUBDOMAIN |
Subdomain for domain configuration (optional) | - |
DOMAIN_NAME |
Domain name for domain configuration (optional) | - |
AWS_ACCESS_KEY_ID |
AWS access key (optional) | - |
AWS_SECRET_ACCESS_KEY |
AWS secret key (optional) | - |
AWS_REGION |
AWS region (optional) | us-east-1 |
TEMP_DIR |
Temporary files directory | ./temp |
LOG_LEVEL |
Logging level | INFO |
YOUTUBE_CLIENT_SECRETS_FILE |
Path to YouTube OAuth credentials file | client_secrets.json |
YOUTUBE_TOKEN_FILE |
Path to YouTube token storage file | token.json |
uvicorn main:app --host 0.0.0.0 --port 8000 --reloadThe API will be available at http://localhost:8000
Once the server is running, you can access:
- Interactive API docs:
http://localhost:8000/docs - ReDoc documentation:
http://localhost:8000/redoc
Merge multiple videos from URLs into a single MP4 file.
Request Body:
{
"video_urls": [
"http://localhost:9000/source-videos/video1.mp4",
"http://localhost:9000/source-videos/video2.mp4",
"http://localhost:9000/source-videos/video3.mp4"
],
"output_filename": "my_merged_video.mp4"
}Response:
{
"merged_video_url": "http://localhost:9000/merged-videos/my_merged_video.mp4",
"filename": "my_merged_video.mp4",
"processing_time_seconds": 15.45
}Upload a video from MinIO to YouTube.
Request Body:
{
"video_url": "http://localhost:9000/source-videos/my-video.mp4",
"title": "My YouTube Video Title",
"description": "A brief description of the video",
"tags": ["tag1", "tag2", "tag3"],
"categoryId": "22",
"privacyStatus": "public",
"callback_url": "https://my-webhook.com/youtube-callback"
}Response:
{
"success": true,
"video_id": "dQw4w9WgXcQ",
"video_url": "https://youtube.com/watch?v=dQw4w9WgXcQ",
"status": "uploaded",
"message": "Video uploaded successfully to YouTube",
"error": null
}Health check endpoint.
Response:
{
"status": "healthy",
"timestamp": "2024-01-15T10:30:00.000000"
}Video Merge:
curl -X POST "http://localhost:8000/merge-videos" \
-H "Content-Type: application/json" \
-H "X-API-Key: your-api-key-here" \
-d '{
"video_urls": [
"http://localhost:9000/source-videos/video1.mp4",
"http://localhost:9000/source-videos/video2.mp4"
],
"output_filename": "merged_result.mp4"
}'YouTube Upload:
curl -X POST "http://localhost:8000/upload/youtube" \
-H "Content-Type: application/json" \
-H "X-API-Key: your-api-key-here" \
-d '{
"video_url": "http://localhost:9000/source-videos/my-video.mp4",
"title": "My YouTube Video",
"description": "Uploaded via API",
"tags": ["api", "automation"],
"privacyStatus": "unlisted"
}'Video Merge:
import requests
url = "http://localhost:8000/merge-videos"
headers = {
"Content-Type": "application/json",
"X-API-Key": "your-api-key-here"
}
payload = {
"video_urls": [
"http://localhost:9000/source-videos/video1.mp4",
"http://localhost:9000/source-videos/video2.mp4"
],
"output_filename": "my_merged_video.mp4"
}
response = requests.post(url, json=payload, headers=headers)
result = response.json()
print(f"Merged video URL: {result['merged_video_url']}")YouTube Upload:
import requests
url = "http://localhost:8000/upload/youtube"
headers = {
"Content-Type": "application/json",
"X-API-Key": "your-api-key-here"
}
payload = {
"video_url": "http://localhost:9000/source-videos/my-video.mp4",
"title": "My YouTube Video",
"description": "Uploaded via API",
"tags": ["api", "automation"],
"privacyStatus": "unlisted"
}
response = requests.post(url, json=payload, headers=headers)
result = response.json()
if result['success']:
print(f"YouTube URL: {result['video_url']}")The project includes example client scripts:
python example_client.py- Interactive demo for video mergingpython youtube_example_client.py- Interactive demo for YouTube uploads
# Run with auto-reload
uvicorn main:app --reload --host 0.0.0.0 --port 8000Create a Dockerfile:
FROM python:3.11-slim
# Install FFmpeg
RUN apt-get update && apt-get install -y ffmpeg && rm -rf /var/lib/apt/lists/*
WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY . .
EXPOSE 8000
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]Build and run:
docker build -t video-merger-api .
docker run -p 8000:8000 --env-file .env video-merger-api- FFmpeg not found: Make sure FFmpeg is installed and available in PATH
- MinIO connection error: Verify MinIO server is running and credentials are correct
- Video format error: Only MP4 files are supported
- Memory issues: Large videos may require more system memory
The application logs detailed information about the video processing pipeline. Check the console output for debugging information.
- Fork the repository
- Create a feature branch
- Make your changes
- Add tests if applicable
- Submit a pull request
This project is licensed under the MIT License.