Spaces:
Sleeping
Sleeping
Delete README.md
Browse files
README.md
DELETED
|
@@ -1,280 +0,0 @@
|
|
| 1 |
-
---
|
| 2 |
-
title: Ffmpeg
|
| 3 |
-
emoji: 👀
|
| 4 |
-
colorFrom: green
|
| 5 |
-
colorTo: yellow
|
| 6 |
-
sdk: docker
|
| 7 |
-
pinned: false
|
| 8 |
-
license: mit
|
| 9 |
-
---
|
| 10 |
-
|
| 11 |
-
# Basyx FFmpeg Automation Hub
|
| 12 |
-
|
| 13 |
-
FastAPI + Gradio app for common FFmpeg media tasks. It can run directly in
|
| 14 |
-
Docker/Hugging Face Spaces and exposes both a browser UI and HTTP API.
|
| 15 |
-
|
| 16 |
-
## Features
|
| 17 |
-
|
| 18 |
-
- Task-specific Gradio controls for video, audio, subtitle, image, and social presets.
|
| 19 |
-
- File and URL inputs, including `yt-dlp` downloads.
|
| 20 |
-
- Input validation with `python-magic`, upload size limits, and temp-file cleanup.
|
| 21 |
-
- Synchronous execution at `/execute/{task_id}`.
|
| 22 |
-
- Background jobs at `/jobs/{task_id}` with `/status/{job_id}` and `/download/{job_id}`.
|
| 23 |
-
- Recent output history at `/history` with per-item download URLs.
|
| 24 |
-
- Configurable FFmpeg options: CRF, preset, resolution, audio bitrate, trim times,
|
| 25 |
-
aspect ratio, GIF settings, watermark settings, speed, frame rate, and text styling.
|
| 26 |
-
- Persistent SQLite job/history state.
|
| 27 |
-
- FFmpeg execution timeout, production readiness checks, and URL download limits.
|
| 28 |
-
- Faceless short-video automation for quote cards, story slides, image narration,
|
| 29 |
-
b-roll narration, and vertical montage generation.
|
| 30 |
-
- TikTok/Reels mini-series packaging with numbered episodes, recap cards, and
|
| 31 |
-
ZIP exports containing publish-order manifests.
|
| 32 |
-
- Built-in MCP server exposing task discovery and media processing as AI tools.
|
| 33 |
-
|
| 34 |
-
## Tasks
|
| 35 |
-
|
| 36 |
-
Call `GET /tasks` to list the current task registry with file requirements.
|
| 37 |
-
|
| 38 |
-
The registry currently contains 90 allowlisted tasks. Major groups include:
|
| 39 |
-
|
| 40 |
-
- Timeline editing: `trim`, `split_video`, `remove_section`, `concat`,
|
| 41 |
-
`reverse_video`, `freeze_frame`, `boomerang`, `loop_video`, and `speed`.
|
| 42 |
-
- Audio post: `audio_trim`, `audio_merge`, `audio_mix`, `audio_normalize`,
|
| 43 |
-
`audio_fade`, `audio_delay`, `audio_speed`, `audio_channels`, and `audio_denoise`.
|
| 44 |
-
- Images/slideshows: `image_process`, `image_watermark`, `slideshow`,
|
| 45 |
-
`crossfade_slideshow`, `ken_burns_slideshow`, and `narrated_slideshow`.
|
| 46 |
-
- Subtitles: `add_subtitles`, `burn_lyrics`, `soft_subtitles`,
|
| 47 |
-
`remove_subtitles`, and SRT/ASS/VTT conversion tasks.
|
| 48 |
-
- Series production: `episode_assembly`, `create_trailer`, `create_teaser`,
|
| 49 |
-
faceless content tasks, and mini-series packaging tasks.
|
| 50 |
-
- Effects/rendering: `video_transition`, `video_animation`, `video_effect`,
|
| 51 |
-
`render_image_sequence`, `render_alpha_webm`, and `video_enhance`.
|
| 52 |
-
- Delivery: `social_format`, `encode_video`, `encode_webm`, MOV/MKV/AVI
|
| 53 |
-
conversion, AAC/MP3/FLAC/WAV/OGG/Opus/AC3 audio, and `streaming_compress`.
|
| 54 |
-
|
| 55 |
-
See the [capability matrix](n8n/FEATURE_MATRIX.md) for the full mapping and
|
| 56 |
-
n8n parameters for every multimedia category.
|
| 57 |
-
|
| 58 |
-
## MCP Server
|
| 59 |
-
|
| 60 |
-
MCP is enabled by default. The mounted Gradio application serves Streamable HTTP
|
| 61 |
-
at:
|
| 62 |
-
|
| 63 |
-
```text
|
| 64 |
-
http://localhost:7860/gradio_api/mcp/
|
| 65 |
-
```
|
| 66 |
-
|
| 67 |
-
Inspect its generated tool schemas at
|
| 68 |
-
`http://localhost:7860/gradio_api/mcp/schema`. It exposes:
|
| 69 |
-
|
| 70 |
-
- `list_ffmpeg_tasks`: returns all task IDs and file requirements.
|
| 71 |
-
- `run_ffmpeg_task`: runs a task with files, a media URL, standard controls, and
|
| 72 |
-
an allowlisted advanced-options JSON object.
|
| 73 |
-
- one fixed tool for each of the 90 task IDs, such as `compress`, `trim`,
|
| 74 |
-
`video_effect`, and `audio_mix`. These tools accept `files`, `url`, and an
|
| 75 |
-
`options` JSON object without requiring a separate task selector.
|
| 76 |
-
|
| 77 |
-
Every MCP tool description includes a fenced JSON payload example. The fixed
|
| 78 |
-
task descriptions also document file-count requirements, accepted media types,
|
| 79 |
-
output extension, and upload order.
|
| 80 |
-
|
| 81 |
-
Set `GRADIO_MCP_SERVER=False` to disable MCP. When `API_AUTH_TOKEN` is set, MCP
|
| 82 |
-
clients must send the same bearer token or `X-API-Key` used by the REST API.
|
| 83 |
-
See [MCP.md](MCP.md) for connection and usage examples.
|
| 84 |
-
|
| 85 |
-
## API Examples
|
| 86 |
-
|
| 87 |
-
Run a task immediately and download the returned file:
|
| 88 |
-
|
| 89 |
-
```bash
|
| 90 |
-
curl -X POST \
|
| 91 |
-
-F "files=@input.mp4" \
|
| 92 |
-
-F "resolution=720p" \
|
| 93 |
-
-F "crf=28" \
|
| 94 |
-
http://localhost:7860/execute/compress \
|
| 95 |
-
--output compressed.mp4
|
| 96 |
-
```
|
| 97 |
-
|
| 98 |
-
Run a background job:
|
| 99 |
-
|
| 100 |
-
```bash
|
| 101 |
-
curl -X POST \
|
| 102 |
-
-F "files=@input.mp4" \
|
| 103 |
-
-F "text=Launch caption" \
|
| 104 |
-
-F "callback_url=https://example.com/ffmpeg-callback" \
|
| 105 |
-
http://localhost:7860/jobs/text_overlay
|
| 106 |
-
```
|
| 107 |
-
|
| 108 |
-
Check the job:
|
| 109 |
-
|
| 110 |
-
```bash
|
| 111 |
-
curl http://localhost:7860/status/<job_id>
|
| 112 |
-
```
|
| 113 |
-
|
| 114 |
-
Download a completed background job:
|
| 115 |
-
|
| 116 |
-
```bash
|
| 117 |
-
curl http://localhost:7860/download/<job_id> --output result.mp4
|
| 118 |
-
```
|
| 119 |
-
|
| 120 |
-
Use a URL input:
|
| 121 |
-
|
| 122 |
-
```bash
|
| 123 |
-
curl -X POST \
|
| 124 |
-
-F "url=https://example.com/video.mp4" \
|
| 125 |
-
http://localhost:7860/execute/thumbnail \
|
| 126 |
-
--output thumbnail.jpg
|
| 127 |
-
```
|
| 128 |
-
|
| 129 |
-
The standard multipart endpoints and browser UI also accept advanced task
|
| 130 |
-
options as an allowlisted JSON object:
|
| 131 |
-
|
| 132 |
-
```bash
|
| 133 |
-
curl -X POST \
|
| 134 |
-
-F "files=@scene.mp4" \
|
| 135 |
-
-F 'options_json={"effect":"vhs"}' \
|
| 136 |
-
http://localhost:7860/jobs/video_effect
|
| 137 |
-
```
|
| 138 |
-
|
| 139 |
-
## n8n Inputs
|
| 140 |
-
|
| 141 |
-
Use `POST /n8n/execute/{task_id}` for immediate file output or
|
| 142 |
-
`POST /n8n/jobs/{task_id}` for background jobs. These endpoints accept common
|
| 143 |
-
n8n HTTP Request node payload styles:
|
| 144 |
-
|
| 145 |
-
- multipart form-data with any binary field name
|
| 146 |
-
- form-data URL fields: `url`, `urls`, `file_url`, `source_url`, `download_url`
|
| 147 |
-
- JSON base64 files in `files`, `binary`, or `data`
|
| 148 |
-
- JSON URL lists
|
| 149 |
-
- raw binary body for single-file tasks, with optional `X-Filename` header
|
| 150 |
-
|
| 151 |
-
For a ready-to-run n8n + API stack and node-by-node setup, see
|
| 152 |
-
[`n8n/README.md`](n8n/README.md):
|
| 153 |
-
|
| 154 |
-
```bash
|
| 155 |
-
cp .env.example .env
|
| 156 |
-
export N8N_ENCRYPTION_KEY="$(openssl rand -hex 32)"
|
| 157 |
-
docker compose -f compose.n8n.yml up --build
|
| 158 |
-
```
|
| 159 |
-
|
| 160 |
-
`GET /n8n` returns a machine-readable integration manifest. Background job
|
| 161 |
-
responses contain absolute `status_url` and, when complete, `download_url`
|
| 162 |
-
values. Set `PUBLIC_BASE_URL` in reverse-proxy or container deployments so those
|
| 163 |
-
URLs are reachable from n8n.
|
| 164 |
-
|
| 165 |
-
Send an `Idempotency-Key` header when creating a job. Repeated requests with the
|
| 166 |
-
same task and key return the original job for 24 hours rather than running
|
| 167 |
-
FFmpeg twice:
|
| 168 |
-
|
| 169 |
-
```bash
|
| 170 |
-
curl -X POST \
|
| 171 |
-
-H "Idempotency-Key: n8n-execution-123-item-0" \
|
| 172 |
-
-H "Content-Type: application/json" \
|
| 173 |
-
-d '{"url":"https://example.com/video.mp4","crf":"25"}' \
|
| 174 |
-
http://localhost:7860/n8n/jobs/compress
|
| 175 |
-
```
|
| 176 |
-
|
| 177 |
-
Multipart binary from n8n:
|
| 178 |
-
|
| 179 |
-
```bash
|
| 180 |
-
curl -X POST \
|
| 181 |
-
-F "myBinary=@input.mp4" \
|
| 182 |
-
-F "text=Episode 1" \
|
| 183 |
-
http://localhost:7860/n8n/execute/series_episode_badge \
|
| 184 |
-
--output episode.mp4
|
| 185 |
-
```
|
| 186 |
-
|
| 187 |
-
JSON base64:
|
| 188 |
-
|
| 189 |
-
```json
|
| 190 |
-
{
|
| 191 |
-
"text": "Episode title",
|
| 192 |
-
"files": [
|
| 193 |
-
{
|
| 194 |
-
"fileName": "input.mp4",
|
| 195 |
-
"mimeType": "video/mp4",
|
| 196 |
-
"data": "<base64>"
|
| 197 |
-
}
|
| 198 |
-
]
|
| 199 |
-
}
|
| 200 |
-
```
|
| 201 |
-
|
| 202 |
-
JSON URLs:
|
| 203 |
-
|
| 204 |
-
```json
|
| 205 |
-
{
|
| 206 |
-
"urls": ["https://example.com/input.mp4"],
|
| 207 |
-
"text": "Mini series title",
|
| 208 |
-
"duration": "60",
|
| 209 |
-
"callback_url": "https://example.com/ffmpeg-callback"
|
| 210 |
-
}
|
| 211 |
-
```
|
| 212 |
-
|
| 213 |
-
Template preset:
|
| 214 |
-
|
| 215 |
-
```json
|
| 216 |
-
{
|
| 217 |
-
"template_id": "faceless_motivation",
|
| 218 |
-
"text": "Small steps compound when you stay consistent."
|
| 219 |
-
}
|
| 220 |
-
```
|
| 221 |
-
|
| 222 |
-
Raw binary:
|
| 223 |
-
|
| 224 |
-
```bash
|
| 225 |
-
curl -X POST \
|
| 226 |
-
-H "Content-Type: application/octet-stream" \
|
| 227 |
-
-H "X-Filename: input.mp4" \
|
| 228 |
-
--data-binary @input.mp4 \
|
| 229 |
-
http://localhost:7860/n8n/execute/reels_blur_fit \
|
| 230 |
-
--output output.mp4
|
| 231 |
-
```
|
| 232 |
-
|
| 233 |
-
## Configuration
|
| 234 |
-
|
| 235 |
-
Environment variables:
|
| 236 |
-
|
| 237 |
-
- `TEMP_DIR`: working directory for uploads and outputs. Default: `temp`.
|
| 238 |
-
- `STATE_DB_PATH`: SQLite path for job/history state. Default: `TEMP_DIR/state.sqlite3`.
|
| 239 |
-
- `FONT_PATH`: font used by FFmpeg `drawtext`. Default:
|
| 240 |
-
`/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf`.
|
| 241 |
-
- `MAX_UPLOAD_MB`: max upload size per file. Default: `500`.
|
| 242 |
-
- `MAX_URL_DOWNLOAD_MB`: max URL download size. Default: same as `MAX_UPLOAD_MB`.
|
| 243 |
-
- `ALLOW_URL_INPUTS`: enable/disable URL downloads. Default: `true`.
|
| 244 |
-
- `FFMPEG_TIMEOUT_SECONDS`: max runtime for an FFmpeg command. Default: `1800`.
|
| 245 |
-
- `CALLBACK_TIMEOUT_SECONDS`: callback POST timeout. Default: `15`.
|
| 246 |
-
- `CALLBACK_RETRIES`: callback attempts after a completed/failed job. Default: `3`.
|
| 247 |
-
- `N8N_CALLBACK_TOKEN`: optional bearer token sent to callback webhooks.
|
| 248 |
-
- `PUBLIC_BASE_URL`: externally reachable API base used in job/callback URLs.
|
| 249 |
-
- `IDEMPOTENCY_TTL_SECONDS`: duplicate n8n job suppression window. Default: `86400`.
|
| 250 |
-
- `FILE_TTL_SECONDS`: temp file lifetime. Default: `3600`.
|
| 251 |
-
- `HISTORY_LIMIT`: number of recent output records to keep. Default: `50`.
|
| 252 |
-
- `API_AUTH_TOKEN`: optional bearer/API-key token for all endpoints except health checks.
|
| 253 |
-
- `GRADIO_MCP_SERVER`: enable the Gradio MCP server. Default: `True`.
|
| 254 |
-
- `MAX_MEDIA_DURATION_SECONDS`: max input audio/video duration. Default: `7200`.
|
| 255 |
-
- `MAX_OUTPUT_MB`: max generated output size. Default: `1000`.
|
| 256 |
-
- `MAX_BATCH_JOBS`: max files accepted by unlimited multi-file tasks. Default: `20`.
|
| 257 |
-
- `WHISPER_MODEL`, `WHISPER_DEVICE`, `WHISPER_COMPUTE_TYPE`: optional
|
| 258 |
-
faster-whisper settings for deployments that add transcription support.
|
| 259 |
-
|
| 260 |
-
## Production Checks
|
| 261 |
-
|
| 262 |
-
- `GET /healthz`: process health and dependency check details.
|
| 263 |
-
- `GET /readyz`: returns `503` if required runtime dependencies are missing.
|
| 264 |
-
|
| 265 |
-
Required runtime dependencies:
|
| 266 |
-
|
| 267 |
-
- `ffmpeg`
|
| 268 |
-
- `ffprobe`
|
| 269 |
-
- writable `TEMP_DIR`
|
| 270 |
-
- writable SQLite state database
|
| 271 |
-
- readable `FONT_PATH`
|
| 272 |
-
|
| 273 |
-
## Local Run
|
| 274 |
-
|
| 275 |
-
```bash
|
| 276 |
-
pip install -r requirements.txt
|
| 277 |
-
python app.py
|
| 278 |
-
```
|
| 279 |
-
|
| 280 |
-
The app listens on `http://localhost:7860`.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|