@editframe/api 0.11.0-beta.9 → 0.12.0-beta.10

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 (58) hide show
  1. package/dist/ProgressIterator.d.ts +25 -0
  2. package/dist/ProgressIterator.test.d.ts +1 -0
  3. package/dist/StreamEventSource.d.ts +50 -0
  4. package/dist/StreamEventSource.test.d.ts +1 -0
  5. package/dist/{CHUNK_SIZE_BYTES.js → api/src/CHUNK_SIZE_BYTES.js} +1 -1
  6. package/dist/api/src/ProgressIterator.js +99 -0
  7. package/dist/api/src/StreamEventSource.js +130 -0
  8. package/dist/api/src/client.js +49 -0
  9. package/dist/api/src/index.js +49 -0
  10. package/dist/{resources → api/src/resources}/caption-file.js +22 -2
  11. package/dist/{resources → api/src/resources}/image-file.js +24 -4
  12. package/dist/api/src/resources/isobmff-file.js +102 -0
  13. package/dist/{resources → api/src/resources}/isobmff-track.js +44 -1
  14. package/dist/api/src/resources/process-isobmff.js +22 -0
  15. package/dist/{resources → api/src/resources}/renders.js +21 -2
  16. package/dist/api/src/resources/transcriptions.js +45 -0
  17. package/dist/api/src/resources/unprocessed-file.js +114 -0
  18. package/dist/api/src/streamChunker.js +28 -0
  19. package/dist/{uploadChunks.js → api/src/uploadChunks.js} +1 -4
  20. package/dist/cli/src/utils/createReadableStreamFromReadable.js +82 -0
  21. package/dist/client.d.ts +6 -3
  22. package/dist/index.d.ts +7 -5
  23. package/dist/readableFromBuffers.d.ts +1 -2
  24. package/dist/resources/caption-file.d.ts +7 -3
  25. package/dist/resources/image-file.d.ts +15 -5
  26. package/dist/resources/isobmff-file.d.ts +29 -3
  27. package/dist/resources/isobmff-track.d.ts +13 -15
  28. package/dist/resources/process-isobmff.d.ts +12 -0
  29. package/dist/resources/process-isobmff.test.d.ts +1 -0
  30. package/dist/resources/renders.d.ts +10 -5
  31. package/dist/resources/transcriptions.d.ts +24 -0
  32. package/dist/resources/transcriptions.test.d.ts +1 -0
  33. package/dist/resources/unprocessed-file.d.ts +15 -53
  34. package/dist/streamChunker.d.ts +1 -2
  35. package/dist/uploadChunks.d.ts +1 -2
  36. package/package.json +3 -2
  37. package/src/resources/caption-file.test.ts +57 -6
  38. package/src/resources/caption-file.ts +34 -5
  39. package/src/resources/image-file.test.ts +59 -11
  40. package/src/resources/image-file.ts +75 -9
  41. package/src/resources/isobmff-file.test.ts +57 -6
  42. package/src/resources/isobmff-file.ts +96 -5
  43. package/src/resources/isobmff-track.test.ts +3 -3
  44. package/src/resources/isobmff-track.ts +50 -5
  45. package/src/resources/process-isobmff.test.ts +62 -0
  46. package/src/resources/process-isobmff.ts +33 -0
  47. package/src/resources/renders.test.ts +51 -6
  48. package/src/resources/renders.ts +34 -5
  49. package/src/resources/transcriptions.test.ts +49 -0
  50. package/src/resources/transcriptions.ts +64 -0
  51. package/src/resources/unprocessed-file.test.ts +24 -437
  52. package/src/resources/unprocessed-file.ts +90 -160
  53. package/dist/client.js +0 -35
  54. package/dist/index.js +0 -36
  55. package/dist/resources/isobmff-file.js +0 -47
  56. package/dist/resources/unprocessed-file.js +0 -180
  57. package/dist/streamChunker.js +0 -17
  58. /package/dist/{resources → api/src/resources}/url-token.js +0 -0
@@ -1,7 +1,5 @@
1
- import type { Readable } from "node:stream";
2
-
3
- import { z } from "zod";
4
1
  import debug from "debug";
2
+ import { z } from "zod";
5
3
 
6
4
  import type { Client } from "../client.ts";
7
5
 
