Skip to main content

The upload() function

upload() takes three arguments: segments, a manifest string, and options.
import { upload } from "@blindcast/uploader"

// 1. Read segments (e.g., from a previous pipeline step or file input)
const segments = [
  { index: 0, data: new Uint8Array(seg0Bytes), filename: "seg-0.ts" },
  { index: 1, data: new Uint8Array(seg1Bytes), filename: "seg-1.ts" },
  { index: 2, data: new Uint8Array(seg2Bytes), filename: "seg-2.ts" },
]

const manifest = await fetch("/api/manifest/my-video").then((r) => r.text())

// 2. Upload — encrypts, presigns, uploads, and rewrites manifest
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(),
})

if (!result.ok) {
  console.error(`Upload failed: [${result.error.code}] ${result.error.message}`)
  return
}

// 3. Use the result
const { manifestUrl, segmentUrls } = result.value
console.log(`Uploaded ${segmentUrls.length} segments`)
console.log(`Manifest: ${manifestUrl}`)

What happens internally

SegmentInput format

interface SegmentInput {
  index: number      // Segment number (used for IV derivation)
  data: Uint8Array   // Raw .ts segment bytes (plaintext — will be encrypted)
  filename: string   // Original filename (e.g., "seg-0.ts")
}

Verify playback

After uploading, verify the content plays back correctly using the Player:
import { createPlayer } from "@blindcast/player"

// Use the manifest URL returned by upload()
const playerResult = createPlayer(videoEl, {
  keyServerUrl: "https://keys.example.com/keys",
  keyServerAuth: async () => getAccessToken(),
})

if (playerResult.ok) {
  playerResult.value.load(result.value.manifestUrl)
}
The player fetches the same content key from the same key server and decrypts the segments you just uploaded. This closes the loop: upload → store → play.

Authentication

The auth callback is called twice:
  1. Key fetch: The uploader sends Authorization: Bearer <token> when fetching the content key
  2. Presign requests: The uploader sends the same header when requesting presigned URLs
Make sure your auth token is valid for both the key server and presign endpoints. If they use different auth, you’ll need to configure auth at the transport level.