Skip to main content
@blindcast/uploader encrypts HLS video segments in the browser and uploads them to S3 via presigned URLs. One function call — no crypto primitives, no transport configuration.

What it does

The uploader handles the entire upload pipeline:
  1. Fetches the content encryption key from your key server
  2. Encrypts each segment with AES-128-CBC
  3. Gets presigned upload URLs from your server
  4. Uploads encrypted bytes directly to S3
  5. Rewrites the manifest with EXT-X-KEY tags
  6. Uploads the rewritten manifest

What it does NOT do

The uploader encrypts and uploads pre-segmented HLS content (.ts files + .m3u8 manifest). It does not convert raw video files to HLS. If your users upload raw video (e.g., .mp4), you need a transcoding step first. Options for HLS segmentation:
  • Server-side: Transcode with FFmpeg, AWS MediaConvert, Mux, or Cloudflare Stream, then pass segments to the uploader
  • FFmpeg one-liner: ffmpeg -i input.mp4 -codec: copy -hls_time 6 -hls_list_size 0 -f hls segments/manifest.m3u8

Install

pnpm add @blindcast/uploader

Quick example

import { upload } from "@blindcast/uploader"

const result = await upload(segments, manifest, {
  contentId: "my-video-001",
  keyServerUrl: "https://keys.example.com/keys",
  presignUrl: "https://api.example.com/presign",
  auth: async () => getAccessToken(),
  onProgress: ({ completed, total }) => {
    console.log(`${completed}/${total} segments uploaded`)
  },
})

if (!result.ok) {
  console.error(result.error.code, result.error.message)
  return
}

console.log("Manifest URL:", result.value.manifestUrl)

Prerequisites

To use the uploader, you need:
  1. A key server running — the uploader fetches the content key from it. See Key Server docs.
  2. A presign endpoint — the uploader gets presigned S3 URLs from your server. The Docker key server bundles one, or you can build your own.
  3. HLS segments — pre-segmented .ts files and a .m3u8 manifest.

Next steps