@stack0/sdk 0.5.17 → 0.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -177,6 +177,16 @@ interface VideoVariant {
177
177
  quality: VideoQuality;
178
178
  codec?: VideoCodec;
179
179
  bitrate?: number;
180
+ /**
181
+ * Bytes actually written to storage for this rendition, measured after the job completes.
182
+ * For HLS this covers the variant playlist and its segments; for MP4, the single file.
183
+ *
184
+ * Response-only — ignored if you set it on a transcode request.
185
+ *
186
+ * Undefined means not measured (job still running, job predates measurement, or the
187
+ * measurement failed), never zero. `bitrate * duration` is an estimate; this is not.
188
+ */
189
+ sizeBytes?: number;
180
190
  }
181
191
  /**
182
192
  * Watermark burned into a video during transcode.
@@ -299,6 +309,13 @@ interface TranscodeJob {
299
309
  /** Provider or preprocessing failure details when status is `failed`. */
300
310
  errorMessage: string | null;
301
311
  mediaConvertJobId: string | null;
312
+ /**
313
+ * Every byte this job wrote: renditions, HLS segments, and manifests together, since
314
+ * storage is billed per object rather than for the media alone.
315
+ *
316
+ * Null until the job completes, and null if the measurement failed. Not zero.
317
+ */
318
+ totalOutputBytes: number | null;
302
319
  createdAt: Date;
303
320
  startedAt: Date | null;
304
321
  completedAt: Date | null;
@@ -534,6 +551,14 @@ interface CdnUsageRequest {
534
551
  environment?: CdnEnvironment;
535
552
  periodStart?: Date | string;
536
553
  periodEnd?: Date | string;
554
+ /**
555
+ * Virtual folder path to scope the stats to, e.g. "/customers/acme". Covers the folder
556
+ * itself and everything nested under it — the same scoping as `getStorageUsage`. Use
557
+ * this to meter bandwidth per tenant when each tenant uploads under its own folder.
558
+ * Folder-scoped stats only cover assets that still exist; deleting an asset removes
559
+ * its serving history, so a period total can shrink.
560
+ */
561
+ folder?: string;
537
562
  }
