Cloudflare R2 video transcoding

Transcode video into your own R2 bucket

Connect your Cloudflare R2 bucket once. After that, every FFmpeg job writes its outputs straight into it — your keys, your access rules, your CDN.

The extra copy step

Most media APIs keep your outputs in their own storage. Your app then downloads each file and uploads it again to the bucket your product actually serves from. That is one more step to write, retry and monitor for every job.

It also means your media lives on a third party until you move it, under their retention rules.

Without BYOB
  1. Source video
  2. Media API
  3. Their storage
  4. your copy job
  5. Your bucket

How Xora BYOB works

You set the destination once. Jobs need no storage fields at all.

  1. Connect R2

    Create an R2 API token with Object Read & Write on one bucket. Add it in the dashboard or with POST /v1/settings/storage-providers. Xora runs a write test before you use it.

  2. Submit jobs as usual

    Send recipes or raw FFmpeg args to POST /v1/jobs. With a default provider set, outputs go to your bucket. Use outputPath to pick the object key.

  3. Serve from your bucket

    When the job reaches completed, the files are already under your prefix. Serve them from your own CDN or custom domain.

Managed storage or your bucket

Both work with every recipe and with raw FFmpeg jobs. Pick per account.

Xora managed storageBYOB (Cloudflare R2)
Where outputs liveXora storage, behind signed URLs that expire Your R2 bucket, under your prefix
Who controls accessSigned URLs; list and delete with the Files API You — your bucket policy, your keys
Counts toward plan storageYes No
Output billing10 credits per GB of output10 credits per GB of output — the same
PlansAll plansPaid plans

Setup in two calls

Register the bucket once with makeDefault: true. Every job after that delivers to it — the job body stays the same as with managed storage.

Inputs can still come from any HTTPS URL, including S3 or R2 presigned URLs. To set the object key for one job, add outputPath, for example "processed/2026/october/final.mp4". Full steps are in the storage providers guide.

Running on Cloudflare already? See FFmpeg on Cloudflare Workers for how a Worker can send the job and serve the result from the same bucket.

1. Register the bucket
POST /v1/settings/storage-providers
{
"name": "Production R2",
"provider": "r2",
"accountId": "your-cloudflare-account-id",
"bucket": "my-media-bucket",
"prefix": "processed/",
"accessKeyId": "your-r2-access-key",
"secretAccessKey": "your-r2-secret-key",
"makeDefault": true
}
2. Submit a job
POST /v1/jobs
{
"mode": "ffmpeg",
"input_files": {
"in_1": "https://example.com/raw-video.mp4"
},
"output_files": {
"out_1": "optimized.mp4"
},
"ffmpeg": {
"args": ["-i", "{{in_1}}", "-c:v", "libx264", "-crf", "23", "{{out_1}}"]
}
}

Frequently asked questions

Can Xora write transcoded video to my Cloudflare R2 bucket?

Yes. Register the bucket with POST /v1/settings/storage-providers and set it as the default. After that, every job writes its outputs to your bucket, under the prefix you set. The job body does not change.

Which storage providers are supported?

Cloudflare R2 only, at the moment. Inputs can still come from any HTTPS URL, including S3 and R2 presigned URLs.

What permissions does the R2 token need?

Object Read & Write, scoped to the one bucket. Xora encrypts the secret key at rest, never returns it in API responses, and runs a write test before you use the bucket.

Can I choose the object key for each output?

Yes. Set outputPath on the job, for example processed/2026/october/final.mp4. The extension must match the output format. outputPath is not supported for jobs that use input_files and output_files. Without outputPath, the key is outputs/jobId/result with the format's extension, under your prefix.

Does BYOB cost extra?

No. Output is billed at the same credits per GB as with managed storage, and files in your bucket do not count toward your plan's storage. BYOB is on the paid plans.

Put your outputs where your product already reads them.

Start free with managed storage. Connect your R2 bucket when you move to a paid plan.