> ## Documentation Index
> Fetch the complete documentation index at: https://docs.blindcast.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Uploader Overview

> Browser-side encrypted upload SDK. Encrypt pre-segmented HLS content in the browser and upload to S3 via presigned URLs with a single function call.

`@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

```bash theme={null}
pnpm add @blindcast/uploader
```

## Quick example

```typescript theme={null}
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](/key-server/overview).
2. **A presign endpoint** — the uploader gets presigned S3 URLs from your server. The [Docker key server](/key-server/presign) bundles one, or you can build your own.
3. **HLS segments** — pre-segmented `.ts` files and a `.m3u8` manifest.

## Next steps

* [Basic Usage](/uploader/basic-usage) — full example with playback verification
* [Progress & Abort](/uploader/progress-and-abort) — track progress and cancel uploads
* [API Reference](/uploader/api-reference) — full types and error codes
