@ai-sdk/revai 0.0.1

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/CHANGELOG.md ADDED
@@ -0,0 +1,7 @@
1
+ # @ai-sdk/revai
2
+
3
+ ## 0.0.1
4
+
5
+ ### Patch Changes
6
+
7
+ - a7cb932: feat(providers/revai): add transcribe
package/LICENSE ADDED
@@ -0,0 +1,13 @@
1
+ Copyright 2023 Vercel, Inc.
2
+
3
+ Licensed under the Apache License, Version 2.0 (the "License");
4
+ you may not use this file except in compliance with the License.
5
+ You may obtain a copy of the License at
6
+
7
+ http://www.apache.org/licenses/LICENSE-2.0
8
+
9
+ Unless required by applicable law or agreed to in writing, software
10
+ distributed under the License is distributed on an "AS IS" BASIS,
11
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ See the License for the specific language governing permissions and
13
+ limitations under the License.
package/README.md ADDED
@@ -0,0 +1,38 @@
1
+ # AI SDK - Rev.ai Provider
2
+
3
+ The **[Rev.ai provider](https://sdk.vercel.ai/providers/ai-sdk-providers/revai)** for the [AI SDK](https://sdk.vercel.ai/docs)
4
+ contains language model support for the Rev.ai transcription API.
5
+
6
+ ## Setup
7
+
8
+ The Rev.ai provider is available in the `@ai-sdk/revai` module. You can install it with
9
+
10
+ ```bash
11
+ npm i @ai-sdk/revai
12
+ ```
13
+
14
+ ## Provider Instance
15
+
16
+ You can import the default provider instance `revai` from `@ai-sdk/revai`:
17
+
18
+ ```ts
19
+ import { revai } from '@ai-sdk/revai';
20
+ ```
21
+
22
+ ## Example
23
+
24
+ ```ts
25
+ import { revai } from '@ai-sdk/revai';
26
+ import { experimental_transcribe as transcribe } from 'ai';
27
+
28
+ const { text } = await transcribe({
29
+ model: revai.transcription('machine'),
30
+ audio: new URL(
31
+ 'https://github.com/vercel/ai/raw/refs/heads/main/examples/ai-core/data/galileo.mp3',
32
+ ),
33
+ });
34
+ ```
35
+
36
+ ## Documentation
37
+
38
+ Please check out the **[Rev.ai provider documentation](https://sdk.vercel.ai/providers/ai-sdk-providers/revai)** for more information.
@@ -0,0 +1,65 @@
1
+ import { TranscriptionModelV1, ProviderV1 } from '@ai-sdk/provider';
2
+ import { FetchFunction } from '@ai-sdk/provider-utils';
3
+
4
+ type RevaiConfig = {
5
+ provider: string;
6
+ url: (options: {
7
+ modelId: string;
8
+ path: string;
9
+ }) => string;
10
+ headers: () => Record<string, string | undefined>;
11
+ fetch?: FetchFunction;
12
+ generateId?: () => string;
13
+ };
14
+
15
+ type RevaiTranscriptionModelId = 'machine' | 'low_cost' | 'fusion';
16
+
17
+ interface RevaiTranscriptionModelConfig extends RevaiConfig {
18
+ _internal?: {
19
+ currentDate?: () => Date;
20
+ };
21
+ }
22
+ declare class RevaiTranscriptionModel implements TranscriptionModelV1 {
23
+ readonly modelId: RevaiTranscriptionModelId;
24
+ private readonly config;
25
+ readonly specificationVersion = "v1";
26
+ get provider(): string;
27
+ constructor(modelId: RevaiTranscriptionModelId, config: RevaiTranscriptionModelConfig);
28
+ private getArgs;
29
+ doGenerate(options: Parameters<TranscriptionModelV1['doGenerate']>[0]): Promise<Awaited<ReturnType<TranscriptionModelV1['doGenerate']>>>;
30
+ }
31
+
32
+ interface RevaiProvider extends Pick<ProviderV1, 'transcriptionModel'> {
33
+ (modelId: 'machine', settings?: {}): {
34
+ transcription: RevaiTranscriptionModel;
35
+ };
36
+ /**
37
+ Creates a model for transcription.
38
+ */
39
+ transcription(modelId: RevaiTranscriptionModelId): TranscriptionModelV1;
40
+ }
41
+ interface RevaiProviderSettings {
42
+ /**
43
+ API key for authenticating requests.
44
+ */
45
+ apiKey?: string;
46
+ /**
47
+ Custom headers to include in the requests.
48
+ */
49
+ headers?: Record<string, string>;
50
+ /**
51
+ Custom fetch implementation. You can use it as a middleware to intercept requests,
52
+ or to provide a custom fetch implementation for e.g. testing.
53
+ */
54
+ fetch?: FetchFunction;
55
+ }
56
+ /**
57
+ Create a Rev.ai provider instance.
58
+ */
59
+ declare function createRevai(options?: RevaiProviderSettings): RevaiProvider;
60
+ /**
61
+ Default Rev.ai provider instance.
62
+ */
63
+ declare const revai: RevaiProvider;
64
+
65
+ export { type RevaiProvider, type RevaiProviderSettings, createRevai, revai };
@@ -0,0 +1,65 @@
1
+ import { TranscriptionModelV1, ProviderV1 } from '@ai-sdk/provider';
2
+ import { FetchFunction } from '@ai-sdk/provider-utils';
3
+
4
+ type RevaiConfig = {
5
+ provider: string;
6
+ url: (options: {
7
+ modelId: string;
8
+ path: string;
9
+ }) => string;
10
+ headers: () => Record<string, string | undefined>;
11
+ fetch?: FetchFunction;
12
+ generateId?: () => string;
13
+ };
14
+
15
+ type RevaiTranscriptionModelId = 'machine' | 'low_cost' | 'fusion';
16
+
17
+ interface RevaiTranscriptionModelConfig extends RevaiConfig {
18
+ _internal?: {
19
+ currentDate?: () => Date;
20
+ };
21
+ }
22
+ declare class RevaiTranscriptionModel implements TranscriptionModelV1 {
23
+ readonly modelId: RevaiTranscriptionModelId;
24
+ private readonly config;
25
+ readonly specificationVersion = "v1";
26
+ get provider(): string;
27
+ constructor(modelId: RevaiTranscriptionModelId, config: RevaiTranscriptionModelConfig);
28
+ private getArgs;
29
+ doGenerate(options: Parameters<TranscriptionModelV1['doGenerate']>[0]): Promise<Awaited<ReturnType<TranscriptionModelV1['doGenerate']>>>;
30
+ }
31
+
32
+ interface RevaiProvider extends Pick<ProviderV1, 'transcriptionModel'> {
33
+ (modelId: 'machine', settings?: {}): {
34
+ transcription: RevaiTranscriptionModel;
35
+ };
36
+ /**
37
+ Creates a model for transcription.
38
+ */
39
+ transcription(modelId: RevaiTranscriptionModelId): TranscriptionModelV1;
40
+ }
41
+ interface RevaiProviderSettings {
42
+ /**
43
+ API key for authenticating requests.
44
+ */
45
+ apiKey?: string;
46
+ /**
47
+ Custom headers to include in the requests.
48
+ */
49
+ headers?: Record<string, string>;
50
+ /**
51
+ Custom fetch implementation. You can use it as a middleware to intercept requests,
52
+ or to provide a custom fetch implementation for e.g. testing.
53
+ */
54
+ fetch?: FetchFunction;
55
+ }
56
+ /**
57
+ Create a Rev.ai provider instance.
58
+ */
59
+ declare function createRevai(options?: RevaiProviderSettings): RevaiProvider;
60
+ /**
61
+ Default Rev.ai provider instance.
62
+ */
63
+ declare const revai: RevaiProvider;
64
+
65
+ export { type RevaiProvider, type RevaiProviderSettings, createRevai, revai };
package/dist/index.js ADDED
@@ -0,0 +1,481 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var src_exports = {};
22
+ __export(src_exports, {
23
+ createRevai: () => createRevai,
24
+ revai: () => revai
25
+ });
26
+ module.exports = __toCommonJS(src_exports);
27
+
28
+ // src/revai-provider.ts
29
+ var import_provider_utils3 = require("@ai-sdk/provider-utils");
30
+
31
+ // src/revai-transcription-model.ts
32
+ var import_provider = require("@ai-sdk/provider");
33
+ var import_provider_utils2 = require("@ai-sdk/provider-utils");
34
+ var import_zod2 = require("zod");
35
+
36
+ // src/revai-error.ts
37
+ var import_zod = require("zod");
38
+ var import_provider_utils = require("@ai-sdk/provider-utils");
39
+ var revaiErrorDataSchema = import_zod.z.object({
40
+ error: import_zod.z.object({
41
+ message: import_zod.z.string(),
42
+ code: import_zod.z.number()
43
+ })
44
+ });
45
+ var revaiFailedResponseHandler = (0, import_provider_utils.createJsonErrorResponseHandler)({
46
+ errorSchema: revaiErrorDataSchema,
47
+ errorToMessage: (data) => data.error.message
48
+ });
49
+
50
+ // src/revai-transcription-model.ts
51
+ var revaiProviderOptionsSchema = import_zod2.z.object({
52
+ /**
53
+ * Optional metadata string to associate with the transcription job.
54
+ */
55
+ metadata: import_zod2.z.string().nullish(),
56
+ /**
57
+ * Configuration for webhook notifications when job is complete.
58
+ */
59
+ notification_config: import_zod2.z.object({
60
+ /**
61
+ * URL to send the notification to.
62
+ */
63
+ url: import_zod2.z.string(),
64
+ /**
65
+ * Optional authorization headers for the notification request.
66
+ */
67
+ auth_headers: import_zod2.z.object({
68
+ Authorization: import_zod2.z.string()
69
+ }).nullish()
70
+ }).nullish(),
71
+ /**
72
+ * Number of seconds after which the job will be automatically deleted.
73
+ */
74
+ delete_after_seconds: import_zod2.z.number().nullish(),
75
+ /**
76
+ * Whether to include filler words and false starts in the transcription.
77
+ */
78
+ verbatim: import_zod2.z.boolean().optional(),
79
+ /**
80
+ * Whether to prioritize the job for faster processing.
81
+ */
82
+ rush: import_zod2.z.boolean().nullish().default(false),
83
+ /**
84
+ * Whether to run the job in test mode.
85
+ */
86
+ test_mode: import_zod2.z.boolean().nullish().default(false),
87
+ /**
88
+ * Specific segments of the audio to transcribe.
89
+ */
90
+ segments_to_transcribe: import_zod2.z.array(
91
+ import_zod2.z.object({
92
+ /**
93
+ * Start time of the segment in seconds.
94
+ */
95
+ start: import_zod2.z.number(),
96
+ /**
97
+ * End time of the segment in seconds.
98
+ */
99
+ end: import_zod2.z.number()
100
+ })
101
+ ).nullish(),
102
+ /**
103
+ * Names to assign to speakers in the transcription.
104
+ */
105
+ speaker_names: import_zod2.z.array(
106
+ import_zod2.z.object({
107
+ /**
108
+ * Display name for the speaker.
109
+ */
110
+ display_name: import_zod2.z.string()
111
+ })
112
+ ).nullish(),
113
+ /**
114
+ * Whether to skip speaker diarization.
115
+ */
116
+ skip_diarization: import_zod2.z.boolean().nullish().default(false),
117
+ /**
118
+ * Whether to skip post-processing steps.
119
+ */
120
+ skip_postprocessing: import_zod2.z.boolean().nullish().default(false),
121
+ /**
122
+ * Whether to skip adding punctuation to the transcription.
123
+ */
124
+ skip_punctuation: import_zod2.z.boolean().nullish().default(false),
125
+ /**
126
+ * Whether to remove disfluencies (um, uh, etc.) from the transcription.
127
+ */
128
+ remove_disfluencies: import_zod2.z.boolean().nullish().default(false),
129
+ /**
130
+ * Whether to remove atmospheric sounds from the transcription.
131
+ */
132
+ remove_atmospherics: import_zod2.z.boolean().nullish().default(false),
133
+ /**
134
+ * Whether to filter profanity from the transcription.
135
+ */
136
+ filter_profanity: import_zod2.z.boolean().nullish().default(false),
137
+ /**
138
+ * Number of speaker channels in the audio.
139
+ */
140
+ speaker_channels_count: import_zod2.z.number().nullish(),
141
+ /**
142
+ * Expected number of speakers in the audio.
143
+ */
144
+ speakers_count: import_zod2.z.number().nullish(),
145
+ /**
146
+ * Type of diarization to use.
147
+ */
148
+ diarization_type: import_zod2.z.enum(["standard", "premium"]).nullish().default("standard"),
149
+ /**
150
+ * ID of a custom vocabulary to use for the transcription.
151
+ */
152
+ custom_vocabulary_id: import_zod2.z.string().nullish(),
153
+ /**
154
+ * Custom vocabularies to use for the transcription.
155
+ */
156
+ custom_vocabularies: import_zod2.z.array(import_zod2.z.object({})).optional(),
157
+ /**
158
+ * Whether to strictly enforce custom vocabulary.
159
+ */
160
+ strict_custom_vocabulary: import_zod2.z.boolean().optional(),
161
+ /**
162
+ * Configuration for generating a summary of the transcription.
163
+ */
164
+ summarization_config: import_zod2.z.object({
165
+ /**
166
+ * Model to use for summarization.
167
+ */
168
+ model: import_zod2.z.enum(["standard", "premium"]).nullish().default("standard"),
169
+ /**
170
+ * Format of the summary.
171
+ */
172
+ type: import_zod2.z.enum(["paragraph", "bullets"]).nullish().default("paragraph"),
173
+ /**
174
+ * Custom prompt for the summarization.
175
+ */
176
+ prompt: import_zod2.z.string().nullish()
177
+ }).nullish(),
178
+ /**
179
+ * Configuration for translating the transcription.
180
+ */
181
+ translation_config: import_zod2.z.object({
182
+ /**
183
+ * Target languages for translation.
184
+ */
185
+ target_languages: import_zod2.z.array(
186
+ import_zod2.z.object({
187
+ /**
188
+ * Language code for translation target.
189
+ */
190
+ language: import_zod2.z.enum([
191
+ "en",
192
+ "en-us",
193
+ "en-gb",
194
+ "ar",
195
+ "pt",
196
+ "pt-br",
197
+ "pt-pt",
198
+ "fr",
199
+ "fr-ca",
200
+ "es",
201
+ "es-es",
202
+ "es-la",
203
+ "it",
204
+ "ja",
205
+ "ko",
206
+ "de",
207
+ "ru"
208
+ ])
209
+ })
210
+ ),
211
+ /**
212
+ * Model to use for translation.
213
+ */
214
+ model: import_zod2.z.enum(["standard", "premium"]).nullish().default("standard")
215
+ }).nullish(),
216
+ /**
217
+ * Language of the audio content.
218
+ */
219
+ language: import_zod2.z.string().nullish().default("en"),
220
+ /**
221
+ * Whether to perform forced alignment.
222
+ */
223
+ forced_alignment: import_zod2.z.boolean().nullish().default(false)
224
+ });
225
+ var RevaiTranscriptionModel = class {
226
+ constructor(modelId, config) {
227
+ this.modelId = modelId;
228
+ this.config = config;
229
+ this.specificationVersion = "v1";
230
+ }
231
+ get provider() {
232
+ return this.config.provider;
233
+ }
234
+ getArgs({
235
+ audio,
236
+ mediaType,
237
+ providerOptions
238
+ }) {
239
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x;
240
+ const warnings = [];
241
+ const revaiOptions = (0, import_provider_utils2.parseProviderOptions)({
242
+ provider: "revai",
243
+ providerOptions,
244
+ schema: revaiProviderOptionsSchema
245
+ });
246
+ const formData = new FormData();
247
+ const blob = audio instanceof Uint8Array ? new Blob([audio]) : new Blob([(0, import_provider_utils2.convertBase64ToUint8Array)(audio)]);
248
+ formData.append("media", new File([blob], "audio", { type: mediaType }));
249
+ const transcriptionModelOptions = {
250
+ transcriber: this.modelId
251
+ };
252
+ if (revaiOptions) {
253
+ const formDataConfig = {
254
+ metadata: (_a = revaiOptions.metadata) != null ? _a : void 0,
255
+ notification_config: (_b = revaiOptions.notification_config) != null ? _b : void 0,
256
+ delete_after_seconds: (_c = revaiOptions.delete_after_seconds) != null ? _c : void 0,
257
+ verbatim: (_d = revaiOptions.verbatim) != null ? _d : void 0,
258
+ rush: (_e = revaiOptions.rush) != null ? _e : void 0,
259
+ test_mode: (_f = revaiOptions.test_mode) != null ? _f : void 0,
260
+ segments_to_transcribe: (_g = revaiOptions.segments_to_transcribe) != null ? _g : void 0,
261
+ speaker_names: (_h = revaiOptions.speaker_names) != null ? _h : void 0,
262
+ skip_diarization: (_i = revaiOptions.skip_diarization) != null ? _i : void 0,
263
+ skip_postprocessing: (_j = revaiOptions.skip_postprocessing) != null ? _j : void 0,
264
+ skip_punctuation: (_k = revaiOptions.skip_punctuation) != null ? _k : void 0,
265
+ remove_disfluencies: (_l = revaiOptions.remove_disfluencies) != null ? _l : void 0,
266
+ remove_atmospherics: (_m = revaiOptions.remove_atmospherics) != null ? _m : void 0,
267
+ filter_profanity: (_n = revaiOptions.filter_profanity) != null ? _n : void 0,
268
+ speaker_channels_count: (_o = revaiOptions.speaker_channels_count) != null ? _o : void 0,
269
+ speakers_count: (_p = revaiOptions.speakers_count) != null ? _p : void 0,
270
+ diarization_type: (_q = revaiOptions.diarization_type) != null ? _q : void 0,
271
+ custom_vocabulary_id: (_r = revaiOptions.custom_vocabulary_id) != null ? _r : void 0,
272
+ custom_vocabularies: (_s = revaiOptions.custom_vocabularies) != null ? _s : void 0,
273
+ strict_custom_vocabulary: (_t = revaiOptions.strict_custom_vocabulary) != null ? _t : void 0,
274
+ summarization_config: (_u = revaiOptions.summarization_config) != null ? _u : void 0,
275
+ translation_config: (_v = revaiOptions.translation_config) != null ? _v : void 0,
276
+ language: (_w = revaiOptions.language) != null ? _w : void 0,
277
+ forced_alignment: (_x = revaiOptions.forced_alignment) != null ? _x : void 0
278
+ };
279
+ for (const key in formDataConfig) {
280
+ const value = formDataConfig[key];
281
+ if (value !== void 0) {
282
+ transcriptionModelOptions[key] = value;
283
+ }
284
+ }
285
+ }
286
+ formData.append("config", JSON.stringify(transcriptionModelOptions));
287
+ return {
288
+ formData,
289
+ warnings
290
+ };
291
+ }
292
+ async doGenerate(options) {
293
+ var _a, _b, _c, _d, _e, _f, _g, _h;
294
+ const currentDate = (_c = (_b = (_a = this.config._internal) == null ? void 0 : _a.currentDate) == null ? void 0 : _b.call(_a)) != null ? _c : /* @__PURE__ */ new Date();
295
+ const { formData, warnings } = this.getArgs(options);
296
+ const { value: submissionResponse } = await (0, import_provider_utils2.postFormDataToApi)({
297
+ url: this.config.url({
298
+ path: "/speechtotext/v1/jobs",
299
+ modelId: this.modelId
300
+ }),
301
+ headers: (0, import_provider_utils2.combineHeaders)(this.config.headers(), options.headers),
302
+ formData,
303
+ failedResponseHandler: revaiFailedResponseHandler,
304
+ successfulResponseHandler: (0, import_provider_utils2.createJsonResponseHandler)(
305
+ revaiTranscriptionJobResponseSchema
306
+ ),
307
+ abortSignal: options.abortSignal,
308
+ fetch: this.config.fetch
309
+ });
310
+ if (submissionResponse.status === "failed") {
311
+ throw new import_provider.AISDKError({
312
+ message: "Failed to submit transcription job to Rev.ai",
313
+ name: "TranscriptionJobSubmissionFailed",
314
+ cause: submissionResponse
315
+ });
316
+ }
317
+ const jobId = submissionResponse.id;
318
+ const timeoutMs = 60 * 1e3;
319
+ const startTime = Date.now();
320
+ const pollingInterval = 1e3;
321
+ let jobResponse = submissionResponse;
322
+ while (jobResponse.status !== "transcribed") {
323
+ if (Date.now() - startTime > timeoutMs) {
324
+ throw new import_provider.AISDKError({
325
+ message: "Transcription job polling timed out",
326
+ name: "TranscriptionJobPollingTimedOut",
327
+ cause: submissionResponse
328
+ });
329
+ }
330
+ const pollingResult = await (0, import_provider_utils2.getFromApi)({
331
+ url: this.config.url({
332
+ path: `/speechtotext/v1/jobs/${jobId}`,
333
+ modelId: this.modelId
334
+ }),
335
+ headers: (0, import_provider_utils2.combineHeaders)(this.config.headers(), options.headers),
336
+ failedResponseHandler: revaiFailedResponseHandler,
337
+ successfulResponseHandler: (0, import_provider_utils2.createJsonResponseHandler)(
338
+ revaiTranscriptionJobResponseSchema
339
+ ),
340
+ abortSignal: options.abortSignal,
341
+ fetch: this.config.fetch
342
+ });
343
+ jobResponse = pollingResult.value;
344
+ if (jobResponse.status === "failed") {
345
+ throw new import_provider.AISDKError({
346
+ message: "Transcription job failed",
347
+ name: "TranscriptionJobFailed",
348
+ cause: jobResponse
349
+ });
350
+ }
351
+ if (jobResponse.status !== "transcribed") {
352
+ await (0, import_provider_utils2.delay)(pollingInterval);
353
+ }
354
+ }
355
+ const {
356
+ value: transcriptionResult,
357
+ responseHeaders,
358
+ rawValue: rawResponse
359
+ } = await (0, import_provider_utils2.getFromApi)({
360
+ url: this.config.url({
361
+ path: `/speechtotext/v1/jobs/${jobId}/transcript`,
362
+ modelId: this.modelId
363
+ }),
364
+ headers: (0, import_provider_utils2.combineHeaders)(this.config.headers(), options.headers),
365
+ failedResponseHandler: revaiFailedResponseHandler,
366
+ successfulResponseHandler: (0, import_provider_utils2.createJsonResponseHandler)(
367
+ revaiTranscriptionResponseSchema
368
+ ),
369
+ abortSignal: options.abortSignal,
370
+ fetch: this.config.fetch
371
+ });
372
+ let durationInSeconds = 0;
373
+ const segments = [];
374
+ for (const monologue of (_d = transcriptionResult.monologues) != null ? _d : []) {
375
+ let currentSegmentText = "";
376
+ let segmentStartSecond = 0;
377
+ let hasStartedSegment = false;
378
+ for (const element of (_e = monologue == null ? void 0 : monologue.elements) != null ? _e : []) {
379
+ currentSegmentText += element.value;
380
+ if (element.type === "text") {
381
+ if (element.end_ts && element.end_ts > durationInSeconds) {
382
+ durationInSeconds = element.end_ts;
383
+ }
384
+ if (!hasStartedSegment && typeof element.ts === "number") {
385
+ segmentStartSecond = element.ts;
386
+ hasStartedSegment = true;
387
+ }
388
+ if (typeof element.end_ts === "number" && hasStartedSegment) {
389
+ if (currentSegmentText.trim()) {
390
+ segments.push({
391
+ text: currentSegmentText.trim(),
392
+ startSecond: segmentStartSecond,
393
+ endSecond: element.end_ts
394
+ });
395
+ }
396
+ currentSegmentText = "";
397
+ hasStartedSegment = false;
398
+ }
399
+ }
400
+ }
401
+ if (hasStartedSegment && currentSegmentText.trim()) {
402
+ const endSecond = durationInSeconds > segmentStartSecond ? durationInSeconds : segmentStartSecond + 1;
403
+ segments.push({
404
+ text: currentSegmentText.trim(),
405
+ startSecond: segmentStartSecond,
406
+ endSecond
407
+ });
408
+ }
409
+ }
410
+ return {
411
+ text: (_g = (_f = transcriptionResult.monologues) == null ? void 0 : _f.map(
412
+ (monologue) => {
413
+ var _a2;
414
+ return (_a2 = monologue == null ? void 0 : monologue.elements) == null ? void 0 : _a2.map((element) => element.value).join("");
415
+ }
416
+ ).join(" ")) != null ? _g : "",
417
+ segments,
418
+ language: (_h = submissionResponse.language) != null ? _h : void 0,
419
+ durationInSeconds,
420
+ warnings,
421
+ response: {
422
+ timestamp: currentDate,
423
+ modelId: this.modelId,
424
+ headers: responseHeaders,
425
+ body: rawResponse
426
+ }
427
+ };
428
+ }
429
+ };
430
+ var revaiTranscriptionJobResponseSchema = import_zod2.z.object({
431
+ id: import_zod2.z.string().nullish(),
432
+ status: import_zod2.z.string().nullish(),
433
+ language: import_zod2.z.string().nullish()
434
+ });
435
+ var revaiTranscriptionResponseSchema = import_zod2.z.object({
436
+ monologues: import_zod2.z.array(
437
+ import_zod2.z.object({
438
+ elements: import_zod2.z.array(
439
+ import_zod2.z.object({
440
+ type: import_zod2.z.string().nullish(),
441
+ value: import_zod2.z.string().nullish(),
442
+ ts: import_zod2.z.number().nullish(),
443
+ end_ts: import_zod2.z.number().nullish()
444
+ })
445
+ ).nullish()
446
+ })
447
+ ).nullish()
448
+ });
449
+
450
+ // src/revai-provider.ts
451
+ function createRevai(options = {}) {
452
+ const getHeaders = () => ({
453
+ authorization: `Bearer ${(0, import_provider_utils3.loadApiKey)({
454
+ apiKey: options.apiKey,
455
+ environmentVariableName: "REVAI_API_KEY",
456
+ description: "Rev.ai"
457
+ })}`,
458
+ ...options.headers
459
+ });
460
+ const createTranscriptionModel = (modelId) => new RevaiTranscriptionModel(modelId, {
461
+ provider: `revai.transcription`,
462
+ url: ({ path }) => `https://api.rev.ai${path}`,
463
+ headers: getHeaders,
464
+ fetch: options.fetch
465
+ });
466
+ const provider = function(modelId) {
467
+ return {
468
+ transcription: createTranscriptionModel(modelId)
469
+ };
470
+ };
471
+ provider.transcription = createTranscriptionModel;
472
+ provider.transcriptionModel = createTranscriptionModel;
473
+ return provider;
474
+ }
475
+ var revai = createRevai();
476
+ // Annotate the CommonJS export names for ESM import in node:
477
+ 0 && (module.exports = {
478
+ createRevai,
479
+ revai
480
+ });
481
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts","../src/revai-provider.ts","../src/revai-transcription-model.ts","../src/revai-error.ts"],"sourcesContent":["export { createRevai, revai } from './revai-provider';\nexport type { RevaiProvider, RevaiProviderSettings } from './revai-provider';\n","import { TranscriptionModelV1, ProviderV1 } from '@ai-sdk/provider';\nimport { FetchFunction, loadApiKey } from '@ai-sdk/provider-utils';\nimport { RevaiTranscriptionModel } from './revai-transcription-model';\nimport { RevaiTranscriptionModelId } from './revai-transcription-settings';\n\nexport interface RevaiProvider extends Pick<ProviderV1, 'transcriptionModel'> {\n (\n modelId: 'machine',\n settings?: {},\n ): {\n transcription: RevaiTranscriptionModel;\n };\n\n /**\nCreates a model for transcription.\n */\n transcription(modelId: RevaiTranscriptionModelId): TranscriptionModelV1;\n}\n\nexport interface RevaiProviderSettings {\n /**\nAPI key for authenticating requests.\n */\n apiKey?: string;\n\n /**\nCustom headers to include in the requests.\n */\n headers?: Record<string, string>;\n\n /**\nCustom fetch implementation. You can use it as a middleware to intercept requests,\nor to provide a custom fetch implementation for e.g. testing.\n */\n fetch?: FetchFunction;\n}\n\n/**\nCreate a Rev.ai provider instance.\n */\nexport function createRevai(\n options: RevaiProviderSettings = {},\n): RevaiProvider {\n const getHeaders = () => ({\n authorization: `Bearer ${loadApiKey({\n apiKey: options.apiKey,\n environmentVariableName: 'REVAI_API_KEY',\n description: 'Rev.ai',\n })}`,\n ...options.headers,\n });\n\n const createTranscriptionModel = (modelId: RevaiTranscriptionModelId) =>\n new RevaiTranscriptionModel(modelId, {\n provider: `revai.transcription`,\n url: ({ path }) => `https://api.rev.ai${path}`,\n headers: getHeaders,\n fetch: options.fetch,\n });\n\n const provider = function (modelId: RevaiTranscriptionModelId) {\n return {\n transcription: createTranscriptionModel(modelId),\n };\n };\n\n provider.transcription = createTranscriptionModel;\n provider.transcriptionModel = createTranscriptionModel;\n\n return provider as RevaiProvider;\n}\n\n/**\nDefault Rev.ai provider instance.\n */\nexport const revai = createRevai();\n","import {\n AISDKError,\n TranscriptionModelV1,\n TranscriptionModelV1CallWarning,\n} from '@ai-sdk/provider';\nimport {\n combineHeaders,\n convertBase64ToUint8Array,\n createJsonResponseHandler,\n delay,\n getFromApi,\n parseProviderOptions,\n postFormDataToApi,\n} from '@ai-sdk/provider-utils';\nimport { z } from 'zod';\nimport { RevaiConfig } from './revai-config';\nimport { revaiFailedResponseHandler } from './revai-error';\nimport { RevaiTranscriptionModelId } from './revai-transcription-settings';\nimport { RevaiTranscriptionAPITypes } from './revai-api-types';\n\n// https://docs.rev.ai/api/asynchronous/reference/#operation/SubmitTranscriptionJob\nconst revaiProviderOptionsSchema = z.object({\n /**\n * Optional metadata string to associate with the transcription job.\n */\n metadata: z.string().nullish(),\n /**\n * Configuration for webhook notifications when job is complete.\n */\n notification_config: z\n .object({\n /**\n * URL to send the notification to.\n */\n url: z.string(),\n /**\n * Optional authorization headers for the notification request.\n */\n auth_headers: z\n .object({\n Authorization: z.string(),\n })\n .nullish(),\n })\n .nullish(),\n /**\n * Number of seconds after which the job will be automatically deleted.\n */\n delete_after_seconds: z.number().nullish(),\n /**\n * Whether to include filler words and false starts in the transcription.\n */\n verbatim: z.boolean().optional(),\n /**\n * Whether to prioritize the job for faster processing.\n */\n rush: z.boolean().nullish().default(false),\n /**\n * Whether to run the job in test mode.\n */\n test_mode: z.boolean().nullish().default(false),\n /**\n * Specific segments of the audio to transcribe.\n */\n segments_to_transcribe: z\n .array(\n z.object({\n /**\n * Start time of the segment in seconds.\n */\n start: z.number(),\n /**\n * End time of the segment in seconds.\n */\n end: z.number(),\n }),\n )\n .nullish(),\n /**\n * Names to assign to speakers in the transcription.\n */\n speaker_names: z\n .array(\n z.object({\n /**\n * Display name for the speaker.\n */\n display_name: z.string(),\n }),\n )\n .nullish(),\n /**\n * Whether to skip speaker diarization.\n */\n skip_diarization: z.boolean().nullish().default(false),\n /**\n * Whether to skip post-processing steps.\n */\n skip_postprocessing: z.boolean().nullish().default(false),\n /**\n * Whether to skip adding punctuation to the transcription.\n */\n skip_punctuation: z.boolean().nullish().default(false),\n /**\n * Whether to remove disfluencies (um, uh, etc.) from the transcription.\n */\n remove_disfluencies: z.boolean().nullish().default(false),\n /**\n * Whether to remove atmospheric sounds from the transcription.\n */\n remove_atmospherics: z.boolean().nullish().default(false),\n /**\n * Whether to filter profanity from the transcription.\n */\n filter_profanity: z.boolean().nullish().default(false),\n /**\n * Number of speaker channels in the audio.\n */\n speaker_channels_count: z.number().nullish(),\n /**\n * Expected number of speakers in the audio.\n */\n speakers_count: z.number().nullish(),\n /**\n * Type of diarization to use.\n */\n diarization_type: z\n .enum(['standard', 'premium'])\n .nullish()\n .default('standard'),\n /**\n * ID of a custom vocabulary to use for the transcription.\n */\n custom_vocabulary_id: z.string().nullish(),\n /**\n * Custom vocabularies to use for the transcription.\n */\n custom_vocabularies: z.array(z.object({})).optional(),\n /**\n * Whether to strictly enforce custom vocabulary.\n */\n strict_custom_vocabulary: z.boolean().optional(),\n /**\n * Configuration for generating a summary of the transcription.\n */\n summarization_config: z\n .object({\n /**\n * Model to use for summarization.\n */\n model: z.enum(['standard', 'premium']).nullish().default('standard'),\n /**\n * Format of the summary.\n */\n type: z.enum(['paragraph', 'bullets']).nullish().default('paragraph'),\n /**\n * Custom prompt for the summarization.\n */\n prompt: z.string().nullish(),\n })\n .nullish(),\n /**\n * Configuration for translating the transcription.\n */\n translation_config: z\n .object({\n /**\n * Target languages for translation.\n */\n target_languages: z.array(\n z.object({\n /**\n * Language code for translation target.\n */\n language: z.enum([\n 'en',\n 'en-us',\n 'en-gb',\n 'ar',\n 'pt',\n 'pt-br',\n 'pt-pt',\n 'fr',\n 'fr-ca',\n 'es',\n 'es-es',\n 'es-la',\n 'it',\n 'ja',\n 'ko',\n 'de',\n 'ru',\n ]),\n }),\n ),\n /**\n * Model to use for translation.\n */\n model: z.enum(['standard', 'premium']).nullish().default('standard'),\n })\n .nullish(),\n /**\n * Language of the audio content.\n */\n language: z.string().nullish().default('en'),\n /**\n * Whether to perform forced alignment.\n */\n forced_alignment: z.boolean().nullish().default(false),\n});\n\nexport type RevaiTranscriptionCallOptions = z.infer<\n typeof revaiProviderOptionsSchema\n>;\n\ninterface RevaiTranscriptionModelConfig extends RevaiConfig {\n _internal?: {\n currentDate?: () => Date;\n };\n}\n\nexport class RevaiTranscriptionModel implements TranscriptionModelV1 {\n readonly specificationVersion = 'v1';\n\n get provider(): string {\n return this.config.provider;\n }\n\n constructor(\n readonly modelId: RevaiTranscriptionModelId,\n private readonly config: RevaiTranscriptionModelConfig,\n ) {}\n\n private getArgs({\n audio,\n mediaType,\n providerOptions,\n }: Parameters<TranscriptionModelV1['doGenerate']>[0]) {\n const warnings: TranscriptionModelV1CallWarning[] = [];\n\n // Parse provider options\n const revaiOptions = parseProviderOptions({\n provider: 'revai',\n providerOptions,\n schema: revaiProviderOptionsSchema,\n });\n\n // Create form data with base fields\n const formData = new FormData();\n const blob =\n audio instanceof Uint8Array\n ? new Blob([audio])\n : new Blob([convertBase64ToUint8Array(audio)]);\n\n formData.append('media', new File([blob], 'audio', { type: mediaType }));\n const transcriptionModelOptions: RevaiTranscriptionAPITypes = {\n transcriber: this.modelId,\n };\n\n // Add provider-specific options\n if (revaiOptions) {\n const formDataConfig: RevaiTranscriptionAPITypes = {\n metadata: revaiOptions.metadata ?? undefined,\n notification_config: revaiOptions.notification_config ?? undefined,\n delete_after_seconds: revaiOptions.delete_after_seconds ?? undefined,\n verbatim: revaiOptions.verbatim ?? undefined,\n rush: revaiOptions.rush ?? undefined,\n test_mode: revaiOptions.test_mode ?? undefined,\n segments_to_transcribe:\n revaiOptions.segments_to_transcribe ?? undefined,\n speaker_names: revaiOptions.speaker_names ?? undefined,\n skip_diarization: revaiOptions.skip_diarization ?? undefined,\n skip_postprocessing: revaiOptions.skip_postprocessing ?? undefined,\n skip_punctuation: revaiOptions.skip_punctuation ?? undefined,\n remove_disfluencies: revaiOptions.remove_disfluencies ?? undefined,\n remove_atmospherics: revaiOptions.remove_atmospherics ?? undefined,\n filter_profanity: revaiOptions.filter_profanity ?? undefined,\n speaker_channels_count:\n revaiOptions.speaker_channels_count ?? undefined,\n speakers_count: revaiOptions.speakers_count ?? undefined,\n diarization_type: revaiOptions.diarization_type ?? undefined,\n custom_vocabulary_id: revaiOptions.custom_vocabulary_id ?? undefined,\n custom_vocabularies: revaiOptions.custom_vocabularies ?? undefined,\n strict_custom_vocabulary:\n revaiOptions.strict_custom_vocabulary ?? undefined,\n summarization_config: revaiOptions.summarization_config ?? undefined,\n translation_config: revaiOptions.translation_config ?? undefined,\n language: revaiOptions.language ?? undefined,\n forced_alignment: revaiOptions.forced_alignment ?? undefined,\n };\n\n for (const key in formDataConfig) {\n const value = formDataConfig[key as keyof RevaiTranscriptionAPITypes];\n if (value !== undefined) {\n (transcriptionModelOptions as Record<string, unknown>)[\n key as keyof RevaiTranscriptionAPITypes\n ] = value;\n }\n }\n }\n\n formData.append('config', JSON.stringify(transcriptionModelOptions));\n\n return {\n formData,\n warnings,\n };\n }\n\n async doGenerate(\n options: Parameters<TranscriptionModelV1['doGenerate']>[0],\n ): Promise<Awaited<ReturnType<TranscriptionModelV1['doGenerate']>>> {\n const currentDate = this.config._internal?.currentDate?.() ?? new Date();\n const { formData, warnings } = this.getArgs(options);\n\n const { value: submissionResponse } = await postFormDataToApi({\n url: this.config.url({\n path: '/speechtotext/v1/jobs',\n modelId: this.modelId,\n }),\n headers: combineHeaders(this.config.headers(), options.headers),\n formData,\n failedResponseHandler: revaiFailedResponseHandler,\n successfulResponseHandler: createJsonResponseHandler(\n revaiTranscriptionJobResponseSchema,\n ),\n abortSignal: options.abortSignal,\n fetch: this.config.fetch,\n });\n\n if (submissionResponse.status === 'failed') {\n throw new AISDKError({\n message: 'Failed to submit transcription job to Rev.ai',\n name: 'TranscriptionJobSubmissionFailed',\n cause: submissionResponse,\n });\n }\n\n const jobId = submissionResponse.id;\n const timeoutMs = 60 * 1000; // 60 seconds timeout\n const startTime = Date.now();\n const pollingInterval = 1000;\n let jobResponse = submissionResponse;\n\n while (jobResponse.status !== 'transcribed') {\n // Check if we've exceeded the timeout\n if (Date.now() - startTime > timeoutMs) {\n throw new AISDKError({\n message: 'Transcription job polling timed out',\n name: 'TranscriptionJobPollingTimedOut',\n cause: submissionResponse,\n });\n }\n\n // Poll for job status\n const pollingResult = await getFromApi({\n url: this.config.url({\n path: `/speechtotext/v1/jobs/${jobId}`,\n modelId: this.modelId,\n }),\n headers: combineHeaders(this.config.headers(), options.headers),\n failedResponseHandler: revaiFailedResponseHandler,\n successfulResponseHandler: createJsonResponseHandler(\n revaiTranscriptionJobResponseSchema,\n ),\n abortSignal: options.abortSignal,\n fetch: this.config.fetch,\n });\n\n jobResponse = pollingResult.value;\n\n if (jobResponse.status === 'failed') {\n throw new AISDKError({\n message: 'Transcription job failed',\n name: 'TranscriptionJobFailed',\n cause: jobResponse,\n });\n }\n\n // Wait before polling again (only if we need to continue polling)\n if (jobResponse.status !== 'transcribed') {\n await delay(pollingInterval);\n }\n }\n\n const {\n value: transcriptionResult,\n responseHeaders,\n rawValue: rawResponse,\n } = await getFromApi({\n url: this.config.url({\n path: `/speechtotext/v1/jobs/${jobId}/transcript`,\n modelId: this.modelId,\n }),\n headers: combineHeaders(this.config.headers(), options.headers),\n failedResponseHandler: revaiFailedResponseHandler,\n successfulResponseHandler: createJsonResponseHandler(\n revaiTranscriptionResponseSchema,\n ),\n abortSignal: options.abortSignal,\n fetch: this.config.fetch,\n });\n\n let durationInSeconds = 0;\n const segments: {\n text: string;\n startSecond: number;\n endSecond: number;\n }[] = [];\n\n for (const monologue of transcriptionResult.monologues ?? []) {\n // Process each monologue to extract segments with timing information\n let currentSegmentText = '';\n let segmentStartSecond = 0;\n let hasStartedSegment = false;\n\n for (const element of monologue?.elements ?? []) {\n // Add the element value to the current segment text\n currentSegmentText += element.value;\n\n // For text elements, track timing information\n if (element.type === 'text') {\n // Update the overall duration if this is the latest timestamp\n if (element.end_ts && element.end_ts > durationInSeconds) {\n durationInSeconds = element.end_ts;\n }\n\n // If this is the first text element in a segment, mark the start time\n if (!hasStartedSegment && typeof element.ts === 'number') {\n segmentStartSecond = element.ts;\n hasStartedSegment = true;\n }\n\n // If we have an end timestamp, we can complete a segment\n if (typeof element.end_ts === 'number' && hasStartedSegment) {\n // Only add non-empty segments\n if (currentSegmentText.trim()) {\n segments.push({\n text: currentSegmentText.trim(),\n startSecond: segmentStartSecond,\n endSecond: element.end_ts,\n });\n }\n\n // Reset for the next segment\n currentSegmentText = '';\n hasStartedSegment = false;\n }\n }\n }\n\n // Handle any remaining segment text that wasn't added\n if (hasStartedSegment && currentSegmentText.trim()) {\n const endSecond =\n durationInSeconds > segmentStartSecond\n ? durationInSeconds\n : segmentStartSecond + 1;\n segments.push({\n text: currentSegmentText.trim(),\n startSecond: segmentStartSecond,\n endSecond: endSecond,\n });\n }\n }\n\n return {\n text:\n transcriptionResult.monologues\n ?.map(monologue =>\n monologue?.elements?.map(element => element.value).join(''),\n )\n .join(' ') ?? '',\n segments,\n language: submissionResponse.language ?? undefined,\n durationInSeconds,\n warnings,\n response: {\n timestamp: currentDate,\n modelId: this.modelId,\n headers: responseHeaders,\n body: rawResponse,\n },\n };\n }\n}\n\nconst revaiTranscriptionJobResponseSchema = z.object({\n id: z.string().nullish(),\n status: z.string().nullish(),\n language: z.string().nullish(),\n});\n\nconst revaiTranscriptionResponseSchema = z.object({\n monologues: z\n .array(\n z.object({\n elements: z\n .array(\n z.object({\n type: z.string().nullish(),\n value: z.string().nullish(),\n ts: z.number().nullish(),\n end_ts: z.number().nullish(),\n }),\n )\n .nullish(),\n }),\n )\n .nullish(),\n});\n","import { z } from 'zod';\nimport { createJsonErrorResponseHandler } from '@ai-sdk/provider-utils';\n\nexport const revaiErrorDataSchema = z.object({\n error: z.object({\n message: z.string(),\n code: z.number(),\n }),\n});\n\nexport type RevaiErrorData = z.infer<typeof revaiErrorDataSchema>;\n\nexport const revaiFailedResponseHandler = createJsonErrorResponseHandler({\n errorSchema: revaiErrorDataSchema,\n errorToMessage: data => data.error.message,\n});\n"],"mappings":"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","names":["import_provider_utils","import_provider_utils","import_zod","_a"]}
package/dist/index.mjs ADDED
@@ -0,0 +1,463 @@
1
+ // src/revai-provider.ts
2
+ import { loadApiKey } from "@ai-sdk/provider-utils";
3
+
4
+ // src/revai-transcription-model.ts
5
+ import {
6
+ AISDKError
7
+ } from "@ai-sdk/provider";
8
+ import {
9
+ combineHeaders,
10
+ convertBase64ToUint8Array,
11
+ createJsonResponseHandler,
12
+ delay,
13
+ getFromApi,
14
+ parseProviderOptions,
15
+ postFormDataToApi
16
+ } from "@ai-sdk/provider-utils";
17
+ import { z as z2 } from "zod";
18
+
19
+ // src/revai-error.ts
20
+ import { z } from "zod";
21
+ import { createJsonErrorResponseHandler } from "@ai-sdk/provider-utils";
22
+ var revaiErrorDataSchema = z.object({
23
+ error: z.object({
24
+ message: z.string(),
25
+ code: z.number()
26
+ })
27
+ });
28
+ var revaiFailedResponseHandler = createJsonErrorResponseHandler({
29
+ errorSchema: revaiErrorDataSchema,
30
+ errorToMessage: (data) => data.error.message
31
+ });
32
+
33
+ // src/revai-transcription-model.ts
34
+ var revaiProviderOptionsSchema = z2.object({
35
+ /**
36
+ * Optional metadata string to associate with the transcription job.
37
+ */
38
+ metadata: z2.string().nullish(),
39
+ /**
40
+ * Configuration for webhook notifications when job is complete.
41
+ */
42
+ notification_config: z2.object({
43
+ /**
44
+ * URL to send the notification to.
45
+ */
46
+ url: z2.string(),
47
+ /**
48
+ * Optional authorization headers for the notification request.
49
+ */
50
+ auth_headers: z2.object({
51
+ Authorization: z2.string()
52
+ }).nullish()
53
+ }).nullish(),
54
+ /**
55
+ * Number of seconds after which the job will be automatically deleted.
56
+ */
57
+ delete_after_seconds: z2.number().nullish(),
58
+ /**
59
+ * Whether to include filler words and false starts in the transcription.
60
+ */
61
+ verbatim: z2.boolean().optional(),
62
+ /**
63
+ * Whether to prioritize the job for faster processing.
64
+ */
65
+ rush: z2.boolean().nullish().default(false),
66
+ /**
67
+ * Whether to run the job in test mode.
68
+ */
69
+ test_mode: z2.boolean().nullish().default(false),
70
+ /**
71
+ * Specific segments of the audio to transcribe.
72
+ */
73
+ segments_to_transcribe: z2.array(
74
+ z2.object({
75
+ /**
76
+ * Start time of the segment in seconds.
77
+ */
78
+ start: z2.number(),
79
+ /**
80
+ * End time of the segment in seconds.
81
+ */
82
+ end: z2.number()
83
+ })
84
+ ).nullish(),
85
+ /**
86
+ * Names to assign to speakers in the transcription.
87
+ */
88
+ speaker_names: z2.array(
89
+ z2.object({
90
+ /**
91
+ * Display name for the speaker.
92
+ */
93
+ display_name: z2.string()
94
+ })
95
+ ).nullish(),
96
+ /**
97
+ * Whether to skip speaker diarization.
98
+ */
99
+ skip_diarization: z2.boolean().nullish().default(false),
100
+ /**
101
+ * Whether to skip post-processing steps.
102
+ */
103
+ skip_postprocessing: z2.boolean().nullish().default(false),
104
+ /**
105
+ * Whether to skip adding punctuation to the transcription.
106
+ */
107
+ skip_punctuation: z2.boolean().nullish().default(false),
108
+ /**
109
+ * Whether to remove disfluencies (um, uh, etc.) from the transcription.
110
+ */
111
+ remove_disfluencies: z2.boolean().nullish().default(false),
112
+ /**
113
+ * Whether to remove atmospheric sounds from the transcription.
114
+ */
115
+ remove_atmospherics: z2.boolean().nullish().default(false),
116
+ /**
117
+ * Whether to filter profanity from the transcription.
118
+ */
119
+ filter_profanity: z2.boolean().nullish().default(false),
120
+ /**
121
+ * Number of speaker channels in the audio.
122
+ */
123
+ speaker_channels_count: z2.number().nullish(),
124
+ /**
125
+ * Expected number of speakers in the audio.
126
+ */
127
+ speakers_count: z2.number().nullish(),
128
+ /**
129
+ * Type of diarization to use.
130
+ */
131
+ diarization_type: z2.enum(["standard", "premium"]).nullish().default("standard"),
132
+ /**
133
+ * ID of a custom vocabulary to use for the transcription.
134
+ */
135
+ custom_vocabulary_id: z2.string().nullish(),
136
+ /**
137
+ * Custom vocabularies to use for the transcription.
138
+ */
139
+ custom_vocabularies: z2.array(z2.object({})).optional(),
140
+ /**
141
+ * Whether to strictly enforce custom vocabulary.
142
+ */
143
+ strict_custom_vocabulary: z2.boolean().optional(),
144
+ /**
145
+ * Configuration for generating a summary of the transcription.
146
+ */
147
+ summarization_config: z2.object({
148
+ /**
149
+ * Model to use for summarization.
150
+ */
151
+ model: z2.enum(["standard", "premium"]).nullish().default("standard"),
152
+ /**
153
+ * Format of the summary.
154
+ */
155
+ type: z2.enum(["paragraph", "bullets"]).nullish().default("paragraph"),
156
+ /**
157
+ * Custom prompt for the summarization.
158
+ */
159
+ prompt: z2.string().nullish()
160
+ }).nullish(),
161
+ /**
162
+ * Configuration for translating the transcription.
163
+ */
164
+ translation_config: z2.object({
165
+ /**
166
+ * Target languages for translation.
167
+ */
168
+ target_languages: z2.array(
169
+ z2.object({
170
+ /**
171
+ * Language code for translation target.
172
+ */
173
+ language: z2.enum([
174
+ "en",
175
+ "en-us",
176
+ "en-gb",
177
+ "ar",
178
+ "pt",
179
+ "pt-br",
180
+ "pt-pt",
181
+ "fr",
182
+ "fr-ca",
183
+ "es",
184
+ "es-es",
185
+ "es-la",
186
+ "it",
187
+ "ja",
188
+ "ko",
189
+ "de",
190
+ "ru"
191
+ ])
192
+ })
193
+ ),
194
+ /**
195
+ * Model to use for translation.
196
+ */
197
+ model: z2.enum(["standard", "premium"]).nullish().default("standard")
198
+ }).nullish(),
199
+ /**
200
+ * Language of the audio content.
201
+ */
202
+ language: z2.string().nullish().default("en"),
203
+ /**
204
+ * Whether to perform forced alignment.
205
+ */
206
+ forced_alignment: z2.boolean().nullish().default(false)
207
+ });
208
+ var RevaiTranscriptionModel = class {
209
+ constructor(modelId, config) {
210
+ this.modelId = modelId;
211
+ this.config = config;
212
+ this.specificationVersion = "v1";
213
+ }
214
+ get provider() {
215
+ return this.config.provider;
216
+ }
217
+ getArgs({
218
+ audio,
219
+ mediaType,
220
+ providerOptions
221
+ }) {
222
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x;
223
+ const warnings = [];
224
+ const revaiOptions = parseProviderOptions({
225
+ provider: "revai",
226
+ providerOptions,
227
+ schema: revaiProviderOptionsSchema
228
+ });
229
+ const formData = new FormData();
230
+ const blob = audio instanceof Uint8Array ? new Blob([audio]) : new Blob([convertBase64ToUint8Array(audio)]);
231
+ formData.append("media", new File([blob], "audio", { type: mediaType }));
232
+ const transcriptionModelOptions = {
233
+ transcriber: this.modelId
234
+ };
235
+ if (revaiOptions) {
236
+ const formDataConfig = {
237
+ metadata: (_a = revaiOptions.metadata) != null ? _a : void 0,
238
+ notification_config: (_b = revaiOptions.notification_config) != null ? _b : void 0,
239
+ delete_after_seconds: (_c = revaiOptions.delete_after_seconds) != null ? _c : void 0,
240
+ verbatim: (_d = revaiOptions.verbatim) != null ? _d : void 0,
241
+ rush: (_e = revaiOptions.rush) != null ? _e : void 0,
242
+ test_mode: (_f = revaiOptions.test_mode) != null ? _f : void 0,
243
+ segments_to_transcribe: (_g = revaiOptions.segments_to_transcribe) != null ? _g : void 0,
244
+ speaker_names: (_h = revaiOptions.speaker_names) != null ? _h : void 0,
245
+ skip_diarization: (_i = revaiOptions.skip_diarization) != null ? _i : void 0,
246
+ skip_postprocessing: (_j = revaiOptions.skip_postprocessing) != null ? _j : void 0,
247
+ skip_punctuation: (_k = revaiOptions.skip_punctuation) != null ? _k : void 0,
248
+ remove_disfluencies: (_l = revaiOptions.remove_disfluencies) != null ? _l : void 0,
249
+ remove_atmospherics: (_m = revaiOptions.remove_atmospherics) != null ? _m : void 0,
250
+ filter_profanity: (_n = revaiOptions.filter_profanity) != null ? _n : void 0,
251
+ speaker_channels_count: (_o = revaiOptions.speaker_channels_count) != null ? _o : void 0,
252
+ speakers_count: (_p = revaiOptions.speakers_count) != null ? _p : void 0,
253
+ diarization_type: (_q = revaiOptions.diarization_type) != null ? _q : void 0,
254
+ custom_vocabulary_id: (_r = revaiOptions.custom_vocabulary_id) != null ? _r : void 0,
255
+ custom_vocabularies: (_s = revaiOptions.custom_vocabularies) != null ? _s : void 0,
256
+ strict_custom_vocabulary: (_t = revaiOptions.strict_custom_vocabulary) != null ? _t : void 0,
257
+ summarization_config: (_u = revaiOptions.summarization_config) != null ? _u : void 0,
258
+ translation_config: (_v = revaiOptions.translation_config) != null ? _v : void 0,
259
+ language: (_w = revaiOptions.language) != null ? _w : void 0,
260
+ forced_alignment: (_x = revaiOptions.forced_alignment) != null ? _x : void 0
261
+ };
262
+ for (const key in formDataConfig) {
263
+ const value = formDataConfig[key];
264
+ if (value !== void 0) {
265
+ transcriptionModelOptions[key] = value;
266
+ }
267
+ }
268
+ }
269
+ formData.append("config", JSON.stringify(transcriptionModelOptions));
270
+ return {
271
+ formData,
272
+ warnings
273
+ };
274
+ }
275
+ async doGenerate(options) {
276
+ var _a, _b, _c, _d, _e, _f, _g, _h;
277
+ const currentDate = (_c = (_b = (_a = this.config._internal) == null ? void 0 : _a.currentDate) == null ? void 0 : _b.call(_a)) != null ? _c : /* @__PURE__ */ new Date();
278
+ const { formData, warnings } = this.getArgs(options);
279
+ const { value: submissionResponse } = await postFormDataToApi({
280
+ url: this.config.url({
281
+ path: "/speechtotext/v1/jobs",
282
+ modelId: this.modelId
283
+ }),
284
+ headers: combineHeaders(this.config.headers(), options.headers),
285
+ formData,
286
+ failedResponseHandler: revaiFailedResponseHandler,
287
+ successfulResponseHandler: createJsonResponseHandler(
288
+ revaiTranscriptionJobResponseSchema
289
+ ),
290
+ abortSignal: options.abortSignal,
291
+ fetch: this.config.fetch
292
+ });
293
+ if (submissionResponse.status === "failed") {
294
+ throw new AISDKError({
295
+ message: "Failed to submit transcription job to Rev.ai",
296
+ name: "TranscriptionJobSubmissionFailed",
297
+ cause: submissionResponse
298
+ });
299
+ }
300
+ const jobId = submissionResponse.id;
301
+ const timeoutMs = 60 * 1e3;
302
+ const startTime = Date.now();
303
+ const pollingInterval = 1e3;
304
+ let jobResponse = submissionResponse;
305
+ while (jobResponse.status !== "transcribed") {
306
+ if (Date.now() - startTime > timeoutMs) {
307
+ throw new AISDKError({
308
+ message: "Transcription job polling timed out",
309
+ name: "TranscriptionJobPollingTimedOut",
310
+ cause: submissionResponse
311
+ });
312
+ }
313
+ const pollingResult = await getFromApi({
314
+ url: this.config.url({
315
+ path: `/speechtotext/v1/jobs/${jobId}`,
316
+ modelId: this.modelId
317
+ }),
318
+ headers: combineHeaders(this.config.headers(), options.headers),
319
+ failedResponseHandler: revaiFailedResponseHandler,
320
+ successfulResponseHandler: createJsonResponseHandler(
321
+ revaiTranscriptionJobResponseSchema
322
+ ),
323
+ abortSignal: options.abortSignal,
324
+ fetch: this.config.fetch
325
+ });
326
+ jobResponse = pollingResult.value;
327
+ if (jobResponse.status === "failed") {
328
+ throw new AISDKError({
329
+ message: "Transcription job failed",
330
+ name: "TranscriptionJobFailed",
331
+ cause: jobResponse
332
+ });
333
+ }
334
+ if (jobResponse.status !== "transcribed") {
335
+ await delay(pollingInterval);
336
+ }
337
+ }
338
+ const {
339
+ value: transcriptionResult,
340
+ responseHeaders,
341
+ rawValue: rawResponse
342
+ } = await getFromApi({
343
+ url: this.config.url({
344
+ path: `/speechtotext/v1/jobs/${jobId}/transcript`,
345
+ modelId: this.modelId
346
+ }),
347
+ headers: combineHeaders(this.config.headers(), options.headers),
348
+ failedResponseHandler: revaiFailedResponseHandler,
349
+ successfulResponseHandler: createJsonResponseHandler(
350
+ revaiTranscriptionResponseSchema
351
+ ),
352
+ abortSignal: options.abortSignal,
353
+ fetch: this.config.fetch
354
+ });
355
+ let durationInSeconds = 0;
356
+ const segments = [];
357
+ for (const monologue of (_d = transcriptionResult.monologues) != null ? _d : []) {
358
+ let currentSegmentText = "";
359
+ let segmentStartSecond = 0;
360
+ let hasStartedSegment = false;
361
+ for (const element of (_e = monologue == null ? void 0 : monologue.elements) != null ? _e : []) {
362
+ currentSegmentText += element.value;
363
+ if (element.type === "text") {
364
+ if (element.end_ts && element.end_ts > durationInSeconds) {
365
+ durationInSeconds = element.end_ts;
366
+ }
367
+ if (!hasStartedSegment && typeof element.ts === "number") {
368
+ segmentStartSecond = element.ts;
369
+ hasStartedSegment = true;
370
+ }
371
+ if (typeof element.end_ts === "number" && hasStartedSegment) {
372
+ if (currentSegmentText.trim()) {
373
+ segments.push({
374
+ text: currentSegmentText.trim(),
375
+ startSecond: segmentStartSecond,
376
+ endSecond: element.end_ts
377
+ });
378
+ }
379
+ currentSegmentText = "";
380
+ hasStartedSegment = false;
381
+ }
382
+ }
383
+ }
384
+ if (hasStartedSegment && currentSegmentText.trim()) {
385
+ const endSecond = durationInSeconds > segmentStartSecond ? durationInSeconds : segmentStartSecond + 1;
386
+ segments.push({
387
+ text: currentSegmentText.trim(),
388
+ startSecond: segmentStartSecond,
389
+ endSecond
390
+ });
391
+ }
392
+ }
393
+ return {
394
+ text: (_g = (_f = transcriptionResult.monologues) == null ? void 0 : _f.map(
395
+ (monologue) => {
396
+ var _a2;
397
+ return (_a2 = monologue == null ? void 0 : monologue.elements) == null ? void 0 : _a2.map((element) => element.value).join("");
398
+ }
399
+ ).join(" ")) != null ? _g : "",
400
+ segments,
401
+ language: (_h = submissionResponse.language) != null ? _h : void 0,
402
+ durationInSeconds,
403
+ warnings,
404
+ response: {
405
+ timestamp: currentDate,
406
+ modelId: this.modelId,
407
+ headers: responseHeaders,
408
+ body: rawResponse
409
+ }
410
+ };
411
+ }
412
+ };
413
+ var revaiTranscriptionJobResponseSchema = z2.object({
414
+ id: z2.string().nullish(),
415
+ status: z2.string().nullish(),
416
+ language: z2.string().nullish()
417
+ });
418
+ var revaiTranscriptionResponseSchema = z2.object({
419
+ monologues: z2.array(
420
+ z2.object({
421
+ elements: z2.array(
422
+ z2.object({
423
+ type: z2.string().nullish(),
424
+ value: z2.string().nullish(),
425
+ ts: z2.number().nullish(),
426
+ end_ts: z2.number().nullish()
427
+ })
428
+ ).nullish()
429
+ })
430
+ ).nullish()
431
+ });
432
+
433
+ // src/revai-provider.ts
434
+ function createRevai(options = {}) {
435
+ const getHeaders = () => ({
436
+ authorization: `Bearer ${loadApiKey({
437
+ apiKey: options.apiKey,
438
+ environmentVariableName: "REVAI_API_KEY",
439
+ description: "Rev.ai"
440
+ })}`,
441
+ ...options.headers
442
+ });
443
+ const createTranscriptionModel = (modelId) => new RevaiTranscriptionModel(modelId, {
444
+ provider: `revai.transcription`,
445
+ url: ({ path }) => `https://api.rev.ai${path}`,
446
+ headers: getHeaders,
447
+ fetch: options.fetch
448
+ });
449
+ const provider = function(modelId) {
450
+ return {
451
+ transcription: createTranscriptionModel(modelId)
452
+ };
453
+ };
454
+ provider.transcription = createTranscriptionModel;
455
+ provider.transcriptionModel = createTranscriptionModel;
456
+ return provider;
457
+ }
458
+ var revai = createRevai();
459
+ export {
460
+ createRevai,
461
+ revai
462
+ };
463
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/revai-provider.ts","../src/revai-transcription-model.ts","../src/revai-error.ts"],"sourcesContent":["import { TranscriptionModelV1, ProviderV1 } from '@ai-sdk/provider';\nimport { FetchFunction, loadApiKey } from '@ai-sdk/provider-utils';\nimport { RevaiTranscriptionModel } from './revai-transcription-model';\nimport { RevaiTranscriptionModelId } from './revai-transcription-settings';\n\nexport interface RevaiProvider extends Pick<ProviderV1, 'transcriptionModel'> {\n (\n modelId: 'machine',\n settings?: {},\n ): {\n transcription: RevaiTranscriptionModel;\n };\n\n /**\nCreates a model for transcription.\n */\n transcription(modelId: RevaiTranscriptionModelId): TranscriptionModelV1;\n}\n\nexport interface RevaiProviderSettings {\n /**\nAPI key for authenticating requests.\n */\n apiKey?: string;\n\n /**\nCustom headers to include in the requests.\n */\n headers?: Record<string, string>;\n\n /**\nCustom fetch implementation. You can use it as a middleware to intercept requests,\nor to provide a custom fetch implementation for e.g. testing.\n */\n fetch?: FetchFunction;\n}\n\n/**\nCreate a Rev.ai provider instance.\n */\nexport function createRevai(\n options: RevaiProviderSettings = {},\n): RevaiProvider {\n const getHeaders = () => ({\n authorization: `Bearer ${loadApiKey({\n apiKey: options.apiKey,\n environmentVariableName: 'REVAI_API_KEY',\n description: 'Rev.ai',\n })}`,\n ...options.headers,\n });\n\n const createTranscriptionModel = (modelId: RevaiTranscriptionModelId) =>\n new RevaiTranscriptionModel(modelId, {\n provider: `revai.transcription`,\n url: ({ path }) => `https://api.rev.ai${path}`,\n headers: getHeaders,\n fetch: options.fetch,\n });\n\n const provider = function (modelId: RevaiTranscriptionModelId) {\n return {\n transcription: createTranscriptionModel(modelId),\n };\n };\n\n provider.transcription = createTranscriptionModel;\n provider.transcriptionModel = createTranscriptionModel;\n\n return provider as RevaiProvider;\n}\n\n/**\nDefault Rev.ai provider instance.\n */\nexport const revai = createRevai();\n","import {\n AISDKError,\n TranscriptionModelV1,\n TranscriptionModelV1CallWarning,\n} from '@ai-sdk/provider';\nimport {\n combineHeaders,\n convertBase64ToUint8Array,\n createJsonResponseHandler,\n delay,\n getFromApi,\n parseProviderOptions,\n postFormDataToApi,\n} from '@ai-sdk/provider-utils';\nimport { z } from 'zod';\nimport { RevaiConfig } from './revai-config';\nimport { revaiFailedResponseHandler } from './revai-error';\nimport { RevaiTranscriptionModelId } from './revai-transcription-settings';\nimport { RevaiTranscriptionAPITypes } from './revai-api-types';\n\n// https://docs.rev.ai/api/asynchronous/reference/#operation/SubmitTranscriptionJob\nconst revaiProviderOptionsSchema = z.object({\n /**\n * Optional metadata string to associate with the transcription job.\n */\n metadata: z.string().nullish(),\n /**\n * Configuration for webhook notifications when job is complete.\n */\n notification_config: z\n .object({\n /**\n * URL to send the notification to.\n */\n url: z.string(),\n /**\n * Optional authorization headers for the notification request.\n */\n auth_headers: z\n .object({\n Authorization: z.string(),\n })\n .nullish(),\n })\n .nullish(),\n /**\n * Number of seconds after which the job will be automatically deleted.\n */\n delete_after_seconds: z.number().nullish(),\n /**\n * Whether to include filler words and false starts in the transcription.\n */\n verbatim: z.boolean().optional(),\n /**\n * Whether to prioritize the job for faster processing.\n */\n rush: z.boolean().nullish().default(false),\n /**\n * Whether to run the job in test mode.\n */\n test_mode: z.boolean().nullish().default(false),\n /**\n * Specific segments of the audio to transcribe.\n */\n segments_to_transcribe: z\n .array(\n z.object({\n /**\n * Start time of the segment in seconds.\n */\n start: z.number(),\n /**\n * End time of the segment in seconds.\n */\n end: z.number(),\n }),\n )\n .nullish(),\n /**\n * Names to assign to speakers in the transcription.\n */\n speaker_names: z\n .array(\n z.object({\n /**\n * Display name for the speaker.\n */\n display_name: z.string(),\n }),\n )\n .nullish(),\n /**\n * Whether to skip speaker diarization.\n */\n skip_diarization: z.boolean().nullish().default(false),\n /**\n * Whether to skip post-processing steps.\n */\n skip_postprocessing: z.boolean().nullish().default(false),\n /**\n * Whether to skip adding punctuation to the transcription.\n */\n skip_punctuation: z.boolean().nullish().default(false),\n /**\n * Whether to remove disfluencies (um, uh, etc.) from the transcription.\n */\n remove_disfluencies: z.boolean().nullish().default(false),\n /**\n * Whether to remove atmospheric sounds from the transcription.\n */\n remove_atmospherics: z.boolean().nullish().default(false),\n /**\n * Whether to filter profanity from the transcription.\n */\n filter_profanity: z.boolean().nullish().default(false),\n /**\n * Number of speaker channels in the audio.\n */\n speaker_channels_count: z.number().nullish(),\n /**\n * Expected number of speakers in the audio.\n */\n speakers_count: z.number().nullish(),\n /**\n * Type of diarization to use.\n */\n diarization_type: z\n .enum(['standard', 'premium'])\n .nullish()\n .default('standard'),\n /**\n * ID of a custom vocabulary to use for the transcription.\n */\n custom_vocabulary_id: z.string().nullish(),\n /**\n * Custom vocabularies to use for the transcription.\n */\n custom_vocabularies: z.array(z.object({})).optional(),\n /**\n * Whether to strictly enforce custom vocabulary.\n */\n strict_custom_vocabulary: z.boolean().optional(),\n /**\n * Configuration for generating a summary of the transcription.\n */\n summarization_config: z\n .object({\n /**\n * Model to use for summarization.\n */\n model: z.enum(['standard', 'premium']).nullish().default('standard'),\n /**\n * Format of the summary.\n */\n type: z.enum(['paragraph', 'bullets']).nullish().default('paragraph'),\n /**\n * Custom prompt for the summarization.\n */\n prompt: z.string().nullish(),\n })\n .nullish(),\n /**\n * Configuration for translating the transcription.\n */\n translation_config: z\n .object({\n /**\n * Target languages for translation.\n */\n target_languages: z.array(\n z.object({\n /**\n * Language code for translation target.\n */\n language: z.enum([\n 'en',\n 'en-us',\n 'en-gb',\n 'ar',\n 'pt',\n 'pt-br',\n 'pt-pt',\n 'fr',\n 'fr-ca',\n 'es',\n 'es-es',\n 'es-la',\n 'it',\n 'ja',\n 'ko',\n 'de',\n 'ru',\n ]),\n }),\n ),\n /**\n * Model to use for translation.\n */\n model: z.enum(['standard', 'premium']).nullish().default('standard'),\n })\n .nullish(),\n /**\n * Language of the audio content.\n */\n language: z.string().nullish().default('en'),\n /**\n * Whether to perform forced alignment.\n */\n forced_alignment: z.boolean().nullish().default(false),\n});\n\nexport type RevaiTranscriptionCallOptions = z.infer<\n typeof revaiProviderOptionsSchema\n>;\n\ninterface RevaiTranscriptionModelConfig extends RevaiConfig {\n _internal?: {\n currentDate?: () => Date;\n };\n}\n\nexport class RevaiTranscriptionModel implements TranscriptionModelV1 {\n readonly specificationVersion = 'v1';\n\n get provider(): string {\n return this.config.provider;\n }\n\n constructor(\n readonly modelId: RevaiTranscriptionModelId,\n private readonly config: RevaiTranscriptionModelConfig,\n ) {}\n\n private getArgs({\n audio,\n mediaType,\n providerOptions,\n }: Parameters<TranscriptionModelV1['doGenerate']>[0]) {\n const warnings: TranscriptionModelV1CallWarning[] = [];\n\n // Parse provider options\n const revaiOptions = parseProviderOptions({\n provider: 'revai',\n providerOptions,\n schema: revaiProviderOptionsSchema,\n });\n\n // Create form data with base fields\n const formData = new FormData();\n const blob =\n audio instanceof Uint8Array\n ? new Blob([audio])\n : new Blob([convertBase64ToUint8Array(audio)]);\n\n formData.append('media', new File([blob], 'audio', { type: mediaType }));\n const transcriptionModelOptions: RevaiTranscriptionAPITypes = {\n transcriber: this.modelId,\n };\n\n // Add provider-specific options\n if (revaiOptions) {\n const formDataConfig: RevaiTranscriptionAPITypes = {\n metadata: revaiOptions.metadata ?? undefined,\n notification_config: revaiOptions.notification_config ?? undefined,\n delete_after_seconds: revaiOptions.delete_after_seconds ?? undefined,\n verbatim: revaiOptions.verbatim ?? undefined,\n rush: revaiOptions.rush ?? undefined,\n test_mode: revaiOptions.test_mode ?? undefined,\n segments_to_transcribe:\n revaiOptions.segments_to_transcribe ?? undefined,\n speaker_names: revaiOptions.speaker_names ?? undefined,\n skip_diarization: revaiOptions.skip_diarization ?? undefined,\n skip_postprocessing: revaiOptions.skip_postprocessing ?? undefined,\n skip_punctuation: revaiOptions.skip_punctuation ?? undefined,\n remove_disfluencies: revaiOptions.remove_disfluencies ?? undefined,\n remove_atmospherics: revaiOptions.remove_atmospherics ?? undefined,\n filter_profanity: revaiOptions.filter_profanity ?? undefined,\n speaker_channels_count:\n revaiOptions.speaker_channels_count ?? undefined,\n speakers_count: revaiOptions.speakers_count ?? undefined,\n diarization_type: revaiOptions.diarization_type ?? undefined,\n custom_vocabulary_id: revaiOptions.custom_vocabulary_id ?? undefined,\n custom_vocabularies: revaiOptions.custom_vocabularies ?? undefined,\n strict_custom_vocabulary:\n revaiOptions.strict_custom_vocabulary ?? undefined,\n summarization_config: revaiOptions.summarization_config ?? undefined,\n translation_config: revaiOptions.translation_config ?? undefined,\n language: revaiOptions.language ?? undefined,\n forced_alignment: revaiOptions.forced_alignment ?? undefined,\n };\n\n for (const key in formDataConfig) {\n const value = formDataConfig[key as keyof RevaiTranscriptionAPITypes];\n if (value !== undefined) {\n (transcriptionModelOptions as Record<string, unknown>)[\n key as keyof RevaiTranscriptionAPITypes\n ] = value;\n }\n }\n }\n\n formData.append('config', JSON.stringify(transcriptionModelOptions));\n\n return {\n formData,\n warnings,\n };\n }\n\n async doGenerate(\n options: Parameters<TranscriptionModelV1['doGenerate']>[0],\n ): Promise<Awaited<ReturnType<TranscriptionModelV1['doGenerate']>>> {\n const currentDate = this.config._internal?.currentDate?.() ?? new Date();\n const { formData, warnings } = this.getArgs(options);\n\n const { value: submissionResponse } = await postFormDataToApi({\n url: this.config.url({\n path: '/speechtotext/v1/jobs',\n modelId: this.modelId,\n }),\n headers: combineHeaders(this.config.headers(), options.headers),\n formData,\n failedResponseHandler: revaiFailedResponseHandler,\n successfulResponseHandler: createJsonResponseHandler(\n revaiTranscriptionJobResponseSchema,\n ),\n abortSignal: options.abortSignal,\n fetch: this.config.fetch,\n });\n\n if (submissionResponse.status === 'failed') {\n throw new AISDKError({\n message: 'Failed to submit transcription job to Rev.ai',\n name: 'TranscriptionJobSubmissionFailed',\n cause: submissionResponse,\n });\n }\n\n const jobId = submissionResponse.id;\n const timeoutMs = 60 * 1000; // 60 seconds timeout\n const startTime = Date.now();\n const pollingInterval = 1000;\n let jobResponse = submissionResponse;\n\n while (jobResponse.status !== 'transcribed') {\n // Check if we've exceeded the timeout\n if (Date.now() - startTime > timeoutMs) {\n throw new AISDKError({\n message: 'Transcription job polling timed out',\n name: 'TranscriptionJobPollingTimedOut',\n cause: submissionResponse,\n });\n }\n\n // Poll for job status\n const pollingResult = await getFromApi({\n url: this.config.url({\n path: `/speechtotext/v1/jobs/${jobId}`,\n modelId: this.modelId,\n }),\n headers: combineHeaders(this.config.headers(), options.headers),\n failedResponseHandler: revaiFailedResponseHandler,\n successfulResponseHandler: createJsonResponseHandler(\n revaiTranscriptionJobResponseSchema,\n ),\n abortSignal: options.abortSignal,\n fetch: this.config.fetch,\n });\n\n jobResponse = pollingResult.value;\n\n if (jobResponse.status === 'failed') {\n throw new AISDKError({\n message: 'Transcription job failed',\n name: 'TranscriptionJobFailed',\n cause: jobResponse,\n });\n }\n\n // Wait before polling again (only if we need to continue polling)\n if (jobResponse.status !== 'transcribed') {\n await delay(pollingInterval);\n }\n }\n\n const {\n value: transcriptionResult,\n responseHeaders,\n rawValue: rawResponse,\n } = await getFromApi({\n url: this.config.url({\n path: `/speechtotext/v1/jobs/${jobId}/transcript`,\n modelId: this.modelId,\n }),\n headers: combineHeaders(this.config.headers(), options.headers),\n failedResponseHandler: revaiFailedResponseHandler,\n successfulResponseHandler: createJsonResponseHandler(\n revaiTranscriptionResponseSchema,\n ),\n abortSignal: options.abortSignal,\n fetch: this.config.fetch,\n });\n\n let durationInSeconds = 0;\n const segments: {\n text: string;\n startSecond: number;\n endSecond: number;\n }[] = [];\n\n for (const monologue of transcriptionResult.monologues ?? []) {\n // Process each monologue to extract segments with timing information\n let currentSegmentText = '';\n let segmentStartSecond = 0;\n let hasStartedSegment = false;\n\n for (const element of monologue?.elements ?? []) {\n // Add the element value to the current segment text\n currentSegmentText += element.value;\n\n // For text elements, track timing information\n if (element.type === 'text') {\n // Update the overall duration if this is the latest timestamp\n if (element.end_ts && element.end_ts > durationInSeconds) {\n durationInSeconds = element.end_ts;\n }\n\n // If this is the first text element in a segment, mark the start time\n if (!hasStartedSegment && typeof element.ts === 'number') {\n segmentStartSecond = element.ts;\n hasStartedSegment = true;\n }\n\n // If we have an end timestamp, we can complete a segment\n if (typeof element.end_ts === 'number' && hasStartedSegment) {\n // Only add non-empty segments\n if (currentSegmentText.trim()) {\n segments.push({\n text: currentSegmentText.trim(),\n startSecond: segmentStartSecond,\n endSecond: element.end_ts,\n });\n }\n\n // Reset for the next segment\n currentSegmentText = '';\n hasStartedSegment = false;\n }\n }\n }\n\n // Handle any remaining segment text that wasn't added\n if (hasStartedSegment && currentSegmentText.trim()) {\n const endSecond =\n durationInSeconds > segmentStartSecond\n ? durationInSeconds\n : segmentStartSecond + 1;\n segments.push({\n text: currentSegmentText.trim(),\n startSecond: segmentStartSecond,\n endSecond: endSecond,\n });\n }\n }\n\n return {\n text:\n transcriptionResult.monologues\n ?.map(monologue =>\n monologue?.elements?.map(element => element.value).join(''),\n )\n .join(' ') ?? '',\n segments,\n language: submissionResponse.language ?? undefined,\n durationInSeconds,\n warnings,\n response: {\n timestamp: currentDate,\n modelId: this.modelId,\n headers: responseHeaders,\n body: rawResponse,\n },\n };\n }\n}\n\nconst revaiTranscriptionJobResponseSchema = z.object({\n id: z.string().nullish(),\n status: z.string().nullish(),\n language: z.string().nullish(),\n});\n\nconst revaiTranscriptionResponseSchema = z.object({\n monologues: z\n .array(\n z.object({\n elements: z\n .array(\n z.object({\n type: z.string().nullish(),\n value: z.string().nullish(),\n ts: z.number().nullish(),\n end_ts: z.number().nullish(),\n }),\n )\n .nullish(),\n }),\n )\n .nullish(),\n});\n","import { z } from 'zod';\nimport { createJsonErrorResponseHandler } from '@ai-sdk/provider-utils';\n\nexport const revaiErrorDataSchema = z.object({\n error: z.object({\n message: z.string(),\n code: z.number(),\n }),\n});\n\nexport type RevaiErrorData = z.infer<typeof revaiErrorDataSchema>;\n\nexport const revaiFailedResponseHandler = createJsonErrorResponseHandler({\n errorSchema: revaiErrorDataSchema,\n errorToMessage: data => data.error.message,\n});\n"],"mappings":"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","names":["z","z","_a"]}
package/package.json ADDED
@@ -0,0 +1,64 @@
1
+ {
2
+ "name": "@ai-sdk/revai",
3
+ "version": "0.0.1",
4
+ "license": "Apache-2.0",
5
+ "sideEffects": false,
6
+ "main": "./dist/index.js",
7
+ "module": "./dist/index.mjs",
8
+ "types": "./dist/index.d.ts",
9
+ "files": [
10
+ "dist/**/*",
11
+ "CHANGELOG.md"
12
+ ],
13
+ "exports": {
14
+ "./package.json": "./package.json",
15
+ ".": {
16
+ "types": "./dist/index.d.ts",
17
+ "import": "./dist/index.mjs",
18
+ "require": "./dist/index.js"
19
+ }
20
+ },
21
+ "dependencies": {
22
+ "@ai-sdk/provider": "1.1.3",
23
+ "@ai-sdk/provider-utils": "2.2.7"
24
+ },
25
+ "devDependencies": {
26
+ "@types/node": "20.17.24",
27
+ "tsup": "^8",
28
+ "typescript": "5.6.3",
29
+ "zod": "3.23.8",
30
+ "@vercel/ai-tsconfig": "0.0.0"
31
+ },
32
+ "peerDependencies": {
33
+ "zod": "^3.0.0"
34
+ },
35
+ "engines": {
36
+ "node": ">=18"
37
+ },
38
+ "publishConfig": {
39
+ "access": "public"
40
+ },
41
+ "homepage": "https://sdk.vercel.ai/docs",
42
+ "repository": {
43
+ "type": "git",
44
+ "url": "git+https://github.com/vercel/ai.git"
45
+ },
46
+ "bugs": {
47
+ "url": "https://github.com/vercel/ai/issues"
48
+ },
49
+ "keywords": [
50
+ "ai"
51
+ ],
52
+ "scripts": {
53
+ "build": "tsup",
54
+ "build:watch": "tsup --watch",
55
+ "clean": "rm -rf dist",
56
+ "lint": "eslint \"./**/*.ts*\"",
57
+ "type-check": "tsc --noEmit",
58
+ "prettier-check": "prettier --check \"./**/*.ts*\"",
59
+ "test": "pnpm test:node && pnpm test:edge",
60
+ "test:edge": "vitest --config vitest.edge.config.js --run",
61
+ "test:node": "vitest --config vitest.node.config.js --run",
62
+ "test:node:watch": "vitest --config vitest.node.config.js --watch"
63
+ }
64
+ }