@editframe/api 0.16.8-beta.0 → 0.17.6-beta.0
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/CHUNK_SIZE_BYTES.js +2 -6
- package/dist/ProgressIterator.js +101 -114
- package/dist/StreamEventSource.js +115 -137
- package/dist/client.js +39 -50
- package/dist/index.js +3 -48
- package/dist/node.js +35 -91
- package/dist/resources/caption-file.js +46 -70
- package/dist/resources/image-file.js +48 -99
- package/dist/resources/isobmff-file.js +37 -86
- package/dist/resources/isobmff-track.js +79 -88
- package/dist/resources/process-isobmff.js +6 -17
- package/dist/resources/renders.bundle.js +28 -37
- package/dist/resources/renders.js +112 -170
- package/dist/resources/transcriptions.js +17 -34
- package/dist/resources/unprocessed-file.js +31 -67
- package/dist/resources/url-token.js +8 -16
- package/dist/streamChunker.js +21 -25
- package/dist/uploadChunks.js +75 -91
- package/dist/utils/assertTypesMatch.js +2 -0
- package/dist/utils/createReadableStreamFromReadable.js +61 -78
- package/package.json +4 -4
- package/src/resources/renders.bundle.ts +1 -1
- package/src/utils/createReadableStreamFromReadable.ts +4 -6
- package/types.json +1 -1
|
@@ -1,104 +1,95 @@
|
|
|
1
|
+
import { uploadChunks } from "../uploadChunks.js";
|
|
2
|
+
import { assertTypesMatch } from "../utils/assertTypesMatch.js";
|
|
1
3
|
import debug from "debug";
|
|
2
4
|
import { z } from "zod";
|
|
3
|
-
import { uploadChunks } from "../uploadChunks.js";
|
|
4
5
|
const AudioStreamSchema = z.object({
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
6
|
+
index: z.number(),
|
|
7
|
+
codec_name: z.string(),
|
|
8
|
+
codec_long_name: z.string(),
|
|
9
|
+
codec_type: z.literal("audio"),
|
|
10
|
+
codec_tag_string: z.string(),
|
|
11
|
+
codec_tag: z.string(),
|
|
12
|
+
sample_fmt: z.string(),
|
|
13
|
+
sample_rate: z.string(),
|
|
14
|
+
channels: z.number(),
|
|
15
|
+
channel_layout: z.string().optional(),
|
|
16
|
+
bits_per_sample: z.number(),
|
|
17
|
+
initial_padding: z.number().optional(),
|
|
18
|
+
r_frame_rate: z.string(),
|
|
19
|
+
avg_frame_rate: z.string(),
|
|
20
|
+
time_base: z.string(),
|
|
21
|
+
start_pts: z.number().optional(),
|
|
22
|
+
start_time: z.coerce.number().optional(),
|
|
23
|
+
duration_ts: z.number(),
|
|
24
|
+
duration: z.coerce.number(),
|
|
25
|
+
bit_rate: z.string(),
|
|
26
|
+
disposition: z.record(z.unknown())
|
|
26
27
|
});
|
|
28
|
+
assertTypesMatch(true);
|
|
27
29
|
const VideoStreamSchema = z.object({
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
30
|
+
index: z.number(),
|
|
31
|
+
codec_name: z.string(),
|
|
32
|
+
codec_long_name: z.string(),
|
|
33
|
+
codec_type: z.literal("video"),
|
|
34
|
+
codec_tag_string: z.string(),
|
|
35
|
+
codec_tag: z.string(),
|
|
36
|
+
width: z.number(),
|
|
37
|
+
height: z.number(),
|
|
38
|
+
coded_width: z.number(),
|
|
39
|
+
coded_height: z.number(),
|
|
40
|
+
r_frame_rate: z.string(),
|
|
41
|
+
avg_frame_rate: z.string(),
|
|
42
|
+
time_base: z.string(),
|
|
43
|
+
start_pts: z.number().optional(),
|
|
44
|
+
start_time: z.coerce.number().optional(),
|
|
45
|
+
duration_ts: z.number().optional(),
|
|
46
|
+
duration: z.coerce.number().optional(),
|
|
47
|
+
bit_rate: z.string().optional(),
|
|
48
|
+
disposition: z.record(z.unknown())
|
|
47
49
|
});
|
|
50
|
+
assertTypesMatch(true);
|
|
48
51
|
const log = debug("ef:api:isobmff-track");
|
|
49
52
|
const MAX_TRACK_SIZE = 1024 * 1024 * 1024;
|
|
50
53
|
const AudioTrackPayload = z.object({
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
54
|
+
file_id: z.string(),
|
|
55
|
+
track_id: z.number().int(),
|
|
56
|
+
type: z.literal("audio"),
|
|
57
|
+
probe_info: AudioStreamSchema,
|
|
58
|
+
duration_ms: z.number().int(),
|
|
59
|
+
codec_name: z.string(),
|
|
60
|
+
byte_size: z.number().int().max(MAX_TRACK_SIZE)
|
|
58
61
|
});
|
|
62
|
+
assertTypesMatch(true);
|
|
59
63
|
const VideoTrackPayload = z.object({
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
64
|
+
file_id: z.string(),
|
|
65
|
+
track_id: z.number().int(),
|
|
66
|
+
type: z.literal("video"),
|
|
67
|
+
probe_info: VideoStreamSchema,
|
|
68
|
+
duration_ms: z.number().int(),
|
|
69
|
+
codec_name: z.string(),
|
|
70
|
+
byte_size: z.number().int().max(MAX_TRACK_SIZE)
|
|
67
71
|
});
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
]);
|
|
72
|
+
assertTypesMatch(true);
|
|
73
|
+
const CreateISOBMFFTrackPayload = z.discriminatedUnion("type", [AudioTrackPayload, VideoTrackPayload]);
|
|
74
|
+
assertTypesMatch(true);
|
|
72
75
|
const createISOBMFFTrack = async (client, payload) => {
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
}
|
|
83
|
-
throw new Error(
|
|
84
|
-
`Failed to create isobmff track ${response.status} ${response.statusText}`
|
|
85
|
-
);
|
|
76
|
+
log("Creating isobmff track", payload);
|
|
77
|
+
CreateISOBMFFTrackPayload.parse(payload);
|
|
78
|
+
const response = await client.authenticatedFetch("/api/v1/isobmff_tracks", {
|
|
79
|
+
method: "POST",
|
|
80
|
+
body: JSON.stringify(payload)
|
|
81
|
+
});
|
|
82
|
+
log("ISOBMFF track created", response);
|
|
83
|
+
if (response.ok) return await response.json();
|
|
84
|
+
throw new Error(`Failed to create isobmff track ${response.status} ${response.statusText}`);
|
|
86
85
|
};
|
|
87
86
|
const uploadISOBMFFTrack = (client, fileId, trackId, fileStream, trackSize) => {
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
};
|
|
96
|
-
export {
|
|
97
|
-
AudioStreamSchema,
|
|
98
|
-
AudioTrackPayload,
|
|
99
|
-
CreateISOBMFFTrackPayload,
|
|
100
|
-
VideoStreamSchema,
|
|
101
|
-
VideoTrackPayload,
|
|
102
|
-
createISOBMFFTrack,
|
|
103
|
-
uploadISOBMFFTrack
|
|
87
|
+
log("Uploading fragment track", fileId);
|
|
88
|
+
return uploadChunks(client, {
|
|
89
|
+
url: `/api/v1/isobmff_tracks/${fileId}/${trackId}/upload`,
|
|
90
|
+
fileStream,
|
|
91
|
+
fileSize: trackSize,
|
|
92
|
+
maxSize: MAX_TRACK_SIZE
|
|
93
|
+
});
|
|
104
94
|
};
|
|
95
|
+
export { AudioTrackPayload, CreateISOBMFFTrackPayload, VideoTrackPayload, createISOBMFFTrack, uploadISOBMFFTrack };
|
|
@@ -1,22 +1,11 @@
|
|
|
1
1
|
import { ProgressIterator } from "../ProgressIterator.js";
|
|
2
2
|
const getIsobmffProcessProgress = async (client, id) => {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
);
|
|
6
|
-
return new ProgressIterator(eventSource);
|
|
3
|
+
const eventSource = await client.authenticatedEventSource(`/api/v1/process_isobmff/${id}/progress`);
|
|
4
|
+
return new ProgressIterator(eventSource);
|
|
7
5
|
};
|
|
8
6
|
const getIsobmffProcessInfo = async (client, id) => {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
if (response.ok) {
|
|
13
|
-
return await response.json();
|
|
14
|
-
}
|
|
15
|
-
throw new Error(
|
|
16
|
-
`Failed to get isobmff process info ${response.status} ${response.statusText}`
|
|
17
|
-
);
|
|
18
|
-
};
|
|
19
|
-
export {
|
|
20
|
-
getIsobmffProcessInfo,
|
|
21
|
-
getIsobmffProcessProgress
|
|
7
|
+
const response = await client.authenticatedFetch(`/api/v1/process_isobmff/${id}`);
|
|
8
|
+
if (response.ok) return await response.json();
|
|
9
|
+
throw new Error(`Failed to get isobmff process info ${response.status} ${response.statusText}`);
|
|
22
10
|
};
|
|
11
|
+
export { getIsobmffProcessInfo, getIsobmffProcessProgress };
|
|
@@ -1,46 +1,37 @@
|
|
|
1
|
+
import { createReadableStreamFromReadable } from "../utils/createReadableStreamFromReadable.js";
|
|
1
2
|
import path from "node:path";
|
|
2
3
|
import { PassThrough } from "node:stream";
|
|
3
4
|
import react from "@vitejs/plugin-react";
|
|
5
|
+
import { build } from "rolldown-vite";
|
|
4
6
|
import * as tar from "tar";
|
|
5
|
-
import { build } from "vite";
|
|
6
7
|
import { viteSingleFile } from "vite-plugin-singlefile";
|
|
7
8
|
import tsconfigPathsPlugin from "vite-tsconfig-paths";
|
|
8
9
|
import { randomUUID } from "node:crypto";
|
|
9
|
-
import { createReadableStreamFromReadable } from "../utils/createReadableStreamFromReadable.js";
|
|
10
10
|
const bundleRender = async (options) => {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
},
|
|
37
|
-
["."]
|
|
38
|
-
);
|
|
39
|
-
const passthrough = new PassThrough();
|
|
40
|
-
tarStream.pipe(passthrough);
|
|
41
|
-
const tarReadStream = createReadableStreamFromReadable(passthrough);
|
|
42
|
-
return tarReadStream;
|
|
43
|
-
};
|
|
44
|
-
export {
|
|
45
|
-
bundleRender
|
|
11
|
+
const outDir = path.join(process.cwd(), "renders", randomUUID());
|
|
12
|
+
await build({
|
|
13
|
+
root: options.root,
|
|
14
|
+
define: { RENDER_DATA: JSON.stringify(options.renderData) },
|
|
15
|
+
build: {
|
|
16
|
+
outDir,
|
|
17
|
+
rollupOptions: { input: path.resolve(options.root, "index.html") }
|
|
18
|
+
},
|
|
19
|
+
plugins: [
|
|
20
|
+
tsconfigPathsPlugin(),
|
|
21
|
+
react({
|
|
22
|
+
include: "**/*.{jsx,js,tsx,ts}",
|
|
23
|
+
jsxRuntime: "automatic"
|
|
24
|
+
}),
|
|
25
|
+
viteSingleFile()
|
|
26
|
+
]
|
|
27
|
+
});
|
|
28
|
+
const tarStream = tar.create({
|
|
29
|
+
gzip: true,
|
|
30
|
+
cwd: outDir
|
|
31
|
+
}, ["."]);
|
|
32
|
+
const passthrough = new PassThrough();
|
|
33
|
+
tarStream.pipe(passthrough);
|
|
34
|
+
const tarReadStream = createReadableStreamFromReadable(passthrough);
|
|
35
|
+
return tarReadStream;
|
|
46
36
|
};
|
|
37
|
+
export { bundleRender };
|
|
@@ -1,197 +1,139 @@
|
|
|
1
|
+
import { assertTypesMatch } from "../utils/assertTypesMatch.js";
|
|
2
|
+
import { CompletionIterator } from "../ProgressIterator.js";
|
|
1
3
|
import debug from "debug";
|
|
2
4
|
import { z } from "zod";
|
|
3
|
-
import { CompletionIterator } from "../ProgressIterator.js";
|
|
4
5
|
const log = debug("ef:api:renders");
|
|
5
|
-
const H264Configuration = z.object({
|
|
6
|
-
|
|
7
|
-
});
|
|
8
|
-
const AACConfiguration = z.object({
|
|
9
|
-
codec: z.literal("aac")
|
|
10
|
-
});
|
|
6
|
+
const H264Configuration = z.object({ codec: z.literal("h264") });
|
|
7
|
+
const AACConfiguration = z.object({ codec: z.literal("aac") });
|
|
11
8
|
const MP4Configuration = z.object({
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
9
|
+
container: z.literal("mp4"),
|
|
10
|
+
video: H264Configuration,
|
|
11
|
+
audio: AACConfiguration
|
|
15
12
|
});
|
|
16
13
|
const JpegConfiguration = z.object({
|
|
17
|
-
|
|
18
|
-
|
|
14
|
+
container: z.literal("jpeg"),
|
|
15
|
+
quality: z.number().int().min(1).max(100).default(80).optional()
|
|
19
16
|
});
|
|
20
17
|
const PngConfiguration = z.object({
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
18
|
+
container: z.literal("png"),
|
|
19
|
+
compression: z.number().int().min(1).max(100).default(80).optional(),
|
|
20
|
+
transparency: z.boolean().default(false).optional()
|
|
24
21
|
});
|
|
25
22
|
const WebpConfiguration = z.object({
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
23
|
+
container: z.literal("webp"),
|
|
24
|
+
quality: z.number().int().min(1).max(100).default(80).optional(),
|
|
25
|
+
compression: z.number().int().min(0).max(6).default(4).optional(),
|
|
26
|
+
transparency: z.boolean().default(false).optional()
|
|
30
27
|
});
|
|
31
28
|
const RenderOutputConfiguration = z.discriminatedUnion("container", [
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
29
|
+
MP4Configuration,
|
|
30
|
+
JpegConfiguration,
|
|
31
|
+
PngConfiguration,
|
|
32
|
+
WebpConfiguration
|
|
36
33
|
]);
|
|
37
34
|
const CreateRenderPayload = z.object({
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
audio: {
|
|
53
|
-
codec: "aac"
|
|
54
|
-
}
|
|
55
|
-
}).optional()
|
|
35
|
+
md5: z.string().optional(),
|
|
36
|
+
fps: z.number().int().min(1).max(120).default(30).optional(),
|
|
37
|
+
width: z.number().int().min(2).optional(),
|
|
38
|
+
height: z.number().int().min(2).optional(),
|
|
39
|
+
work_slice_ms: z.number().int().min(1e3).max(1e4).default(4e3).optional(),
|
|
40
|
+
html: z.string().optional(),
|
|
41
|
+
metadata: z.record(z.string(), z.string()).optional(),
|
|
42
|
+
duration_ms: z.number().int().optional(),
|
|
43
|
+
strategy: z.enum(["v1"]).default("v1").optional(),
|
|
44
|
+
output: RenderOutputConfiguration.default({
|
|
45
|
+
container: "mp4",
|
|
46
|
+
video: { codec: "h264" },
|
|
47
|
+
audio: { codec: "aac" }
|
|
48
|
+
}).optional()
|
|
56
49
|
});
|
|
57
|
-
CreateRenderPayload.extend({
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
return this.output.container === "png" ? this.output : null;
|
|
101
|
-
}
|
|
102
|
-
get webpConfig() {
|
|
103
|
-
return this.output.container === "webp" ? this.output : null;
|
|
104
|
-
}
|
|
105
|
-
get mp4Config() {
|
|
106
|
-
return this.output.container === "mp4" ? this.output : null;
|
|
107
|
-
}
|
|
108
|
-
}
|
|
50
|
+
const CreateRenderPayloadWithOutput = CreateRenderPayload.extend({ output: RenderOutputConfiguration });
|
|
51
|
+
var OutputConfiguration = class OutputConfiguration {
|
|
52
|
+
static parse(input) {
|
|
53
|
+
const output = RenderOutputConfiguration.parse(input ?? {
|
|
54
|
+
container: "mp4",
|
|
55
|
+
video: { codec: "h264" },
|
|
56
|
+
audio: { codec: "aac" }
|
|
57
|
+
});
|
|
58
|
+
return new OutputConfiguration(output);
|
|
59
|
+
}
|
|
60
|
+
constructor(output) {
|
|
61
|
+
this.output = output;
|
|
62
|
+
}
|
|
63
|
+
get isStill() {
|
|
64
|
+
return this.output.container === "jpeg" || this.output.container === "png" || this.output.container === "webp";
|
|
65
|
+
}
|
|
66
|
+
get isVideo() {
|
|
67
|
+
return this.output.container === "mp4";
|
|
68
|
+
}
|
|
69
|
+
get fileExtension() {
|
|
70
|
+
return this.output.container;
|
|
71
|
+
}
|
|
72
|
+
get contentType() {
|
|
73
|
+
if (this.isStill) return `image/${this.fileExtension}`;
|
|
74
|
+
return `video/${this.fileExtension}`;
|
|
75
|
+
}
|
|
76
|
+
get container() {
|
|
77
|
+
return this.output.container;
|
|
78
|
+
}
|
|
79
|
+
get jpegConfig() {
|
|
80
|
+
return this.output.container === "jpeg" ? this.output : null;
|
|
81
|
+
}
|
|
82
|
+
get pngConfig() {
|
|
83
|
+
return this.output.container === "png" ? this.output : null;
|
|
84
|
+
}
|
|
85
|
+
get webpConfig() {
|
|
86
|
+
return this.output.container === "webp" ? this.output : null;
|
|
87
|
+
}
|
|
88
|
+
get mp4Config() {
|
|
89
|
+
return this.output.container === "mp4" ? this.output : null;
|
|
90
|
+
}
|
|
91
|
+
};
|
|
92
|
+
assertTypesMatch(true);
|
|
109
93
|
const createRender = async (client, payload) => {
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
});
|
|
126
|
-
log("Render created", response);
|
|
127
|
-
if (response.ok) {
|
|
128
|
-
return await response.json();
|
|
129
|
-
}
|
|
130
|
-
throw new Error(
|
|
131
|
-
`Failed to create render ${response.status} ${response.statusText} ${await response.text()}`
|
|
132
|
-
);
|
|
94
|
+
log("Creating render", payload);
|
|
95
|
+
payload.strategy ??= "v1";
|
|
96
|
+
payload.work_slice_ms ??= 4e3;
|
|
97
|
+
payload.output ??= {
|
|
98
|
+
container: "mp4",
|
|
99
|
+
video: { codec: "h264" },
|
|
100
|
+
audio: { codec: "aac" }
|
|
101
|
+
};
|
|
102
|
+
const response = await client.authenticatedFetch("/api/v1/renders", {
|
|
103
|
+
method: "POST",
|
|
104
|
+
body: JSON.stringify(payload)
|
|
105
|
+
});
|
|
106
|
+
log("Render created", response);
|
|
107
|
+
if (response.ok) return await response.json();
|
|
108
|
+
throw new Error(`Failed to create render ${response.status} ${response.statusText} ${await response.text()}`);
|
|
133
109
|
};
|
|
134
110
|
const uploadRender = async (client, renderId, fileStream) => {
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
);
|
|
144
|
-
if (response.ok) {
|
|
145
|
-
return response.json();
|
|
146
|
-
}
|
|
147
|
-
throw new Error(
|
|
148
|
-
`Failed to upload render ${response.status} ${response.statusText}`
|
|
149
|
-
);
|
|
111
|
+
log("Uploading render", renderId);
|
|
112
|
+
const response = await client.authenticatedFetch(`/api/v1/renders/${renderId}/upload`, {
|
|
113
|
+
method: "POST",
|
|
114
|
+
body: fileStream,
|
|
115
|
+
duplex: "half"
|
|
116
|
+
});
|
|
117
|
+
if (response.ok) return response.json();
|
|
118
|
+
throw new Error(`Failed to upload render ${response.status} ${response.statusText}`);
|
|
150
119
|
};
|
|
151
120
|
const getRenderInfo = async (client, id) => {
|
|
152
|
-
|
|
153
|
-
|
|
121
|
+
const response = await client.authenticatedFetch(`/api/v1/renders/${id}`);
|
|
122
|
+
return response.json();
|
|
154
123
|
};
|
|
155
124
|
const lookupRenderByMd5 = async (client, md5) => {
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
}
|
|
161
|
-
);
|
|
162
|
-
if (response.ok) {
|
|
163
|
-
return await response.json();
|
|
164
|
-
}
|
|
165
|
-
if (response.status === 404) {
|
|
166
|
-
return null;
|
|
167
|
-
}
|
|
168
|
-
throw new Error(
|
|
169
|
-
`Failed to lookup render by md5 ${md5} ${response.status} ${response.statusText}`
|
|
170
|
-
);
|
|
125
|
+
const response = await client.authenticatedFetch(`/api/v1/renders/md5/${md5}`, { method: "GET" });
|
|
126
|
+
if (response.ok) return await response.json();
|
|
127
|
+
if (response.status === 404) return null;
|
|
128
|
+
throw new Error(`Failed to lookup render by md5 ${md5} ${response.status} ${response.statusText}`);
|
|
171
129
|
};
|
|
172
130
|
const getRenderProgress = async (client, id) => {
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
);
|
|
176
|
-
return new CompletionIterator(eventSource);
|
|
131
|
+
const eventSource = await client.authenticatedEventSource(`/api/v1/renders/${id}/progress`);
|
|
132
|
+
return new CompletionIterator(eventSource);
|
|
177
133
|
};
|
|
178
134
|
const downloadRender = async (client, id) => {
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
}
|
|
183
|
-
throw new Error(
|
|
184
|
-
`Failed to download render ${id} ${response.status} ${response.statusText}`
|
|
185
|
-
);
|
|
186
|
-
};
|
|
187
|
-
export {
|
|
188
|
-
CreateRenderPayload,
|
|
189
|
-
OutputConfiguration,
|
|
190
|
-
RenderOutputConfiguration,
|
|
191
|
-
createRender,
|
|
192
|
-
downloadRender,
|
|
193
|
-
getRenderInfo,
|
|
194
|
-
getRenderProgress,
|
|
195
|
-
lookupRenderByMd5,
|
|
196
|
-
uploadRender
|
|
135
|
+
const response = await client.authenticatedFetch(`/api/v1/renders/${id}.mp4`);
|
|
136
|
+
if (response.ok) return response;
|
|
137
|
+
throw new Error(`Failed to download render ${id} ${response.status} ${response.statusText}`);
|
|
197
138
|
};
|
|
139
|
+
export { CreateRenderPayload, OutputConfiguration, RenderOutputConfiguration, createRender, downloadRender, getRenderInfo, getRenderProgress, lookupRenderByMd5, uploadRender };
|
|
@@ -1,45 +1,28 @@
|
|
|
1
|
+
import { CompletionIterator } from "../ProgressIterator.js";
|
|
1
2
|
import debug from "debug";
|
|
2
3
|
import { z } from "zod";
|
|
3
|
-
import { CompletionIterator } from "../ProgressIterator.js";
|
|
4
4
|
const log = debug("ef:api:transcriptions");
|
|
5
5
|
const CreateTranscriptionPayload = z.object({
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
file_id: z.string(),
|
|
7
|
+
track_id: z.number().int()
|
|
8
8
|
});
|
|
9
9
|
const createTranscription = async (client, payload) => {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
}
|
|
19
|
-
throw new Error(
|
|
20
|
-
`Failed to create transcription ${response.status} ${response.statusText}`
|
|
21
|
-
);
|
|
10
|
+
log("Creating transcription", payload);
|
|
11
|
+
const response = await client.authenticatedFetch("/api/v1/transcriptions", {
|
|
12
|
+
method: "POST",
|
|
13
|
+
body: JSON.stringify(payload)
|
|
14
|
+
});
|
|
15
|
+
log("Transcription created", response);
|
|
16
|
+
if (response.ok) return await response.json();
|
|
17
|
+
throw new Error(`Failed to create transcription ${response.status} ${response.statusText}`);
|
|
22
18
|
};
|
|
23
19
|
const getTranscriptionProgress = async (client, id) => {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
);
|
|
27
|
-
return new CompletionIterator(eventSource);
|
|
20
|
+
const eventSource = await client.authenticatedEventSource(`/api/v1/transcriptions/${id}/progress`);
|
|
21
|
+
return new CompletionIterator(eventSource);
|
|
28
22
|
};
|
|
29
23
|
const getTranscriptionInfo = async (client, id) => {
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
if (response.ok) {
|
|
34
|
-
return await response.json();
|
|
35
|
-
}
|
|
36
|
-
throw new Error(
|
|
37
|
-
`Failed to get transcription info ${response.status} ${response.statusText}`
|
|
38
|
-
);
|
|
39
|
-
};
|
|
40
|
-
export {
|
|
41
|
-
CreateTranscriptionPayload,
|
|
42
|
-
createTranscription,
|
|
43
|
-
getTranscriptionInfo,
|
|
44
|
-
getTranscriptionProgress
|
|
24
|
+
const response = await client.authenticatedFetch(`/api/v1/transcriptions/${id}`);
|
|
25
|
+
if (response.ok) return await response.json();
|
|
26
|
+
throw new Error(`Failed to get transcription info ${response.status} ${response.statusText}`);
|
|
45
27
|
};
|
|
28
|
+
export { CreateTranscriptionPayload, createTranscription, getTranscriptionInfo, getTranscriptionProgress };
|