Media Prepare

Plan Builder

Declarative API for defining transcoding plans

The CmafPlanBuilder provides a fluent API for constructing transcoding plans with full TypeScript support and Zod validation.

Basic Usage

import { CmafPlanBuilder } from "@shelby-protocol/media-prepare/core";

const plan = new CmafPlanBuilder()
  .withInput("input.mp4")
  .withOutputDir("output")
  .withVideoLadder([
    { width: 1920, height: 1080, bitrateBps: 5_000_000, name: "1080p" },
    { width: 1280, height: 720, bitrateBps: 3_000_000, name: "720p" },
  ])
  .withVideoCodec({ kind: "x264", preset: "medium" })
  .addAudioTrack({ language: "eng", bitrateBps: 128_000, default: true })
  .withSegmentDuration(4)
  .withHlsOutput()
  .build();

Builder Methods

Input / Output

MethodDescription
withInput(path)Set the source media file path
withOutputDir(path)Set the output directory for segments and playlists
force()Overwrite existing output files

Video Configuration

MethodDescription
withVideoLadder(rungs)Set the complete video bitrate ladder
addVideoRung(rung)Add a single video rung to the ladder
withVideoCodec(codec)Set the video encoder (x264, x265, aom-av1, copy)
withFrameRateHint(fps)Provide frame rate hint for segment calculation

Audio Configuration

MethodDescription
withAudioTracks(tracks)Set all audio tracks at once
addAudioTrack(track)Add a single audio track
withAudioCodec(codec)Set the audio encoder (aac, copy)

Segment Configuration

MethodDescription
withSegmentDuration(seconds)Set fixed segment duration (1-30 seconds)
withComputedSegmentDuration(params)Compute segment duration from blob size constraints

Output Format

MethodDescription
withHlsOutput()Enable HLS playlist generation
withDashOutput()Enable DASH manifest generation
skipHls()Disable HLS output
skipDash()Disable DASH output

Build

MethodDescription
build()Validate and return the CmafPlan

Video Rung

Each video rung defines a quality level in the adaptive bitrate ladder:

interface VideoRung {
  width: number;        // Frame width in pixels
  height: number;       // Frame height in pixels
  bitrateBps: number;   // Target bitrate in bits per second
  name?: string;        // Optional identifier (e.g., "1080p")
}

Example:

builder.withVideoLadder([
  { width: 1920, height: 1080, bitrateBps: 5_000_000, name: "1080p" },
  { width: 1280, height: 720, bitrateBps: 3_000_000, name: "720p" },
  { width: 854, height: 480, bitrateBps: 1_200_000, name: "480p" },
]);

Audio Track

Each audio track defines a language variant:

interface AudioTrack {
  language: string;      // ISO 639-1/2 language code (e.g., "eng", "spa")
  bitrateBps: number;    // Target bitrate in bits per second
  default?: boolean;     // Mark as default track in HLS playlist
  name?: string;         // Optional identifier
  inputIndex?: number;   // Source stream index (for multi-track sources)
}

Example:

builder
  .addAudioTrack({ language: "eng", bitrateBps: 128_000, default: true })
  .addAudioTrack({ language: "spa", bitrateBps: 128_000 });

Computed Segment Duration

For Shelby blob storage integration, you can compute optimal segment duration based on maximum blob size:

builder.withComputedSegmentDuration({
  maxBlobBytes: 10 * 1024 * 1024,  // 10 MB max blob size
  safety: 0.9,                      // 10% safety margin
  minSeconds: 1,                    // Minimum segment duration
  align: 1,                         // Alignment factor
});

The computed duration ensures segments fit within blob size limits while maximizing segment length for efficient playback.

Validation

The builder validates all inputs at build time:

try {
  const plan = builder.build();
} catch (error) {
  // Zod validation error with detailed message
  console.error(error.message);
}

Common validation errors:

  • Missing required fields (input, output, video ladder)
  • Invalid bitrate values (must be positive)
  • Invalid segment duration (must be 1-30 seconds)
  • Invalid language codes