From bb6aa31411d357a037de652dda87821ef3ecab3e Mon Sep 17 00:00:00 2001 From: AssemblyAI Date: Tue, 23 Jan 2024 16:04:15 -0500 Subject: [PATCH] Project import generated by Copybara. GitOrigin-RevId: ac079adb8f337563cbf27b0e6a1dfa0bb1c17de8 --- CHANGELOG.md | 9 +++++++++ README.md | 10 +++++----- docs/compat.md | 10 +++++----- package.json | 2 +- scripts/generate-types.ts | 15 ++------------- scripts/kitchensink.ts | 6 +++--- src/services/index.ts | 13 ++++++++++--- src/services/realtime/factory.ts | 23 ++++++++++++++++++----- src/services/realtime/service.ts | 20 +++++++++++++------- src/types/asyncapi.generated.ts | 9 +++++---- src/types/openapi.generated.ts | 25 +++++++++++++++++++++---- src/types/realtime/index.ts | 16 ++++++++++++++-- tests/realtime.test.ts | 22 +++++++++++----------- 13 files changed, 117 insertions(+), 63 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3236f35..80a88f1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,14 @@ # Changelog +## [4.2.1] - 2024-01-23 + +### Added +- Add `answer_format` to `LemurActionItemsParams` type + +### Changed +- Rename `RealtimeService` to `RealtimeTranscriber`, `RealtimeServiceFactory` to `RealtimeTranscriberFactory`, `RealtimeTranscriberFactory.createService()` to `RealtimeTranscriberFactory.transcriber()`. Deprecated aliases are provided for all old types and functions for backwards compatibility. +- Restrict the type for `redact_pii_audio_quality` from `string` to `RedactPiiAudioQuality` an enum string. + ## [4.2.0] - 2024-01-11 ### Added diff --git a/README.md b/README.md index e7cc3d3..d04f947 100644 --- a/README.md +++ b/README.md @@ -184,18 +184,18 @@ const { response } = await client.lemur.task({ }); ``` -## Transcribe in real time +## Transcribe in real-time -Create the real-time service. +Create the real-time transcriber. ```typescript -const rt = client.realtime.createService(); +const rt = client.realtime.transcriber(); ``` You can also pass in the following options. ```typescript -const rt = client.realtime.createService({ +const rt = client.realtime.transcriber({ realtimeUrl: 'wss://localhost/override', apiKey: process.env.ASSEMBLYAI_API_KEY // The API key passed to `AssemblyAI` will be used by default, sampleRate: 16_000, @@ -207,7 +207,7 @@ You can also generate a temporary auth token for real-time. ```typescript const token = await client.realtime.createTemporaryToken({ expires_in = 60 }); -const rt = client.realtime.createService({ +const rt = client.realtime.transcriber({ token: token, }); ``` diff --git a/docs/compat.md b/docs/compat.md index f952624..9a4ca0e 100644 --- a/docs/compat.md +++ b/docs/compat.md @@ -13,7 +13,7 @@ If you do use an older version of Node.js like version 16, you'll need to polyfi To make the SDK compatible with the browser, the SDK aims to use web standards as much as possible. However, there are still incompatibilities between Node.js and the browser. -- `RealtimeService` doesn't support the AssemblyAI API key in the browser. +- `RealtimeTranscriber` doesn't support the AssemblyAI API key in the browser. Instead, you have to generate a temporary auth token using `client.realtime.createTemporaryToken`, and pass in the resulting token to the real-time transcriber. Generate a temporary auth token on the server. @@ -31,16 +31,16 @@ However, there are still incompatibilities between Node.js and the browser. > If you embed the API key on the client, everyone can see it and use it for themselves. Then pass the token via an API to the client. - On the client, create an instance of `RealtimeService` using the token. + On the client, create an instance of `RealtimeTranscriber` using the token. ```js - import { RealtimeService } from "assemblyai"; + import { RealtimeTranscriber } from "assemblyai"; // or the following if you're using UMD - // const { RealtimeService } = assemblyai; + // const { RealtimeTranscriber } = assemblyai; const token = getToken(); // getToken is a function for you to implement - const rt = new RealtimeService({ + const rt = new RealtimeTranscriber({ token: token, }); ``` diff --git a/package.json b/package.json index 787dc27..4490788 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "assemblyai", - "version": "4.2.0", + "version": "4.2.1", "description": "The AssemblyAI JavaScript SDK provides an easy-to-use interface for interacting with the AssemblyAI API, which supports async and real-time transcription, as well as the latest LeMUR models.", "engines": { "node": ">=18" diff --git a/scripts/generate-types.ts b/scripts/generate-types.ts index 706f976..0c566c0 100644 --- a/scripts/generate-types.ts +++ b/scripts/generate-types.ts @@ -7,19 +7,8 @@ async function generateTypes(apiSpecPath: string, outputPath: string) { alphabetize: true, exportType: true, transform(schemaObject) { - if ( - "x-fern-type" in schemaObject && - schemaObject["x-fern-type"] === "datetime" - ) { - // Use Date as type instead of String, even though it will be a string. - // The service code manually converts the string into a Date. - // Fe see `TranscriptService#list`. - return schemaObject.nullable ? "Date | null" : "Date"; - } - }, - postTransform(type) { - if (type === `components["schemas"]["LemurModel"] | string`) { - return `LiteralUnion`; + if ("x-ts-type" in schemaObject) { + return schemaObject["x-ts-type"]; } }, }); diff --git a/scripts/kitchensink.ts b/scripts/kitchensink.ts index 1d91a77..3e128e3 100644 --- a/scripts/kitchensink.ts +++ b/scripts/kitchensink.ts @@ -7,7 +7,7 @@ import { LemurBaseResponse, PartialTranscript, RealtimeTranscript, - CreateRealtimeServiceParams, + CreateRealtimeTranscriberParams, TranscribeParams, } from "../src"; @@ -17,7 +17,7 @@ const client = new AssemblyAI({ (async function transcribeUsingRealtime() { const useToken = false; - const serviceParams: CreateRealtimeServiceParams = { + const serviceParams: CreateRealtimeTranscriberParams = { sampleRate: 16_000, wordBoost: ["gore", "climate"], token: useToken @@ -27,7 +27,7 @@ const client = new AssemblyAI({ : undefined, encoding: "pcm_s16le", }; - const rt = client.realtime.createService(serviceParams); + const rt = client.realtime.transcriber(serviceParams); rt.on("open", ({ sessionId, expiresAt }) => { console.log("Session ID:", sessionId, "Expires At:", expiresAt); diff --git a/src/services/index.ts b/src/services/index.ts index 93f2259..cb4bb79 100644 --- a/src/services/index.ts +++ b/src/services/index.ts @@ -1,6 +1,11 @@ import { BaseServiceParams } from ".."; import { LemurService } from "./lemur"; -import { RealtimeService, RealtimeServiceFactory } from "./realtime"; +import { + RealtimeTranscriber, + RealtimeTranscriberFactory, + RealtimeService, + RealtimeServiceFactory, +} from "./realtime"; import { TranscriptService } from "./transcripts"; import { FileService } from "./files"; @@ -25,7 +30,7 @@ class AssemblyAI { /** * The realtime service. */ - public realtime: RealtimeServiceFactory; + public realtime: RealtimeTranscriberFactory; /** * Create a new AssemblyAI client. @@ -38,13 +43,15 @@ class AssemblyAI { this.files = new FileService(params); this.transcripts = new TranscriptService(params, this.files); this.lemur = new LemurService(params); - this.realtime = new RealtimeServiceFactory(params); + this.realtime = new RealtimeTranscriberFactory(params); } } export { AssemblyAI, LemurService, + RealtimeTranscriberFactory, + RealtimeTranscriber, RealtimeServiceFactory, RealtimeService, TranscriptService, diff --git a/src/services/realtime/factory.ts b/src/services/realtime/factory.ts index d4622b9..eb9b329 100644 --- a/src/services/realtime/factory.ts +++ b/src/services/realtime/factory.ts @@ -1,27 +1,35 @@ import { BaseServiceParams, RealtimeTokenParams, - CreateRealtimeServiceParams, - RealtimeServiceParams, + CreateRealtimeTranscriberParams, + RealtimeTranscriberParams, RealtimeTemporaryTokenResponse, + CreateRealtimeServiceParams, } from "../.."; -import { RealtimeService } from "./service"; +import { RealtimeService, RealtimeTranscriber } from "./service"; import { BaseService } from "../base"; -export class RealtimeServiceFactory extends BaseService { +export class RealtimeTranscriberFactory extends BaseService { private rtFactoryParams: BaseServiceParams; constructor(params: BaseServiceParams) { super(params); this.rtFactoryParams = params; } + /** + * @deprecated Use transcriber(...) instead + */ createService(params?: CreateRealtimeServiceParams): RealtimeService { + return this.transcriber(params); + } + + transcriber(params?: CreateRealtimeTranscriberParams): RealtimeTranscriber { const serviceParams = { ...params } as Record; if (!serviceParams.token && !serviceParams.apiKey) { serviceParams.apiKey = this.rtFactoryParams.apiKey; } - return new RealtimeService(serviceParams as RealtimeServiceParams); + return new RealtimeTranscriber(serviceParams as RealtimeTranscriberParams); } async createTemporaryToken(params: RealtimeTokenParams) { @@ -35,3 +43,8 @@ export class RealtimeServiceFactory extends BaseService { return data.token; } } + +/** + * @deprecated Use RealtimeTranscriberFactory instead + */ +export class RealtimeServiceFactory extends RealtimeTranscriberFactory {} diff --git a/src/services/realtime/service.ts b/src/services/realtime/service.ts index 8ab2235..bc7ca09 100644 --- a/src/services/realtime/service.ts +++ b/src/services/realtime/service.ts @@ -4,13 +4,14 @@ import { ErrorEvent, MessageEvent, CloseEvent } from "ws"; import { RealtimeEvents, RealtimeListeners, - RealtimeServiceParams, + RealtimeTranscriberParams, RealtimeMessage, RealtimeTranscript, PartialTranscript, FinalTranscript, SessionBeginsEventData, AudioEncoding, + AudioData, } from "../.."; import { RealtimeError, @@ -20,7 +21,7 @@ import { const defaultRealtimeUrl = "wss://api.assemblyai.com/v2/realtime/ws"; -export class RealtimeService { +export class RealtimeTranscriber { private realtimeUrl: string; private sampleRate: number; private wordBoost?: string[]; @@ -31,7 +32,7 @@ export class RealtimeService { private listeners: RealtimeListeners = {}; private sessionTerminatedResolve?: () => void; - constructor(params: RealtimeServiceParams) { + constructor(params: RealtimeTranscriberParams) { this.realtimeUrl = params.realtimeUrl ?? defaultRealtimeUrl; this.sampleRate = params.sampleRate ?? 16_000; this.wordBoost = params.wordBoost; @@ -157,16 +158,16 @@ export class RealtimeService { }); } - sendAudio(audio: ArrayBufferLike) { + sendAudio(audio: AudioData) { if (!this.socket || this.socket.readyState !== WebSocket.OPEN) { throw new Error("Socket is not open for communication"); } this.socket.send(audio); } - stream(): WritableStream { - return new WritableStream({ - write: (chunk: ArrayBufferLike) => { + stream(): WritableStream { + return new WritableStream({ + write: (chunk: AudioData) => { this.sendAudio(chunk); }, }); @@ -194,3 +195,8 @@ export class RealtimeService { this.socket = undefined; } } + +/** + * @deprecated Use RealtimeTranscriber instead + */ +export class RealtimeService extends RealtimeTranscriber {} diff --git a/src/types/asyncapi.generated.ts b/src/types/asyncapi.generated.ts index edef167..fba7dd1 100644 --- a/src/types/asyncapi.generated.ts +++ b/src/types/asyncapi.generated.ts @@ -15,10 +15,11 @@ type OneOf = T extends [infer Only] ? OneOf<[XOR, ...Rest]> : never; -export type AudioData = { - /** @description Base64 encoded raw audio data */ - audio_data: string; -}; +/** + * Format: binary + * @description Binary audio data + */ +export type AudioData = ArrayBufferLike; /** * @description The encoding of the audio data diff --git a/src/types/openapi.generated.ts b/src/types/openapi.generated.ts index f68cc6b..0f648d7 100644 --- a/src/types/openapi.generated.ts +++ b/src/types/openapi.generated.ts @@ -475,12 +475,21 @@ export type Error = { * "64nygnr62k-405c-4ae8-8a6b-d90b40ff3cce" * ], * "context": "This is an interview about wildfires.", + * "answer_format": "Bullet Points", * "final_model": "default", * "temperature": 0, * "max_output_size": 3000 * } */ -export type LemurActionItemsParams = LemurBaseParams; +export type LemurActionItemsParams = LemurBaseParams & { + /** + * @description How you want the action items to be returned. This can be any text. + * Defaults to "Bullet Points". + * + * @default Bullet Points + */ + answer_format?: string; +}; /** * @example { @@ -931,6 +940,14 @@ export type RedactedAudioResponse = { */ export type RedactedAudioStatus = "redacted_audio_ready"; +/** + * @description Controls the filetype of the audio created by redact_pii_audio. Currently supports mp3 (default) and wav. See [PII redaction](https://www.assemblyai.com/docs/models/pii-redaction) for more details. + * @default mp3 + * @example mp3 + * @enum {string} + */ +export type RedactPiiAudioQuality = "mp3" | "wav"; + /** * @example { * "sentences": [ @@ -2076,7 +2093,7 @@ export type Transcript = { * @description The audio quality of the PII-redacted audio file, if redact_pii_audio is enabled. * See [PII redaction](https://www.assemblyai.com/docs/models/pii-redaction) for more information. */ - redact_pii_audio_quality?: string | null; + redact_pii_audio_quality?: RedactPiiAudioQuality | null; /** * @description The list of PII Redaction policies that were enabled, if PII Redaction is enabled. * See [PII redaction](https://www.assemblyai.com/docs/models/pii-redaction) for more information. @@ -2244,7 +2261,7 @@ export type TranscriptList = { */ export type TranscriptListItem = { audio_url: string; - completed?: Date; + completed: Date | null; created: Date; /** Format: uuid */ id: string; @@ -2346,7 +2363,7 @@ export type TranscriptOptionalParams = { * @description Controls the filetype of the audio created by redact_pii_audio. Currently supports mp3 (default) and wav. See [PII redaction](https://www.assemblyai.com/docs/models/pii-redaction) for more details. * @default mp3 */ - redact_pii_audio_quality?: string; + redact_pii_audio_quality?: RedactPiiAudioQuality; /** @description The list of PII Redaction policies to enable. See [PII redaction](https://www.assemblyai.com/docs/models/pii-redaction) for more details. */ redact_pii_policies?: PiiPolicy[]; /** @description The replacement logic for detected PII, can be "entity_type" or "hash". See [PII redaction](https://www.assemblyai.com/docs/models/pii-redaction) for more details. */ diff --git a/src/types/realtime/index.ts b/src/types/realtime/index.ts index 0372c01..54e76f6 100644 --- a/src/types/realtime/index.ts +++ b/src/types/realtime/index.ts @@ -6,7 +6,7 @@ import { RealtimeTranscriptType, } from "../asyncapi.generated"; -type CreateRealtimeServiceParams = { +type CreateRealtimeTranscriberParams = { realtimeUrl?: string; sampleRate?: number; wordBoost?: string[]; @@ -20,7 +20,12 @@ type CreateRealtimeServiceParams = { } ); -type RealtimeServiceParams = { +/** + * @deprecated Use CreateRealtimeTranscriberParams instead + */ +type CreateRealtimeServiceParams = CreateRealtimeTranscriberParams; + +type RealtimeTranscriberParams = { realtimeUrl?: string; sampleRate?: number; wordBoost?: string[]; @@ -34,6 +39,11 @@ type RealtimeServiceParams = { } ); +/** + * @deprecated Use RealtimeTranscriberParams instead + */ +type RealtimeServiceParams = RealtimeTranscriberParams; + type RealtimeEvents = | "open" | "close" @@ -61,6 +71,8 @@ type RealtimeTokenParams = { }; export type { + CreateRealtimeTranscriberParams, + RealtimeTranscriberParams, CreateRealtimeServiceParams, RealtimeServiceParams, RealtimeEvents, diff --git a/tests/realtime.test.ts b/tests/realtime.test.ts index 84fe72c..d44cfa0 100644 --- a/tests/realtime.test.ts +++ b/tests/realtime.test.ts @@ -1,7 +1,7 @@ import { TransformStream } from "stream/web"; import WS from "jest-websocket-mock"; import fetchMock from "jest-fetch-mock"; -import { AssemblyAI, RealtimeService } from "../src"; +import { AssemblyAI, RealtimeTranscriber } from "../src"; import { RealtimeError, RealtimeErrorType, @@ -25,16 +25,16 @@ const sessionTerminatedMessage = { }; let server: WS; let aai: AssemblyAI; -let rt: RealtimeService; +let rt: RealtimeTranscriber; let onOpen: jest.Mock; -async function connect(rt: RealtimeService, server: WS) { +async function connect(rt: RealtimeTranscriber, server: WS) { const connectPromise = rt.connect(); await server.connected; server.send(JSON.stringify(sessionBeginsMessage)); await connectPromise; } -async function close(rt: RealtimeService, server: WS) { +async function close(rt: RealtimeTranscriber, server: WS) { const closePromise = rt.close(); server.send(JSON.stringify(sessionTerminatedMessage)); await closePromise; @@ -45,7 +45,7 @@ describe("realtime", () => { beforeEach(async () => { server = new WS(realtimeUrl); aai = createClient(); - rt = aai.realtime.createService({ realtimeUrl }); + rt = aai.realtime.transcriber({ realtimeUrl }); onOpen = jest.fn(); rt.on("open", onOpen); await connect(rt, server); @@ -64,7 +64,7 @@ describe("realtime", () => { }); it("fails with no websocket URL", async () => { - const rt = new RealtimeService({ + const rt = new RealtimeTranscriber({ apiKey, realtimeUrl: "https://api.assemblyai.com", }); @@ -85,7 +85,7 @@ describe("realtime", () => { const baseUrlOverride = "wss://localhost:1235"; const server = new WS(baseUrlOverride); const aai = new AssemblyAI({ apiKey }); - const rt = aai.realtime.createService({ + const rt = aai.realtime.transcriber({ realtimeUrl: baseUrlOverride, token, }); @@ -98,7 +98,7 @@ describe("realtime", () => { const realtimeUrl = "wss://localhost:5678"; const server = new WS(realtimeUrl); const aai = createClient(); - const rt = aai.realtime.createService({ realtimeUrl, token }); + const rt = aai.realtime.transcriber({ realtimeUrl, token }); await connect(rt, server); await close(rt, server); }); @@ -107,7 +107,7 @@ describe("realtime", () => { const realtimeUrl = "wss://localhost:5678"; const server = new WS(realtimeUrl); const aai = createClient(); - const rt = aai.realtime.createService({ realtimeUrl, apiKey: "123" }); + const rt = aai.realtime.transcriber({ realtimeUrl, apiKey: "123" }); await connect(rt, server); await close(rt, server); }); @@ -127,7 +127,7 @@ describe("realtime", () => { const realtimeUrl = "wss://localhost:5678"; const server = new WS(realtimeUrl); const aai = createClient(); - const rt = aai.realtime.createService({ realtimeUrl, apiKey: "123" }); + const rt = aai.realtime.transcriber({ realtimeUrl, apiKey: "123" }); await connect(rt, server); await rt.close(false); await server.closed; @@ -198,7 +198,7 @@ describe("realtime", () => { const realtimeUrl = "wss://localhost:5678"; const server = new WS(realtimeUrl); const aai = createClient(); - const rt = aai.realtime.createService({ realtimeUrl, apiKey: "123" }); + const rt = aai.realtime.transcriber({ realtimeUrl, apiKey: "123" }); const onOpen = jest.fn(); rt.on("open", onOpen); await connect(rt, server);