All Resemble media now mirrored to Cloudflare R2
TTS clips, uploads, and async-job audio are stored on Cloudflare R2 with per-asset retention. Voice-clone source recordings are kept permanently; generated audio expires automatically.What's new
IndoxHub now mirrors every media asset Resemble produces — TTS audio, audio enhance/edit results, watermark output, and user uploads — to Cloudflare R2. Responses include an audio_url (a presigned R2 URL) plus an expires_at timestamp so clients know exactly when an asset will be deleted.
Per-asset retention
| Asset type | Retention |
|---|---|
| TTS generated audio | 7 days |
| Audio enhance / edit / watermark output | 7 days |
| Voice design candidates | 14 days |
| STT input / generic uploads | 30 days |
| Voice-clone source recordings | PERMANENT |
| Built voice models | PERMANENT |
Identity assets (voice clones, trained voices) are kept forever. Disposable derivatives expire on a short clock to control storage cost.
Marking voice-clone uploads as permanent
When uploading audio meant for cloning a voice, pass purpose=voice_clone in the multipart form to land the file under voice-recordings/ (no expiry):
curl https://api.indoxhub.com/api/v1/resemble/uploads \
-H "Authorization: Bearer $INDOXHUB_API_KEY" \
-F "[email protected]" \
-F "purpose=voice_clone"
Other purposes: stt_input, watermark_input, audio_job_input. Default (no purpose) lands under uploads/ with 30-day retention.
Why R2
- Zero egress fees — large audio playback hits the bucket from end-user browsers; egress dominates the bill at scale.
- Per-user isolation — keys follow
{prefix}{user_id}/{YYYY}/{MM}/{DD}/{HHMMSS}-{request_id}.{ext}so per-user GDPR delete is one command. - Rollback safe — AWS S3 path stays in place; flip
STORAGE_BACKEND=s3to instantly revert.
What you should do
- Use the new
audio_urlfield — it's a clean R2 presigned URL valid for 1 hour. The original Resemble URL is still inresemble_urlas a fallback. - Read
expires_at— show users when their generated audio will disappear. - Tag voice-clone uploads — pass
purpose=voice_cloneso we keep the source recording forever.