@@ -18,7 +16,21 @@ export interface CreateISOBMFFFileResult {
18
16
  filename: string;
19
17
  id: string;
20
18
  md5: string;
21
- asset_id: string;
19
+ }
20
+
21
+ export interface LookupISOBMFFFileByMd5Result {
22
+ fragment_index_complete: boolean;
23
+ filename: string;
24
+ id: string;
25
+ md5: string;
26
+ }
27
+
28
+ export interface GetISOBMFFFileTranscriptionResult {
29
+ id: string;
30
+ work_slice_ms: number;
31
+ isobmff_track: {
32
+ duration_ms: number;
33
+ };
22
34
  }
23
35
 
24
36
  export const createISOBMFFFile = async (
@@ -45,7 +57,7 @@ export const createISOBMFFFile = async (
45
57
  export const uploadFragmentIndex = async (
46
58
  client: Client,
47
59
  fileId: string,
48
- fileStream: Readable,
60
+ fileStream: ReadableStream,
49
61
  fileSize: number,
50
62
  ) => {
51
63
  log("Uploading fragment index", fileId);
@@ -57,6 +69,7 @@ export const uploadFragmentIndex = async (
57
69
  {
58
70
  method: "POST",
59
71
  body: fileStream,
72
+ duplex: "half",
60
73
  },
61
74
  );
62
75
 
@@ -69,3 +82,81 @@ export const uploadFragmentIndex = async (
69
82
  `Failed to create fragment index ${response.status} ${response.statusText}`,
70
83
  );
71
84
  };
85
+
86
+ export const lookupISOBMFFFileByMd5 = async (
87
+ client: Client,
88
+ md5: string,
89
+ ): Promise<LookupISOBMFFFileByMd5Result | null> => {
90
+ const response = await client.authenticatedFetch(
91
+ `/api/v1/isobmff_files/md5/${md5}`,
92
+ {
93
+ method: "GET",
94
+ },
95
+ );
96
+ log("ISOBMFF file lookup", response);
97
+
98
+ if (response.ok) {
99
+ return (await response.json()) as LookupISOBMFFFileByMd5Result;
100
+ }
101
+
102
+ if (response.status === 404) {
103
+ return null;
104
+ }
105
+
106
+ throw new Error(
107
+ `Failed to lookup isobmff file by md5 ${md5} ${response.status} ${response.statusText}`,
108
+ );
109
+ };
110
+
111
+ export const getISOBMFFFileTranscription = async (
112
+ client: Client,
113
+ id: string,
114
+ ): Promise<GetISOBMFFFileTranscriptionResult | null> => {
115
+ const response = await client.authenticatedFetch(
116
+ `/api/v1/isobmff_files/${id}/transcription`,
117
+ );
118
+
119
+ if (response.ok) {
120
+ return (await response.json()) as GetISOBMFFFileTranscriptionResult;
121
+ }
122
+
123
+ if (response.status === 404) {
124
+ return null;
125
+ }
126
+
127
+ throw new Error(
128
+ `Failed to get isobmff file transcription ${id} ${response.status} ${response.statusText}`,
129
+ );
130
+ };
131
+
132
+ export const TranscribeISOBMFFFilePayload = z.object({
133
+ trackId: z.string().optional(),
134
+ });
135
+
136
+ export interface TranscribeISOBMFFFileResult {
137
+ id: string;
138
+ file_id: string;
139
+ track_id: number;
140
+ }
141
+
142
+ export const transcribeISOBMFFFile = async (
143
+ client: Client,
144
+ id: string,
145
+ payload: z.infer<typeof TranscribeISOBMFFFilePayload> = {},
146
+ ) => {
147
+ const response = await client.authenticatedFetch(
148
+ `/api/v1/isobmff_files/${id}/transcribe`,
149
+ {
150
+ method: "POST",
151
+ body: JSON.stringify(payload),
152
+ },
153
+ );
154
+
155
+ if (response.ok) {
156
+ return (await response.json()) as TranscribeISOBMFFFileResult;
157
+ }
158
+
159
+ throw new Error(
160
+ `Failed to transcribe isobmff file ${id} ${response.status} ${response.statusText}`,
161
+ );
162
+ };
@@ -5,7 +5,7 @@ import { ZodError } from "zod";
5
5
 
6
6
  import { createTestTrack } from "TEST/createTestTrack.ts";
7
7
  import { Client } from "../client.ts";
8
- import { readableFromBuffers } from "../readableFromBuffers.ts";
8
+ import { webReadableFromBuffers } from "../readableFromBuffers.ts";
9
9
  import { createISOBMFFTrack, uploadISOBMFFTrack } from "./isobmff-track.ts";
10
10
 
11
11
  const server = setupServer();
@@ -92,7 +92,7 @@ describe("ISOBMFF Track", () => {
92
92
  client,
93
93
  "test-file",
94
94
  1,
95
- readableFromBuffers(Buffer.from("test")),
95
+ webReadableFromBuffers(Buffer.from("test")),
96
96
  4,
97
97
  ).whenUploaded(),
98
98
  ).rejects.toThrowError(
@@ -114,7 +114,7 @@ describe("ISOBMFF Track", () => {
114
114
  client,
115
115
  "test-file",
116
116
  1,
117
- readableFromBuffers(Buffer.from("test")),
117
+ webReadableFromBuffers(Buffer.from("test")),
118
118
  4,
119
119
  ).whenUploaded(),
120
120
  ).resolves.toEqual([
@@ -1,9 +1,55 @@
1
- import type { Readable } from "node:stream";
2
-
3
1
  import debug from "debug";
4
2
  import { z } from "zod";
5
3
 
6
- import { AudioStreamSchema, VideoStreamSchema } from "@editframe/assets";
4
+ const AudioStreamSchema = z.object({
5
+ index: z.number(),
6
+ codec_name: z.string(),
7
+ codec_long_name: z.string(),
8
+ codec_type: z.literal("audio"),
9
+ codec_tag_string: z.string(),
10
+ codec_tag: z.string(),
11
+ sample_fmt: z.string(),
12
+ sample_rate: z.string(),
13
+ channels: z.number(),
14
+ channel_layout: z.string(),
15
+ bits_per_sample: z.number(),
16
+ initial_padding: z.number().optional(),
17
+ r_frame_rate: z.string(),
18
+ avg_frame_rate: z.string(),
19
+ time_base: z.string(),
20
+ start_pts: z.number(),
21
+ start_time: z.coerce.number(),
22
+ duration_ts: z.number(),
23
+ duration: z.coerce.number(),
24
+ bit_rate: z.string(),
25
+ disposition: z.record(z.unknown()),
26
+ });
27
+
28
+ type AudioStreamSchema = z.infer<typeof AudioStreamSchema>;
29
+
30
+ const VideoStreamSchema = z.object({
31
+ index: z.number(),
32
+ codec_name: z.string(),
33
+ codec_long_name: z.string(),
34
+ codec_type: z.literal("video"),
35
+ codec_tag_string: z.string(),
36
+ codec_tag: z.string(),
37
+ width: z.number(),
38
+ height: z.number(),
39
+ coded_width: z.number(),
40
+ coded_height: z.number(),
41
+ r_frame_rate: z.string(),
42
+ avg_frame_rate: z.string(),
43
+ time_base: z.string(),
44
+ start_pts: z.number().optional(),
45
+ start_time: z.coerce.number().optional(),
46
+ duration_ts: z.number().optional(),
47
+ duration: z.coerce.number().optional(),
48
+ bit_rate: z.string().optional(),
49
+ disposition: z.record(z.unknown()),
50
+ });
51
+
52
+ type VideoStreamSchema = z.infer<typeof VideoStreamSchema>;
7
53
 
8
54
  import type { Client } from "../client.ts";
9
55
  import { uploadChunks } from "../uploadChunks.ts";
@@ -38,7 +84,6 @@ export interface CreateISOBMFFTrackResult {
38
84
  byte_size: number;
39
85
  track_id: number;
40
86
  file_id: string;
41
- asset_id: string;
42
87
  complete: boolean;
43
88
  }
44
89
 
@@ -67,7 +112,7 @@ export const uploadISOBMFFTrack = (
67
112
  client: Client,
68
113
  fileId: string,
69
114
  trackId: number,
70
- fileStream: Readable,
115
+ fileStream: ReadableStream,
71
116
  trackSize: number,
72
117
  ) => {
73
118
  log("Uploading fragment track", fileId);
@@ -0,0 +1,62 @@
1
+ import { describe, expect, test } from "vitest";
2
+ import {
3
+ getIsobmffProcessInfo,
4
+ getIsobmffProcessProgress,
5
+ } from "./process-isobmff.ts";
6
+
7
+ import { useMSW } from "TEST/useMSW.ts";
8
+ import { http, HttpResponse } from "msw";
9
+ import { Client } from "../client.ts";
10
+
11
+ const client = new Client("ef_TEST_TOKEN", "http://localhost");
12
+
13
+ describe("process-isobmff", () => {
14
+ const server = useMSW();
15
+ describe("getIsobmffProcessInfo", () => {
16
+ test("returns the process info", async () => {
17
+ server.use(
18
+ http.get("http://localhost/api/v1/process_isobmff/123", async () => {
19
+ return HttpResponse.json({
20
+ id: "123",
21
+ created_at: "2021-01-01T00:00:00.000Z",
22
+ updated_at: "2021-01-01T00:00:00.000Z",
23
+ });
24
+ }),
25
+ );
26
+ const info = await getIsobmffProcessInfo(client, "123");
27
+ expect(info).toEqual({
28
+ id: "123",
29
+ created_at: "2021-01-01T00:00:00.000Z",
30
+ updated_at: "2021-01-01T00:00:00.000Z",
31
+ });
32
+ });
33
+
34
+ test("throws when the server returns an error", async () => {
35
+ server.use(
36
+ http.get("http://localhost/api/v1/process_isobmff/123", () =>
37
+ HttpResponse.text("Internal Server Error", { status: 500 }),
38
+ ),
39
+ );
40
+ await expect(getIsobmffProcessInfo(client, "123")).rejects.toThrow(
41
+ "Failed to get isobmff process info 500 Internal Server Error",
42
+ );
43
+ });
44
+ });
45
+
46
+ describe("getIsobmffProcessProgress", () => {
47
+ test("returns the progress", async () => {
48
+ server.use(
49
+ http.get(
50
+ "http://localhost/api/v1/process_isobmff/123/progress",
51
+ async () => {
52
+ return HttpResponse.text("event: complete\ndata: {}\n\n");
53
+ },
54
+ ),
55
+ );
56
+ const progress = await getIsobmffProcessProgress(client, "123");
57
+ await expect(progress.whenComplete()).resolves.toEqual([
58
+ { type: "complete", data: {} },
59
+ ]);
60
+ });
61
+ });
62
+ });
@@ -0,0 +1,33 @@
1
+ import { ProgressIterator } from "../ProgressIterator.ts";
2
+ import type { Client } from "../client.ts";
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;
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,10 +1,10 @@
1
- import { test, expect, beforeAll, afterEach, afterAll, describe } from "vitest";
2
1
  import { http, HttpResponse } from "msw";
3
2
  import { setupServer } from "msw/node";
3
+ import { afterAll, afterEach, beforeAll, describe, expect, test } from "vitest";
4
4
 
5
5
  import { Client } from "../client.ts";
6
- import { readableFromBuffers } from "../readableFromBuffers.ts";
7
- import { createRender, uploadRender } from "./renders.ts";
6
+ import { webReadableFromBuffers } from "../readableFromBuffers.ts";
7
+ import { createRender, lookupRenderByMd5, uploadRender } from "./renders.ts";
8
8
 
9
9
  const server = setupServer();
10
10
  const client = new Client("ef_TEST_TOKEN", "http://localhost");
@@ -51,7 +51,7 @@ describe("Renders", () => {
51
51
  uploadRender(
52
52
  client,
53
53
  "test-id",
54
- readableFromBuffers(Buffer.from("test")),
54
+ webReadableFromBuffers(Buffer.from("test")),
55
55
  1024 * 1024 * 17,
56
56
  ),
57
57
  ).rejects.toThrowError(
@@ -70,7 +70,7 @@ describe("Renders", () => {
70
70
  uploadRender(
71
71
  client,
72
72
  "test-id",
73
- readableFromBuffers(Buffer.from("test")),
73
+ webReadableFromBuffers(Buffer.from("test")),
74
74
  1024 * 1024 * 2,
75
75
  ),
76
76
  ).rejects.toThrowError(
@@ -91,13 +91,58 @@ describe("Renders", () => {
91
91
  const response = await uploadRender(
92
92
  client,
93
93
  "test-id",
94
- readableFromBuffers(Buffer.from("test")),
94
+ webReadableFromBuffers(Buffer.from("test")),
95
95
  1024 * 1024 * 2,
96
96
  );
97
97
 
98
98
  expect(response).toEqual({ testResponse: "test" });
99
99
  });
100
100
  });
101
+
102
+ describe("lookupRenderByMd5", () => {
103
+ test("Returns json data from the http response", async () => {
104
+ server.use(
105
+ http.get("http://localhost/api/v1/renders/md5/test-md5", () =>
106
+ HttpResponse.json(
107
+ { id: "test-id", md5: "test-md5", status: "complete" },
108
+ { status: 200, statusText: "OK" },
109
+ ),
110
+ ),
111
+ );
112
+
113
+ const response = await lookupRenderByMd5(client, "test-md5");
114
+
115
+ expect(response).toEqual({
116
+ id: "test-id",
117
+ md5: "test-md5",
118
+ status: "complete",
119
+ });
120
+ });
121
+
122
+ test("Returns null when file is not found", async () => {
123
+ server.use(
124
+ http.get("http://localhost/api/v1/renders/md5/test-md5", () =>
125
+ HttpResponse.json({}, { status: 404 }),
126
+ ),
127
+ );
128
+
129
+ const response = await lookupRenderByMd5(client, "test-md5");
130
+
131
+ expect(response).toBeNull();
132
+ });
133
+
134
+ test("Throws when server returns an error", async () => {
135
+ server.use(
136
+ http.get("http://localhost/api/v1/renders/md5/test-md5", () =>
137
+ HttpResponse.text("Internal Server Error", { status: 500 }),
138
+ ),
139
+ );
140
+
141
+ await expect(lookupRenderByMd5(client, "test-md5")).rejects.toThrowError(
142
+ "Failed to lookup render by md5 test-md5 500 Internal Server Error",
143
+ );
144
+ });
145
+ });
101
146
  });
102
147
 
103
148
  const createTestRender = () =>
@@ -1,7 +1,5 @@
1
- import type { Readable } from "node:stream";
2
-
3
- import { z } from "zod";
4
1
  import debug from "debug";
2
+ import { z } from "zod";
5
3
 
6
4
  import type { Client } from "../client.ts";
7
5
 
@@ -21,7 +19,13 @@ export const CreateRenderPayload = z.object({
21
19
  export interface CreateRenderResult {
22
20
  id: string;
23
21
  md5: string;
24
- status: "complete" | "created" | "failed" | "pending" | "rendering";
22
+ status: "complete" | "created" | "failed" | "pending" | "rendering" | string;
23
+ }
24
+
25
+ export interface LookupRenderByMd5Result {
26
+ id: string;
27
+ md5: string;
28
+ status: "complete" | "created" | "failed" | "pending" | "rendering" | string;
25
29
  }
26
30
 
27
31
  export const createRender = async (
@@ -47,7 +51,7 @@ export const createRender = async (
47
51
  export const uploadRender = async (
48
52
  client: Client,
49
53
  fileId: string,
50
- fileStream: Readable,
54
+ fileStream: ReadableStream,
51
55
  folderSize: number,
52
56
  ) => {
53
57
  log("Uploading render", fileId);
@@ -60,6 +64,7 @@ export const uploadRender = async (
60
64
  {
61
65
  method: "POST",
62
66
  body: fileStream,
67
+ duplex: "half",
63
68
  },
64
69
  );
65
70
 
@@ -71,3 +76,27 @@ export const uploadRender = async (
71
76
  `Failed to upload render ${response.status} ${response.statusText}`,
72
77
  );
73
78
  };
79
+
80
+ export const lookupRenderByMd5 = async (
81
+ client: Client,
82
+ md5: string,
83
+ ): Promise<LookupRenderByMd5Result | null> => {
84
+ const response = await client.authenticatedFetch(
85
+ `/api/v1/renders/md5/${md5}`,
86
+ {
87
+ method: "GET",
88
+ },
89
+ );
90
+
91
+ if (response.ok) {
92
+ return (await response.json()) as LookupRenderByMd5Result;
93
+ }
94
+
95
+ if (response.status === 404) {
96
+ return null;
97
+ }
98
+
99
+ throw new Error(
100
+ `Failed to lookup render by md5 ${md5} ${response.status} ${response.statusText}`,
101
+ );
102
+ };
@@ -0,0 +1,49 @@
1
+ import { http, HttpResponse } from "msw";
2
+ import { setupServer } from "msw/node";
3
+ import { afterAll, afterEach, beforeAll, describe, expect, test } from "vitest";
4
+
5
+ import { Client } from "../client.ts";
6
+ import { createTranscription } from "./transcriptions.ts";
7
+
8
+ const server = setupServer();
9
+ const client = new Client("ef_TEST_TOKEN", "http://localhost");
10
+
11
+ describe("Transcriptions", () => {
12
+ beforeAll(() => server.listen());
13
+ afterEach(() => server.resetHandlers());
14
+ afterAll(() => server.close());
15
+
16
+ describe("createTranscription", () => {
17
+ test("throws if server returns an error", async () => {
18
+ server.use(
19
+ http.post("http://localhost/api/v1/transcriptions", () =>
20
+ HttpResponse.text("Internal Server Error", { status: 500 }),
21
+ ),
22
+ );
23
+
24
+ await expect(
25
+ createTranscription(client, { file_id: "test", track_id: 1 }),
26
+ ).rejects.toThrowError(
27
+ "Failed to create transcription 500 Internal Server Error",
28
+ );
29
+ });
30
+
31
+ test("returns json data from the http response", async () => {
32
+ server.use(
33
+ http.post("http://localhost/api/v1/transcriptions", () =>
34
+ HttpResponse.json(
35
+ { testResponse: "test" },
36
+ { status: 200, statusText: "OK" },
37
+ ),
38
+ ),
39
+ );
40
+
41
+ const response = await createTranscription(client, {
42
+ file_id: "test",
43
+ track_id: 1,
44
+ });
45
+
46
+ expect(response).toEqual({ testResponse: "test" });
47
+ });
48
+ });
49
+ });
@@ -0,0 +1,64 @@
1
+ import debug from "debug";
2
+ import { z } from "zod";
3
+
4
+ import { CompletionIterator } from "../ProgressIterator.ts";
5
+ import type { Client } from "../client.ts";
6
+
7
+ const log = debug("ef:api:transcriptions");
8
+
9
+ export const CreateTranscriptionPayload = z.object({
10
+ file_id: z.string(),
11
+ track_id: z.number().int(),
12
+ });
13
+
14
+ export interface CreateTranscriptionResult {
15
+ id: string;
16
+ status: "complete" | "created" | "failed" | "pending" | "transcribing";
17
+ }
18
+
19
+ export interface TranscriptionInfoResult {
20
+ id: string;
21
+ status: "complete" | "created" | "failed" | "pending" | "transcribing";
22
+ }
23
+
24
+ export const createTranscription = async (
25
+ client: Client,
26
+ payload: z.infer<typeof CreateTranscriptionPayload>,
27
+ ) => {
28
+ log("Creating transcription", payload);
29
+ const response = await client.authenticatedFetch("/api/v1/transcriptions", {
30
+ method: "POST",
31
+ body: JSON.stringify(payload),
32
+ });
33
+
34
+ log("Transcription created", response);
35
+ if (response.ok) {
36
+ return (await response.json()) as CreateTranscriptionResult;
37
+ }
38
+
39
+ throw new Error(
40
+ `Failed to create transcription ${response.status} ${response.statusText}`,
41
+ );
42
+ };
43
+
44
+ export const getTranscriptionProgress = async (client: Client, id: string) => {
45
+ const eventSource = await client.authenticatedEventSource(
46
+ `/api/v1/transcriptions/${id}/progress`,
47
+ );
48
+
49
+ return new CompletionIterator(eventSource);
50
+ };
51
+
52
+ export const getTranscriptionInfo = async (client: Client, id: string) => {
53
+ const response = await client.authenticatedFetch(
54
+ `/api/v1/transcriptions/${id}`,
55
+ );
56
+
57
+ if (response.ok) {
58
+ return (await response.json()) as TranscriptionInfoResult;
59
+ }
60
+
61
+ throw new Error(
62
+ `Failed to get transcription info ${response.status} ${response.statusText}`,
63
+ );
64
+ };