@editframe/api 0.8.0-beta.4 → 0.8.0-beta.7

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.
Files changed (47) hide show
  1. package/dist/CHUNK_SIZE_BYTES.d.ts +1 -0
  2. package/dist/CHUNK_SIZE_BYTES.js +7 -0
  3. package/dist/client.d.ts +0 -2
  4. package/dist/client.js +2 -14
  5. package/dist/client.test.d.ts +1 -0
  6. package/dist/readableFromBuffers.d.ts +2 -0
  7. package/dist/resources/caption-file.d.ts +22 -3
  8. package/dist/resources/caption-file.js +28 -26
  9. package/dist/resources/caption-file.test.d.ts +1 -0
  10. package/dist/resources/image-file.d.ts +5 -3
  11. package/dist/resources/image-file.js +23 -27
  12. package/dist/resources/image-file.test.d.ts +1 -0
  13. package/dist/resources/isobmff-file.d.ts +2 -3
  14. package/dist/resources/isobmff-file.js +17 -23
  15. package/dist/resources/isobmff-file.test.d.ts +1 -0
  16. package/dist/resources/isobmff-track.d.ts +27 -28
  17. package/dist/resources/isobmff-track.js +18 -31
  18. package/dist/resources/isobmff-track.test.d.ts +1 -0
  19. package/dist/resources/renders.d.ts +4 -5
  20. package/dist/resources/renders.js +17 -21
  21. package/dist/resources/renders.test.d.ts +1 -0
  22. package/dist/resources/unprocessed-file.d.ts +14 -12
  23. package/dist/resources/unprocessed-file.js +36 -45
  24. package/dist/resources/unprocessed-file.test.d.ts +1 -0
  25. package/dist/resources/url-token.d.ts +0 -1
  26. package/dist/resources/url-token.test.d.ts +1 -0
  27. package/dist/streamChunker.d.ts +2 -0
  28. package/dist/streamChunker.js +17 -0
  29. package/dist/streamChunker.test.d.ts +1 -0
  30. package/dist/uploadChunks.d.ts +10 -0
  31. package/dist/uploadChunks.js +65 -0
  32. package/dist/uploadChunks.test.d.ts +1 -0
  33. package/package.json +4 -3
  34. package/src/resources/caption-file.test.ts +124 -0
  35. package/src/resources/caption-file.ts +49 -24
  36. package/src/resources/image-file.test.ts +138 -0
  37. package/src/resources/image-file.ts +28 -25
  38. package/src/resources/isobmff-file.test.ts +108 -0
  39. package/src/resources/isobmff-file.ts +19 -22
  40. package/src/resources/isobmff-track.test.ts +152 -0
  41. package/src/resources/isobmff-track.ts +22 -31
  42. package/src/resources/renders.test.ts +112 -0
  43. package/src/resources/renders.ts +19 -20
  44. package/src/resources/test-av-file.txt +1 -0
  45. package/src/resources/unprocessed-file.test.ts +312 -0
  46. package/src/resources/unprocessed-file.ts +41 -44
  47. package/src/resources/url-token.test.ts +46 -0
@@ -0,0 +1 @@
1
+ export declare let CHUNK_SIZE_BYTES: number;
@@ -0,0 +1,7 @@
1
+ let CHUNK_SIZE_BYTES = 8 * 1024 * 1024;
2
+ if (process.env.CHUNK_SIZE_BYTES) {
3
+ CHUNK_SIZE_BYTES = Number.parseInt(process.env.CHUNK_SIZE_BYTES, 10);
4
+ }
5
+ export {
6
+ CHUNK_SIZE_BYTES
7
+ };
package/dist/client.d.ts CHANGED
@@ -1,8 +1,6 @@
1
1
  import { RequestInit } from 'node-fetch';
2
- import * as jwt from "jsonwebtoken";
3
2
  export declare class Client {
4
3
  #private;
5
4
  constructor(token: string, efHost?: string);
6
5
  authenticatedFetch: (path: string, init?: RequestInit) => Promise<import('node-fetch').Response>;
7
- sign(payload: Record<string, unknown>, expiresIn?: Parameters<typeof jwt.sign>[2]["expiresIn"]): string;
8
6
  }
