@editframe/api 0.9.0-beta.1 → 0.10.0-beta.2
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/dist/index.d.ts +1 -1
- package/dist/index.js +3 -1
- package/dist/resources/caption-file.d.ts +5 -4
- package/dist/resources/caption-file.js +6 -9
- package/dist/resources/image-file.d.ts +5 -4
- package/dist/resources/image-file.js +3 -3
- package/dist/resources/isobmff-file.d.ts +6 -4
- package/dist/resources/isobmff-file.js +6 -9
- package/dist/resources/isobmff-track.js +5 -8
- package/dist/resources/renders.d.ts +5 -4
- package/dist/resources/renders.js +3 -3
- package/dist/resources/unprocessed-file.d.ts +18 -10
- package/dist/resources/unprocessed-file.js +70 -41
- package/package.json +2 -2
- package/src/resources/caption-file.test.ts +12 -15
- package/src/resources/caption-file.ts +8 -10
- package/src/resources/image-file.test.ts +10 -10
- package/src/resources/image-file.ts +5 -4
- package/src/resources/isobmff-file.test.ts +6 -6
- package/src/resources/isobmff-file.ts +9 -10
- package/src/resources/isobmff-track.test.ts +5 -5
- package/src/resources/isobmff-track.ts +5 -8
- package/src/resources/renders.test.ts +5 -5
- package/src/resources/renders.ts +5 -4
- package/src/resources/unprocessed-file.test.ts +237 -9
- package/src/resources/unprocessed-file.ts +92 -58
package/dist/index.d.ts
CHANGED
|
@@ -4,5 +4,5 @@ export { createISOBMFFFile, CreateISOBMFFFilePayload, type CreateISOBMFFFileResu
|
|
|
4
4
|
export { createISOBMFFTrack, CreateISOBMFFTrackPayload, type CreateISOBMFFTrackResult, uploadISOBMFFTrack, } from './resources/isobmff-track.ts';
|
|
5
5
|
export { createRender, CreateRenderPayload, type CreateRenderResult, uploadRender, } from './resources/renders.ts';
|
|
6
6
|
export { createURLToken, type URLTokenResult, } from './resources/url-token.ts';
|
|
7
|
-
export { createUnprocessedFile, CreateUnprocessedFilePayload, type CreateUnprocessedFileResult, updateUnprocessedFile, UpdateUnprocessedFilePayload, type UpdateUnprocessedFileResult, uploadUnprocessedFile, processAVFile, processAVFileBuffer, } from './resources/unprocessed-file.ts';
|
|
7
|
+
export { createUnprocessedFile, CreateUnprocessedFilePayload, type CreateUnprocessedFileResult, updateUnprocessedFile, UpdateUnprocessedFilePayload, type UpdateUnprocessedFileResult, uploadUnprocessedFile, processAVFile, processAVFileBuffer, processImageFile, processImageFileBuffer, } from './resources/unprocessed-file.ts';
|
|
8
8
|
export { Client } from './client.ts';
|
package/dist/index.js
CHANGED
|
@@ -4,7 +4,7 @@ import { CreateISOBMFFFilePayload, createISOBMFFFile, uploadFragmentIndex } from
|
|
|
4
4
|
import { CreateISOBMFFTrackPayload, createISOBMFFTrack, uploadISOBMFFTrack } from "./resources/isobmff-track.js";
|
|
5
5
|
import { CreateRenderPayload, createRender, uploadRender } from "./resources/renders.js";
|
|
6
6
|
import { createURLToken } from "./resources/url-token.js";
|
|
7
|
-
import { CreateUnprocessedFilePayload, UpdateUnprocessedFilePayload, createUnprocessedFile, processAVFile, processAVFileBuffer, updateUnprocessedFile, uploadUnprocessedFile } from "./resources/unprocessed-file.js";
|
|
7
|
+
import { CreateUnprocessedFilePayload, UpdateUnprocessedFilePayload, createUnprocessedFile, processAVFile, processAVFileBuffer, processImageFile, processImageFileBuffer, updateUnprocessedFile, uploadUnprocessedFile } from "./resources/unprocessed-file.js";
|
|
8
8
|
import { Client } from "./client.js";
|
|
9
9
|
export {
|
|
10
10
|
Client,
|
|
@@ -24,6 +24,8 @@ export {
|
|
|
24
24
|
createUnprocessedFile,
|
|
25
25
|
processAVFile,
|
|
26
26
|
processAVFileBuffer,
|
|
27
|
+
processImageFile,
|
|
28
|
+
processImageFileBuffer,
|
|
27
29
|
updateUnprocessedFile,
|
|
28
30
|
uploadCaptionFile,
|
|
29
31
|
uploadFragmentIndex,
|
|
@@ -2,22 +2,23 @@ import { Readable } from 'node:stream';
|
|
|
2
2
|
import { z } from 'zod';
|
|
3
3
|
import { Client } from '../client.ts';
|
|
4
4
|
export declare const CreateCaptionFilePayload: z.ZodObject<{
|
|
5
|
-
|
|
5
|
+
md5: z.ZodString;
|
|
6
6
|
filename: z.ZodString;
|
|
7
7
|
byte_size: z.ZodNumber;
|
|
8
8
|
}, "strip", z.ZodTypeAny, {
|
|
9
|
-
|
|
9
|
+
md5: string;
|
|
10
10
|
filename: string;
|
|
11
11
|
byte_size: number;
|
|
12
12
|
}, {
|
|
13
|
-
|
|
13
|
+
md5: string;
|
|
14
14
|
filename: string;
|
|
15
15
|
byte_size: number;
|
|
16
16
|
}>;
|
|
17
17
|
export interface CreateCaptionFileResult {
|
|
18
18
|
complete: boolean | null;
|
|
19
19
|
id: string;
|
|
20
|
-
|
|
20
|
+
md5: string;
|
|
21
|
+
asset_id: string;
|
|
21
22
|
}
|
|
22
23
|
/**
|
|
23
24
|
* Create a caption file
|
|
@@ -3,7 +3,7 @@ import debug from "debug";
|
|
|
3
3
|
const log = debug("ef:api:caption-file");
|
|
4
4
|
const MAX_CAPTION_SIZE = 1024 * 1024 * 2;
|
|
5
5
|
const CreateCaptionFilePayload = z.object({
|
|
6
|
-
|
|
6
|
+
md5: z.string(),
|
|
7
7
|
filename: z.string(),
|
|
8
8
|
byte_size: z.number().int().max(MAX_CAPTION_SIZE)
|
|
9
9
|
});
|
|
@@ -18,13 +18,10 @@ const restrictSize = (size) => {
|
|
|
18
18
|
const createCaptionFile = async (client, payload) => {
|
|
19
19
|
log("Creating caption file", payload);
|
|
20
20
|
restrictSize(payload.byte_size);
|
|
21
|
-
const response = await client.authenticatedFetch(
|
|
22
|
-
"
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
body: JSON.stringify(payload)
|
|
26
|
-
}
|
|
27
|
-
);
|
|
21
|
+
const response = await client.authenticatedFetch("/api/v1/caption_files", {
|
|
22
|
+
method: "POST",
|
|
23
|
+
body: JSON.stringify(payload)
|
|
24
|
+
});
|
|
28
25
|
log("Caption file created", response);
|
|
29
26
|
if (response.ok) {
|
|
30
27
|
return await response.json();
|
|
@@ -37,7 +34,7 @@ const uploadCaptionFile = async (client, fileId, fileStream, fileSize) => {
|
|
|
37
34
|
log("Uploading caption file", fileId);
|
|
38
35
|
restrictSize(fileSize);
|
|
39
36
|
const response = await client.authenticatedFetch(
|
|
40
|
-
`/api/
|
|
37
|
+
`/api/v1/caption_files/${fileId}/upload`,
|
|
41
38
|
{
|
|
42
39
|
method: "POST",
|
|
43
40
|
body: fileStream
|
|
@@ -2,21 +2,21 @@ import { Readable } from 'node:stream';
|
|
|
2
2
|
import { z } from 'zod';
|
|
3
3
|
import { Client } from '../client.ts';
|
|
4
4
|
export declare const CreateImageFilePayload: z.ZodObject<{
|
|
5
|
-
|
|
5
|
+
md5: z.ZodString;
|
|
6
6
|
height: z.ZodNumber;
|
|
7
7
|
width: z.ZodNumber;
|
|
8
8
|
mime_type: z.ZodEnum<["image/jpeg", "image/png", "image/jpg", "image/webp"]>;
|
|
9
9
|
filename: z.ZodString;
|
|
10
10
|
byte_size: z.ZodNumber;
|
|
11
11
|
}, "strip", z.ZodTypeAny, {
|
|
12
|
-
|
|
12
|
+
md5: string;
|
|
13
13
|
filename: string;
|
|
14
14
|
byte_size: number;
|
|
15
15
|
height: number;
|
|
16
16
|
width: number;
|
|
17
17
|
mime_type: "image/jpeg" | "image/png" | "image/jpg" | "image/webp";
|
|
18
18
|
}, {
|
|
19
|
-
|
|
19
|
+
md5: string;
|
|
20
20
|
filename: string;
|
|
21
21
|
byte_size: number;
|
|
22
22
|
height: number;
|
|
@@ -26,7 +26,8 @@ export declare const CreateImageFilePayload: z.ZodObject<{
|
|
|
26
26
|
export interface CreateImageFileResult {
|
|
27
27
|
complete: boolean | null;
|
|
28
28
|
id: string;
|
|
29
|
-
|
|
29
|
+
md5: string;
|
|
30
|
+
asset_id: string;
|
|
30
31
|
}
|
|
31
32
|
export declare const createImageFile: (client: Client, payload: z.infer<typeof CreateImageFilePayload>) => Promise<CreateImageFileResult>;
|
|
32
33
|
export declare const uploadImageFile: (client: Client, fileId: string, fileStream: Readable, fileSize: number) => Promise<void>;
|
|
@@ -4,7 +4,7 @@ import { uploadChunks } from "../uploadChunks.js";
|
|
|
4
4
|
const log = debug("ef:api:image-file");
|
|
5
5
|
const MAX_IMAGE_SIZE = 1024 * 1024 * 16;
|
|
6
6
|
const CreateImageFilePayload = z.object({
|
|
7
|
-
|
|
7
|
+
md5: z.string(),
|
|
8
8
|
height: z.number().int(),
|
|
9
9
|
width: z.number().int(),
|
|
10
10
|
mime_type: z.enum(["image/jpeg", "image/png", "image/jpg", "image/webp"]),
|
|
@@ -14,7 +14,7 @@ const CreateImageFilePayload = z.object({
|
|
|
14
14
|
const createImageFile = async (client, payload) => {
|
|
15
15
|
log("Creating image file", payload);
|
|
16
16
|
CreateImageFilePayload.parse(payload);
|
|
17
|
-
const response = await client.authenticatedFetch("/api/
|
|
17
|
+
const response = await client.authenticatedFetch("/api/v1/image_files", {
|
|
18
18
|
method: "POST",
|
|
19
19
|
body: JSON.stringify(payload)
|
|
20
20
|
});
|
|
@@ -34,7 +34,7 @@ const uploadImageFile = async (client, fileId, fileStream, fileSize) => {
|
|
|
34
34
|
);
|
|
35
35
|
}
|
|
36
36
|
const result = await uploadChunks(client, {
|
|
37
|
-
url: `/api/
|
|
37
|
+
url: `/api/v1/image_files/${fileId}/upload`,
|
|
38
38
|
fileSize,
|
|
39
39
|
fileStream
|
|
40
40
|
});
|
|
@@ -2,19 +2,21 @@ import { Readable } from 'node:stream';
|
|
|
2
2
|
import { z } from 'zod';
|
|
3
3
|
import { Client } from '../client.ts';
|
|
4
4
|
export declare const CreateISOBMFFFilePayload: z.ZodObject<{
|
|
5
|
-
|
|
5
|
+
md5: z.ZodString;
|
|
6
6
|
filename: z.ZodString;
|
|
7
7
|
}, "strip", z.ZodTypeAny, {
|
|
8
|
-
|
|
8
|
+
md5: string;
|
|
9
9
|
filename: string;
|
|
10
10
|
}, {
|
|
11
|
-
|
|
11
|
+
md5: string;
|
|
12
12
|
filename: string;
|
|
13
13
|
}>;
|
|
14
14
|
export interface CreateISOBMFFFileResult {
|
|
15
15
|
fragment_index_complete: boolean;
|
|
16
|
+
filename: string;
|
|
16
17
|
id: string;
|
|
17
|
-
|
|
18
|
+
md5: string;
|
|
19
|
+
asset_id: string;
|
|
18
20
|
}
|
|
19
21
|
export declare const createISOBMFFFile: (client: Client, payload: z.infer<typeof CreateISOBMFFFilePayload>) => Promise<CreateISOBMFFFileResult>;
|
|
20
22
|
export declare const uploadFragmentIndex: (client: Client, fileId: string, fileStream: Readable, fileSize: number) => Promise<unknown>;
|
|
@@ -3,18 +3,15 @@ import debug from "debug";
|
|
|
3
3
|
const log = debug("ef:api:isobmff-file");
|
|
4
4
|
const FILE_SIZE_LIMIT = 1024 * 1024 * 2;
|
|
5
5
|
const CreateISOBMFFFilePayload = z.object({
|
|
6
|
-
|
|
6
|
+
md5: z.string(),
|
|
7
7
|
filename: z.string()
|
|
8
8
|
});
|
|
9
9
|
const createISOBMFFFile = async (client, payload) => {
|
|
10
10
|
log("Creating isobmff file", payload);
|
|
11
|
-
const response = await client.authenticatedFetch(
|
|
12
|
-
"
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
body: JSON.stringify(payload)
|
|
16
|
-
}
|
|
17
|
-
);
|
|
11
|
+
const response = await client.authenticatedFetch("/api/v1/isobmff_files", {
|
|
12
|
+
method: "POST",
|
|
13
|
+
body: JSON.stringify(payload)
|
|
14
|
+
});
|
|
18
15
|
log("ISOBMFF file created", response);
|
|
19
16
|
if (response.ok) {
|
|
20
17
|
return await response.json();
|
|
@@ -29,7 +26,7 @@ const uploadFragmentIndex = async (client, fileId, fileStream, fileSize) => {
|
|
|
29
26
|
throw new Error(`File size exceeds limit of ${FILE_SIZE_LIMIT} bytes`);
|
|
30
27
|
}
|
|
31
28
|
const response = await client.authenticatedFetch(
|
|
32
|
-
`/api/
|
|
29
|
+
`/api/v1/isobmff_files/${fileId}/index/upload`,
|
|
33
30
|
{
|
|
34
31
|
method: "POST",
|
|
35
32
|
body: fileStream
|
|
@@ -27,13 +27,10 @@ const CreateISOBMFFTrackPayload = z.discriminatedUnion("type", [
|
|
|
27
27
|
const createISOBMFFTrack = async (client, payload) => {
|
|
28
28
|
log("Creating isobmff track", payload);
|
|
29
29
|
CreateISOBMFFTrackPayload.parse(payload);
|
|
30
|
-
const response = await client.authenticatedFetch(
|
|
31
|
-
"
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
body: JSON.stringify(payload)
|
|
35
|
-
}
|
|
36
|
-
);
|
|
30
|
+
const response = await client.authenticatedFetch("/api/v1/isobmff_tracks", {
|
|
31
|
+
method: "POST",
|
|
32
|
+
body: JSON.stringify(payload)
|
|
33
|
+
});
|
|
37
34
|
log("ISOBMFF track created", response);
|
|
38
35
|
if (response.ok) {
|
|
39
36
|
return await response.json();
|
|
@@ -45,7 +42,7 @@ const createISOBMFFTrack = async (client, payload) => {
|
|
|
45
42
|
const uploadISOBMFFTrack = async (client, fileId, trackId, fileStream, trackSize) => {
|
|
46
43
|
log("Uploading fragment track", fileId);
|
|
47
44
|
await uploadChunks(client, {
|
|
48
|
-
url: `/api/
|
|
45
|
+
url: `/api/v1/isobmff_tracks/${fileId}/${trackId}/upload`,
|
|
49
46
|
fileStream,
|
|
50
47
|
fileSize: trackSize
|
|
51
48
|
});
|
|
@@ -2,7 +2,7 @@ import { Readable } from 'node:stream';
|
|
|
2
2
|
import { z } from 'zod';
|
|
3
3
|
import { Client } from '../client.ts';
|
|
4
4
|
export declare const CreateRenderPayload: z.ZodObject<{
|
|
5
|
-
|
|
5
|
+
md5: z.ZodString;
|
|
6
6
|
fps: z.ZodNumber;
|
|
7
7
|
width: z.ZodNumber;
|
|
8
8
|
height: z.ZodNumber;
|
|
@@ -10,7 +10,7 @@ export declare const CreateRenderPayload: z.ZodObject<{
|
|
|
10
10
|
duration_ms: z.ZodNumber;
|
|
11
11
|
strategy: z.ZodEnum<["v1", "v2"]>;
|
|
12
12
|
}, "strip", z.ZodTypeAny, {
|
|
13
|
-
|
|
13
|
+
md5: string;
|
|
14
14
|
height: number;
|
|
15
15
|
width: number;
|
|
16
16
|
strategy: "v1" | "v2";
|
|
@@ -18,7 +18,7 @@ export declare const CreateRenderPayload: z.ZodObject<{
|
|
|
18
18
|
fps: number;
|
|
19
19
|
work_slice_ms: number;
|
|
20
20
|
}, {
|
|
21
|
-
|
|
21
|
+
md5: string;
|
|
22
22
|
height: number;
|
|
23
23
|
width: number;
|
|
24
24
|
strategy: "v1" | "v2";
|
|
@@ -27,8 +27,9 @@ export declare const CreateRenderPayload: z.ZodObject<{
|
|
|
27
27
|
work_slice_ms: number;
|
|
28
28
|
}>;
|
|
29
29
|
export interface CreateRenderResult {
|
|
30
|
-
status: "complete" | "created" | "failed" | "pending" | "rendering";
|
|
31
30
|
id: string;
|
|
31
|
+
md5: string;
|
|
32
|
+
status: "complete" | "created" | "failed" | "pending" | "rendering";
|
|
32
33
|
}
|
|
33
34
|
export declare const createRender: (client: Client, payload: z.infer<typeof CreateRenderPayload>) => Promise<CreateRenderResult>;
|
|
34
35
|
export declare const uploadRender: (client: Client, fileId: string, fileStream: Readable, folderSize: number) => Promise<unknown>;
|
|
@@ -3,7 +3,7 @@ import debug from "debug";
|
|
|
3
3
|
const log = debug("ef:api:renders");
|
|
4
4
|
const FILE_SIZE_LIMIT = 1024 * 1024 * 16;
|
|
5
5
|
const CreateRenderPayload = z.object({
|
|
6
|
-
|
|
6
|
+
md5: z.string(),
|
|
7
7
|
fps: z.number(),
|
|
8
8
|
width: z.number().int(),
|
|
9
9
|
height: z.number().int(),
|
|
@@ -13,7 +13,7 @@ const CreateRenderPayload = z.object({
|
|
|
13
13
|
});
|
|
14
14
|
const createRender = async (client, payload) => {
|
|
15
15
|
log("Creating render", payload);
|
|
16
|
-
const response = await client.authenticatedFetch("/api/
|
|
16
|
+
const response = await client.authenticatedFetch("/api/v1/renders", {
|
|
17
17
|
method: "POST",
|
|
18
18
|
body: JSON.stringify(payload)
|
|
19
19
|
});
|
|
@@ -32,7 +32,7 @@ const uploadRender = async (client, fileId, fileStream, folderSize) => {
|
|
|
32
32
|
throw new Error(`File size exceeds limit of ${FILE_SIZE_LIMIT} bytes`);
|
|
33
33
|
}
|
|
34
34
|
const response = await client.authenticatedFetch(
|
|
35
|
-
`/api/
|
|
35
|
+
`/api/v1/renders/${fileId}/upload`,
|
|
36
36
|
{
|
|
37
37
|
method: "POST",
|
|
38
38
|
body: fileStream
|
|
@@ -1,45 +1,53 @@
|
|
|
1
1
|
import { Readable } from 'node:stream';
|
|
2
2
|
import { z } from 'zod';
|
|
3
3
|
import { Client } from '../client.ts';
|
|
4
|
-
declare const FileProcessors: z.ZodEffects<z.ZodArray<z.ZodUnion<[z.ZodLiteral<"isobmff">, z.ZodLiteral<"captions">]>, "many">, ("captions" | "isobmff")[], ("captions" | "isobmff")[]>;
|
|
4
|
+
declare const FileProcessors: z.ZodEffects<z.ZodArray<z.ZodUnion<[z.ZodLiteral<"isobmff">, z.ZodLiteral<"image">, z.ZodLiteral<"captions">]>, "many">, ("captions" | "image" | "isobmff")[], ("captions" | "image" | "isobmff")[]>;
|
|
5
5
|
export declare const CreateUnprocessedFilePayload: z.ZodObject<{
|
|
6
|
-
|
|
6
|
+
md5: z.ZodString;
|
|
7
7
|
filename: z.ZodString;
|
|
8
|
-
processes: z.ZodOptional<z.ZodEffects<z.ZodArray<z.ZodUnion<[z.ZodLiteral<"isobmff">, z.ZodLiteral<"captions">]>, "many">, ("captions" | "isobmff")[], ("captions" | "isobmff")[]>>;
|
|
8
|
+
processes: z.ZodOptional<z.ZodEffects<z.ZodArray<z.ZodUnion<[z.ZodLiteral<"isobmff">, z.ZodLiteral<"image">, z.ZodLiteral<"captions">]>, "many">, ("captions" | "image" | "isobmff")[], ("captions" | "image" | "isobmff")[]>>;
|
|
9
9
|
byte_size: z.ZodNumber;
|
|
10
10
|
}, "strip", z.ZodTypeAny, {
|
|
11
|
-
|
|
11
|
+
md5: string;
|
|
12
12
|
filename: string;
|
|
13
13
|
byte_size: number;
|
|
14
|
-
processes?: ("captions" | "isobmff")[] | undefined;
|
|
14
|
+
processes?: ("captions" | "image" | "isobmff")[] | undefined;
|
|
15
15
|
}, {
|
|
16
|
-
|
|
16
|
+
md5: string;
|
|
17
17
|
filename: string;
|
|
18
18
|
byte_size: number;
|
|
19
|
-
processes?: ("captions" | "isobmff")[] | undefined;
|
|
19
|
+
processes?: ("captions" | "image" | "isobmff")[] | undefined;
|
|
20
20
|
}>;
|
|
21
21
|
export declare const UpdateUnprocessedFilePayload: z.ZodObject<{
|
|
22
|
-
processes: z.ZodOptional<z.ZodEffects<z.ZodArray<z.ZodUnion<[z.ZodLiteral<"isobmff">, z.ZodLiteral<"captions">]>, "many">, ("captions" | "isobmff")[], ("captions" | "isobmff")[]>>;
|
|
22
|
+
processes: z.ZodOptional<z.ZodEffects<z.ZodArray<z.ZodUnion<[z.ZodLiteral<"isobmff">, z.ZodLiteral<"image">, z.ZodLiteral<"captions">]>, "many">, ("captions" | "image" | "isobmff")[], ("captions" | "image" | "isobmff")[]>>;
|
|
23
23
|
}, "strip", z.ZodTypeAny, {
|
|
24
|
-
processes?: ("captions" | "isobmff")[] | undefined;
|
|
24
|
+
processes?: ("captions" | "image" | "isobmff")[] | undefined;
|
|
25
25
|
}, {
|
|
26
|
-
processes?: ("captions" | "isobmff")[] | undefined;
|
|
26
|
+
processes?: ("captions" | "image" | "isobmff")[] | undefined;
|
|
27
27
|
}>;
|
|
28
28
|
export interface CreateUnprocessedFileResult {
|
|
29
29
|
byte_size: number;
|
|
30
30
|
next_byte: number;
|
|
31
|
+
complete: boolean;
|
|
31
32
|
id: string;
|
|
33
|
+
md5: string;
|
|
32
34
|
processes: z.infer<typeof FileProcessors>;
|
|
35
|
+
asset_id: string;
|
|
33
36
|
}
|
|
34
37
|
export interface UpdateUnprocessedFileResult {
|
|
35
38
|
byte_size?: number;
|
|
36
39
|
next_byte: number;
|
|
40
|
+
complete: boolean;
|
|
37
41
|
id: string;
|
|
42
|
+
md5: string;
|
|
38
43
|
processes: z.infer<typeof FileProcessors>;
|
|
44
|
+
asset_id: string;
|
|
39
45
|
}
|
|
40
46
|
export declare const createUnprocessedFile: (client: Client, payload: z.infer<typeof CreateUnprocessedFilePayload>) => Promise<CreateUnprocessedFileResult>;
|
|
41
47
|
export declare const updateUnprocessedFile: (client: Client, fileId: string, payload: Partial<z.infer<typeof UpdateUnprocessedFilePayload>>) => Promise<UpdateUnprocessedFileResult>;
|
|
42
48
|
export declare const uploadUnprocessedFile: (client: Client, fileId: string, fileStream: Readable, fileSize: number) => Promise<void>;
|
|
43
49
|
export declare const processAVFileBuffer: (client: Client, buffer: Buffer, filename?: string) => Promise<UpdateUnprocessedFileResult>;
|
|
44
50
|
export declare const processAVFile: (client: Client, filePath: string) => Promise<UpdateUnprocessedFileResult>;
|
|
51
|
+
export declare const processImageFileBuffer: (client: Client, buffer: Buffer, filename?: string) => Promise<UpdateUnprocessedFileResult>;
|
|
52
|
+
export declare const processImageFile: (client: Client, filePath: string) => Promise<UpdateUnprocessedFileResult>;
|
|
45
53
|
export {};
|
|
@@ -7,7 +7,12 @@ import debug from "debug";
|
|
|
7
7
|
import { md5Buffer, md5FilePath } from "@editframe/assets";
|
|
8
8
|
import { uploadChunks } from "../uploadChunks.js";
|
|
9
9
|
const log = debug("ef:api:unprocessed-file");
|
|
10
|
-
const
|
|
10
|
+
const FileProcessor = z.union([
|
|
11
|
+
z.literal("isobmff"),
|
|
12
|
+
z.literal("image"),
|
|
13
|
+
z.literal("captions")
|
|
14
|
+
]);
|
|
15
|
+
const FileProcessors = z.array(FileProcessor).refine(
|
|
11
16
|
(value) => {
|
|
12
17
|
return new Set(value).size === value.length;
|
|
13
18
|
},
|
|
@@ -17,7 +22,7 @@ const FileProcessors = z.array(z.union([z.literal("isobmff"), z.literal("caption
|
|
|
17
22
|
);
|
|
18
23
|
const MAX_FILE_SIZE = 1024 * 1024 * 1024;
|
|
19
24
|
const CreateUnprocessedFilePayload = z.object({
|
|
20
|
-
|
|
25
|
+
md5: z.string(),
|
|
21
26
|
filename: z.string(),
|
|
22
27
|
processes: FileProcessors.optional(),
|
|
23
28
|
byte_size: z.number().int().max(MAX_FILE_SIZE)
|
|
@@ -75,59 +80,83 @@ const uploadUnprocessedFile = async (client, fileId, fileStream, fileSize) => {
|
|
|
75
80
|
});
|
|
76
81
|
log("Unprocessed file upload complete");
|
|
77
82
|
};
|
|
78
|
-
const
|
|
79
|
-
log("Processing
|
|
80
|
-
const
|
|
81
|
-
|
|
82
|
-
log(`File size: ${buffer.byteLength} bytes`);
|
|
83
|
-
await createUnprocessedFile(client, {
|
|
84
|
-
id: fileId,
|
|
83
|
+
const processResource = async (client, filename, md5, byteSize, processor, doUpload) => {
|
|
84
|
+
log("Processing", { filename, md5, byteSize, processor });
|
|
85
|
+
const unprocessedFile = await createUnprocessedFile(client, {
|
|
86
|
+
md5,
|
|
85
87
|
processes: [],
|
|
86
88
|
filename,
|
|
87
|
-
byte_size:
|
|
89
|
+
byte_size: byteSize
|
|
88
90
|
});
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
const fileInformation = await updateUnprocessedFile(
|
|
97
|
-
processes: ["isobmff"]
|
|
98
|
-
});
|
|
99
|
-
log("File processed", fileInformation);
|
|
100
|
-
return fileInformation;
|
|
101
|
-
};
|
|
102
|
-
const processAVFile = async (client, filePath) => {
|
|
103
|
-
log("Processing AV file", filePath);
|
|
104
|
-
const fileId = await md5FilePath(filePath);
|
|
105
|
-
log("File ID", fileId);
|
|
106
|
-
await createUnprocessedFile(client, {
|
|
107
|
-
id: fileId,
|
|
108
|
-
processes: [],
|
|
109
|
-
filename: basename(filePath),
|
|
110
|
-
byte_size: (await stat(filePath)).size
|
|
111
|
-
});
|
|
112
|
-
const readStream = createReadStream(filePath);
|
|
113
|
-
await uploadUnprocessedFile(
|
|
91
|
+
if (unprocessedFile.complete === false) {
|
|
92
|
+
await doUpload(unprocessedFile.id);
|
|
93
|
+
}
|
|
94
|
+
if (unprocessedFile.processes.includes(processor)) {
|
|
95
|
+
log("File already processed", unprocessedFile);
|
|
96
|
+
return unprocessedFile;
|
|
97
|
+
}
|
|
98
|
+
const fileInformation = await updateUnprocessedFile(
|
|
114
99
|
client,
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
100
|
+
unprocessedFile.id,
|
|
101
|
+
{
|
|
102
|
+
processes: [processor]
|
|
103
|
+
}
|
|
118
104
|
);
|
|
119
|
-
const fileInformation = await updateUnprocessedFile(client, fileId, {
|
|
120
|
-
processes: ["isobmff"]
|
|
121
|
-
});
|
|
122
105
|
log("File processed", fileInformation);
|
|
123
106
|
return fileInformation;
|
|
124
107
|
};
|
|
108
|
+
const buildBufferProcessor = (processor) => {
|
|
109
|
+
return async (client, buffer, filename = "buffer") => {
|
|
110
|
+
log(`Processing file buffer: ${processor}`, filename);
|
|
111
|
+
const md5 = md5Buffer(buffer);
|
|
112
|
+
return await processResource(
|
|
113
|
+
client,
|
|
114
|
+
filename,
|
|
115
|
+
md5,
|
|
116
|
+
buffer.byteLength,
|
|
117
|
+
processor,
|
|
118
|
+
async (id) => {
|
|
119
|
+
const readStream = new Readable({
|
|
120
|
+
read() {
|
|
121
|
+
readStream.push(buffer);
|
|
122
|
+
readStream.push(null);
|
|
123
|
+
}
|
|
124
|
+
});
|
|
125
|
+
await uploadUnprocessedFile(client, id, readStream, buffer.byteLength);
|
|
126
|
+
}
|
|
127
|
+
);
|
|
128
|
+
};
|
|
129
|
+
};
|
|
130
|
+
const buildFileProcessor = (processor) => {
|
|
131
|
+
return async (client, filePath) => {
|
|
132
|
+
log(`Processing file ${processor}`, filePath);
|
|
133
|
+
const md5 = await md5FilePath(filePath);
|
|
134
|
+
const byteSize = (await stat(filePath)).size;
|
|
135
|
+
return await processResource(
|
|
136
|
+
client,
|
|
137
|
+
basename(filePath),
|
|
138
|
+
md5,
|
|
139
|
+
byteSize,
|
|
140
|
+
processor,
|
|
141
|
+
async (id) => {
|
|
142
|
+
const readStream = createReadStream(filePath);
|
|
143
|
+
return await uploadUnprocessedFile(client, id, readStream, byteSize);
|
|
144
|
+
}
|
|
145
|
+
);
|
|
146
|
+
};
|
|
147
|
+
};
|
|
148
|
+
const processAVFileBuffer = buildBufferProcessor("isobmff");
|
|
149
|
+
const processAVFile = buildFileProcessor("isobmff");
|
|
150
|
+
const processImageFileBuffer = buildBufferProcessor("image");
|
|
151
|
+
const processImageFile = buildFileProcessor("image");
|
|
125
152
|
export {
|
|
126
153
|
CreateUnprocessedFilePayload,
|
|
127
154
|
UpdateUnprocessedFilePayload,
|
|
128
155
|
createUnprocessedFile,
|
|
129
156
|
processAVFile,
|
|
130
157
|
processAVFileBuffer,
|
|
158
|
+
processImageFile,
|
|
159
|
+
processImageFileBuffer,
|
|
131
160
|
updateUnprocessedFile,
|
|
132
161
|
uploadUnprocessedFile
|
|
133
162
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@editframe/api",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.10.0-beta.2",
|
|
4
4
|
"description": "API functions for EditFrame",
|
|
5
5
|
"exports": {
|
|
6
6
|
".": {
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
"vite-tsconfig-paths": "^4.3.2"
|
|
29
29
|
},
|
|
30
30
|
"dependencies": {
|
|
31
|
-
"@editframe/assets": "0.
|
|
31
|
+
"@editframe/assets": "0.10.0-beta.2",
|
|
32
32
|
"debug": "^4.3.5",
|
|
33
33
|
"jsonwebtoken": "^9.0.2",
|
|
34
34
|
"node-fetch": "^3.3.2",
|
|
@@ -18,7 +18,7 @@ describe("CaptionFile", () => {
|
|
|
18
18
|
test("Throws when file is too large", async () => {
|
|
19
19
|
await expect(
|
|
20
20
|
createCaptionFile(client, {
|
|
21
|
-
|
|
21
|
+
md5: "test-md5",
|
|
22
22
|
filename: "test",
|
|
23
23
|
byte_size: 1024 * 1024 * 3,
|
|
24
24
|
}),
|
|
@@ -29,14 +29,14 @@ describe("CaptionFile", () => {
|
|
|
29
29
|
|
|
30
30
|
test("Throws when server returns an error", async () => {
|
|
31
31
|
server.use(
|
|
32
|
-
http.post("http://localhost/api/
|
|
32
|
+
http.post("http://localhost/api/v1/caption_files", () =>
|
|
33
33
|
HttpResponse.text("Internal Server Error", { status: 500 }),
|
|
34
34
|
),
|
|
35
35
|
);
|
|
36
36
|
|
|
37
37
|
await expect(
|
|
38
38
|
createCaptionFile(client, {
|
|
39
|
-
|
|
39
|
+
md5: "test-md5",
|
|
40
40
|
filename: "test",
|
|
41
41
|
byte_size: 4,
|
|
42
42
|
}),
|
|
@@ -47,7 +47,7 @@ describe("CaptionFile", () => {
|
|
|
47
47
|
|
|
48
48
|
test("Returns json data from the http response", async () => {
|
|
49
49
|
server.use(
|
|
50
|
-
http.post("http://localhost/api/
|
|
50
|
+
http.post("http://localhost/api/v1/caption_files", () =>
|
|
51
51
|
HttpResponse.json(
|
|
52
52
|
{ id: "test-id" },
|
|
53
53
|
{ status: 200, statusText: "OK" },
|
|
@@ -56,7 +56,7 @@ describe("CaptionFile", () => {
|
|
|
56
56
|
);
|
|
57
57
|
|
|
58
58
|
const response = await createCaptionFile(client, {
|
|
59
|
-
|
|
59
|
+
md5: "test-md5",
|
|
60
60
|
filename: "test",
|
|
61
61
|
byte_size: 4,
|
|
62
62
|
});
|
|
@@ -81,9 +81,8 @@ describe("CaptionFile", () => {
|
|
|
81
81
|
|
|
82
82
|
test("Throws when server returns an error", async () => {
|
|
83
83
|
server.use(
|
|
84
|
-
http.post(
|
|
85
|
-
"
|
|
86
|
-
() => HttpResponse.text("Internal Server Error", { status: 500 }),
|
|
84
|
+
http.post("http://localhost/api/v1/caption_files/test-id/upload", () =>
|
|
85
|
+
HttpResponse.text("Internal Server Error", { status: 500 }),
|
|
87
86
|
),
|
|
88
87
|
);
|
|
89
88
|
|
|
@@ -101,13 +100,11 @@ describe("CaptionFile", () => {
|
|
|
101
100
|
|
|
102
101
|
test("Returns json data from the http response", async () => {
|
|
103
102
|
server.use(
|
|
104
|
-
http.post(
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
{ status: 200, statusText: "OK" },
|
|
110
|
-
),
|
|
103
|
+
http.post("http://localhost/api/v1/caption_files/test-id/upload", () =>
|
|
104
|
+
HttpResponse.json(
|
|
105
|
+
{ id: "test-id" },
|
|
106
|
+
{ status: 200, statusText: "OK" },
|
|
107
|
+
),
|
|
111
108
|
),
|
|
112
109
|
);
|
|
113
110
|
|
|
@@ -10,7 +10,7 @@ const log = debug("ef:api:caption-file");
|
|
|
10
10
|
const MAX_CAPTION_SIZE = 1024 * 1024 * 2; // 2MB
|
|
11
11
|
|
|
12
12
|
export const CreateCaptionFilePayload = z.object({
|
|
13
|
-
|
|
13
|
+
md5: z.string(),
|
|
14
14
|
filename: z.string(),
|
|
15
15
|
byte_size: z.number().int().max(MAX_CAPTION_SIZE),
|
|
16
16
|
});
|
|
@@ -18,7 +18,8 @@ export const CreateCaptionFilePayload = z.object({
|
|
|
18
18
|
export interface CreateCaptionFileResult {
|
|
19
19
|
complete: boolean | null;
|
|
20
20
|
id: string;
|
|
21
|
-
|
|
21
|
+
md5: string;
|
|
22
|
+
asset_id: string;
|
|
22
23
|
}
|
|
23
24
|
|
|
24
25
|
const restrictSize = (size: number) => {
|
|
@@ -52,13 +53,10 @@ export const createCaptionFile = async (
|
|
|
52
53
|
) => {
|
|
53
54
|
log("Creating caption file", payload);
|
|
54
55
|
restrictSize(payload.byte_size);
|
|
55
|
-
const response = await client.authenticatedFetch(
|
|
56
|
-
"
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
body: JSON.stringify(payload),
|
|
60
|
-
},
|
|
61
|
-
);
|
|
56
|
+
const response = await client.authenticatedFetch("/api/v1/caption_files", {
|
|
57
|
+
method: "POST",
|
|
58
|
+
body: JSON.stringify(payload),
|
|
59
|
+
});
|
|
62
60
|
log("Caption file created", response);
|
|
63
61
|
|
|
64
62
|
if (response.ok) {
|
|
@@ -80,7 +78,7 @@ export const uploadCaptionFile = async (
|
|
|
80
78
|
restrictSize(fileSize);
|
|
81
79
|
|
|
82
80
|
const response = await client.authenticatedFetch(
|
|
83
|
-
`/api/
|
|
81
|
+
`/api/v1/caption_files/${fileId}/upload`,
|
|
84
82
|
{
|
|
85
83
|
method: "POST",
|
|
86
84
|
body: fileStream,
|