---
name: Rendi
description: Use Rendi when you need to run FFmpeg commands at scale without managing servers. Reach for this skill when building video processing workflows, automating media transformations (transcoding, compression, trimming, thumbnail generation), integrating FFmpeg into applications, or orchestrating multi-step video pipelines through APIs.
metadata:
    mintlify-proj: rendi
    version: "1.0"
---

# Rendi Skill

## Product summary

Rendi is a cloud FFmpeg API that runs video processing commands without installation or server management. Submit FFmpeg commands via REST API, Rendi processes them on auto-scaling infrastructure, and returns results. Key endpoints: `POST /v1/run-ffmpeg-command` (single command), `POST /v1/run-chained-ffmpeg-commands` (multi-step pipelines), `GET /v1/commands/{command_id}` (poll status), `POST /v1/files/store-file` (analyze and store media). Authenticate with `X-API-KEY` header. Primary docs: https://rendi.dev/docs

## When to use

Use Rendi when:
- Building video processing features into applications (thumbnails, compression, format conversion)
- Automating media workflows that require FFmpeg (trimming, merging, extracting audio, burning subtitles)
- Running FFmpeg at scale without managing servers or containers
- Chaining multiple FFmpeg operations in a single request (faster than separate calls)
- Integrating video processing into no-code platforms (Make, n8n, Zapier)
- Analyzing media files with FFprobe metadata extraction
- Processing videos longer than 45 minutes or with long-running operations

Do NOT use Rendi for: real-time video streaming, interactive editing, or operations that require local file system access.

## Quick reference

### Core API endpoints

| Endpoint | Method | Purpose |
|----------|--------|---------|
| `/v1/run-ffmpeg-command` | POST | Submit single FFmpeg command |
| `/v1/run-chained-ffmpeg-commands` | POST | Submit multiple commands in sequence |
| `/v1/commands/{command_id}` | GET | Poll command status and results |
| `/v1/files/store-file` | POST | Analyze and store a media file |
| `/v1/files/{file_id}` | GET | Retrieve file metadata and storage URL |
| `/v1/files` | GET | List all stored files |
| `/v1/commands` | GET | List all submitted commands |

### Request structure

```json
{
  "ffmpeg_command": "-i {{in_1}} [filters] {{out_1}}",
  "input_files": {
    "in_1": "https://example.com/video.mp4"
  },
  "output_files": {
    "out_1": "output.mp4"
  },
  "vcpu_count": 8,
  "max_command_run_seconds": 300,
  "metadata": {"key": "value"}
}
```

### File aliasing rules

- Input keys must start with `in_` (e.g., `in_1`, `in_video`)
- Output keys must start with `out_` (e.g., `out_1`, `out_gif`)
- Reference in command as `{{in_1}}` and `{{out_1}}`
- Input values: any publicly accessible HTTP/HTTPS URL
- Output values: filename only (no paths), alphanumeric + underscore + period

### Command status values

| Status | Meaning |
|--------|---------|
| `QUEUED` | Waiting to process |
| `PROCESSING` | Currently running |
| `SUCCESS` | Completed successfully |
| `FAILED` | Error occurred (check `error_status` field) |

### Common error statuses

| Error | Cause | Fix |
|-------|-------|-----|
| `UNREACHABLE_INPUT_FILE` | Input URL not accessible | Verify URL is public and returns 200 |
| `FFMPEG_COMMAND_FAILED` | FFmpeg syntax error or filter issue | Test command locally, check filter syntax |
| `TIMEOUT` | Exceeded `max_command_run_seconds` | Increase timeout or optimize command |
| `INVALID_OUTPUT_FILENAME` | Output name violates rules | Use only alphanumeric, underscore, period |

## Decision guidance

### When to use polling vs webhooks

| Scenario | Use | Why |
|----------|-----|-----|
| Expected runtime < 30 seconds | Polling (`GET /v1/commands/{command_id}`) | Low latency, simple implementation |
| Expected runtime > 30 seconds | Webhooks | Avoid polling overhead, get notified on completion |
| Batch processing many jobs | Webhooks | Scales better than polling loops |
| Real-time feedback needed | Polling | Immediate status updates |

### When to use single vs chained commands

| Scenario | Use | Why |
|----------|-----|-----|
| One operation (trim, compress, transcode) | Single command | Simpler request, fewer round-trips |
| Multi-step pipeline (extract → process → encode) | Chained commands | Reuse intermediate outputs, lower latency, shared quota |
| Output of step 1 feeds step 2 | Chained commands | Avoid storing intermediate files |
| Independent operations | Single commands in parallel | Each uses full vCPU allocation |

### When to use dynamic files

| Scenario | Use | Why |
|----------|-----|-----|
| Image sequence input (frame_001.png, etc.) | `input_compressed_folder` with ZIP | FFmpeg reads numbered patterns |
| Multiple auxiliary files (fonts, subtitles, watermarks) | `input_compressed_folder` with ZIP | Bundle all dependencies in one request |
| Output is many files (frame extraction, HLS segments) | `output_files: "OUTPUT_FOLDER"` | Automatically compressed and stored |
| Single output file | Regular `output_files` dict | Simpler, no compression overhead |

## Workflow

### Typical task: submit and retrieve a video processing job

