diff --git a/.claude-plugin/marketplace.json b/.claude-plugin/marketplace.json index 4c10308..bd8b257 100644 --- a/.claude-plugin/marketplace.json +++ b/.claude-plugin/marketplace.json @@ -10,7 +10,7 @@ "plugins": [ { "name": "rendobar", - "description": "Integrate Rendobar's media processing and AI generation API: FFmpeg jobs, target size compression, captions, image generation, webhooks, and MCP", + "description": "Integrate Rendobar's media processing and AI generation API: FFmpeg jobs, target size compression, captions, composition, image generation, webhooks, and MCP", "source": "./", "category": "developer-tools", "homepage": "https://rendobar.com", diff --git a/.claude-plugin/plugin.json b/.claude-plugin/plugin.json index c8ad2e1..b7c32d1 100644 --- a/.claude-plugin/plugin.json +++ b/.claude-plugin/plugin.json @@ -2,7 +2,7 @@ "$schema": "https://json.schemastore.org/claude-code-plugin-manifest.json", "name": "rendobar", "description": "Process and generate media over one API: FFmpeg jobs, target size compression, captions, composition, and image generation, editing, and upscaling", - "version": "1.2.0", + "version": "1.3.0", "author": { "name": "Rendobar", "url": "https://rendobar.com" diff --git a/skills/rendobar/SKILL.md b/skills/rendobar/SKILL.md index 01d7bfe..1e491d2 100644 --- a/skills/rendobar/SKILL.md +++ b/skills/rendobar/SKILL.md @@ -4,7 +4,7 @@ description: "Use this skill whenever a task involves media files or media gener license: MIT metadata: author: rendobar - version: "1.2.0" + version: "1.3.0" source: https://github.com/rendobar/agent-skills homepage: https://rendobar.com --- @@ -114,11 +114,35 @@ right.** - `dryRun` on `compress.target` reads like a free estimate. It is not: it runs real probe encodes and bills close to the full job. Do not sprinkle it in to "check cost first". -- Never smoke test with a long or high resolution source. Billing tracks the - compute a job actually uses, so a 2 hour 4K render costs real money and - proves nothing the 5 second sample does not. Current rates are on the - [pricing page](https://rendobar.com/pricing/), and the charge for a specific - job appears on the job once billing settles, shortly after it completes. +- Never smoke test with a long or high resolution source. A 2 hour 4K render + costs real money and proves nothing the 5 second sample does not. How a job + bills depends on its type: + - Most types bill the compute the job actually uses. + - `compose` bills $0.04 per minute of the video it returns, counted by the + second, with a 15 second minimum per render. The rate is the same on every + plan, at every frame size and with animated graphics, so a low resolution + draft costs the same per second as a 1080p final. Keep test renders short + rather than small. + - What a plan can render differs. Free renders compose up to 1080p at + 30 fps. Pro adds 1440p, and Studio adds 4K and 60 fps. Animated + graphics (text split into letters, words or lines, a `blur` or `scale` + entrance, any text exit, and 3D turns) above 1080p or 30 fps need an + enterprise plan. They work only on top-level tracks and in `overlays`, + never inside a scene or a composition. Lottie animations are not + animated graphics. A video above the plan fails at submit with + `PLAN_LIMIT`. Read `upgradeTo` on the problem in `error.details`: + `"pro"` or `"studio"` names the plan that renders it, and `null` means + only an enterprise plan does. Do not parse the message. Tell the user, + do not retry. + - The `validate_compose` MCP tool (or `POST /compose/validate`) runs the + same plan check for free and quotes the price as + `{ perMinuteUsd, minSeconds }` before you render. + - Every compose feature is listed with its JSON field and a rendered preview + at https://rendobar.com/compose/features/, searchable by name. + + Current rates are on the [pricing page](https://rendobar.com/pricing/), and + the charge for a specific job appears on the job once billing settles, + shortly after it completes. - Check the balance before a large batch: `client.billing.state()`. ## Common mistakes @@ -150,7 +174,7 @@ bugs in both directions. | Field | Means | Typical | |---|---|---| | `output.expiresAt` | When this signed download URL stops working | 1 hour | -| `retentionExpiresAt` | When the stored file is actually deleted | Plan driven, 7 days on free, 30 on pro | +| `retentionExpiresAt` | When the stored file is actually deleted | Plan driven, 7 days on free, 30 on pro, 90 on studio | So a URL going stale does not mean the output is gone: re-fetch the job for a fresh URL. And a file still being in retention does not mean an old URL works. diff --git a/skills/rendobar/references/errors.md b/skills/rendobar/references/errors.md index 3ed52fc..ad7edd3 100644 --- a/skills/rendobar/references/errors.md +++ b/skills/rendobar/references/errors.md @@ -66,22 +66,24 @@ must handle. |---|---|---| | `VALIDATION_ERROR` | 400 | The request body or params failed schema validation. Fix the payload. Re-read the type's schema at `GET /jobs/types/{type}/schema`. Do not retry unchanged. | | `INVALID_JOB_TYPE` | 400 | The type does not exist. Re-read the live catalog at `GET /jobs/types`. Never guess type names. | +| `FEATURE_NOT_ENABLED` | 400 | A compose job uses animated text or 3D turns, which are still rolling out and not enabled for this account. Tell the user. Offer to render without them, or point them to support for access. Do not retry unchanged. | | `UNAUTHORIZED` | 401 | Two distinct causes, check both before reporting: the key may not be reaching the process env, or the key itself may be invalid for this API (revoked, mistyped, or issued for another environment such as staging). Confirm which one rather than guessing. | | `INSUFFICIENT_CREDITS` | 402 | The org balance cannot cover the job. Tell the user to top up at https://app.rendobar.com/billing. Do not retry until they do. | | `FORBIDDEN` | 403 | The key's org cannot access this resource. | -| `PLAN_LIMIT` | 403 | A plan limit was hit (file size, concurrency, and similar). Surface it to the user, do not silently retry. | +| `PLAN_LIMIT` | 403 | A plan limit was hit (file size, job timeout, GPU FFmpeg on the free plan, a compose frame or frame rate above the plan, and similar). A compose or GPU refusal lists problems in `details`, each with `upgradeTo`: `"pro"` or `"studio"` for the cheapest plan that runs it, `null` when only an enterprise plan does. Read `upgradeTo`, not the message. Surface it to the user, do not silently retry. | | `NOT_FOUND` | 404 | The resource does not exist or belongs to another org. Check the id. | | `CONFLICT` | 409 | State conflict, for example cancelling a job that already finished. | | `RATE_LIMITED` | 429 | Too many requests. Retry with exponential backoff and jitter. | | `RUNNER_ERROR` | 502 | The processing backend failed. Safe to retry the job (use an `idempotencyKey`). | -| `RUNNER_TIMEOUT` | 504 | The job exceeded its timeout. Retrying the same input usually times out again, so reconsider the input or params. | +| `RUNNER_TIMEOUT` | 504 | A runner accepted the job but never started it, or lost the run. Not charged. A job that ran past its plan timeout fails with `JOB_TIMEOUT` instead, and retrying the same input usually times out again. | | `INTERNAL_ERROR` | 500 | Unexpected server error. Retry with backoff, then surface. | ## Rules of thumb - Retryable with backoff: `RATE_LIMITED`, `RUNNER_ERROR`, `INTERNAL_ERROR`. - Fix-then-retry: `VALIDATION_ERROR`, `INVALID_JOB_TYPE`, `UNAUTHORIZED`. -- User action required: `INSUFFICIENT_CREDITS`, `PLAN_LIMIT`. +- User action required: `INSUFFICIENT_CREDITS`, `PLAN_LIMIT`, + `FEATURE_NOT_ENABLED`. - For a failed job, do not apply these rules of thumb at all. Read `error.retryable` on the job, which is authoritative for that specific failure. diff --git a/skills/rendobar/references/jobs.md b/skills/rendobar/references/jobs.md index 2786cdf..962de08 100644 --- a/skills/rendobar/references/jobs.md +++ b/skills/rendobar/references/jobs.md @@ -103,8 +103,9 @@ A completed job carries `output` with four fields: `output.expiresAt` is the URL's life, not the file's. The file itself is deleted at `retentionExpiresAt` on the job, which is plan driven (7 days on -free, 30 on pro). Re-fetch the job for a fresh URL rather than caching one, and -copy anything that must outlive retention into your own storage. +free, 30 on pro, 90 on studio). Re-fetch the job for a fresh URL rather than +caching one, and copy anything that must outlive retention into your own +storage. ## Response envelope