Blog
Guides 6 min read

Import a video library from S3 without re-uploading

Move a video catalog already sitting in S3 into rehelios with one API call — no re-upload, no re-encode, fully reversible.

rehelios

Engineering

Most guides on serving video “from S3” walk you through bucket policies, CORS headers, and MIME types — how to make raw MP4 files playable straight out of a bucket. That’s a different problem from the one most teams actually have. If you already have hundreds of gigabytes of original video sitting in S3 and you want adaptive HLS, a real CDN, and signed playback, you don’t want to serve the raw files better. You want them somewhere that transcodes and delivers them properly — without downloading and re-uploading the whole catalog first.

rehelios imports video straight from an S3 URL, server-side. You give it a presigned (or public) URL to a file that’s already in your bucket, and rehelios fetches it, transcodes to HLS, and stores it — none of the bytes pass through your client or your server. You get back a video id and a playbackUrl you can drop into a player. Encoding is free, so transcoding an entire catalog costs nothing beyond storage and delivery.

Why re-uploading a library is the wrong move

The obvious path — download every file from S3, then upload it again to a new provider — has three costs most teams underestimate until they’re mid-migration:

  • Bandwidth, twice. Every byte gets pulled out of S3 (egress) and pushed back up to the new host (ingress). For a multi-hundred-GB catalog that’s a meaningful bill and a slow one, especially if the migration script runs serially through a queue.
  • Time proportional to catalog size, not to the work being done. A re-upload migration takes hours or days to move data that’s already sitting in a bucket you control. The actual “work” — pointing a new provider at existing bytes — should take seconds per video.
  • Creator-facing disruption. If the videos belong to end users (course creators, SaaS customers, an AI pipeline’s output), a re-upload migration usually means asking them to re-upload, or running a fragile background job that has to touch every file without breaking anything that’s live.

None of that is necessary when the files are already in object storage you control. The right move is to have the new provider pull the files itself.

How server-side import works

rehelios’s import endpoint takes a URL and does the fetch, transcode, and store on its side:

npx @rehelios/cli import https://my-bucket.s3.amazonaws.com/videos/lecture-042.mp4 \
  --collection col_courses \
  --wait \
  --json

Or call the REST API directly with a presigned S3 URL:

POST /v1/videos/import
{
  "url": "https://my-bucket.s3.amazonaws.com/videos/lecture-042.mp4"
}

rehelios fetches the file from that URL, transcodes it to adaptive HLS (with optional MPEG-DASH and progressive MP4), and stores the result behind the Cloudflare edge. GET /v1/videos/{id} returns the metadata once it’s ready, including the playbackUrl your player reads. A video.ready webhook (HMAC-signed) fires when transcoding finishes, so a migration job doesn’t need to poll — it can queue imports and let the webhook drive the next step.

If your bucket is private, generate a short-lived presigned GET URL per object before calling import — rehelios only needs read access for the duration of the fetch, not a standing credential to your bucket.

Free encoding changes the math for a large catalog

The reason this is viable for an entire library and not just a handful of files is that encoding is free. rehelios bills $0.02 per GB-month stored and $0.005 per GB delivered, with a $1/month minimum — the same per-gigabyte model as Bunny Stream, and the opposite of per-minute pricing. Transcoding a thousand lecture videos costs the same $0 as transcoding one. The bill only reflects what’s actually stored and actually watched, so a large but lightly-viewed back catalog — the kind every course platform, SaaS product, or content archive accumulates — stays cheap instead of becoming a line item that grows every time someone imports another file. Full numbers are on the pricing section.

The reversible dual-id migration pattern

The safest way to move a live catalog is to never do a hard cutover. Import one video, keep both ids, and let a resolver decide which one to serve:

  1. Import the video by URL and get back a rehelios id and playbackUrl.
  2. Store the new id next to the old one on the same row — don’t replace the existing reference to the old provider.
  3. Flip a single video at a time. The playback resolver checks: does this row have a rehelios id? Serve that. Otherwise, fall back to whatever was serving it before.
  4. Stay reversible. Because the old id and old file are untouched, you can flip a video back by clearing the rehelios id — no data loss, no re-import needed.

This is the exact pattern used in LearnBase’s migration: course video originated in S3, got pushed to another provider for HLS, and was later imported into rehelios one video at a time via the same POST /v1/videos/import call, with both provider ids stored on the row so the swap stayed reversible the whole way. The player never had to change — it just asks the backend for a URL and plays whatever comes back.

A migration that touches the storage layer shouldn’t touch the player, the upload flow, or force a big-bang cutover — importing by URL and keeping both ids lets you move a whole catalog one video at a time, with a rollback that’s always one field away.

Captions and chapters come along for free

Import isn’t just a copy operation — it runs the same pipeline as a direct upload. Captions (VTT/SRT, multiple languages) and chapters are generated automatically once the import finishes, so a catalog that never had subtitles can pick them up as part of the migration instead of needing a separate captioning pass afterward. If you’re building the import job yourself, see Import from URL for the shape of that flow end to end.

What this doesn’t do

Import moves and transcodes the file — it doesn’t add copy protection. Playback is gated with a short-lived signed token or a per-org domain allowlist, which stops casual link-sharing and hotlinking. It is not Widevine- or FairPlay-grade DRM, and it won’t stop someone from screen-recording a video they can already watch. If that distinction matters for your content, plan around it before you migrate, not after.

Where this leaves you

If the files are already in S3, the migration is a backend job: loop over your catalog, call import with a presigned URL per object, store the returned id next to the old one, and flip the resolver as each video comes back ready. No client re-upload, no bandwidth spent moving bytes you already own, and no encoding bill for doing it at scale. The catalog ends up on adaptive HLS behind a CDN with captions and chapters generated along the way — and if something looks wrong on one video, you can flip it back without touching the rest.

Put your first video live today

Create an account, upload a file, and have a fast, embeddable video live in minutes. Pay only for what you store and stream.