1. **Prepare the FFmpeg command**
   - Write and test locally: `ffmpeg -i input.mp4 [filters] output.mp4`
   - Replace input path with `{{in_1}}`, output with `{{out_1}}`
   - Escape special characters (quotes, backslashes) for JSON

2. **Construct the request**
   - Set `input_files` with public URLs (Google Drive share links, S3, CDN all work)
   - Set `output_files` with desired filenames
   - Set `vcpu_count` (1–8 depending on plan)
   - Set `max_command_run_seconds` to match expected runtime (default 300)
   - Add `metadata` for tracking if needed

3. **Submit the command**
   - POST to `/v1/run-ffmpeg-command` with `X-API-KEY` header
   - Capture `command_id` from response

4. **Check status**
   - For short jobs: poll `GET /v1/commands/{command_id}` every 1–2 seconds
   - For long jobs: set webhook URL in dashboard, wait for callback
   - Response includes `status`, `output_files` (with `storage_url` when ready), and error details if failed

5. **Retrieve results**
   - When status is `SUCCESS`, use `storage_url` from response
   - Files stored indefinitely; delete with `DELETE /v1/files/{file_id}` if needed
   - Metadata available via `GET /v1/files/{file_id}` even after deletion

### Multi-step pipeline: chained commands

1. **Design the pipeline**
   - Step 1: extract frames → `out_1` (intermediate)
   - Step 2: process frames → `out_2` (intermediate)
   - Step 3: encode to video → `out_3` (final)

2. **Build chained request**
   - `ffmpeg_commands` array with each step
   - `input_files` for step 1 only
   - `output_files` includes all outputs (intermediates and final)
   - Later commands reference earlier outputs: `{{out_1}}` as input to step 2

3. **Submit and monitor**
   - POST to `/v1/run-chained-ffmpeg-commands`
   - Poll single `command_id` for entire pipeline
   - All outputs available when status is `SUCCESS`

## Common gotchas

- **Forgetting `in_` / `out_` prefixes**: Keys must start with these prefixes or Rendi rejects the request. Reference as `{{in_1}}`, not `{{in_video}}` unless the key is literally `in_video`.

- **Input URLs not publicly accessible**: Rendi cannot fetch files from private S3, Google Drive without share links, or localhost. Test the URL in an incognito browser first.

- **Escaping curly brackets in automation platforms**: Make.com, Zapier, and others treat `{{` as special. Replace with `\{\{` and `\}\}` in the JSON body.

- **Setting `max_command_run_seconds` too low**: Default is 300s (5 min). Long transcodes, frame extraction, or HLS generation may timeout. Estimate runtime and set explicitly.

- **Mixing `input_files` and `input_compressed_folder`**: Use one or the other, not both. If using a ZIP, all inputs must be inside it.

- **Output filenames with invalid characters**: Only alphanumeric, underscore, and period allowed. No spaces, slashes, or special chars. `output_1.mp4` works; `output 1.mp4` fails.

- **Polling too aggressively**: Avoid polling every 100ms; use 1–2 second intervals or webhooks for long jobs.

- **Assuming output files persist forever**: They do, but delete them explicitly if storage quota matters. Use `DELETE /v1/files/{file_id}`.

- **Not checking `error_status` on failure**: When `status` is `FAILED`, read `error_status` and `error_message` to diagnose (e.g., `UNREACHABLE_INPUT_FILE`, `FFMPEG_COMMAND_FAILED`).

- **Forgetting to set `vcpu_count`**: Defaults to 1. For video processing, use 4–8 for faster encoding. Higher vCPU = faster but uses more quota.

## Verification checklist

Before submitting work:

- [ ] Input URLs are publicly accessible (test in incognito browser)
- [ ] FFmpeg command tested locally and syntax is correct
- [ ] Input keys start with `in_`, output keys start with `out_`
- [ ] All `{{in_*}}` and `{{out_*}}` placeholders match keys in `input_files` and `output_files`
- [ ] Output filenames contain only alphanumeric, underscore, period (no spaces or special chars)
- [ ] `max_command_run_seconds` is set appropriately for expected runtime
- [ ] `vcpu_count` is set (default 1 is slow for video; use 4–8 for typical jobs)
- [ ] `X-API-KEY` header is present and valid
- [ ] For automation platforms: curly brackets escaped as `\{\{` and `\}\}`
- [ ] For chained commands: later commands reference outputs from earlier steps correctly
- [ ] Webhook URL (if used) is reachable and responds within 15 seconds

## Resources

- **Comprehensive page index**: https://rendi.dev/docs/llms.txt
- **Full documentation**: https://rendi.dev/docs/llms-full.txt
- **OpenAPI spec** (canonical request/response schema): https://rendi.dev/docs/api-reference/openapi.json
- **FFmpeg cheatsheet** (command patterns for common tasks): https://raw.githubusercontent.com/rendi-api/ffmpeg-cheatsheet/refs/heads/main/README.md
- **API reference**: https://rendi.dev/docs/api-reference/introduction
- **Examples** (thumbnails, trimming, merging, compression): https://rendi.dev/docs/examples
- **Webhooks** (async notifications): https://rendi.dev/docs/webhooks
- **Dynamic files** (image sequences, HLS, compressed folders): https://rendi.dev/docs/dynamic-files
- **Integrations** (Make, n8n, Zapier): https://rendi.dev/docs/make-com

---

> For additional documentation and navigation, see: https://rendi.dev/docs/llms.txt