Skip to main content

upload(segments, manifest, options)

Encrypts HLS segments in the browser and uploads them to S3 via presigned URLs. Parameters:
ParameterTypeDescription
segmentsSegmentInput[]Array of HLS segments to encrypt and upload
manifeststringThe .m3u8 manifest text
optionsUploadOptionsConfiguration for the upload
Returns: Promise<Result<UploadResult, UploaderError>>

UploadOptions

interface UploadOptions {
  /** Unique identifier for this content (used for key derivation) */
  contentId: string

  /** Key server URL including the /keys path (e.g., "https://your-worker.workers.dev/keys") */
  keyServerUrl: string

  /** URL of the presign endpoint */
  presignUrl: string

  /** Returns a Bearer token for auth (called for key fetch and presign requests) */
  auth?: () => Promise<string>

  /** Called after each segment is uploaded */
  onProgress?: (progress: { completed: number; total: number }) => void

  /** AbortSignal to cancel the upload */
  signal?: AbortSignal

  /** Number of parallel uploads (default: 4) */
  concurrency?: number

  /** S3 key prefix (default: "content/<contentId>/") */
  prefix?: string
}

SegmentInput

interface SegmentInput {
  /** Segment number (used for IV derivation) */
  index: number

  /** Raw .ts segment bytes (plaintext — will be encrypted) */
  data: Uint8Array

  /** Object key/path in storage (e.g., "seg-0.ts") */
  key: string
}

UploadResult

interface UploadResult {
  /** URL of the uploaded (rewritten) manifest */
  manifestUrl: string

  /** URLs of uploaded encrypted segments, in order */
  segmentUrls: string[]

  /** Total number of segments uploaded */
  segmentCount: number
}

UploadProgress

The onProgress callback receives:
{ completed: number; total: number }
FieldTypeDescription
completednumberNumber of segments uploaded so far
totalnumberTotal number of segments

rewriteManifest(manifest, opts)

Rewrites an HLS manifest to include EXT-X-KEY tags pointing to the key server and replaces segment URIs with uploaded URLs. This is called internally by upload() — you only need it directly for custom upload pipelines. Exported from @blindcast/storage:
import { rewriteManifest } from "@blindcast/storage"
Parameters:
ParameterTypeDescription
manifeststringOriginal .m3u8 manifest text
optsRewriteOptsRewrite configuration
Returns: Result<string, StorageError> — the rewritten manifest text
interface RewriteOpts {
  /** Key server base URL — /keys/:contentId is appended automatically */
  keyServerUrl: string

  /** Content identifier (used in the EXT-X-KEY URI) */
  contentId: string

  /** Map original segment filenames → uploaded URLs */
  segmentUrlMap: Record<string, string>

  /** If set, insert new EXT-X-KEY every N segments (key rotation) */
  segmentsPerEpoch?: number
}
keyServerUrl here is the base server URL (e.g., https://your-worker.workers.dev) — NOT the /keys path. The function appends /keys/:contentId automatically. This is different from the Player and Uploader SDKs, which expect the URL to include /keys.

Error codes

CodeCause
KEY_FETCH_FAILEDCould not fetch content key from key server
ENCRYPT_FAILEDSegment encryption failed
PRESIGN_FAILEDPresign endpoint returned an error or non-200 status
UPLOAD_FAILEDS3 upload failed (network error or rejected)
MANIFEST_PARSE_ERRORThe manifest text is not valid HLS
INVALID_INPUTSegments array is empty, contentId is invalid, or segment data is missing
ABORTEDUpload was cancelled via AbortSignal
See Error Codes for all error codes across BlindCast.