vargai 0.4.0-alpha111 → 0.4.0-alpha112

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
@@ -107,7 +107,7 @@
107
107
  "license": "Apache-2.0",
108
108
  "author": "varg.ai <hello@varg.ai> (https://varg.ai)",
109
109
  "sideEffects": false,
110
- "version": "0.4.0-alpha111",
110
+ "version": "0.4.0-alpha112",
111
111
  "exports": {
112
112
  ".": "./src/index.ts",
113
113
  "./ai": "./src/ai-sdk/index.ts",
@@ -904,100 +904,34 @@ async function resolveSourceUrl(
904
904
  throw new Error("cannot resolve source URL from input");
905
905
  }
906
906
 
907
- /** Get the varg gateway client settings. */
908
- function getGatewayConfig(): { apiKey: string; baseUrl: string } | null {
909
- const apiKey = process.env.VARG_API_KEY;
910
- if (!apiKey) return null;
911
- return {
912
- apiKey,
913
- baseUrl: process.env.VARG_API_URL ?? "https://api.varg.ai",
914
- };
915
- }
916
-
917
- /** Call gateway and wait for job completion. */
918
- async function gatewayJobRequest(
919
- path: string,
920
- body: Record<string, unknown>,
921
- ): Promise<Record<string, unknown>> {
922
- const config = getGatewayConfig();
923
- if (!config) throw new Error("VARG_API_KEY not set");
924
-
925
- const submitRes = await fetch(`${config.baseUrl}/v1${path}`, {
926
- method: "POST",
927
- headers: {
928
- "Content-Type": "application/json",
929
- Authorization: `Bearer ${config.apiKey}`,
930
- },
931
- body: JSON.stringify(body),
932
- signal: AbortSignal.timeout(30_000),
933
- });
934
- if (!submitRes.ok) {
935
- const text = await submitRes.text().catch(() => "");
936
- throw new Error(`gateway ${path} failed: ${submitRes.status} ${text}`);
937
- }
938
- const job = (await submitRes.json()) as {
939
- job_id: string;
940
- status: string;
941
- output?: Record<string, unknown>;
942
- };
943
-
944
- if (job.status === "completed" && job.output) return job;
945
-
946
- const maxAttempts = 300;
947
- for (let i = 0; i < maxAttempts; i++) {
948
- await new Promise((r) => setTimeout(r, 2_000));
949
- const pollRes = await fetch(`${config.baseUrl}/v1/jobs/${job.job_id}`, {
950
- headers: { Authorization: `Bearer ${config.apiKey}` },
951
- signal: AbortSignal.timeout(15_000),
952
- });
953
- if (!pollRes.ok) continue;
954
- const result = (await pollRes.json()) as {
955
- status: string;
956
- output?: Record<string, unknown>;
957
- error?: string;
958
- };
959
- if (result.status === "completed") return result;
960
- if (result.status === "failed")
961
- throw new Error(`gateway job failed: ${result.error ?? "unknown"}`);
962
- }
963
- throw new Error("gateway job timed out");
964
- }
965
-
966
907
  /**
967
- * Resolve a Slice element -- splits video into segments.
968
- * Returns a ResolvedElement with `.segments` populated (same pattern as Speech).
908
+ * Resolve a Slice element -- splits video into segments via gateway.
909
+ * Requires `gateway` prop (e.g., varg) for authenticated API access.
969
910
  */
970
911
  export async function resolveSliceElement(
971
912
  element: VargElement<"slice">,
972
913
  props: import("./types").SliceProps,
973
914
  ): Promise<ResolvedElement<"slice">> {
915
+ if (!props.gateway) {
916
+ throw new Error(
917
+ "await Slice() requires 'gateway' prop (e.g., Slice({ gateway: varg, src: video, every: 5 }))",
918
+ );
919
+ }
920
+
974
921
  const srcUrl = await resolveSourceUrl(props.src);
975
922
 
976
- const body: Record<string, unknown> = {
923
+ const result = await props.gateway.slice({
977
924
  video_url: srcUrl,
978
925
  codec: props.codec ?? "copy",
979
- };
980
- if (props.every !== undefined) body.every = props.every;
981
- if (props.at !== undefined) body.at = props.at;
982
- if (props.count !== undefined) body.count = props.count;
983
- if (props.ranges !== undefined) body.ranges = props.ranges;
984
-
985
- const result = await gatewayJobRequest("/ffmpeg/slice", body);
986
- const output = result.output as
987
- | { url?: string; metadata?: Record<string, unknown> }
988
- | undefined;
989
- const metadata = output?.metadata as
990
- | {
991
- segments?: Array<{ url: string; index: number; filename: string }>;
992
- total_segments?: number;
993
- }
994
- | undefined;
995
-
996
- const segmentData = metadata?.segments ?? [];
926
+ every: props.every,
927
+ at: props.at,
928
+ count: props.count,
929
+ ranges: props.ranges,
930
+ });
997
931
 
998
932
  const segments: import("./types").SliceSegment[] = [];
999
933
  let cursor = 0;
1000
- for (const seg of segmentData) {
934
+ for (const seg of result.segments) {
1001
935
  const segFile = File.fromUrl(seg.url);
1002
936
  const segDuration = await probeDuration(segFile);
1003
937
  const segElement = new ResolvedElement(
@@ -1015,8 +949,8 @@ export async function resolveSliceElement(
1015
949
  cursor += segDuration;
1016
950
  }
1017
951
 
1018
- const firstFile = segmentData[0]
1019
- ? File.fromUrl(segmentData[0].url)
952
+ const firstFile = result.segments[0]
953
+ ? File.fromUrl(result.segments[0].url)
1020
954
  : File.fromBuffer(new Uint8Array(0), "video/mp4");
1021
955
 
1022
956
  return new ResolvedElement(element, {
@@ -1028,11 +962,18 @@ export async function resolveSliceElement(
1028
962
 
1029
963
  /**
1030
964
  * Resolve an FFmpeg element -- runs arbitrary FFmpeg command via gateway.
965
+ * Requires `gateway` prop (e.g., varg) for authenticated API access.
1031
966
  */
1032
967
  export async function resolveFFmpegElement(
1033
968
  element: VargElement<"ffmpeg">,
1034
969
  props: import("./types").FFmpegProps,
1035
970
  ): Promise<ResolvedElement<"ffmpeg">> {
971
+ if (!props.gateway) {
972
+ throw new Error(
973
+ "await FFmpeg() requires 'gateway' prop (e.g., FFmpeg({ gateway: varg, command: '...' }))",
974
+ );
975
+ }
976
+
1036
977
  const inputFiles: Record<string, string> = {};
1037
978
  if (props.src) {
1038
979
  inputFiles.in_1 = await resolveSourceUrl(props.src);
@@ -1049,64 +990,39 @@ export async function resolveFFmpegElement(
1049
990
  }
1050
991
 
1051
992
  const outputFiles = command.includes("OUTPUT_FOLDER")
1052
- ? "OUTPUT_FOLDER"
993
+ ? ("OUTPUT_FOLDER" as const)
1053
994
  : { out_1: "output.mp4" };
1054
995
 
1055
- const result = await gatewayJobRequest("/ffmpeg", {
996
+ const result = await props.gateway.ffmpeg({
1056
997
  command,
1057
998
  input_files: inputFiles,
1058
999
  output_files: outputFiles,
1059
1000
  });
1060
1001
 
1061
- const output = result.output as
1062
- | { url?: string; media_type?: string }
1063
- | undefined;
1064
- const url = output?.url ?? "";
1065
- const file = url
1066
- ? File.fromUrl(url)
1002
+ const file = result.url
1003
+ ? File.fromUrl(result.url)
1067
1004
  : File.fromBuffer(new Uint8Array(0), "video/mp4");
1068
- const duration = url ? await probeDuration(file) : 0;
1005
+ const duration = result.url ? await probeDuration(file) : 0;
1069
1006
 
1070
1007
  return new ResolvedElement(element, { file, duration });
1071
1008
  }
1072
1009
 
1073
1010
  /**
1074
1011
  * Resolve a Probe element -- gets media metadata via gateway.
1012
+ * Requires `gateway` prop (e.g., varg) for authenticated API access.
1075
1013
  */
1076
1014
  export async function resolveProbeElement(
1077
1015
  element: VargElement<"probe">,
1078
1016
  props: import("./types").ProbeProps,
1079
1017
  ): Promise<ResolvedElement<"probe">> {
1080
- const srcUrl = await resolveSourceUrl(props.src);
1081
-
1082
- const config = getGatewayConfig();
1083
- if (!config) throw new Error("VARG_API_KEY not set");
1084
-
1085
- const res = await fetch(`${config.baseUrl}/v1/ffmpeg/probe`, {
1086
- method: "POST",
1087
- headers: {
1088
- "Content-Type": "application/json",
1089
- Authorization: `Bearer ${config.apiKey}`,
1090
- },
1091
- body: JSON.stringify({ url: srcUrl }),
1092
- signal: AbortSignal.timeout(30_000),
1093
- });
1094
- if (!res.ok) {
1095
- const text = await res.text().catch(() => "");
1096
- throw new Error(`probe failed: ${res.status} ${text}`);
1018
+ if (!props.gateway) {
1019
+ throw new Error(
1020
+ "await Probe() requires 'gateway' prop (e.g., Probe({ gateway: varg, src: video }))",
1021
+ );
1097
1022
  }
1098
1023
 
1099
- const probeData = (await res.json()) as {
1100
- duration?: number;
1101
- width?: number;
1102
- height?: number;
1103
- codec?: string;
1104
- audio_codec?: string;
1105
- format?: string;
1106
- bitrate?: number;
1107
- fps?: number;
1108
- size_bytes?: number;
1109
- };
1024
+ const srcUrl = await resolveSourceUrl(props.src);
1025
+ const probeData = await props.gateway.probe({ url: srcUrl });
1110
1026
 
1111
1027
  const file = File.fromUrl(srcUrl);
1112
1028
 
@@ -406,6 +406,43 @@ export interface RenderResult {
406
406
 
407
407
  // ── FFmpeg processing element props ──────────────────────────────────
408
408
 
409
+ /** Minimal gateway interface for FFmpeg utility methods. Implemented by VargProvider. */
410
+ export interface FFmpegGateway {
411
+ slice(params: {
412
+ video_url: string;
413
+ codec?: "copy" | "reencode";
414
+ every?: number;
415
+ at?: number[];
416
+ count?: number;
417
+ ranges?: Array<{ start: number; end: number }>;
418
+ }): Promise<{
419
+ url: string;
420
+ segments: Array<{ url: string; index: number; filename: string }>;
421
+ jobId: string;
422
+ }>;
423
+ probe(params: { url: string }): Promise<{
424
+ duration?: number;
425
+ width?: number;
426
+ height?: number;
427
+ codec?: string;
428
+ audio_codec?: string;
429
+ format?: string;
430
+ bitrate?: number;
431
+ fps?: number;
432
+ size_bytes?: number;
433
+ }>;
434
+ ffmpeg(params: {
435
+ command: string;
436
+ input_files?: Record<string, string>;
437
+ output_files?: Record<string, string> | string;
438
+ }): Promise<{
439
+ url: string;
440
+ mediaType: string;
441
+ jobId: string;
442
+ metadata?: Record<string, unknown>;
443
+ }>;
444
+ }
445
+
409
446
  export interface SliceProps {
410
447
  /** Source video: URL string, File object, or ResolvedElement */
411
448
  src: string | File | VargElement;
@@ -419,6 +456,8 @@ export interface SliceProps {
419
456
  count?: number;
420
457
  /** Split at explicit time ranges */
421
458
  ranges?: Array<{ start: number; end: number }>;
459
+ /** Authenticated gateway provider (e.g., varg). Required for cloud rendering. */
460
+ gateway?: FFmpegGateway;
422
461
  }
423
462
 
424
463
  export interface FFmpegProps {
@@ -428,11 +467,15 @@ export interface FFmpegProps {
428
467
  inputs?: Record<string, string | File | VargElement>;
429
468
  /** FFmpeg command flags (without -i input, which is added automatically for src) */
430
469
  command: string;
470
+ /** Authenticated gateway provider (e.g., varg). Required for cloud rendering. */
471
+ gateway?: FFmpegGateway;
431
472
  }
432
473
 
433
474
  export interface ProbeProps {
434
475
  /** Source to probe: URL string, File object, or ResolvedElement */
435
476
  src: string | File | VargElement;
477
+ /** Authenticated gateway provider (e.g., varg). Required for cloud rendering. */
478
+ gateway?: FFmpegGateway;
436
479
  }
437
480
 
438
481
  /**