Storage providers
Storage
Storage setup guide. Configure AWS S3, Cloudflare R2, or a public S3-compatible service to receive transcoded videos.
Storage is where the processed files are kept when a transcoding job is finished.
Chunkify routes workloads from the storage's Chunkify location. For AWS, Chunkify derives that location from the AWS region. S3-compatible storage asks for the workload location explicitly.
By default Chunkify provides a test storage, this is for development and test purposes only. All the files will be deleted 24h after their creation. For production you'll need to setup your own storage to keep your processed files safe.
Use an object as a Source
Create a Source from an object in a connected AWS S3 or S3-compatible Storage:
{
"storage": {
"id": "stor_aws_example",
"path": "incoming/video.mp4"
},
"metadata": { "label": "original" }
}
Send this body to POST /api/sources. Provide either a root-level url or a storage object. Within storage, path is required and you can supply id to select external Storage belonging to the same Project, or omit it to use the Project's external default Storage:
{
"storage": {
"path": "incoming/video.mp4"
}
}
If the Project has no default Storage or uses Chunkify-managed Storage, provide an external storage.id or use url. Public Source creation cannot use Chunkify-managed temporary Storage. Do not combine url with storage.
storage.path is the exact object key, including any spaces, Unicode characters, or leading slashes. It must contain 1 to 1024 UTF-8 bytes. Chunkify does not add the Storage's output base_prefix or use its CDN hostname when reading the input.
The Storage credentials must allow GetObject for this object, in addition to the permissions needed for connection validation below the output prefix. A missing, unreadable, or invalid media object causes Source creation to fail.
Source responses contain storage_id and path instead of url. Chunkify saves the resolved Storage ID, so changing the Project's default Storage later does not affect existing Sources. It stores that reference and signs a temporary GET URL when probing the object and when each processing attempt starts. Queued Jobs do not store a signed input URL. Runtime signatures last 65 minutes, subject to earlier credential expiry or provider restrictions.
Chunkify reads the object directly and does not copy or retain the original. You control its lifetime. Deleting the object or revoking access can make later Jobs fail. A Storage cannot be deleted while a Source references it; delete the Source or wait for Source cleanup first.
Job compute regions still follow the output Storage. Reading from another provider or region may incur source egress charges from your provider.
AWS S3 source-read permissions
Add the following statement to the IAM policy for the user whose access key you connected to Chunkify. Keep the policy's existing statements.
{
"Sid": "ReadChunkifySources",
"Effect": "Allow",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::YOUR_BUCKET/incoming/*"
}
Replace YOUR_BUCKET with your bucket name and incoming/* with the source prefix you want Chunkify to read. To allow one object, use its exact key instead of a prefix wildcard. This prefix is independent of the Storage's output base_prefix.
Source reads do not require s3:ListBucket: you provide the exact object key, and Chunkify does not browse the bucket. See AWS GetObject permissions.
When the IAM user and bucket belong to the same AWS account, an IAM allow is generally sufficient, provided no applicable policy denies access. For cross-account access, the bucket policy must also allow that IAM principal to read the source objects. The statement above is an IAM policy statement; a bucket policy also needs a Principal. The bucket can remain private. See AWS S3 policies and permissions.
If your source objects use SSE-KMS encryption, also grant kms:Decrypt on the specific KMS key and ensure its key policy permits the IAM user to use it. Add this as a separate statement with the KMS key ARN as its resource. SSE-S3 encryption does not require KMS permissions. See AWS KMS permissions for S3.
Keep the existing write permissions on the output prefix. When you connect a Storage, Chunkify uploads a unique probe under <base_prefix>chunkify-validation/, then reads its metadata and content to verify access, even if you plan to use the Storage only for Sources. It attempts to delete the uploaded version; cleanup failures are logged without blocking storage creation. The read statement above supplements these validation permissions; it is not a complete Storage connection policy.
Choose an output prefix
Customer-owned storage connections can set an Output prefix in the app. The API field is named base_prefix. This setting applies to generated job outputs; source paths remain exact object keys and do not use the prefix. We recommend chunkify/, which keeps generated files in one bucket directory. The dashboard fills this value for new AWS S3 and Cloudflare R2 connections.
The API accepts chunkify and stores the canonical chunkify/ form. It removes leading and duplicate slashes. Send base_prefix: "", or clear the dashboard field, to write at the bucket root. Omitting the API field also keeps the legacy bucket-root behavior.
Job storage.path values are relative to this prefix. For a media/chunkify/ output prefix and exports/video.mp4 job path, the final object key is media/chunkify/exports/video.mp4. Do not repeat the prefix in the job path. Leading slashes are accepted for compatibility and removed before Chunkify stores the job path, so /exports/video.mp4 produces the same object key.
You can edit the prefix in the dashboard at any time. Existing files keep their stored object keys. Jobs that have not uploaded their final outputs yet use the current prefix when they upload.
Supported storage providers
AWS S3 Storage
Free egress - no additional costs for data transfer.
Cloudflare R2 Storage
Egress costs: $0.09 per GiB of processed output transferred from Chunkify to R2.
Use the correct location when setting up your storage to avoid bad performances.
S3-compatible storage
Chunkify supports any S3-compatible provider, including self-hosted services such as MinIO, that meets the connection requirements below. Choose S3-compatible when adding the storage, or use s3_compatible as the API provider identifier.
Egress costs: $0.09 per GiB of processed output transferred from Chunkify to your storage. This rate applies to all S3-compatible providers, including services behind custom endpoints.
The storage list recognizes these providers by their endpoint and displays their name and logo:
-
Backblaze B2
-
Wasabi
-
Google Cloud Storage
-
DigitalOcean Spaces
-
Hetzner Object Storage
-
Scaleway Object Storage
-
OVHcloud Object Storage
-
Akamai Object Storage
-
Vultr Object Storage
-
IDrive e2
-
Storj
-
Tigris
You can connect providers outside this list and services behind a custom domain. Unrecognized endpoints display a generic storage icon and their hostname.
For Google Cloud Storage, use the XML API endpoint https://storage.googleapis.com and HMAC access keys.
Connection requirements
The optional public field defaults to false, matching AWS S3 and Cloudflare R2. This tells Chunkify whether the bucket is publicly readable; it does not change the provider's bucket permissions.
The two region fields have different jobs:
- Provider region is sent in AWS Signature Version 4 requests. Enter the exact identifier required by the provider; Chunkify never defaults it to
auto. - Chunkify location is
US,EU, orASIA. It selects the Chunkify region that runs the workload and does not change request signing.
Chunkify tries virtual-hosted and path-style addressing while it validates the connection, then saves the working style for uploads, downloads, metadata requests, and presigned URLs. Validation writes a unique temporary object and reads its metadata and content. The credentials therefore need permission to put, get, and head objects below the configured base prefix. Chunkify then attempts to delete the probe. Cleanup is best-effort: deletion failures are logged without blocking storage creation, but may leave the probe behind.
For successful cleanup, allow object deletion and, for versioned buckets, version deletion (for example, s3:DeleteObjectVersion on AWS or deleteFiles on Backblaze B2). Validation deletes the specific object version returned by the upload. When no version ID is available, cleanup falls back to deleting by key. If an upload succeeds but its response is lost, this fallback may leave a retained version in a versioned bucket.
Only public HTTPS origins are supported. The endpoint cannot contain credentials, a path, query, or fragment, and it must not resolve to localhost, loopback, link-local, private, or reserved network addresses. A private-network or HTTP-only MinIO server is not compatible.
The compatibility contract covers the S3 object operations exercised by Chunkify: input and output upload/download, user metadata, presigned upload/download URLs, and cleanup deletes. Chunkify does not attach object tags to customer-owned outputs, which keeps the workflow compatible with Backblaze B2's documented object-tagging limitation. The provider list above is not an allowlist. Chunkify validates bucket access when you connect a storage and returns a validation error if that check fails.
Use the endpoint and signing region assigned to the bucket:
| Service | Endpoint example | Provider region example |
|---|---|---|
| MinIO | https://minio.example.com |
The deployment's configured region, such as us-east-1 |
| Wasabi | https://s3.eu-west-2.wasabisys.com |
eu-west-2 |
| Backblaze B2 | https://s3.us-west-004.backblazeb2.com |
us-west-004 |
For vendor details, see the official MinIO client endpoint guide, Wasabi service URL list, and Backblaze B2 S3-compatible endpoint guide.
{
"provider": "s3_compatible",
"endpoint": "https://s3.us-west-004.backblazeb2.com",
"region": "us-west-004",
"location": "US",
"bucket": "my-bucket",
"access_key_id": "your-access-key",
"secret_access_key": "your-secret-key",
"public": false,
"base_prefix": "chunkify/"
}
Serve outputs through your CDN
Customer-owned AWS S3, Cloudflare R2, and S3-compatible storage can have one optional cdn_base_url, such as https://media.example.com.
Set it while creating the storage, or use Edit CDN URL in Settings → Storages to replace or remove it later. Chunkify-managed temporary storage does not support this setting.
Chunkify combines this HTTPS origin with each output's complete object path. For example, chunkify/output.mp4 becomes https://media.example.com/chunkify/output.mp4.
File API responses continue to include the temporary presigned url. When configured, they also include the stable, unsigned cdn_url.
Changing the storage hostname affects later API responses and webhook payloads. It does not move or modify stored files.
The URL must be an HTTPS origin without credentials, a path, query string, or fragment. Chunkify validates its syntax but does not contact the hostname or verify your CDN configuration.
Before using a CDN URL in production, verify that:
- the hostname root maps to the storage bucket root, including every object-key prefix;
- DNS and a valid HTTPS certificate are active;
- CORS allows your application origins and the methods your player uses;
- manifests, video, audio, images, and subtitle files have the correct MIME types;
- byte-range requests are forwarded to the origin and returned correctly;
- cache rules suit immutable media segments and any files that may change;
- private CDN authentication is added by your application when required.
cdn_url is unsigned. Private CDNs may require your application to add signed cookies or produce a provider-specific signed URL before playback.
Storage Creation
You can create your own storage using the App or the SDK. Our system will test the storage bucket connection using your provided credentials. The creation will fail if the bucket is inaccessible.
Using the APP
You will find a storage tab in the top right corner of the project settings page. From here you can create a new storage for your project.
Using the SDK
AWS S3
Example of S3 storage creation:
import Chunkify from '@chunkify/chunkify';
let client = new Chunkify({
projectAccessToken: 'My Project Access Token',
});
// Create a new storage
const storage = await client.storages.create({
storage: {
access_key_id: '1234567890',
bucket: 'my-bucket',
provider: 'aws',
region: 'us-east-1',
secret_access_key: '1234567890',
base_prefix: 'chunkify/',
public: false,
}
});
// Attach the storage to your project to use it
// Note: This requires a team access token, not a project access token
client = new Chunkify({
teamAccessToken: 'My Team Access Token',
});
await client.projects.update('projectId', { storage_id: storage.id });
Cloudflare R2
Example of R2 storage creation:
import Chunkify from '@chunkify/chunkify';
let client = new Chunkify({
projectAccessToken: 'My Project Access Token',
});
// Create a storage
const storage = await client.storages.create({
storage: {
bucket: 'my-bucket',
provider: 'cloudflare',
endpoint: 'https://your-endpoint.r2.cloudflarestorage.com',
access_key_id: '1234567890',
secret_access_key: 'abcdefghijklmnopqrstuvwxyz',
location: 'US',
base_prefix: 'chunkify/',
public: false,
}
});
// Attach the storage to your project
// Note: This requires a team access token, not a project access token
client = new Chunkify({
teamAccessToken: 'My Team Access Token',
});
await client.projects.update('projectId', { storage_id: storage.id });