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
| Method | Description |
|---|---|
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
| Method | Description |
|---|---|
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
| Method | Description |
|---|---|
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
| Method | Description |
|---|---|
withSegmentDuration(seconds) | Set fixed segment duration (1-30 seconds) |
withComputedSegmentDuration(params) | Compute segment duration from blob size constraints |
Output Format
| Method | Description |
|---|---|
withHlsOutput() | Enable HLS playlist generation |
withDashOutput() | Enable DASH manifest generation |
skipHls() | Disable HLS output |
skipDash() | Disable DASH output |
Build
| Method | Description |
|---|---|
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