538
563
  interface CdnUsageResponse {
539
564
  periodStart: Date;
@@ -546,6 +571,12 @@ interface CdnUsageResponse {
546
571
  storageFormatted: string;
547
572
  estimatedCostCents: number;
548
573
  estimatedCostFormatted: string;
574
+ /**
575
+ * Echoes the folder the stats cover, null when the whole project or org was counted.
576
+ * When metering a tenant, check this echo — a server that predates folder scoping
577
+ * ignores the parameter and silently returns org-wide numbers.
578
+ */
579
+ folder: string | null;
549
580
  }
550
581
  interface CdnUsageHistoryRequest {
551
582
  projectSlug?: string;
@@ -587,6 +618,42 @@ interface CdnStorageBreakdownResponse {
587
618
  sizeFormatted: string;
588
619
  };
589
620
  }
621
+ interface CdnStorageUsageRequest {
622
+ projectSlug?: string;
623
+ environment?: CdnEnvironment;
624
+ /**
625
+ * Virtual folder path to scope the total to, e.g. "/customers/acme". The folder itself and
626
+ * everything nested under it are counted. Omit to total the whole project or organization.
627
+ */
628
+ folder?: string;
629
+ }
630
+ interface CdnStorageUsageBucket {
631
+ bytes: number;
632
+ bytesFormatted: string;
633
+ objectCount: number;
634
+ }
635
+ interface CdnStorageUsageResponse {
636
+ /** Uploads plus every measured derived object stored under the scope. */
637
+ totalBytes: number;
638
+ totalFormatted: string;
639
+ /** Objects behind that total. Storage is billed per object, so segments and manifests count. */
640
+ objectCount: number;
641
+ /** Split by asset type; a video's renditions count as video. */
642
+ byType: Record<string, CdnStorageUsageBucket>;
643
+ breakdown: {
644
+ /** The uploaded files themselves. */
645
+ originals: CdnStorageUsageBucket;
646
+ /** Renditions, HLS segments and manifests, thumbnails, GIFs. */
647
+ derived: CdnStorageUsageBucket;
648
+ };
649
+ /**
650
+ * Assets known to have derivatives whose bytes have not been measured yet. Their storage is
651
+ * missing from `totalBytes`, so a nonzero count means the total is a floor, not the answer.
652
+ */
653
+ unmeasuredAssets: number;
654
+ /** The folder the total covers, or null when the whole project or org was counted. */
655
+ folder: string | null;
656
+ }
590
657
  interface GetFolderRequest {
591
658
  id: string;
592
659
  }
@@ -894,6 +961,107 @@ interface ListMergeJobsResponse {
894
961
  total: number;
895
962
  hasMore: boolean;
896
963
  }
964
+ type RenderStatus = TranscodingStatus;
965
+ type RenderOutputFormat = "mp4" | "webm";
966
+ /**
967
+ * The declarative video spec.
968
+ *
969
+ * Typed loosely on purpose. The authoritative schema lives in
970
+ * `@stack0/video-spec`, which also ships worked examples and the timing engine;
971
+ * restating its shape here would create a second description of one contract
972
+ * that silently drifts. Install that package for full types and validation:
973
+ *
974
+ * ```typescript
975
+ * import { validateSpec, prankWithDemoExample } from '@stack0/video-spec'
976
+ * ```
977
+ */
978
+ type VideoSpec = Record<string, unknown>;
979
+ /**
980
+ * How the finished video is encoded.
981
+ *
982
+ * There is no quality or aspect ratio here: the spec's canvas declares width,
983
+ * height and fps, so scale is the only encode-side lever left.
984
+ */
985
+ interface RenderOutputConfig {
986
+ /** Container and codec: mp4/h264 or webm/vp8 (default: mp4) */
987
+ format?: RenderOutputFormat;
988
+ /** Multiplier on the spec's canvas, 0.1-4 (default: 1). Cost scales with the square of this. */
989
+ scale?: number;
990
+ /** Custom filename for the output */
991
+ filename?: string;
992
+ }
993
+ /**
994
+ * Request to render a video spec
995
+ */
996
+ interface CreateRenderJobRequest {
997
+ /** Project slug to create the render job in */
998
+ projectSlug: string;
999
+ /** The video spec: scenes, layers, timing and media. Data, not code. */
1000
+ spec: VideoSpec;
1001
+ /** Output configuration */
1002
+ output?: RenderOutputConfig;
1003
+ /** Webhook URL for completion notification */
1004
+ webhookUrl?: string;
1005
+ }
1006
+ /**
1007
+ * Request to list render jobs
1008
+ */
1009
+ interface ListRenderJobsRequest {
1010
+ projectSlug: string;
1011
+ /** Filter by status */
1012
+ status?: RenderStatus;
1013
+ /** Maximum number of results (default: 20, max: 100) */
1014
+ limit?: number;
1015
+ /** Offset for pagination */
1016
+ offset?: number;
1017
+ }
1018
+ /**
1019
+ * Render job response
1020
+ */
1021
+ interface RenderJob {
1022
+ id: string;
1023
+ organizationId: string;
1024
+ projectId: string;
1025
+ environment: "sandbox" | "production";
1026
+ /** The submitted spec, with media references resolved to URLs */
1027
+ spec: VideoSpec;
1028
+ outputFormat: RenderOutputFormat;
1029
+ outputScale: number;
1030
+ outputFilename: string | null;
1031
+ outputAssetId: string | null;
1032
+ status: RenderStatus;
1033
+ progress: number | null;
1034
+ errorMessage: string | null;
1035
+ startedAt: Date | null;
1036
+ completedAt: Date | null;
1037
+ /** Resolved from the spec at submission, before a single frame renders */
1038
+ width: number | null;
1039
+ height: number | null;
1040
+ fps: number | null;
1041
+ durationInFrames: number | null;
1042
+ outputDurationSeconds: number | null;
1043
+ webhookUrl: string | null;
1044
+ createdAt: Date;
1045
+ updatedAt: Date | null;
1046
+ }
1047
+ /**
1048
+ * Render job with output asset details
1049
+ */
1050
+ interface RenderJobWithOutput extends RenderJob {
1051
+ outputAsset: {
1052
+ id: string;
1053
+ cdnUrl: string;
1054
+ directUrl: string;
1055
+ filename: string;
1056
+ size: number;
1057
+ duration: number | null;
1058
+ } | null;
1059
+ }
1060
+ interface ListRenderJobsResponse {
1061
+ jobs: RenderJob[];
1062
+ total: number;
1063
+ hasMore: boolean;
1064
+ }
897
1065
  type ImportJobStatus = "pending" | "validating" | "importing" | "completed" | "failed" | "cancelled";
898
1066
  type ImportAuthType = "iam_credentials" | "role_assumption";
899
1067
  type ImportPathMode = "preserve" | "flatten";
@@ -1696,6 +1864,29 @@ declare class CDN {
1696
1864
  * ```
1697
1865
  */
1698
1866
  getStorageBreakdown(request?: CdnStorageBreakdownRequest): Promise<CdnStorageBreakdownResponse>;
1867
+ /**
1868
+ * Get total stored bytes for a project or folder, derived assets included.
1869
+ *
1870
+ * Totals uploads plus everything the pipelines derived from them — video renditions, HLS
1871
+ * segments and manifests, thumbnails, GIFs — in one call. Use this to meter a plan limit:
1872
+ * paging `list()` and summing `size` counts uploads only, and an HLS ladder typically runs
1873
+ * well past the size of the source it came from.
1874
+ *
1875
+ * Check `unmeasuredAssets`. A nonzero value means some assets have derivatives whose bytes
1876
+ * have not been measured, so `totalBytes` is a floor rather than the full number.
1877
+ *
1878
+ * @example
1879
+ * ```typescript
1880
+ * const usage = await cdn.getStorageUsage({
1881
+ * projectSlug: 'my-project',
1882
+ * folder: '/customers/acme',
1883
+ * });
1884
+ * console.log(`${usage.totalFormatted} across ${usage.objectCount} objects`);
1885
+ * console.log(` uploads: ${usage.breakdown.originals.bytesFormatted}`);
1886
+ * console.log(` derived: ${usage.breakdown.derived.bytesFormatted}`);
1887
+ * ```
1888
+ */
1889
+ getStorageUsage(request?: CdnStorageUsageRequest): Promise<CdnStorageUsageResponse>;
1699
1890
  private convertUsageDates;
1700
1891
  private convertUsageDataPointDates;
1701
1892
  /**
@@ -1878,6 +2069,78 @@ declare class CDN {
1878
2069
  }>;
1879
2070
  private convertMergeJobDates;
1880
2071
  private convertMergeJobWithOutputDates;
2072
+ /**
2073
+ * Render a declarative video spec into a video asset
2074
+ *
2075
+ * The spec describes scenes, layers, timing and media as data. There are no
2076
+ * compositions to write and no code to upload — Stack0 owns the renderer.
2077
+ *
2078
+ * `@stack0/video-spec` has the full types, validation and worked examples;
2079
+ * validating locally before you POST turns a round trip into a type error.
2080
+ *
2081
+ * @example
2082
+ * ```typescript
2083
+ * const job = await cdn.createRenderJob({
2084
+ * projectSlug: 'my-project',
2085
+ * spec: {
2086
+ * canvas: { width: 1080, height: 1920, fps: 30 },
2087
+ * audio: [{ src: musicAssetId, volume: 0.34 }],
2088
+ * scenes: [
2089
+ * {
2090
+ * id: 'hook',
2091
+ * duration: 2.5,
2092
+ * layers: [
2093
+ * { type: 'image', src: afterImageAssetId, zoom: { from: 1, to: 1.06 } },
2094
+ * { type: 'caption', text: 'i told my mom\nthe kitchen exploded', position: 'upperThird' },
2095
+ * ],
2096
+ * },
2097
+ * {
2098
+ * // No duration: the thread derives its own length from the messages
2099
+ * id: 'payoff',
2100
+ * layers: [
2101
+ * {
2102
+ * type: 'messageThread',
2103
+ * recipient: 'Mom',
2104
+ * imageSrc: afterImageAssetId,
2105
+ * messages: [
2106
+ * { sender: 'recipient', text: 'you home?', history: true },
2107
+ * { sender: 'user', text: '[IMAGE]' },
2108
+ * { sender: 'recipient', text: 'WHAT IS THAT' },
2109
+ * ],
2110
+ * },
2111
+ * ],
2112
+ * },
2113
+ * ],
2114
+ * },
2115
+ * webhookUrl: 'https://your-app.com/webhook',
2116
+ * });
2117
+ * console.log(job.durationInFrames); // known before rendering starts
2118
+ * ```
2119
+ */
2120
+ createRenderJob(request: CreateRenderJobRequest): Promise<RenderJob>;
2121
+ /**
2122
+ * Get a render job by ID with output asset details
2123
+ *
2124
+ * @example
2125
+ * ```typescript
2126
+ * const job = await cdn.getRenderJob('job-id');
2127
+ * if (job.status === 'completed' && job.outputAsset) {
2128
+ * console.log(`Output video: ${job.outputAsset.cdnUrl}`);
2129
+ * }
2130
+ * ```
2131
+ */
2132
+ getRenderJob(jobId: string): Promise<RenderJobWithOutput>;
2133
+ /**
2134
+ * List render jobs with optional filters
2135
+ */
2136
+ listRenderJobs(request: ListRenderJobsRequest): Promise<ListRenderJobsResponse>;
2137
+ /**
2138
+ * Cancel a pending or processing render job
2139
+ */
2140
+ cancelRenderJob(jobId: string): Promise<{
2141
+ success: boolean;
2142
+ }>;
2143
+ private convertRenderJobDates;
1881
2144
  /**
1882
2145
  * Create an S3 import job to bulk import files from an external S3 bucket.
1883
2146
  * Requires Pro plan or higher.
@@ -1995,4 +2258,4 @@ declare class CDN {
1995
2258
  private convertImportFileDates;
1996
2259
  }
1997
2260
 
1998
- export { type Asset, type AssetStatus, type AssetType, type AudioTrackInput, type BundleDownloadUrlRequest, type BundleDownloadUrlResponse, type BundleStatus, CDN, type CancelImportResponse, type CancelMergeJobRequest, type CdnEnvironment, type CdnStorageBreakdownItem, type CdnStorageBreakdownRequest, type CdnStorageBreakdownResponse, type CdnUsageDataPoint, type CdnUsageHistoryRequest, type CdnUsageHistoryResponse, type CdnUsageRequest, type CdnUsageResponse, type CompositeChromaKey, type CompositeConfig, type CompositePoint, type CompositeQuad, type CompositeRect, type ConfirmUploadRequest, type ConfirmUploadResponse, type CreateBundleRequest, type CreateBundleResponse, type CreateFolderRequest, type CreateImportRequest, type CreateImportResponse, type CreateMergeJobRequest, type DeleteAssetRequest, type DeleteAssetsRequest, type DeleteAssetsResponse, type DownloadBundle, type ExtractAudioRequest, type ExtractAudioResponse, type Folder, type FolderListItem, type FolderTreeNode, type GenerateGifRequest, type GetAssetRequest, type GetFolderByPathRequest, type GetFolderRequest, type GetFolderTreeRequest, type GetMergeJobRequest, type GifStatus, type ImageVideoWatermarkOptions, type ImageWatermarkConfig, type ImageWatermarkPosition, type ImageWatermarkSizingMode, type ImportAuthType, type ImportError, type ImportFile, type ImportFileStatus, type ImportJob, type ImportJobStatus, type ImportJobSummary, type ImportPathMode, type ListAssetsRequest, type ListAssetsResponse, type ListBundlesRequest, type ListBundlesResponse, type ListFoldersRequest, type ListFoldersResponse, type ListGifsRequest, type ListImportFilesRequest, type ListImportFilesResponse, type ListImportsRequest, type ListImportsResponse, type ListJobsRequest, type ListJobsResponse, type ListMergeJobsRequest, type ListMergeJobsResponse, type ListPrivateFilesRequest, type ListPrivateFilesResponse, type ListThumbnailsRequest, type ListThumbnailsResponse, type MergeAspectRatio, type MergeInputItem, type MergeJob, type MergeJobWithOutput, type MergeOutputConfig, type MergeOutputFormat, type MergeQuality, type MergeStatus, type MoveAssetsRequest, type MoveAssetsResponse, type MoveFolderRequest, type MoveFolderResponse, type MovePrivateFilesRequest, type MovePrivateFilesResponse, type PrivateDownloadUrlRequest, type PrivateDownloadUrlResponse, type PrivateFile, type PrivateFileStatus, type PrivateUploadUrlRequest, type PrivateUploadUrlResponse, type RegenerateThumbnailRequest, type RegenerateThumbnailResponse, type RetryImportResponse, type StreamingUrls, type TextOverlay, type TextOverlayShadow, type TextOverlayStroke, type TextVideoWatermarkOptions, type ThumbnailRequest, type ThumbnailResponse, type TranscodeJob, type TranscodeVideoRequest, type TranscodingStatus, type TransformOptions, type TrimOptions, type UpdateAssetRequest, type UpdateFolderRequest, type UpdatePrivateFileRequest, type UploadFromUrlRequest, type UploadUrlRequest, type UploadUrlResponse, type VideoCodec, type VideoGif, type VideoOutputFormat, type VideoQuality, type VideoThumbnail, type VideoVariant, type WatermarkOptions };
2261
+ export { type Asset, type AssetStatus, type AssetType, type AudioTrackInput, type BundleDownloadUrlRequest, type BundleDownloadUrlResponse, type BundleStatus, CDN, type CancelImportResponse, type CancelMergeJobRequest, type CdnEnvironment, type CdnStorageBreakdownItem, type CdnStorageBreakdownRequest, type CdnStorageBreakdownResponse, type CdnStorageUsageBucket, type CdnStorageUsageRequest, type CdnStorageUsageResponse, type CdnUsageDataPoint, type CdnUsageHistoryRequest, type CdnUsageHistoryResponse, type CdnUsageRequest, type CdnUsageResponse, type CompositeChromaKey, type CompositeConfig, type CompositePoint, type CompositeQuad, type CompositeRect, type ConfirmUploadRequest, type ConfirmUploadResponse, type CreateBundleRequest, type CreateBundleResponse, type CreateFolderRequest, type CreateImportRequest, type CreateImportResponse, type CreateMergeJobRequest, type CreateRenderJobRequest, type DeleteAssetRequest, type DeleteAssetsRequest, type DeleteAssetsResponse, type DownloadBundle, type ExtractAudioRequest, type ExtractAudioResponse, type Folder, type FolderListItem, type FolderTreeNode, type GenerateGifRequest, type GetAssetRequest, type GetFolderByPathRequest, type GetFolderRequest, type GetFolderTreeRequest, type GetMergeJobRequest, type GifStatus, type ImageVideoWatermarkOptions, type ImageWatermarkConfig, type ImageWatermarkPosition, type ImageWatermarkSizingMode, type ImportAuthType, type ImportError, type ImportFile, type ImportFileStatus, type ImportJob, type ImportJobStatus, type ImportJobSummary, type ImportPathMode, type ListAssetsRequest, type ListAssetsResponse, type ListBundlesRequest, type ListBundlesResponse, type ListFoldersRequest, type ListFoldersResponse, type ListGifsRequest, type ListImportFilesRequest, type ListImportFilesResponse, type ListImportsRequest, type ListImportsResponse, type ListJobsRequest, type ListJobsResponse, type ListMergeJobsRequest, type ListMergeJobsResponse, type ListPrivateFilesRequest, type ListPrivateFilesResponse, type ListRenderJobsRequest, type ListRenderJobsResponse, type ListThumbnailsRequest, type ListThumbnailsResponse, type MergeAspectRatio, type MergeInputItem, type MergeJob, type MergeJobWithOutput, type MergeOutputConfig, type MergeOutputFormat, type MergeQuality, type MergeStatus, type MoveAssetsRequest, type MoveAssetsResponse, type MoveFolderRequest, type MoveFolderResponse, type MovePrivateFilesRequest, type MovePrivateFilesResponse, type PrivateDownloadUrlRequest, type PrivateDownloadUrlResponse, type PrivateFile, type PrivateFileStatus, type PrivateUploadUrlRequest, type PrivateUploadUrlResponse, type RegenerateThumbnailRequest, type RegenerateThumbnailResponse, type RenderJob, type RenderJobWithOutput, type RenderOutputConfig, type RenderOutputFormat, type RenderStatus, type RetryImportResponse, type StreamingUrls, type TextOverlay, type TextOverlayShadow, type TextOverlayStroke, type TextVideoWatermarkOptions, type ThumbnailRequest, type ThumbnailResponse, type TranscodeJob, type TranscodeVideoRequest, type TranscodingStatus, type TransformOptions, type TrimOptions, type UpdateAssetRequest, type UpdateFolderRequest, type UpdatePrivateFileRequest, type UploadFromUrlRequest, type UploadUrlRequest, type UploadUrlResponse, type VideoCodec, type VideoGif, type VideoOutputFormat, type VideoQuality, type VideoSpec, type VideoThumbnail, type VideoVariant, type WatermarkOptions };
@@ -177,6 +177,16 @@ interface VideoVariant {
177
177
  quality: VideoQuality;
178
178
  codec?: VideoCodec;
179
179
  bitrate?: number;
180
+ /**
181
+ * Bytes actually written to storage for this rendition, measured after the job completes.
182
+ * For HLS this covers the variant playlist and its segments; for MP4, the single file.
183
+ *
184
+ * Response-only — ignored if you set it on a transcode request.
185
+ *
186
+ * Undefined means not measured (job still running, job predates measurement, or the
187
+ * measurement failed), never zero. `bitrate * duration` is an estimate; this is not.
188
+ */
189
+ sizeBytes?: number;
180
190
  }
181
191
  /**
182
192
  * Watermark burned into a video during transcode.
@@ -299,6 +309,13 @@ interface TranscodeJob {
299
309
  /** Provider or preprocessing failure details when status is `failed`. */
300
310
  errorMessage: string | null;
301
311
  mediaConvertJobId: string | null;
312
+ /**
313
+ * Every byte this job wrote: renditions, HLS segments, and manifests together, since
314
+ * storage is billed per object rather than for the media alone.
315
+ *
316
+ * Null until the job completes, and null if the measurement failed. Not zero.
317
+ */
318
+ totalOutputBytes: number | null;
302
319
  createdAt: Date;
303
320
  startedAt: Date | null;
304
321
  completedAt: Date | null;
@@ -534,6 +551,14 @@ interface CdnUsageRequest {
534
551
  environment?: CdnEnvironment;
535
552
  periodStart?: Date | string;
536
553
  periodEnd?: Date | string;
554
+ /**
555
+ * Virtual folder path to scope the stats to, e.g. "/customers/acme". Covers the folder
556
+ * itself and everything nested under it — the same scoping as `getStorageUsage`. Use
557
+ * this to meter bandwidth per tenant when each tenant uploads under its own folder.
558
+ * Folder-scoped stats only cover assets that still exist; deleting an asset removes
559
+ * its serving history, so a period total can shrink.
560
+ */
561
+ folder?: string;
537
562
  }
538
563
  interface CdnUsageResponse {
539
564
  periodStart: Date;
@@ -546,6 +571,12 @@ interface CdnUsageResponse {
546
571
  storageFormatted: string;
547
572
  estimatedCostCents: number;
548
573
  estimatedCostFormatted: string;
574
+ /**
575
+ * Echoes the folder the stats cover, null when the whole project or org was counted.
576
+ * When metering a tenant, check this echo — a server that predates folder scoping
577
+ * ignores the parameter and silently returns org-wide numbers.
578
+ */
579
+ folder: string | null;
549
580
  }
550
581
  interface CdnUsageHistoryRequest {
551
582
  projectSlug?: string;
@@ -587,6 +618,42 @@ interface CdnStorageBreakdownResponse {
587
618
  sizeFormatted: string;
588
619
  };
589
620
  }
621
+ interface CdnStorageUsageRequest {
622
+ projectSlug?: string;
623
+ environment?: CdnEnvironment;
624
+ /**
625
+ * Virtual folder path to scope the total to, e.g. "/customers/acme". The folder itself and
626
+ * everything nested under it are counted. Omit to total the whole project or organization.
627
+ */
628
+ folder?: string;
629
+ }
630
+ interface CdnStorageUsageBucket {
631
+ bytes: number;
632
+ bytesFormatted: string;
633
+ objectCount: number;
634
+ }
635
+ interface CdnStorageUsageResponse {
636
+ /** Uploads plus every measured derived object stored under the scope. */
637
+ totalBytes: number;
638
+ totalFormatted: string;
639
+ /** Objects behind that total. Storage is billed per object, so segments and manifests count. */
640
+ objectCount: number;
641
+ /** Split by asset type; a video's renditions count as video. */
642
+ byType: Record<string, CdnStorageUsageBucket>;
643
+ breakdown: {
644
+ /** The uploaded files themselves. */
645
+ originals: CdnStorageUsageBucket;
646
+ /** Renditions, HLS segments and manifests, thumbnails, GIFs. */
647
+ derived: CdnStorageUsageBucket;
648
+ };
649
+ /**
650
+ * Assets known to have derivatives whose bytes have not been measured yet. Their storage is
651
+ * missing from `totalBytes`, so a nonzero count means the total is a floor, not the answer.
652
+ */
653
+ unmeasuredAssets: number;
654
+ /** The folder the total covers, or null when the whole project or org was counted. */
655
+ folder: string | null;
656
+ }
590
657
  interface GetFolderRequest {
591
658
  id: string;
592
659
  }
@@ -894,6 +961,107 @@ interface ListMergeJobsResponse {
894
961
  total: number;
895
962
  hasMore: boolean;
896
963
  }
964
+ type RenderStatus = TranscodingStatus;
965
+ type RenderOutputFormat = "mp4" | "webm";
966
+ /**
967
+ * The declarative video spec.
968
+ *
969
+ * Typed loosely on purpose. The authoritative schema lives in
970
+ * `@stack0/video-spec`, which also ships worked examples and the timing engine;
971
+ * restating its shape here would create a second description of one contract
972
+ * that silently drifts. Install that package for full types and validation:
973
+ *
974
+ * ```typescript
975
+ * import { validateSpec, prankWithDemoExample } from '@stack0/video-spec'
976
+ * ```
977
+ */
978
+ type VideoSpec = Record<string, unknown>;
979
+ /**
980
+ * How the finished video is encoded.
981
+ *
982
+ * There is no quality or aspect ratio here: the spec's canvas declares width,
983
+ * height and fps, so scale is the only encode-side lever left.
984
+ */
985
+ interface RenderOutputConfig {
986
+ /** Container and codec: mp4/h264 or webm/vp8 (default: mp4) */
987
+ format?: RenderOutputFormat;
988
+ /** Multiplier on the spec's canvas, 0.1-4 (default: 1). Cost scales with the square of this. */
989
+ scale?: number;
990
+ /** Custom filename for the output */
991
+ filename?: string;
992
+ }
993
+ /**
994
+ * Request to render a video spec
995
+ */
996
+ interface CreateRenderJobRequest {
997
+ /** Project slug to create the render job in */
998
+ projectSlug: string;
999
+ /** The video spec: scenes, layers, timing and media. Data, not code. */
1000
+ spec: VideoSpec;
1001
+ /** Output configuration */
1002
+ output?: RenderOutputConfig;
1003
+ /** Webhook URL for completion notification */
1004
+ webhookUrl?: string;
1005
+ }
1006
+ /**
1007
+ * Request to list render jobs
1008
+ */
1009
+ interface ListRenderJobsRequest {
1010
+ projectSlug: string;
1011
+ /** Filter by status */
1012
+ status?: RenderStatus;
1013
+ /** Maximum number of results (default: 20, max: 100) */
1014
+ limit?: number;
1015
+ /** Offset for pagination */
1016
+ offset?: number;
1017
+ }
1018
+ /**
1019
+ * Render job response
1020
+ */
1021
+ interface RenderJob {
1022
+ id: string;
1023
+ organizationId: string;
1024
+ projectId: string;
1025
+ environment: "sandbox" | "production";
1026
+ /** The submitted spec, with media references resolved to URLs */
1027
+ spec: VideoSpec;
1028
+ outputFormat: RenderOutputFormat;
1029
+ outputScale: number;
1030
+ outputFilename: string | null;
1031
+ outputAssetId: string | null;
1032
+ status: RenderStatus;
1033
+ progress: number | null;
1034
+ errorMessage: string | null;
1035
+ startedAt: Date | null;
1036
+ completedAt: Date | null;
1037
+ /** Resolved from the spec at submission, before a single frame renders */
1038
+ width: number | null;
1039
+ height: number | null;
1040
+ fps: number | null;
1041
+ durationInFrames: number | null;
1042
+ outputDurationSeconds: number | null;
1043
+ webhookUrl: string | null;
1044
+ createdAt: Date;
1045
+ updatedAt: Date | null;
1046
+ }
1047
+ /**
1048
+ * Render job with output asset details
1049
+ */
1050
+ interface RenderJobWithOutput extends RenderJob {
1051
+ outputAsset: {
1052
+ id: string;
1053
+ cdnUrl: string;
1054
+ directUrl: string;
1055
+ filename: string;
1056
+ size: number;
1057
+ duration: number | null;
1058
+ } | null;
1059
+ }
1060
+ interface ListRenderJobsResponse {
1061
+ jobs: RenderJob[];
1062
+ total: number;
1063
+ hasMore: boolean;
1064
+ }
897
1065
  type ImportJobStatus = "pending" | "validating" | "importing" | "completed" | "failed" | "cancelled";
898
1066
  type ImportAuthType = "iam_credentials" | "role_assumption";
899
1067
  type ImportPathMode = "preserve" | "flatten";
@@ -1696,6 +1864,29 @@ declare class CDN {
1696
1864
  * ```
1697
1865
  */
1698
1866
  getStorageBreakdown(request?: CdnStorageBreakdownRequest): Promise<CdnStorageBreakdownResponse>;
1867
+ /**
1868
+ * Get total stored bytes for a project or folder, derived assets included.
1869
+ *
1870
+ * Totals uploads plus everything the pipelines derived from them — video renditions, HLS
1871
+ * segments and manifests, thumbnails, GIFs — in one call. Use this to meter a plan limit:
1872
+ * paging `list()` and summing `size` counts uploads only, and an HLS ladder typically runs
1873
+ * well past the size of the source it came from.
1874
+ *
1875
+ * Check `unmeasuredAssets`. A nonzero value means some assets have derivatives whose bytes
1876
+ * have not been measured, so `totalBytes` is a floor rather than the full number.
1877
+ *
1878
+ * @example
1879
+ * ```typescript
1880
+ * const usage = await cdn.getStorageUsage({
1881
+ * projectSlug: 'my-project',
1882
+ * folder: '/customers/acme',
1883
+ * });
1884
+ * console.log(`${usage.totalFormatted} across ${usage.objectCount} objects`);
1885
+ * console.log(` uploads: ${usage.breakdown.originals.bytesFormatted}`);
1886
+ * console.log(` derived: ${usage.breakdown.derived.bytesFormatted}`);
1887
+ * ```
1888
+ */
1889
+ getStorageUsage(request?: CdnStorageUsageRequest): Promise<CdnStorageUsageResponse>;
1699
1890
  private convertUsageDates;
1700
1891
  private convertUsageDataPointDates;
1701
1892
  /**
@@ -1878,6 +2069,78 @@ declare class CDN {
1878
2069
  }>;
1879
2070
  private convertMergeJobDates;
1880
2071
  private convertMergeJobWithOutputDates;
2072
+ /**
2073
+ * Render a declarative video spec into a video asset
2074
+ *
2075
+ * The spec describes scenes, layers, timing and media as data. There are no
2076
+ * compositions to write and no code to upload — Stack0 owns the renderer.
2077
+ *
2078
+ * `@stack0/video-spec` has the full types, validation and worked examples;
2079
+ * validating locally before you POST turns a round trip into a type error.
2080
+ *
2081
+ * @example
2082
+ * ```typescript
2083
+ * const job = await cdn.createRenderJob({
2084
+ * projectSlug: 'my-project',
2085
+ * spec: {
2086
+ * canvas: { width: 1080, height: 1920, fps: 30 },
2087
+ * audio: [{ src: musicAssetId, volume: 0.34 }],
2088
+ * scenes: [
2089
+ * {
2090
+ * id: 'hook',
2091
+ * duration: 2.5,
2092
+ * layers: [
2093
+ * { type: 'image', src: afterImageAssetId, zoom: { from: 1, to: 1.06 } },
2094
+ * { type: 'caption', text: 'i told my mom\nthe kitchen exploded', position: 'upperThird' },
2095
+ * ],
2096
+ * },
2097
+ * {
2098
+ * // No duration: the thread derives its own length from the messages
2099
+ * id: 'payoff',
2100
+ * layers: [
2101
+ * {
2102
+ * type: 'messageThread',
2103
+ * recipient: 'Mom',
2104
+ * imageSrc: afterImageAssetId,
2105
+ * messages: [
2106
+ * { sender: 'recipient', text: 'you home?', history: true },
2107
+ * { sender: 'user', text: '[IMAGE]' },
2108
+ * { sender: 'recipient', text: 'WHAT IS THAT' },
2109
+ * ],
2110
+ * },
2111
+ * ],
2112
+ * },
2113
+ * ],
2114
+ * },
2115
+ * webhookUrl: 'https://your-app.com/webhook',
2116
+ * });
2117
+ * console.log(job.durationInFrames); // known before rendering starts
2118
+ * ```
2119
+ */
2120
+ createRenderJob(request: CreateRenderJobRequest): Promise<RenderJob>;
2121
+ /**
2122
+ * Get a render job by ID with output asset details
2123
+ *
2124
+ * @example
2125
+ * ```typescript
2126
+ * const job = await cdn.getRenderJob('job-id');
2127
+ * if (job.status === 'completed' && job.outputAsset) {
2128
+ * console.log(`Output video: ${job.outputAsset.cdnUrl}`);
2129
+ * }
2130
+ * ```
2131
+ */
2132
+ getRenderJob(jobId: string): Promise<RenderJobWithOutput>;
2133
+ /**
2134
+ * List render jobs with optional filters
2135
+ */
2136
+ listRenderJobs(request: ListRenderJobsRequest): Promise<ListRenderJobsResponse>;
2137
+ /**
2138
+ * Cancel a pending or processing render job
2139
+ */
2140
+ cancelRenderJob(jobId: string): Promise<{
2141
+ success: boolean;
2142
+ }>;
2143
+ private convertRenderJobDates;
1881
2144
  /**
1882
2145
  * Create an S3 import job to bulk import files from an external S3 bucket.
1883
2146
  * Requires Pro plan or higher.
@@ -1995,4 +2258,4 @@ declare class CDN {
1995
2258
  private convertImportFileDates;
1996
2259
  }
1997
2260
 
1998
- export { type Asset, type AssetStatus, type AssetType, type AudioTrackInput, type BundleDownloadUrlRequest, type BundleDownloadUrlResponse, type BundleStatus, CDN, type CancelImportResponse, type CancelMergeJobRequest, type CdnEnvironment, type CdnStorageBreakdownItem, type CdnStorageBreakdownRequest, type CdnStorageBreakdownResponse, type CdnUsageDataPoint, type CdnUsageHistoryRequest, type CdnUsageHistoryResponse, type CdnUsageRequest, type CdnUsageResponse, type CompositeChromaKey, type CompositeConfig, type CompositePoint, type CompositeQuad, type CompositeRect, type ConfirmUploadRequest, type ConfirmUploadResponse, type CreateBundleRequest, type CreateBundleResponse, type CreateFolderRequest, type CreateImportRequest, type CreateImportResponse, type CreateMergeJobRequest, type DeleteAssetRequest, type DeleteAssetsRequest, type DeleteAssetsResponse, type DownloadBundle, type ExtractAudioRequest, type ExtractAudioResponse, type Folder, type FolderListItem, type FolderTreeNode, type GenerateGifRequest, type GetAssetRequest, type GetFolderByPathRequest, type GetFolderRequest, type GetFolderTreeRequest, type GetMergeJobRequest, type GifStatus, type ImageVideoWatermarkOptions, type ImageWatermarkConfig, type ImageWatermarkPosition, type ImageWatermarkSizingMode, type ImportAuthType, type ImportError, type ImportFile, type ImportFileStatus, type ImportJob, type ImportJobStatus, type ImportJobSummary, type ImportPathMode, type ListAssetsRequest, type ListAssetsResponse, type ListBundlesRequest, type ListBundlesResponse, type ListFoldersRequest, type ListFoldersResponse, type ListGifsRequest, type ListImportFilesRequest, type ListImportFilesResponse, type ListImportsRequest, type ListImportsResponse, type ListJobsRequest, type ListJobsResponse, type ListMergeJobsRequest, type ListMergeJobsResponse, type ListPrivateFilesRequest, type ListPrivateFilesResponse, type ListThumbnailsRequest, type ListThumbnailsResponse, type MergeAspectRatio, type MergeInputItem, type MergeJob, type MergeJobWithOutput, type MergeOutputConfig, type MergeOutputFormat, type MergeQuality, type MergeStatus, type MoveAssetsRequest, type MoveAssetsResponse, type MoveFolderRequest, type MoveFolderResponse, type MovePrivateFilesRequest, type MovePrivateFilesResponse, type PrivateDownloadUrlRequest, type PrivateDownloadUrlResponse, type PrivateFile, type PrivateFileStatus, type PrivateUploadUrlRequest, type PrivateUploadUrlResponse, type RegenerateThumbnailRequest, type RegenerateThumbnailResponse, type RetryImportResponse, type StreamingUrls, type TextOverlay, type TextOverlayShadow, type TextOverlayStroke, type TextVideoWatermarkOptions, type ThumbnailRequest, type ThumbnailResponse, type TranscodeJob, type TranscodeVideoRequest, type TranscodingStatus, type TransformOptions, type TrimOptions, type UpdateAssetRequest, type UpdateFolderRequest, type UpdatePrivateFileRequest, type UploadFromUrlRequest, type UploadUrlRequest, type UploadUrlResponse, type VideoCodec, type VideoGif, type VideoOutputFormat, type VideoQuality, type VideoThumbnail, type VideoVariant, type WatermarkOptions };
2261
+ export { type Asset, type AssetStatus, type AssetType, type AudioTrackInput, type BundleDownloadUrlRequest, type BundleDownloadUrlResponse, type BundleStatus, CDN, type CancelImportResponse, type CancelMergeJobRequest, type CdnEnvironment, type CdnStorageBreakdownItem, type CdnStorageBreakdownRequest, type CdnStorageBreakdownResponse, type CdnStorageUsageBucket, type CdnStorageUsageRequest, type CdnStorageUsageResponse, type CdnUsageDataPoint, type CdnUsageHistoryRequest, type CdnUsageHistoryResponse, type CdnUsageRequest, type CdnUsageResponse, type CompositeChromaKey, type CompositeConfig, type CompositePoint, type CompositeQuad, type CompositeRect, type ConfirmUploadRequest, type ConfirmUploadResponse, type CreateBundleRequest, type CreateBundleResponse, type CreateFolderRequest, type CreateImportRequest, type CreateImportResponse, type CreateMergeJobRequest, type CreateRenderJobRequest, type DeleteAssetRequest, type DeleteAssetsRequest, type DeleteAssetsResponse, type DownloadBundle, type ExtractAudioRequest, type ExtractAudioResponse, type Folder, type FolderListItem, type FolderTreeNode, type GenerateGifRequest, type GetAssetRequest, type GetFolderByPathRequest, type GetFolderRequest, type GetFolderTreeRequest, type GetMergeJobRequest, type GifStatus, type ImageVideoWatermarkOptions, type ImageWatermarkConfig, type ImageWatermarkPosition, type ImageWatermarkSizingMode, type ImportAuthType, type ImportError, type ImportFile, type ImportFileStatus, type ImportJob, type ImportJobStatus, type ImportJobSummary, type ImportPathMode, type ListAssetsRequest, type ListAssetsResponse, type ListBundlesRequest, type ListBundlesResponse, type ListFoldersRequest, type ListFoldersResponse, type ListGifsRequest, type ListImportFilesRequest, type ListImportFilesResponse, type ListImportsRequest, type ListImportsResponse, type ListJobsRequest, type ListJobsResponse, type ListMergeJobsRequest, type ListMergeJobsResponse, type ListPrivateFilesRequest, type ListPrivateFilesResponse, type ListRenderJobsRequest, type ListRenderJobsResponse, type ListThumbnailsRequest, type ListThumbnailsResponse, type MergeAspectRatio, type MergeInputItem, type MergeJob, type MergeJobWithOutput, type MergeOutputConfig, type MergeOutputFormat, type MergeQuality, type MergeStatus, type MoveAssetsRequest, type MoveAssetsResponse, type MoveFolderRequest, type MoveFolderResponse, type MovePrivateFilesRequest, type MovePrivateFilesResponse, type PrivateDownloadUrlRequest, type PrivateDownloadUrlResponse, type PrivateFile, type PrivateFileStatus, type PrivateUploadUrlRequest, type PrivateUploadUrlResponse, type RegenerateThumbnailRequest, type RegenerateThumbnailResponse, type RenderJob, type RenderJobWithOutput, type RenderOutputConfig, type RenderOutputFormat, type RenderStatus, type RetryImportResponse, type StreamingUrls, type TextOverlay, type TextOverlayShadow, type TextOverlayStroke, type TextVideoWatermarkOptions, type ThumbnailRequest, type ThumbnailResponse, type TranscodeJob, type TranscodeVideoRequest, type TranscodingStatus, type TransformOptions, type TrimOptions, type UpdateAssetRequest, type UpdateFolderRequest, type UpdatePrivateFileRequest, type UploadFromUrlRequest, type UploadUrlRequest, type UploadUrlResponse, type VideoCodec, type VideoGif, type VideoOutputFormat, type VideoQuality, type VideoSpec, type VideoThumbnail, type VideoVariant, type WatermarkOptions };