@editframe/api 0.26.3-beta.0 → 0.30.0-beta.13
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/client.js +1 -1
- package/dist/client.js.map +1 -1
- package/package.json +5 -4
- package/tsdown.config.ts +3 -0
- package/types.json +1 -1
- package/src/resources/caption-file.test.ts +0 -172
- package/src/resources/caption-file.ts +0 -154
- package/src/resources/image-file.test.ts +0 -220
- package/src/resources/image-file.ts +0 -205
- package/src/resources/isobmff-file.test.ts +0 -159
- package/src/resources/isobmff-file.ts +0 -186
- package/src/resources/isobmff-track.test.ts +0 -126
- package/src/resources/isobmff-track.ts +0 -248
- package/src/resources/process-isobmff.test.ts +0 -68
- package/src/resources/process-isobmff.ts +0 -33
- package/src/resources/renders.bundle.ts +0 -53
- package/src/resources/renders.test.ts +0 -202
- package/src/resources/renders.ts +0 -282
- package/src/resources/test-av-file.txt +0 -1
- package/src/resources/transcriptions.test.ts +0 -49
- package/src/resources/transcriptions.ts +0 -67
- package/src/resources/unprocessed-file.test.ts +0 -171
- package/src/resources/unprocessed-file.ts +0 -138
- package/src/resources/url-token.test.ts +0 -46
- package/src/resources/url-token.ts +0 -27
- package/src/utils/assertTypesMatch.ts +0 -10
- package/src/utils/createReadableStreamFromReadable.ts +0 -115
|
@@ -1,248 +0,0 @@
|
|
|
1
|
-
import debug from "debug";
|
|
2
|
-
import { z } from "zod";
|
|
3
|
-
import type { Client } from "../client.js";
|
|
4
|
-
import { uploadChunks } from "../uploadChunks.js";
|
|
5
|
-
import { assertTypesMatch } from "../utils/assertTypesMatch.ts";
|
|
6
|
-
|
|
7
|
-
export const AudioStreamSchema = z.object({
|
|
8
|
-
index: z.number(),
|
|
9
|
-
codec_name: z.string(),
|
|
10
|
-
codec_long_name: z.string(),
|
|
11
|
-
codec_type: z.literal("audio"),
|
|
12
|
-
codec_tag_string: z.string(),
|
|
13
|
-
codec_tag: z.string(),
|
|
14
|
-
sample_fmt: z.string(),
|
|
15
|
-
sample_rate: z.string(),
|
|
16
|
-
channels: z.number(),
|
|
17
|
-
channel_layout: z.string().optional(),
|
|
18
|
-
bits_per_sample: z.number(),
|
|
19
|
-
initial_padding: z.number().optional(),
|
|
20
|
-
r_frame_rate: z.string(),
|
|
21
|
-
avg_frame_rate: z.string(),
|
|
22
|
-
time_base: z.string(),
|
|
23
|
-
start_pts: z.number().optional(),
|
|
24
|
-
start_time: z.coerce.number().optional(),
|
|
25
|
-
duration_ts: z.number(),
|
|
26
|
-
duration: z.coerce.number(),
|
|
27
|
-
bit_rate: z.string(),
|
|
28
|
-
disposition: z.record(z.unknown()),
|
|
29
|
-
});
|
|
30
|
-
|
|
31
|
-
export interface AudioStreamSchema {
|
|
32
|
-
/** The index of the stream in the file */
|
|
33
|
-
index: number;
|
|
34
|
-
/** The name of the codec */
|
|
35
|
-
codec_name: string;
|
|
36
|
-
/** The long name of the codec */
|
|
37
|
-
codec_long_name: string;
|
|
38
|
-
/** The type of the codec */
|
|
39
|
-
codec_type: "audio";
|
|
40
|
-
/** The tag string of the codec */
|
|
41
|
-
codec_tag_string: string;
|
|
42
|
-
/** The tag of the codec */
|
|
43
|
-
codec_tag: string;
|
|
44
|
-
/** The sample format */
|
|
45
|
-
sample_fmt: string;
|
|
46
|
-
/** The sample rate */
|
|
47
|
-
sample_rate: string;
|
|
48
|
-
/** The number of channels */
|
|
49
|
-
channels: number;
|
|
50
|
-
/** The channel layout */
|
|
51
|
-
channel_layout?: string;
|
|
52
|
-
/** The number of bits per sample */
|
|
53
|
-
bits_per_sample: number;
|
|
54
|
-
/** The initial padding */
|
|
55
|
-
initial_padding?: number;
|
|
56
|
-
/** The frame rate */
|
|
57
|
-
r_frame_rate: string;
|
|
58
|
-
/** The average frame rate */
|
|
59
|
-
avg_frame_rate: string;
|
|
60
|
-
/** The time base */
|
|
61
|
-
time_base: string;
|
|
62
|
-
/** The start presentation timestamp */
|
|
63
|
-
start_pts?: number;
|
|
64
|
-
/** The start time */
|
|
65
|
-
start_time?: number;
|
|
66
|
-
/** The duration timestamp */
|
|
67
|
-
duration_ts: number;
|
|
68
|
-
/** The duration */
|
|
69
|
-
duration: number;
|
|
70
|
-
/** The bit rate */
|
|
71
|
-
bit_rate: string;
|
|
72
|
-
/** The disposition record. Subject to change, not documented. */
|
|
73
|
-
disposition: Record<string, unknown>;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
assertTypesMatch<z.infer<typeof AudioStreamSchema>, AudioStreamSchema>(true);
|
|
77
|
-
|
|
78
|
-
export const VideoStreamSchema = z.object({
|
|
79
|
-
index: z.number(),
|
|
80
|
-
codec_name: z.string(),
|
|
81
|
-
codec_long_name: z.string(),
|
|
82
|
-
codec_type: z.literal("video"),
|
|
83
|
-
codec_tag_string: z.string(),
|
|
84
|
-
codec_tag: z.string(),
|
|
85
|
-
width: z.number(),
|
|
86
|
-
height: z.number(),
|
|
87
|
-
coded_width: z.number(),
|
|
88
|
-
coded_height: z.number(),
|
|
89
|
-
r_frame_rate: z.string(),
|
|
90
|
-
avg_frame_rate: z.string(),
|
|
91
|
-
time_base: z.string(),
|
|
92
|
-
start_pts: z.number().optional(),
|
|
93
|
-
start_time: z.coerce.number().optional(),
|
|
94
|
-
duration_ts: z.number().optional(),
|
|
95
|
-
duration: z.coerce.number().optional(),
|
|
96
|
-
bit_rate: z.string().optional(),
|
|
97
|
-
disposition: z.record(z.unknown()),
|
|
98
|
-
});
|
|
99
|
-
|
|
100
|
-
export interface VideoStreamSchema {
|
|
101
|
-
/** The index of the stream in the file */
|
|
102
|
-
index: number;
|
|
103
|
-
/** The name of the codec */
|
|
104
|
-
codec_name: string;
|
|
105
|
-
/** The long name of the codec */
|
|
106
|
-
codec_long_name: string;
|
|
107
|
-
/** The type of the codec */
|
|
108
|
-
codec_type: "video";
|
|
109
|
-
/** The tag string of the codec */
|
|
110
|
-
codec_tag_string: string;
|
|
111
|
-
/** The tag of the codec */
|
|
112
|
-
codec_tag: string;
|
|
113
|
-
/** The width */
|
|
114
|
-
width: number;
|
|
115
|
-
/** The height */
|
|
116
|
-
height: number;
|
|
117
|
-
/** The coded width */
|
|
118
|
-
coded_width: number;
|
|
119
|
-
/** The coded height */
|
|
120
|
-
coded_height: number;
|
|
121
|
-
/** The frame rate */
|
|
122
|
-
r_frame_rate: string;
|
|
123
|
-
/** The average frame rate */
|
|
124
|
-
avg_frame_rate: string;
|
|
125
|
-
/** The time base */
|
|
126
|
-
time_base: string;
|
|
127
|
-
/** The start presentation timestamp */
|
|
128
|
-
start_pts?: number;
|
|
129
|
-
/** The start time */
|
|
130
|
-
start_time?: number;
|
|
131
|
-
/** The duration timestamp */
|
|
132
|
-
duration_ts?: number;
|
|
133
|
-
/** The duration */
|
|
134
|
-
duration?: number;
|
|
135
|
-
/** The bit rate */
|
|
136
|
-
bit_rate?: string;
|
|
137
|
-
/** The disposition record. Subject to change, not documented. */
|
|
138
|
-
disposition: Record<string, unknown>;
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
assertTypesMatch<z.infer<typeof VideoStreamSchema>, VideoStreamSchema>(true);
|
|
142
|
-
|
|
143
|
-
const log = debug("ef:api:isobmff-track");
|
|
144
|
-
|
|
145
|
-
const MAX_TRACK_SIZE = 1024 * 1024 * 1024; // 1GB
|
|
146
|
-
|
|
147
|
-
export const AudioTrackPayload = z.object({
|
|
148
|
-
file_id: z.string(),
|
|
149
|
-
track_id: z.number().int(),
|
|
150
|
-
type: z.literal("audio"),
|
|
151
|
-
probe_info: AudioStreamSchema,
|
|
152
|
-
duration_ms: z.number().int(),
|
|
153
|
-
codec_name: z.string(),
|
|
154
|
-
byte_size: z.number().int().max(MAX_TRACK_SIZE),
|
|
155
|
-
});
|
|
156
|
-
|
|
157
|
-
export interface AudioTrackPayload {
|
|
158
|
-
file_id: string;
|
|
159
|
-
track_id: number;
|
|
160
|
-
type: "audio";
|
|
161
|
-
probe_info: AudioStreamSchema;
|
|
162
|
-
duration_ms: number;
|
|
163
|
-
codec_name: string;
|
|
164
|
-
byte_size: number;
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
// These will actually error if types don't match
|
|
168
|
-
assertTypesMatch<z.infer<typeof AudioTrackPayload>, AudioTrackPayload>(true);
|
|
169
|
-
|
|
170
|
-
export const VideoTrackPayload = z.object({
|
|
171
|
-
file_id: z.string(),
|
|
172
|
-
track_id: z.number().int(),
|
|
173
|
-
type: z.literal("video"),
|
|
174
|
-
probe_info: VideoStreamSchema,
|
|
175
|
-
duration_ms: z.number().int(),
|
|
176
|
-
codec_name: z.string(),
|
|
177
|
-
byte_size: z.number().int().max(MAX_TRACK_SIZE),
|
|
178
|
-
});
|
|
179
|
-
|
|
180
|
-
export interface VideoTrackPayload {
|
|
181
|
-
file_id: string;
|
|
182
|
-
track_id: number;
|
|
183
|
-
type: "video";
|
|
184
|
-
probe_info: VideoStreamSchema;
|
|
185
|
-
duration_ms: number;
|
|
186
|
-
codec_name: string;
|
|
187
|
-
byte_size: number;
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
assertTypesMatch<z.infer<typeof VideoTrackPayload>, VideoTrackPayload>(true);
|
|
191
|
-
|
|
192
|
-
export const CreateISOBMFFTrackPayload = z.discriminatedUnion("type", [
|
|
193
|
-
AudioTrackPayload,
|
|
194
|
-
VideoTrackPayload,
|
|
195
|
-
]);
|
|
196
|
-
|
|
197
|
-
export type CreateISOBMFFTrackPayload = VideoTrackPayload | AudioTrackPayload;
|
|
198
|
-
|
|
199
|
-
assertTypesMatch<
|
|
200
|
-
z.infer<typeof CreateISOBMFFTrackPayload>,
|
|
201
|
-
CreateISOBMFFTrackPayload
|
|
202
|
-
>(true);
|
|
203
|
-
|
|
204
|
-
export interface CreateISOBMFFTrackResult {
|
|
205
|
-
next_byte: number;
|
|
206
|
-
byte_size: number;
|
|
207
|
-
track_id: number;
|
|
208
|
-
file_id: string;
|
|
209
|
-
complete: boolean;
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
export const createISOBMFFTrack = async (
|
|
213
|
-
client: Client,
|
|
214
|
-
payload: CreateISOBMFFTrackPayload,
|
|
215
|
-
) => {
|
|
216
|
-
log("Creating isobmff track", payload);
|
|
217
|
-
CreateISOBMFFTrackPayload.parse(payload);
|
|
218
|
-
const response = await client.authenticatedFetch("/api/v1/isobmff_tracks", {
|
|
219
|
-
method: "POST",
|
|
220
|
-
body: JSON.stringify(payload),
|
|
221
|
-
});
|
|
222
|
-
|
|
223
|
-
log("ISOBMFF track created", response);
|
|
224
|
-
if (response.ok) {
|
|
225
|
-
return (await response.json()) as CreateISOBMFFTrackResult;
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
throw new Error(
|
|
229
|
-
`Failed to create isobmff track ${response.status} ${response.statusText}`,
|
|
230
|
-
);
|
|
231
|
-
};
|
|
232
|
-
|
|
233
|
-
export const uploadISOBMFFTrack = (
|
|
234
|
-
client: Client,
|
|
235
|
-
fileId: string,
|
|
236
|
-
trackId: number,
|
|
237
|
-
fileStream: ReadableStream,
|
|
238
|
-
trackSize: number,
|
|
239
|
-
) => {
|
|
240
|
-
log("Uploading fragment track", fileId);
|
|
241
|
-
|
|
242
|
-
return uploadChunks(client, {
|
|
243
|
-
url: `/api/v1/isobmff_tracks/${fileId}/${trackId}/upload`,
|
|
244
|
-
fileStream,
|
|
245
|
-
fileSize: trackSize,
|
|
246
|
-
maxSize: MAX_TRACK_SIZE,
|
|
247
|
-
});
|
|
248
|
-
};
|
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
import { HttpResponse, http } from "msw";
|
|
2
|
-
import { setupServer } from "msw/node";
|
|
3
|
-
import { afterAll, afterEach, beforeAll, describe, expect, test } from "vitest";
|
|
4
|
-
import { Client } from "../client.js";
|
|
5
|
-
import {
|
|
6
|
-
getIsobmffProcessInfo,
|
|
7
|
-
getIsobmffProcessProgress,
|
|
8
|
-
} from "./process-isobmff.js";
|
|
9
|
-
|
|
10
|
-
const client = new Client("ef_TEST_TOKEN", "http://localhost");
|
|
11
|
-
const server = setupServer();
|
|
12
|
-
|
|
13
|
-
describe("process-isobmff", () => {
|
|
14
|
-
beforeAll(() => {
|
|
15
|
-
server.listen();
|
|
16
|
-
process.env.EF_TOKEN = "ef_SECRET_TOKEN";
|
|
17
|
-
process.env.EF_HOST = "http://localhost:3000";
|
|
18
|
-
});
|
|
19
|
-
afterAll(() => server.close());
|
|
20
|
-
afterEach(() => server.resetHandlers());
|
|
21
|
-
describe("getIsobmffProcessInfo", () => {
|
|
22
|
-
test("returns the process info", async () => {
|
|
23
|
-
server.use(
|
|
24
|
-
http.get("http://localhost/api/v1/process_isobmff/123", async () => {
|
|
25
|
-
return HttpResponse.json({
|
|
26
|
-
id: "123",
|
|
27
|
-
created_at: "2021-01-01T00:00:00.000Z",
|
|
28
|
-
updated_at: "2021-01-01T00:00:00.000Z",
|
|
29
|
-
});
|
|
30
|
-
}),
|
|
31
|
-
);
|
|
32
|
-
const info = await getIsobmffProcessInfo(client, "123");
|
|
33
|
-
expect(info).toEqual({
|
|
34
|
-
id: "123",
|
|
35
|
-
created_at: "2021-01-01T00:00:00.000Z",
|
|
36
|
-
updated_at: "2021-01-01T00:00:00.000Z",
|
|
37
|
-
});
|
|
38
|
-
});
|
|
39
|
-
|
|
40
|
-
test("throws when the server returns an error", async () => {
|
|
41
|
-
server.use(
|
|
42
|
-
http.get("http://localhost/api/v1/process_isobmff/123", () =>
|
|
43
|
-
HttpResponse.text("Internal Server Error", { status: 500 }),
|
|
44
|
-
),
|
|
45
|
-
);
|
|
46
|
-
await expect(getIsobmffProcessInfo(client, "123")).rejects.toThrow(
|
|
47
|
-
"Failed to get isobmff process info 500 Internal Server Error",
|
|
48
|
-
);
|
|
49
|
-
});
|
|
50
|
-
});
|
|
51
|
-
|
|
52
|
-
describe("getIsobmffProcessProgress", () => {
|
|
53
|
-
test("returns the progress", async () => {
|
|
54
|
-
server.use(
|
|
55
|
-
http.get(
|
|
56
|
-
"http://localhost/api/v1/process_isobmff/123/progress",
|
|
57
|
-
async () => {
|
|
58
|
-
return HttpResponse.text("event: complete\ndata: {}\n\n");
|
|
59
|
-
},
|
|
60
|
-
),
|
|
61
|
-
);
|
|
62
|
-
const progress = await getIsobmffProcessProgress(client, "123");
|
|
63
|
-
await expect(progress.whenComplete()).resolves.toEqual([
|
|
64
|
-
{ type: "complete", data: {} },
|
|
65
|
-
]);
|
|
66
|
-
});
|
|
67
|
-
});
|
|
68
|
-
});
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
import type { Client } from "../client.js";
|
|
2
|
-
import { ProgressIterator } from "../ProgressIterator.js";
|
|
3
|
-
|
|
4
|
-
export interface IsobmffProcessInfoResult {
|
|
5
|
-
id: string;
|
|
6
|
-
created_at: string;
|
|
7
|
-
completed_at: string | null;
|
|
8
|
-
failed_at: string | null;
|
|
9
|
-
isobmff_file_id: string | null;
|
|
10
|
-
unprocessed_file_id: string | null;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
export const getIsobmffProcessProgress = async (client: Client, id: string) => {
|
|
14
|
-
const eventSource = await client.authenticatedEventSource(
|
|
15
|
-
`/api/v1/process_isobmff/${id}/progress`,
|
|
16
|
-
);
|
|
17
|
-
|
|
18
|
-
return new ProgressIterator(eventSource);
|
|
19
|
-
};
|
|
20
|
-
|
|
21
|
-
export const getIsobmffProcessInfo = async (client: Client, id: string) => {
|
|
22
|
-
const response = await client.authenticatedFetch(
|
|
23
|
-
`/api/v1/process_isobmff/${id}`,
|
|
24
|
-
);
|
|
25
|
-
|
|
26
|
-
if (response.ok) {
|
|
27
|
-
return (await response.json()) as IsobmffProcessInfoResult;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
throw new Error(
|
|
31
|
-
`Failed to get isobmff process info ${response.status} ${response.statusText}`,
|
|
32
|
-
);
|
|
33
|
-
};
|
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
import { randomUUID } from "node:crypto";
|
|
2
|
-
import path from "node:path";
|
|
3
|
-
import { PassThrough } from "node:stream";
|
|
4
|
-
import react from "@vitejs/plugin-react";
|
|
5
|
-
import * as tar from "tar";
|
|
6
|
-
import { build } from "vite";
|
|
7
|
-
import { viteSingleFile } from "vite-plugin-singlefile";
|
|
8
|
-
import tsconfigPathsPlugin from "vite-tsconfig-paths";
|
|
9
|
-
import { createReadableStreamFromReadable } from "../utils/createReadableStreamFromReadable.ts";
|
|
10
|
-
|
|
11
|
-
interface BundlerOptions {
|
|
12
|
-
root: string;
|
|
13
|
-
renderData: any;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
export const bundleRender = async (options: BundlerOptions) => {
|
|
17
|
-
const outDir = path.join(process.cwd(), "renders", randomUUID());
|
|
18
|
-
|
|
19
|
-
await build({
|
|
20
|
-
root: options.root,
|
|
21
|
-
define: {
|
|
22
|
-
RENDER_DATA: JSON.stringify(options.renderData),
|
|
23
|
-
},
|
|
24
|
-
build: {
|
|
25
|
-
outDir,
|
|
26
|
-
rollupOptions: {
|
|
27
|
-
input: path.resolve(options.root, "index.html"),
|
|
28
|
-
},
|
|
29
|
-
},
|
|
30
|
-
plugins: [
|
|
31
|
-
tsconfigPathsPlugin(),
|
|
32
|
-
react({
|
|
33
|
-
include: "**/*.{jsx,js,tsx,ts}",
|
|
34
|
-
jsxRuntime: "automatic",
|
|
35
|
-
}),
|
|
36
|
-
viteSingleFile(),
|
|
37
|
-
],
|
|
38
|
-
});
|
|
39
|
-
|
|
40
|
-
const tarStream = tar.create(
|
|
41
|
-
{
|
|
42
|
-
gzip: true,
|
|
43
|
-
cwd: outDir,
|
|
44
|
-
},
|
|
45
|
-
["."],
|
|
46
|
-
);
|
|
47
|
-
|
|
48
|
-
const passthrough = new PassThrough();
|
|
49
|
-
tarStream.pipe(passthrough);
|
|
50
|
-
const tarReadStream = createReadableStreamFromReadable(passthrough);
|
|
51
|
-
|
|
52
|
-
return tarReadStream;
|
|
53
|
-
};
|
|
@@ -1,202 +0,0 @@
|
|
|
1
|
-
import { HttpResponse, http } from "msw";
|
|
2
|
-
import { setupServer } from "msw/node";
|
|
3
|
-
import { afterAll, afterEach, beforeAll, describe, expect, test } from "vitest";
|
|
4
|
-
|
|
5
|
-
import { Client } from "../client.js";
|
|
6
|
-
import { webReadableFromBuffers } from "../readableFromBuffers.js";
|
|
7
|
-
import {
|
|
8
|
-
createRender,
|
|
9
|
-
lookupRenderByMd5,
|
|
10
|
-
OutputConfiguration,
|
|
11
|
-
uploadRender,
|
|
12
|
-
} from "./renders.js";
|
|
13
|
-
|
|
14
|
-
const server = setupServer();
|
|
15
|
-
const client = new Client("ef_TEST_TOKEN", "http://localhost");
|
|
16
|
-
|
|
17
|
-
describe("Renders", () => {
|
|
18
|
-
beforeAll(() => server.listen());
|
|
19
|
-
afterEach(() => server.resetHandlers());
|
|
20
|
-
afterAll(() => server.close());
|
|
21
|
-
|
|
22
|
-
describe("createRender", () => {
|
|
23
|
-
test("throws if server returns an error", async () => {
|
|
24
|
-
server.use(
|
|
25
|
-
http.post("http://localhost/api/v1/renders", () =>
|
|
26
|
-
HttpResponse.text("Internal Server Error", { status: 500 }),
|
|
27
|
-
),
|
|
28
|
-
);
|
|
29
|
-
|
|
30
|
-
await expect(
|
|
31
|
-
createRender(client, createTestRender()),
|
|
32
|
-
).rejects.toThrowError(
|
|
33
|
-
"Failed to create render 500 Internal Server Error",
|
|
34
|
-
);
|
|
35
|
-
});
|
|
36
|
-
|
|
37
|
-
test("returns json data from the http response", async () => {
|
|
38
|
-
server.use(
|
|
39
|
-
http.post("http://localhost/api/v1/renders", () =>
|
|
40
|
-
HttpResponse.json(
|
|
41
|
-
{ testResponse: "test" },
|
|
42
|
-
{ status: 200, statusText: "OK" },
|
|
43
|
-
),
|
|
44
|
-
),
|
|
45
|
-
);
|
|
46
|
-
|
|
47
|
-
const response = await createRender(client, createTestRender());
|
|
48
|
-
|
|
49
|
-
expect(response).toEqual({ testResponse: "test" });
|
|
50
|
-
});
|
|
51
|
-
});
|
|
52
|
-
|
|
53
|
-
describe("uploadRender", () => {
|
|
54
|
-
test("throws if server returns an error", async () => {
|
|
55
|
-
server.use(
|
|
56
|
-
http.post("http://localhost/api/v1/renders/test-id/upload", () =>
|
|
57
|
-
HttpResponse.text("Internal Server Error", { status: 500 }),
|
|
58
|
-
),
|
|
59
|
-
);
|
|
60
|
-
|
|
61
|
-
await expect(
|
|
62
|
-
uploadRender(
|
|
63
|
-
client,
|
|
64
|
-
"test-id",
|
|
65
|
-
webReadableFromBuffers(Buffer.from("test")),
|
|
66
|
-
),
|
|
67
|
-
).rejects.toThrowError(
|
|
68
|
-
"Failed to upload render 500 Internal Server Error",
|
|
69
|
-
);
|
|
70
|
-
});
|
|
71
|
-
|
|
72
|
-
test("returns json data from the http response", async () => {
|
|
73
|
-
server.use(
|
|
74
|
-
http.post("http://localhost/api/v1/renders/test-id/upload", () =>
|
|
75
|
-
HttpResponse.json(
|
|
76
|
-
{ testResponse: "test" },
|
|
77
|
-
{ status: 200, statusText: "OK" },
|
|
78
|
-
),
|
|
79
|
-
),
|
|
80
|
-
);
|
|
81
|
-
|
|
82
|
-
const response = await uploadRender(
|
|
83
|
-
client,
|
|
84
|
-
"test-id",
|
|
85
|
-
webReadableFromBuffers(Buffer.from("test")),
|
|
86
|
-
);
|
|
87
|
-
|
|
88
|
-
expect(response).toEqual({ testResponse: "test" });
|
|
89
|
-
});
|
|
90
|
-
});
|
|
91
|
-
|
|
92
|
-
describe("lookupRenderByMd5", () => {
|
|
93
|
-
test("Returns json data from the http response", async () => {
|
|
94
|
-
server.use(
|
|
95
|
-
http.get("http://localhost/api/v1/renders/md5/test-md5", () =>
|
|
96
|
-
HttpResponse.json(
|
|
97
|
-
{ id: "test-id", md5: "test-md5", status: "complete" },
|
|
98
|
-
{ status: 200, statusText: "OK" },
|
|
99
|
-
),
|
|
100
|
-
),
|
|
101
|
-
);
|
|
102
|
-
|
|
103
|
-
const response = await lookupRenderByMd5(client, "test-md5");
|
|
104
|
-
|
|
105
|
-
expect(response).toEqual({
|
|
106
|
-
id: "test-id",
|
|
107
|
-
md5: "test-md5",
|
|
108
|
-
status: "complete",
|
|
109
|
-
});
|
|
110
|
-
});
|
|
111
|
-
|
|
112
|
-
test("Returns null when file is not found", async () => {
|
|
113
|
-
server.use(
|
|
114
|
-
http.get("http://localhost/api/v1/renders/md5/test-md5", () =>
|
|
115
|
-
HttpResponse.json({}, { status: 404 }),
|
|
116
|
-
),
|
|
117
|
-
);
|
|
118
|
-
|
|
119
|
-
const response = await lookupRenderByMd5(client, "test-md5");
|
|
120
|
-
|
|
121
|
-
expect(response).toBeNull();
|
|
122
|
-
});
|
|
123
|
-
|
|
124
|
-
test("Throws when server returns an error", async () => {
|
|
125
|
-
server.use(
|
|
126
|
-
http.get("http://localhost/api/v1/renders/md5/test-md5", () =>
|
|
127
|
-
HttpResponse.text("Internal Server Error", { status: 500 }),
|
|
128
|
-
),
|
|
129
|
-
);
|
|
130
|
-
|
|
131
|
-
await expect(lookupRenderByMd5(client, "test-md5")).rejects.toThrowError(
|
|
132
|
-
"Failed to lookup render by md5 test-md5 500 Internal Server Error",
|
|
133
|
-
);
|
|
134
|
-
});
|
|
135
|
-
});
|
|
136
|
-
});
|
|
137
|
-
|
|
138
|
-
describe("OutputConfiguration", () => {
|
|
139
|
-
test("should create a valid output configuration from nullish values", () => {
|
|
140
|
-
const outputConfiguration = OutputConfiguration.parse();
|
|
141
|
-
expect(outputConfiguration.output).toEqual({
|
|
142
|
-
container: "mp4",
|
|
143
|
-
audio: {
|
|
144
|
-
codec: "aac",
|
|
145
|
-
},
|
|
146
|
-
video: {
|
|
147
|
-
codec: "h264",
|
|
148
|
-
},
|
|
149
|
-
});
|
|
150
|
-
});
|
|
151
|
-
|
|
152
|
-
test("should permit mp4 configuration", () => {
|
|
153
|
-
const outputConfiguration = OutputConfiguration.parse({
|
|
154
|
-
container: "mp4",
|
|
155
|
-
video: {
|
|
156
|
-
codec: "h264",
|
|
157
|
-
},
|
|
158
|
-
audio: {
|
|
159
|
-
codec: "aac",
|
|
160
|
-
},
|
|
161
|
-
});
|
|
162
|
-
expect(outputConfiguration.isVideo).toBe(true);
|
|
163
|
-
});
|
|
164
|
-
|
|
165
|
-
test("should permit png configuration", () => {
|
|
166
|
-
const outputConfiguration = OutputConfiguration.parse({
|
|
167
|
-
container: "png",
|
|
168
|
-
compression: 100,
|
|
169
|
-
transparency: true,
|
|
170
|
-
});
|
|
171
|
-
expect(outputConfiguration.isStill).toBe(true);
|
|
172
|
-
});
|
|
173
|
-
|
|
174
|
-
test("should permit webp configuration", () => {
|
|
175
|
-
const outputConfiguration = OutputConfiguration.parse({
|
|
176
|
-
container: "webp",
|
|
177
|
-
quality: 100,
|
|
178
|
-
compression: 6,
|
|
179
|
-
transparency: true,
|
|
180
|
-
});
|
|
181
|
-
expect(outputConfiguration.isStill).toBe(true);
|
|
182
|
-
});
|
|
183
|
-
|
|
184
|
-
test("should permit jpeg configuration", () => {
|
|
185
|
-
const outputConfiguration = OutputConfiguration.parse({
|
|
186
|
-
container: "jpeg",
|
|
187
|
-
quality: 100,
|
|
188
|
-
});
|
|
189
|
-
expect(outputConfiguration.isStill).toBe(true);
|
|
190
|
-
});
|
|
191
|
-
});
|
|
192
|
-
|
|
193
|
-
const createTestRender = () =>
|
|
194
|
-
({
|
|
195
|
-
md5: "test-md5",
|
|
196
|
-
fps: 30,
|
|
197
|
-
width: 1920,
|
|
198
|
-
height: 1080,
|
|
199
|
-
work_slice_ms: 100,
|
|
200
|
-
duration_ms: 1000,
|
|
201
|
-
strategy: "v1",
|
|
202
|
-
}) as const;
|