vargai 0.4.0-alpha63 → 0.4.0-alpha65

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.
package/package.json CHANGED
@@ -70,7 +70,7 @@
70
70
  "zod": "^4.2.1"
71
71
  },
72
72
  "sideEffects": false,
73
- "version": "0.4.0-alpha63",
73
+ "version": "0.4.0-alpha65",
74
74
  "exports": {
75
75
  ".": "./src/index.ts",
76
76
  "./ai": "./src/ai-sdk/index.ts",
@@ -268,6 +268,8 @@ export class File {
268
268
  "video/mp4": ".mp4",
269
269
  "video/webm": ".webm",
270
270
  "video/quicktime": ".mov",
271
+ "text/x-ssa": ".ass",
272
+ "application/x-subrip": ".srt",
271
273
  };
272
274
  return extMap[this._mediaType] ?? "";
273
275
  }
@@ -290,6 +292,9 @@ function inferMediaType(path: string): string {
290
292
  mp4: "video/mp4",
291
293
  webm: "video/webm",
292
294
  mov: "video/quicktime",
295
+ ass: "text/x-ssa",
296
+ ssa: "text/x-ssa",
297
+ srt: "application/x-subrip",
293
298
  };
294
299
  return mimeTypes[ext ?? ""] ?? "application/octet-stream";
295
300
  }
@@ -170,6 +170,30 @@ export async function renderRoot(
170
170
  const audioTracks: AudioTrack[] = [];
171
171
  let captionsResult: Awaited<ReturnType<typeof renderCaptions>> | undefined;
172
172
 
173
+ // Hoist <Captions> out of <Clip> elements — the AI often places them inside
174
+ // clips, but captions must be processed at the <Render> level to work.
175
+ const hoistedCaptions: VargElement<"captions">[] = [];
176
+ for (const child of element.children) {
177
+ if (!child || typeof child !== "object" || !("type" in child)) continue;
178
+ const childElement = child as VargElement;
179
+ if (childElement.type === "clip" && childElement.children) {
180
+ const kept: typeof childElement.children = [];
181
+ for (const clipChild of childElement.children) {
182
+ if (
183
+ clipChild &&
184
+ typeof clipChild === "object" &&
185
+ "type" in clipChild &&
186
+ (clipChild as VargElement).type === "captions"
187
+ ) {
188
+ hoistedCaptions.push(clipChild as VargElement<"captions">);
189
+ } else {
190
+ kept.push(clipChild);
191
+ }
192
+ }
193
+ childElement.children = kept;
194
+ }
195
+ }
196
+
173
197
  for (const child of element.children) {
174
198
  if (!child || typeof child !== "object" || !("type" in child)) continue;
175
199
 
@@ -206,6 +230,18 @@ export async function renderRoot(
206
230
  }
207
231
  }
208
232
 
233
+ // Process any <Captions> that were hoisted from inside <Clip> elements
234
+ if (!captionsResult && hoistedCaptions.length > 0) {
235
+ const captionsElement = hoistedCaptions[0]!;
236
+ captionsResult = await renderCaptions(captionsElement, ctx);
237
+ if (captionsResult.audioPath) {
238
+ audioTracks.push({
239
+ path: captionsResult.audioPath,
240
+ mixVolume: 1,
241
+ });
242
+ }
243
+ }
244
+
209
245
  const renderedOverlays: RenderedOverlay[] = [];
210
246
  for (const overlay of overlayElements) {
211
247
  const overlayProps = overlay.props as OverlayProps;