Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 14 additions & 6 deletions schemas/richcaptionasset.yaml
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
RichCaptionAsset:
description: |
The RichCaptionAsset provides word-level caption animations with rich-text styling. It supports
karaoke-style highlighting, word-by-word animations, and advanced typography. Use with SRT/VTT
files or auto-transcription via aliases.
karaoke-style highlighting, word-by-word animations, and advanced typography. Captions can be
sourced from SRT/VTT/TTML subtitle files, from audio/video media URLs (auto-transcribed), or
from alias references to other clips in the same timeline.
type: object
properties:
type:
Expand All @@ -12,10 +13,17 @@ RichCaptionAsset:
type: string
src:
description: >-
The URL to an SRT or VTT subtitles file, or an alias reference to auto-generate captions
from an audio or video clip. For file URLs, the URL must be publicly accessible or include
credentials. For auto-captioning, use the format `alias://clip-name` where clip-name is
the alias of an audio, video, or text-to-speech clip.
Source for the caption words. Accepts three formats:
(1) the URL to a subtitle file (`.srt`, `.vtt`, `.ttml`, or `.dfxp`) which is parsed
directly;
(2) the URL to an audio or video media file (`.mp4`, `.mov`, `.webm`, `.mp3`, `.wav`,
`.m4a`, `.flac`, `.aac`, `.ogg`, and related formats) which is auto-transcribed;
(3) an alias reference in the form `alias://clip-name` where `clip-name` is the alias of
another audio, video, or text-to-speech clip in the same timeline — the referenced clip's
source is auto-transcribed.
For file URLs, the URL must be publicly accessible or include credentials. Content is
classified at runtime and unsupported content types (HTML, PDF, images, archives) are
rejected with a structured error.
type: string
minLength: 1
example: "alias://audio"
Expand Down
45 changes: 0 additions & 45 deletions scripts/fix-discriminator.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -330,50 +330,7 @@ function addStrictToObjects(src, prefix) {
}


// --- Rich-caption src media file validation ---
const MEDIA_FILE_EXTENSIONS = [
".m4a", ".mp3", ".wav", ".aac", ".ogg", ".flac", ".wma",
".mp4", ".mov", ".avi", ".mkv", ".webm", ".wmv", ".flv", ".3gp",
];

function addRichCaptionSrcValidation(code, zPrefix) {
const schemaName = 'richcaptionassetRichCaptionAssetSchema';
const idx = code.indexOf(schemaName);
if (idx === -1) {
console.log("⚠ Could not find " + schemaName);
return code;
}

const strictMarker = '.strict()';
const strictIdx = code.indexOf(strictMarker, idx);
if (strictIdx === -1 || strictIdx - idx > 3000) {
console.log("⚠ Could not find .strict() for " + schemaName);
return code;
}

const superRefine = strictMarker + '.superRefine((data, ctx) => {\n' +
' if (data.src) {\n' +
' try {\n' +
' const pathname = new URL(data.src).pathname.toLowerCase();\n' +
' const mediaExts = ' + JSON.stringify(MEDIA_FILE_EXTENSIONS) + ';\n' +
' if (mediaExts.some((ext) => pathname.endsWith(ext))) {\n' +
' ctx.addIssue({\n' +
' code: ' + zPrefix + '.ZodIssueCode.custom,\n' +
' message: "Caption src must be an SRT or VTT subtitle file. To generate captions from a media asset, use an alias reference (e.g. \\"alias://my-clip\\") instead of a direct URL. See: https://shotstack.io/docs/guide/architecting-an-application/rich-captions/",\n' +
' path: ["src"],\n' +
' });\n' +
' }\n' +
' } catch {}\n' +
' }\n' +
'})';

code = code.substring(0, strictIdx) + superRefine + code.substring(strictIdx + strictMarker.length);
console.log("✓ Added rich-caption src media validation (" + zPrefix + ")");
return code;
}

content = addStrictToObjects(content, "z");
content = addRichCaptionSrcValidation(content, "z");

fs.writeFileSync(zodGenPath, content);

Expand Down Expand Up @@ -593,7 +550,6 @@ const clipClipSchemaWithFitFilter = exports.clipClipSchema.transform((clip) => {
}

cjsContent = addStrictToObjects(cjsContent, "zod_1.z");
cjsContent = addRichCaptionSrcValidation(cjsContent, "zod_1.z");

fs.writeFileSync(zodGenCjsPath, cjsContent);
}
Expand Down Expand Up @@ -726,7 +682,6 @@ const clipClipSchemaWithFitFilter = clipClipSchema.transform((clip) => {
}

jsContent = addStrictToObjects(jsContent, "z");
jsContent = addRichCaptionSrcValidation(jsContent, "z");

fs.writeFileSync(zodGenJsPath, jsContent);
}
Expand Down
Loading