package/dist/client.js CHANGED
@@ -1,5 +1,4 @@
1
1
  import debug from "debug";
2
- import * as jwt from "jsonwebtoken";
3
2
  import fetch from "node-fetch";
4
3
  const log = debug("ef:api:client");
5
4
  class Client {
@@ -9,7 +8,7 @@ class Client {
9
8
  const url = new URL(path, this.#efHost);
10
9
  log(
11
10
  "Authenticated fetch",
12
- { url, init },
11
+ { url: url.toString(), init },
13
12
  "(Token will be added as Bearer token)"
14
13
  );
15
14
  Object.assign(init.headers, {
@@ -25,22 +24,11 @@ class Client {
25
24
  this.#efHost = efHost;
26
25
  const { apiKey, apiSecret } = token.match(/^(?<apiSecret>ef_[^_]+)_(?<apiKey>.+)$/)?.groups ?? {};
27
26
  if (!apiKey || !apiSecret) {
28
- throw new Error("Invalid token format");
27
+ throw new Error("Invalid token format. Must look like: ef_{}_{}");
29
28
  }
30
- this.#apiKey = apiKey;
31
- this.#apiSecret = apiSecret;
32
29
  }
33
- #apiKey;
34
- #apiSecret;
35
30
  #token;
36
31
  #efHost;
37
- sign(payload, expiresIn = 60) {
38
- payload.cid = this.#apiKey;
39
- return jwt.sign(payload, this.#apiSecret, {
40
- algorithm: "HS256",
41
- expiresIn
42
- });
43
- }
44
32
  }
45
33
  export {
46
34
  Client
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,2 @@
1
+ import { Readable } from 'node:stream';
2
+ export declare const readableFromBuffers: (...buffers: Buffer[]) => Readable;
@@ -1,20 +1,39 @@
1
1
  import { Readable } from 'node:stream';
2
2
  import { z } from 'zod';
3
3
  import { Client } from '../client.ts';
4
-
5
4
  export declare const CreateCaptionFilePayload: z.ZodObject<{
6
5
  id: z.ZodString;
7
6
  filename: z.ZodString;
7
+ byte_size: z.ZodNumber;
8
8
  }, "strip", z.ZodTypeAny, {
9
9
  id: string;
10
10
  filename: string;
11
+ byte_size: number;
11
12
  }, {
12
13
  id: string;
13
14
  filename: string;
15
+ byte_size: number;
14
16
  }>;
15
17
  export interface CreateCaptionFileResult {
16
18
  complete: boolean | null;
17
19
  id: string;
18
20
  }
19
- export declare const createCaptionFile: (client: Client, payload: z.infer<typeof CreateCaptionFilePayload>) => Promise<CreateCaptionFileResult | undefined>;
20
- export declare const uploadCaptionFile: (client: Client, fileId: string, fileStream: Readable) => Promise<unknown>;
21
+ /**
22
+ * Create a caption file
23
+ * @param client - The authenticated client to use for the request
24
+ * @param payload - The payload to send to the server
25
+ * @returns The result of the request
26
+ * @example
27
+ * ```ts
28
+ * const result = await createCaptionFile(client, {
29
+ * id: "123",
30
+ * filename: "caption.srt",
31
+ * });
32
+ * console.log(result);
33
+ * ```
34
+ * @category CaptionFile
35
+ * @resource
36
+ * @beta
37
+ */
38
+ export declare const createCaptionFile: (client: Client, payload: z.infer<typeof CreateCaptionFilePayload>) => Promise<CreateCaptionFileResult>;
39
+ export declare const uploadCaptionFile: (client: Client, fileId: string, fileStream: Readable, fileSize: number) => Promise<unknown>;
@@ -1,53 +1,55 @@
1
1
  import { z } from "zod";
2
2
  import debug from "debug";
3
3
  const log = debug("ef:api:caption-file");
4
+ const MAX_CAPTION_SIZE = 1024 * 1024 * 2;
4
5
  const CreateCaptionFilePayload = z.object({
5
6
  id: z.string(),
6
- filename: z.string()
7
+ filename: z.string(),
8
+ byte_size: z.number().int().max(MAX_CAPTION_SIZE)
7
9
  });
10
+ const restrictSize = (size) => {
11
+ if (size > MAX_CAPTION_SIZE) {
12
+ throw new Error(
13
+ `File size ${size} bytes exceeds limit ${MAX_CAPTION_SIZE} bytes
14
+ `
15
+ );
16
+ }
17
+ };
8
18
  const createCaptionFile = async (client, payload) => {
9
19
  log("Creating caption file", payload);
10
- const fileCreation = await client.authenticatedFetch(
20
+ restrictSize(payload.byte_size);
21
+ const response = await client.authenticatedFetch(
11
22
  "/api/video2/caption_files",
12
23
  {
13
24
  method: "POST",
14
25
  body: JSON.stringify(payload)
15
26
  }
16
27
  );
17
- log("Caption file created", fileCreation);
18
- switch (fileCreation.status) {
19
- case 200: {
20
- return await fileCreation.json();
21
- }
22
- default: {
23
- console.error(
24
- `Failed to create file ${fileCreation.status} ${fileCreation.statusText}`
25
- );
26
- return;
27
- }
28
+ log("Caption file created", response);
29
+ if (response.ok) {
30
+ return await response.json();
28
31
  }
32
+ throw new Error(
33
+ `Failed to create caption ${response.status} ${response.statusText}`
34
+ );
29
35
  };
30
- const uploadCaptionFile = async (client, fileId, fileStream) => {
36
+ const uploadCaptionFile = async (client, fileId, fileStream, fileSize) => {
31
37
  log("Uploading caption file", fileId);
32
- const fileIndex = await client.authenticatedFetch(
38
+ restrictSize(fileSize);
39
+ const response = await client.authenticatedFetch(
33
40
  `/api/video2/caption_files/${fileId}/upload`,
34
41
  {
35
42
  method: "POST",
36
43
  body: fileStream
37
44
  }
38
45
  );
39
- log("Caption file uploaded", fileIndex);
40
- switch (fileIndex.status) {
41
- case 200: {
42
- return fileIndex.json();
43
- }
44
- default: {
45
- console.error(
46
- `Failed to upload caption ${fileIndex.status} ${fileIndex.statusText}`
47
- );
48
- return;
49
- }
46
+ log("Caption file uploaded", response);
47
+ if (response.ok) {
48
+ return response.json();
50
49
  }
50
+ throw new Error(
51
+ `Failed to upload caption ${response.status} ${response.statusText}`
52
+ );
51
53
  };
52
54
  export {
53
55
  CreateCaptionFilePayload,
@@ -0,0 +1 @@
1
+ export {};
@@ -1,22 +1,24 @@
1
1
  import { Readable } from 'node:stream';
2
2
  import { z } from 'zod';
3
3
  import { Client } from '../client.ts';
4
-
5
4
  export declare const CreateImageFilePayload: z.ZodObject<{
6
5
  id: z.ZodString;
7
6
  height: z.ZodNumber;
8
7
  width: z.ZodNumber;
9
8
  mime_type: z.ZodEnum<["image/jpeg", "image/png", "image/jpg", "image/webp"]>;
10
9
  filename: z.ZodString;
10
+ byte_size: z.ZodNumber;
11
11
  }, "strip", z.ZodTypeAny, {
12
12
  id: string;
13
13
  filename: string;
14
+ byte_size: number;
14
15
  height: number;
15
16
  width: number;
16
17
  mime_type: "image/jpeg" | "image/png" | "image/jpg" | "image/webp";
17
18
  }, {
18
19
  id: string;
19
20
  filename: string;
21
+ byte_size: number;
20
22
  height: number;
21
23
  width: number;
22
24
  mime_type: "image/jpeg" | "image/png" | "image/jpg" | "image/webp";
@@ -25,5 +27,5 @@ export interface CreateImageFileResult {
25
27
  complete: boolean | null;
26
28
  id: string;
27
29
  }
28
- export declare const createImageFile: (client: Client, payload: z.infer<typeof CreateImageFilePayload>) => Promise<CreateImageFileResult | undefined>;
29
- export declare const uploadImageFile: (client: Client, fileId: string, fileStream: Readable) => Promise<unknown>;
30
+ export declare const createImageFile: (client: Client, payload: z.infer<typeof CreateImageFilePayload>) => Promise<CreateImageFileResult>;
31
+ export declare const uploadImageFile: (client: Client, fileId: string, fileStream: Readable, fileSize: number) => Promise<void>;
@@ -1,49 +1,45 @@
1
1
  import { z } from "zod";
2
2
  import debug from "debug";
3
+ import { uploadChunks } from "../uploadChunks.js";
3
4
  const log = debug("ef:api:image-file");
5
+ const MAX_IMAGE_SIZE = 1024 * 1024 * 16;
4
6
  const CreateImageFilePayload = z.object({
5
7
  id: z.string(),
6
8
  height: z.number().int(),
7
9
  width: z.number().int(),
8
10
  mime_type: z.enum(["image/jpeg", "image/png", "image/jpg", "image/webp"]),
9
- filename: z.string()
11
+ filename: z.string(),
12
+ byte_size: z.number().int().max(MAX_IMAGE_SIZE)
10
13
  });
11
14
  const createImageFile = async (client, payload) => {
12
15
  log("Creating image file", payload);
16
+ CreateImageFilePayload.parse(payload);
13
17
  const response = await client.authenticatedFetch("/api/video2/image_files", {
14
18
  method: "POST",
15
19
  body: JSON.stringify(payload)
16
20
  });
17
21
  log("Image file created", response);
18
- switch (response.status) {
19
- case 200: {
20
- return await response.json();
21
- }
22
- default: {
23
- console.error(
24
- `Failed to create file ${response.status} ${response.statusText}`
25
- );
26
- return;
27
- }
22
+ if (response.ok) {
23
+ return await response.json();
28
24
  }
29
- };
30
- const uploadImageFile = async (client, fileId, fileStream) => {
31
- const fileIndex = await client.authenticatedFetch(
32
- `/api/video2/image_files/${fileId}/upload`,
33
- {
34
- method: "POST",
35
- body: fileStream
36
- }
25
+ throw new Error(
26
+ `Failed to create file ${response.status} ${response.statusText}`
37
27
  );
38
- switch (fileIndex.status) {
39
- case 200: {
40
- return fileIndex.json();
41
- }
42
- default: {
43
- console.error("Failed to upload image");
44
- return;
45
- }
28
+ };
29
+ const uploadImageFile = async (client, fileId, fileStream, fileSize) => {
30
+ log("Uploading image file", fileId);
31
+ if (fileSize > MAX_IMAGE_SIZE) {
32
+ throw new Error(
33
+ `File size ${fileSize} bytes exceeds limit ${MAX_IMAGE_SIZE} bytes`
34
+ );
46
35
  }
36
+ const result = await uploadChunks(client, {
37
+ url: `/api/video2/image_files/${fileId}/upload`,
38
+ fileSize,
39
+ fileStream
40
+ });
41
+ log("Image file upload complete");
42
+ return result;
47
43
  };
48
44
  export {
49
45
  CreateImageFilePayload,
@@ -0,0 +1 @@
1
+ export {};
@@ -1,7 +1,6 @@
1
1
  import { Readable } from 'node:stream';
2
2
  import { z } from 'zod';
3
3
  import { Client } from '../client.ts';
4
-
5
4
  export declare const CreateISOBMFFFilePayload: z.ZodObject<{
6
5
  id: z.ZodString;
7
6
  filename: z.ZodString;
@@ -16,5 +15,5 @@ export interface CreateISOBMFFFileResult {
16
15
  fragment_index_complete: boolean;
17
16
  id: string;
18
17
  }
19
- export declare const createISOBMFFFile: (client: Client, payload: z.infer<typeof CreateISOBMFFFilePayload>) => Promise<CreateISOBMFFFileResult | undefined>;
20
- export declare const uploadFragmentIndex: (client: Client, fileId: string, fileStream: Readable) => Promise<unknown>;
18
+ export declare const createISOBMFFFile: (client: Client, payload: z.infer<typeof CreateISOBMFFFilePayload>) => Promise<CreateISOBMFFFileResult>;
19
+ export declare const uploadFragmentIndex: (client: Client, fileId: string, fileStream: Readable, fileSize: number) => Promise<unknown>;
@@ -1,6 +1,7 @@
1
1
  import { z } from "zod";
2
2
  import debug from "debug";
3
3
  const log = debug("ef:api:isobmff-file");
4
+ const FILE_SIZE_LIMIT = 1024 * 1024 * 2;
4
5
  const CreateISOBMFFFilePayload = z.object({
5
6
  id: z.string(),
6
7
  filename: z.string()
@@ -15,39 +16,32 @@ const createISOBMFFFile = async (client, payload) => {
15
16
  }
16
17
  );
17
18
  log("ISOBMFF file created", response);
18
- switch (response.status) {
19
- case 200: {
20
- return await response.json();
21
- }
22
- default: {
23
- console.error(
24
- `Failed to create file ${response.status} ${response.statusText}`
25
- );
26
- return;
27
- }
19
+ if (response.ok) {
20
+ return await response.json();
28
21
  }
22
+ throw new Error(
23
+ `Failed to create isobmff file ${response.status} ${response.statusText}`
24
+ );
29
25
  };
30
- const uploadFragmentIndex = async (client, fileId, fileStream) => {
26
+ const uploadFragmentIndex = async (client, fileId, fileStream, fileSize) => {
31
27
  log("Uploading fragment index", fileId);
32
- const fileIndex = await client.authenticatedFetch(
28
+ if (fileSize > FILE_SIZE_LIMIT) {
29
+ throw new Error(`File size exceeds limit of ${FILE_SIZE_LIMIT} bytes`);
30
+ }
31
+ const response = await client.authenticatedFetch(
33
32
  `/api/video2/isobmff_files/${fileId}/index/upload`,
34
33
  {
35
34
  method: "POST",
36
35
  body: fileStream
37
36
  }
38
37
  );
39
- log("Fragment index uploaded", fileIndex);
40
- switch (fileIndex.status) {
41
- case 200: {
42
- return fileIndex.json();
43
- }
44
- default: {
45
- console.error(
46
- `Failed to create fragment index ${fileIndex.status} ${fileIndex.statusText}`
47
- );
48
- return;
49
- }
38
+ log("Fragment index uploaded", response);
39
+ if (response.ok) {
40
+ return response.json();
50
41
  }
42
+ throw new Error(
43
+ `Failed to create fragment index ${response.status} ${response.statusText}`
44
+ );
51
45
  };
52
46
  export {
53
47
  CreateISOBMFFFilePayload,
@@ -0,0 +1 @@
1
+ export {};
@@ -1,7 +1,6 @@
1
1
  import { Readable } from 'node:stream';
2
2
  import { z } from 'zod';
3
3
  import { Client } from '../client.ts';
4
-
5
4
  export declare const CreateISOBMFFTrackPayload: z.ZodDiscriminatedUnion<"type", [z.ZodObject<{
6
5
  file_id: z.ZodString;
7
6
  track_id: z.ZodNumber;
@@ -29,7 +28,6 @@ export declare const CreateISOBMFFTrackPayload: z.ZodDiscriminatedUnion<"type",
29
28
  bit_rate: z.ZodString;
30
29
  disposition: z.ZodRecord<z.ZodString, z.ZodUnknown>;
31
30
  }, "strip", z.ZodTypeAny, {
32
- duration: number;
33
31
  index: number;
34
32
  codec_name: string;
35
33
  codec_long_name: string;
@@ -47,11 +45,11 @@ export declare const CreateISOBMFFTrackPayload: z.ZodDiscriminatedUnion<"type",
47
45
  start_pts: number;
48
46
  start_time: number;
49
47
  duration_ts: number;
48
+ duration: number;
50
49
  bit_rate: string;
51
50
  disposition: Record<string, unknown>;
52
51
  initial_padding?: number | undefined;
53
52
  }, {
54
- duration: number;
55
53
  index: number;
56
54
  codec_name: string;
57
55
  codec_long_name: string;
@@ -69,6 +67,7 @@ export declare const CreateISOBMFFTrackPayload: z.ZodDiscriminatedUnion<"type",
69
67
  start_pts: number;
70
68
  start_time: number;
71
69
  duration_ts: number;
70
+ duration: number;
72
71
  bit_rate: string;
73
72
  disposition: Record<string, unknown>;
74
73
  initial_padding?: number | undefined;
@@ -77,11 +76,12 @@ export declare const CreateISOBMFFTrackPayload: z.ZodDiscriminatedUnion<"type",
77
76
  codec_name: z.ZodString;
78
77
  byte_size: z.ZodNumber;
79
78
  }, "strip", z.ZodTypeAny, {
79
+ byte_size: number;
80
80
  type: "audio";
81
+ codec_name: string;
81
82
  file_id: string;
82
83
  track_id: number;
83
84
  probe_info: {
84
- duration: number;
85
85
  index: number;
86
86
  codec_name: string;
87
87
  codec_long_name: string;
@@ -99,19 +99,19 @@ export declare const CreateISOBMFFTrackPayload: z.ZodDiscriminatedUnion<"type",
99
99
  start_pts: number;
100
100
  start_time: number;
101
101
  duration_ts: number;
102
+ duration: number;
102
103
  bit_rate: string;
103
104
  disposition: Record<string, unknown>;
104
105
  initial_padding?: number | undefined;
105
106
  };
106
107
  duration_ms: number;
107
- codec_name: string;
108
- byte_size: number;
109
108
  }, {
109
+ byte_size: number;
110
110
  type: "audio";
111
+ codec_name: string;
111
112
  file_id: string;
112
113
  track_id: number;
113
114
  probe_info: {
114
- duration: number;
115
115
  index: number;
116
116
  codec_name: string;
117
117
  codec_long_name: string;
@@ -129,13 +129,12 @@ export declare const CreateISOBMFFTrackPayload: z.ZodDiscriminatedUnion<"type",
129
129
  start_pts: number;
130
130
  start_time: number;
131
131
  duration_ts: number;
132
+ duration: number;
132
133
  bit_rate: string;
133
134
  disposition: Record<string, unknown>;
134
135
  initial_padding?: number | undefined;
135
136
  };
136
137
  duration_ms: number;
137
- codec_name: string;
138
- byte_size: number;
139
138
  }>, z.ZodObject<{
140
139
  file_id: z.ZodString;
141
140
  track_id: z.ZodNumber;
@@ -161,6 +160,8 @@ export declare const CreateISOBMFFTrackPayload: z.ZodDiscriminatedUnion<"type",
161
160
  bit_rate: z.ZodOptional<z.ZodString>;
162
161
  disposition: z.ZodRecord<z.ZodString, z.ZodUnknown>;
163
162
  }, "strip", z.ZodTypeAny, {
163
+ height: number;
164
+ width: number;
164
165
  index: number;
165
166
  codec_name: string;
166
167
  codec_long_name: string;
@@ -171,16 +172,16 @@ export declare const CreateISOBMFFTrackPayload: z.ZodDiscriminatedUnion<"type",
171
172
  avg_frame_rate: string;
172
173
  time_base: string;
173
174
  disposition: Record<string, unknown>;
174
- width: number;
175
- height: number;
176
175
  coded_width: number;
177
176
  coded_height: number;
178
- duration?: number | undefined;
179
177
  start_pts?: number | undefined;
180
178
  start_time?: number | undefined;
181
179
  duration_ts?: number | undefined;
180
+ duration?: number | undefined;
182
181
  bit_rate?: string | undefined;
183
182
  }, {
183
+ height: number;
184
+ width: number;
184
185
  index: number;
185
186
  codec_name: string;
186
187
  codec_long_name: string;
@@ -191,24 +192,26 @@ export declare const CreateISOBMFFTrackPayload: z.ZodDiscriminatedUnion<"type",
191
192
  avg_frame_rate: string;
192
193
  time_base: string;
193
194
  disposition: Record<string, unknown>;
194
- width: number;
195
- height: number;
196
195
  coded_width: number;
197
196
  coded_height: number;
198
- duration?: number | undefined;
199
197
  start_pts?: number | undefined;
200
198
  start_time?: number | undefined;
201
199
  duration_ts?: number | undefined;
200
+ duration?: number | undefined;
202
201
  bit_rate?: string | undefined;
203
202
  }>;
204
203
  duration_ms: z.ZodNumber;
205
204
  codec_name: z.ZodString;
206
205
  byte_size: z.ZodNumber;
207
206
  }, "strip", z.ZodTypeAny, {
207
+ byte_size: number;
208
208
  type: "video";
209
+ codec_name: string;
209
210
  file_id: string;
210
211
  track_id: number;
211
212
  probe_info: {
213
+ height: number;
214
+ width: number;
212
215
  index: number;
213
216
  codec_name: string;
214
217
  codec_long_name: string;
@@ -219,24 +222,24 @@ export declare const CreateISOBMFFTrackPayload: z.ZodDiscriminatedUnion<"type",
219
222
  avg_frame_rate: string;
220
223
  time_base: string;
221
224
  disposition: Record<string, unknown>;
222
- width: number;
223
- height: number;
224
225
  coded_width: number;
225
226
  coded_height: number;
226
- duration?: number | undefined;
227
227
  start_pts?: number | undefined;
228
228
  start_time?: number | undefined;
229
229
  duration_ts?: number | undefined;
230
+ duration?: number | undefined;
230
231
  bit_rate?: string | undefined;
231
232
  };
232
233
  duration_ms: number;
233
- codec_name: string;
234
- byte_size: number;
235
234
  }, {
235
+ byte_size: number;
236
236
  type: "video";
237
+ codec_name: string;
237
238
  file_id: string;
238
239
  track_id: number;
239
240
  probe_info: {
241
+ height: number;
242
+ width: number;
240
243
  index: number;
241
244
  codec_name: string;
242
245
  codec_long_name: string;
@@ -247,25 +250,21 @@ export declare const CreateISOBMFFTrackPayload: z.ZodDiscriminatedUnion<"type",
247
250
  avg_frame_rate: string;
248
251
  time_base: string;
249
252
  disposition: Record<string, unknown>;
250
- width: number;
251
- height: number;
252
253
  coded_width: number;
253
254
  coded_height: number;
254
- duration?: number | undefined;
255
255
  start_pts?: number | undefined;
256
256
  start_time?: number | undefined;
257
257
  duration_ts?: number | undefined;
258
+ duration?: number | undefined;
258
259
  bit_rate?: string | undefined;
259
260
  };
260
261
  duration_ms: number;
261
- codec_name: string;
262
- byte_size: number;
263
262
  }>]>;
264
263
  export interface CreateISOBMFFTrackResult {
265
- last_received_byte: number;
264
+ next_byte: number;
266
265
  byte_size: number;
267
266
  track_id: number;
268
267
  file_id: string;
269
268
  }
270
- export declare const createISOBMFFTrack: (client: Client, payload: z.infer<typeof CreateISOBMFFTrackPayload>) => Promise<CreateISOBMFFTrackResult | undefined>;
271
- export declare const uploadISOBMFFTrack: (client: Client, fileId: string, trackId: number, fileStream: Readable) => Promise<unknown>;
269
+ export declare const createISOBMFFTrack: (client: Client, payload: z.infer<typeof CreateISOBMFFTrackPayload>) => Promise<CreateISOBMFFTrackResult>;
270
+ export declare const uploadISOBMFFTrack: (client: Client, fileId: string, trackId: number, fileStream: Readable, trackSize: number) => Promise<void>;
@@ -1,7 +1,9 @@
1
1
  import { z } from "zod";
2
2
  import debug from "debug";
3
3
  import { AudioStreamSchema, VideoStreamSchema } from "@editframe/assets";
4
+ import { uploadChunks } from "../uploadChunks.js";
4
5
  const log = debug("ef:api:isobmff-track");
6
+ const MAX_TRACK_SIZE = 1024 * 1024 * 1024;
5
7
  const CreateISOBMFFTrackPayload = z.discriminatedUnion("type", [
6
8
  z.object({
7
9
  file_id: z.string(),
@@ -10,7 +12,7 @@ const CreateISOBMFFTrackPayload = z.discriminatedUnion("type", [
10
12
  probe_info: AudioStreamSchema,
11
13
  duration_ms: z.number().int(),
12
14
  codec_name: z.string(),
13
- byte_size: z.number().int()
15
+ byte_size: z.number().int().max(MAX_TRACK_SIZE)
14
16
  }),
15
17
  z.object({
16
18
  file_id: z.string(),
@@ -19,11 +21,12 @@ const CreateISOBMFFTrackPayload = z.discriminatedUnion("type", [
19
21
  probe_info: VideoStreamSchema,
20
22
  duration_ms: z.number().int(),
21
23
  codec_name: z.string(),
22
- byte_size: z.number().int()
24
+ byte_size: z.number().int().max(MAX_TRACK_SIZE)
23
25
  })
24
26
  ]);
25
27
  const createISOBMFFTrack = async (client, payload) => {
26
28
  log("Creating isobmff track", payload);
29
+ CreateISOBMFFTrackPayload.parse(payload);
27
30
  const response = await client.authenticatedFetch(
28
31
  "/api/video2/isobmff_tracks",
29
32
  {
@@ -32,37 +35,21 @@ const createISOBMFFTrack = async (client, payload) => {
32
35
  }
33
36
  );
34
37
  log("ISOBMFF track created", response);
35
- switch (response.status) {
36
- case 200: {
37
- return await response.json();
38
- }
39
- default: {
40
- console.error("Failed to create track");
41
- console.error(await response.json());
42
- return;
43
- }
38
+ if (response.ok) {
39
+ return await response.json();
44
40
  }
45
- };
46
- const uploadISOBMFFTrack = async (client, fileId, trackId, fileStream) => {
47
- log("Uploading isobmff track", fileId, trackId);
48
- const trackIndex = await client.authenticatedFetch(
49
- `/api/video2/isobmff_tracks/${fileId}/${trackId}/upload`,
50
- {
51
- method: "POST",
52
- body: fileStream
53
- }
41
+ throw new Error(
42
+ `Failed to create isobmff track ${response.status} ${response.statusText}`
54
43
  );
55
- log("ISOBMFF track uploaded", trackIndex);
56
- switch (trackIndex.status) {
57
- case 200: {
58
- return trackIndex.json();
59
- }
60
- default: {
61
- console.error("Failed to upload track");
62
- console.error(trackIndex.status, trackIndex.statusText);
63
- return;
64
- }
65
- }
44
+ };
45
+ const uploadISOBMFFTrack = async (client, fileId, trackId, fileStream, trackSize) => {
46
+ log("Uploading fragment track", fileId);
47
+ await uploadChunks(client, {
48
+ url: `/api/video2/isobmff_tracks/${fileId}/${trackId}/upload`,
49
+ fileStream,
50
+ fileSize: trackSize
51
+ });
52
+ log("Fragment track upload complete");
66
53
  };
67
54
  export {
68
55
  CreateISOBMFFTrackPayload,