A REST API that wraps FFmpeg for media processing operations. Built with Node.js, Hono, and BullMQ for reliable async job processing.
Convert and process media files through simple HTTP endpoints:
- Video: Convert any video to MP4, extract audio tracks (mono/stereo), extract frames at custom FPS (compressed as ZIP/GZIP)
- Audio: Convert any audio to MP3 or WAV
- Image: Convert any image format to JPG
- Media Info: Probe any media file for metadata and stream information
The API supports two storage modes to fit different deployment scenarios:
Files are processed and returned directly in the HTTP response. Simple and straightforward for immediate consumption.
Cost Consideration: On Railway, stateless mode is cheaper than running S3 Mode unless you have free egress at your S3-storage provider (like Cloudflare R2). Railway charges $0.05 per GB egress vs S3's typical $0.09 per GB, but you trade off file persistence - processed files aren't stored for later retrieval.
Processed files are uploaded to S3-compatible storage and a URL is returned. This mode significantly reduces egress bandwidth costs since users download the processed files directly from S3 rather than through your API server. Ideal for production deployments where bandwidth costs matter.
Why Cloudflare R2? R2 is S3-compatible and offers no egress fees, which dramatically lowers costs when serving processed media from your bucket via Cloudflare's global network. While any S3-compatible storage works, R2 is the only major provider with zero egress charges—making it the optimal choice for media delivery.
Configure S3 mode by setting STORAGE_MODE=s3
and providing S3 credentials in your environment variables.
S3 Mode includes intelligent content-based deduplication to optimize storage costs and upload performance:
- SHA-256 File Hashing: Each processed file is hashed using SHA-256 before upload
- Redis Cache: File hashes are mapped to S3 URLs with a 90-day TTL (configurable)
- Automatic Deduplication: Identical files are only uploaded once - subsequent requests return the cached S3 URL
- Zero-Cost Cache Hits: When a duplicate file is processed, the upload to S3 is skipped entirely
- Graceful Degradation: Cache failures don't block uploads - the system falls back to normal upload behavior
Configuration:
S3_DEDUP_ENABLED=1 # Enable/disable deduplication (default: true)
S3_DEDUP_TTL_DAYS=90 # Cache TTL in days (default: 90)
This feature dramatically reduces S3 storage costs and upload bandwidth for workloads with duplicate media content, while improving response times through cache hits.
This API is built with documentation-first approach using Hono Zod OpenAPI and Scalar:
- Type-Safe Schemas: All endpoints use Zod schemas for validation, ensuring type safety and automatic OpenAPI spec generation
- Interactive API Reference: Beautiful, interactive documentation powered by Scalar at
/reference
- OpenAPI 3.1 Spec: Complete machine-readable API specification at
/doc
- LLM-Friendly Docs: Markdown documentation optimized for AI assistants at
/llms.txt
(following llmstxt.org standard)
Every endpoint is fully documented with request/response schemas, validation rules, and example payloads. No manual documentation maintenance required.
- Node.js 20+ and npm
- FFmpeg installed and available in PATH
- Redis server running
-
Clone the repository
git clone https://github.com/crisog/ffmpeg-rest cd ffmpeg-rest
-
Install dependencies
npm install
-
Start Redis (using Docker)
docker-compose up -d
-
Configure environment
cp .env.example .env # Edit .env with your settings
-
Run the API
Development mode (with auto-reload):
# Terminal 1 - Start the API server npm run dev # Terminal 2 - Start the worker npm run dev:worker
Production mode:
npm run build npm start