diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml
new file mode 100644
index 0000000..fdf4667
--- /dev/null
+++ b/.github/workflows/publish.yml
@@ -0,0 +1,45 @@
+name: Publish to npmjs.com
+
+on:
+ release:
+ types: [published]
+
+jobs:
+ build-and-publish:
+ name: Build and publish to npmjs.com
+ runs-on: ubuntu-latest
+ steps:
+ - name: Setup Node.js 20
+ uses: actions/setup-node@v3
+ with:
+ node-version: 20
+ - name: Checkout source code
+ uses: actions/checkout@v3
+ - name: Install pnpm
+ run: npm install -g pnpm@8.7.4
+ # doesn't work with Node 20
+ # - name: Install pnpm
+ # uses: pnpm/action-setup@v2
+ # with:
+ # version: 8.7.4
+ # run_install: false
+ - name: Get pnpm store directory
+ shell: bash
+ run: |
+ echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV
+ - uses: actions/cache@v3
+ name: Setup pnpm cache
+ with:
+ path: ${{ env.STORE_PATH }}
+ key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
+ restore-keys: |
+ ${{ runner.os }}-pnpm-store-
+ - name: Install dependencies
+ run: pnpm install --frozen-lockfile false
+ - name: Build code
+ run: npm run build
+ - run: |
+ npm config set //registry.npmjs.org/:_authToken=$NPM_AUTH_TOKEN
+ npm publish
+ env:
+ NPM_AUTH_TOKEN: ${{ secrets.NPM_AUTH_TOKEN }}
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
new file mode 100644
index 0000000..a974a01
--- /dev/null
+++ b/.github/workflows/test.yml
@@ -0,0 +1,54 @@
+name: Test
+on:
+ push:
+ branches: ["main"]
+ pull_request:
+ branches: ["main"]
+
+jobs:
+ test:
+ name: Node.js ${{ matrix['node-version'] }} on ${{ matrix.os }}
+ runs-on: ${{ matrix.os }}
+ strategy:
+ fail-fast: false
+ matrix:
+ node-version:
+ - "20"
+ # - "18"
+ # - "16"
+ os:
+ - ubuntu-latest
+ # - macos-latest
+ # - windows-latest
+ steps:
+ - name: Setup Node.js ${{ matrix['node-version'] }}
+ uses: actions/setup-node@v3
+ with:
+ node-version: ${{ matrix['node-version'] }}
+ - name: Checkout source code
+ uses: actions/checkout@v3
+ - name: Install pnpm
+ run: npm install -g pnpm@8.7.4
+ # doesn't work with Node 20
+ # - name: Install pnpm
+ # uses: pnpm/action-setup@v2
+ # with:
+ # version: 8.7.4
+ # run_install: false
+ - name: Get pnpm store directory
+ shell: bash
+ run: |
+ echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV
+ - uses: actions/cache@v3
+ name: Setup pnpm cache
+ with:
+ path: ${{ env.STORE_PATH }}
+ key: ${{ matrix.os }}${{ matrix['node-version'] }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
+ restore-keys: |
+ ${{ matrix.os }}${{ matrix['node-version'] }}-pnpm-store-
+ - name: Install dependencies
+ run: pnpm install --frozen-lockfile false
+ - name: Build code
+ run: npm run build
+ - name: Run tests
+ run: npm test
diff --git a/.gitignore b/.gitignore
index 7837156..5bf8d6c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,80 +1,22 @@
-
-# Created by https://www.gitignore.io/api/node
-
-### Node ###
-# Logs
-logs
-*.log
-npm-debug.log*
-yarn-debug.log*
-yarn-error.log*
-
-# Runtime data
-pids
-*.pid
-*.seed
-*.pid.lock
-
-# Directory for instrumented libs generated by jscoverage/JSCover
-lib-cov
-
-# Coverage directory used by tools like istanbul
+# Coverage reports
coverage
-# nyc test coverage
-.nyc_output
-
-# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
-.grunt
-
-# Bower dependency directory (https://bower.io/)
-bower_components
-
-# node-waf configuration
-.lock-wscript
-
-# Compiled binary addons (https://nodejs.org/api/addons.html)
-build/Release
-
-# Dependency directories
-node_modules/
-jspm_packages/
-
-# TypeScript v1 declaration files
-typings/
-
-# Optional npm cache directory
-.npm
-
-# Optional eslint cache
-.eslintcache
-
-# Optional REPL history
-.node_repl_history
-
-# Output of 'npm pack'
-*.tgz
-
-# Yarn Integrity file
-.yarn-integrity
-
-# dotenv environment variables file
+# API keys and secrets
.env
-# parcel-bundler cache (https://parceljs.org/)
-.cache
-
-# next.js build output
-.next
-
-# nuxt.js build output
-.nuxt
+# Dependency directory
+node_modules
-# vuepress build output
-.vuepress/dist
+# Editors
+.idea
+*.iml
-# Serverless directories
-.serverless
+# OS metadata
+.DS_Store
+Thumbs.db
+# Ignore built ts files
+dist/**/*
-# End of https://www.gitignore.io/api/node
+# Ignore Jest directory
+.jest
diff --git a/.prettierrc b/.prettierrc
new file mode 100644
index 0000000..d89eb42
--- /dev/null
+++ b/.prettierrc
@@ -0,0 +1 @@
+semi: true
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..f132aec
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2023 AssemblyAI
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/README.md b/README.md
index 109a313..6d21c13 100644
--- a/README.md
+++ b/README.md
@@ -1,116 +1,225 @@
-## Installing the module:
+
- `npm i assemblyai`
+---
-## Authenticating with the API
+# AssemblyAI Node.js SDK
-### Using Environment Variables
+The AssemblyAI Node.js 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.
-If you have the `ASSEMBLYAI_API_KEY` environment variable set, then the application
-will attempt to read it and use this value to authenticate with the API.
+## Installation
-### Setting the value manually
+You can install the AssemblyAI SDK by running:
-Here is what the code would look like if you were to set the API token manually.
+```bash
+npm install assemblyai
+```
+
+```bash
+yarn add assemblyai
+```
+
+```bash
+pnpm add assemblyai
+```
+
+```bash
+bun add assemblyai
+```
+
+# Usage
+
+Import the AssemblyAI package and create an AssemblyAI object with your API key:
```javascript
-const assemblyai = require('assemblyai')
-assemblyai.setAPIKey("ENTER YOUR KEY HERE")
+import AssemblyAI from "assemblyai";
+
+const client = new AssemblyAI({
+ apiKey: process.env.ASSEMBLYAI_API_KEY,
+})
```
-## Usage
+You can now use the `client` object to interact with the AssemblyAI API.
-### Initialization
+## Create a transcript
-The initialization of the module of course has to be at the beginning of your project.
+When you create a transcript, you can either pass in a URL to an audio file, or upload a file directly.
```javascript
-const assemblyai = require('assemblyai')
-assemblyai.setAPIKey("ENTER YOUR KEY HERE")
+// Using a remote URL
+const transcript = await client.transcripts.create({
+ audio_url: 'https://storage.googleapis.com/aai-web-samples/espn-bears.m4a',
+})
```
-### Upload an audio file for transcription
+```javascript
+// Uploading a file
+const transcript = await client.transcripts.create({
+ audio_url: './news.mp4',
+})
+```
+
+By default, when you create a transcript, it'll be polled until the status is `completed` or `error`.
+You can configure whether to poll, the polling interval, and polling timeout using these options:
```javascript
-async function upload () {
- try {
- const transcript = new assemblyai.Upload('/path/to/audiofile.wav')
- const response = await transcript.create()
- const data = response.get()
-
- // do something with the JSON response
- console.log(data);
-
- } catch (e) {
- // Do some error handling here
- }
-}
+const transcript = await client.transcripts.create({
+ audio_url: 'https://storage.googleapis.com/aai-web-samples/espn-bears.m4a',
+},
+{
+ // Enable or disable polling. Defaults to true.
+ poll: true,
+ // How frequently the transcript is polled in ms. Defaults to 3000.
+ pollingInterval: 1000,
+ // How long to wait in ms until the "Polling timeout" error is thrown. Defaults to 180000.
+ pollingTimeout: 5000,
+})
```
-### Transcribe audio from a URL
+## Get a transcript
-The only required parameter is the `audio_src_url` parameter. For more information about transcribing audio, please see the full API documentation [here](https://docs.assemblyai.com/api/#posttranscript).
+This will return the transcript object in its current state. If the transcript is still processing, the `status` field will be `queued` or `processing`. Once the transcript is complete, the `status` field will be `completed`.
```javascript
-async function transcribe () {
- try {
- const transcript = new assemblyai.Transcript()
- const response = await transcript.create({
- audio_src_url: "https://example.com/example.wav",
- model_id: 123,
- options: {
- format_text: true || false
- }
- })
- const { id } = response.get()
- const data = await transcript.poll(id)
-
- // do something with the response data.
- // `data` is a wrapper of the API's JSON
- // response. `data.get()` returns the JSON
- // response of the API
- var responseJson = data.get();
- console.log(responseJson);
-
- } catch (e) {
- // Do some error handling here
- }
-}
+const transcript = await client.transcripts.get(transcript.id)
```
-### Create a custom model
+## List transcripts
-Boost accuracy for keywords/phrases, and add custom terms to the vocabulary with a custom model. For more information, please see the full API documentation [here](https://docs.assemblyai.com/guides/custom_models_101/).
+This will return a paged list of transcripts that you have transcript.
```javascript
-async function model() {
- try {
- const instance = new assemblyai.Model()
- const response = await instance.create({
- phrases: ['foo', 'bar']
- })
- const { id } = response.get()
- const data = await instance.poll(id)
-
- // do something with the response data.
- // `data` is a wrapper of the API's JSON
- // response. `data.get()` returns the JSON
- // response of the API
- var responseJson = data.get();
- console.log(responseJson);
-
- } catch (e) {
- // Do some error handling
+const page = await client.transcripts.list()
+```
+
+You can also paginate over all pages.
+
+```typescript
+let nextPageUrl: string | null = null;
+do {
+ const page = await client.transcripts.list(nextPageUrl)
+ nextPageUrl = page.page_details.next_url
+} while(nextPageUrl !== null)
+```
+
+## Delete a transcript
+
+```javascript
+const res = await client.transcripts.delete(transcript.id)
+```
+
+## Use LeMUR
+
+Call [LeMUR endpoints](https://www.assemblyai.com/docs/API%20reference/lemur) to summarize, ask questions, generate action items, or run a custom task.
+
+Custom Summary:
+```javascript
+const { response } = await client.lemur.summary({
+ transcript_ids: ['0d295578-8c75-421a-885a-2c487f188927'],
+ answer_format: 'one sentence',
+ context: {
+ speakers: ['Alex', 'Bob'],
}
-}
+})
+```
+
+Question & Answer:
+```javascript
+const { response } = await client.lemur.questionAnswer({
+ transcript_ids: ['0d295578-8c75-421a-885a-2c487f188927'],
+ questions: [
+ {
+ question: 'What are they discussing?',
+ answer_format: 'text',
+ }
+ ]
+})
```
-
-### The Response Object
-When using the `Response` object, you will find a couple of methods:
+Action Items:
+```javascript
+const { response } = await client.lemur.actionItems({
+ transcript_ids: ['0d295578-8c75-421a-885a-2c487f188927'],
+})
+```
+
+Custom Task:
+```javascript
+const { response } = await client.lemur.task({
+ transcript_ids: ['0d295578-8c75-421a-885a-2c487f188927'],
+ prompt: 'Write a haiku about this conversation.',
+})
+```
+
+## Transcribe in real time
+
+Create the real-time service.
+
+```typescript
+const service = client.realtime.createService();
+```
+
+You can also pass in the following options.
+
+```typescript
+const service = client.realtime.createService({
+ realtimeUrl: 'wss://localhost/override',
+ apiKey: process.env.ASSEMBLYAI_API_KEY // The API key passed to `AssemblyAI` will be used by default,
+ sampleRate: 16_000,
+ wordBoost: ['foo', 'bar']
+});
+```
+
+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({
+ token: token
+});
+```
-- `get()`
-- `toString()`
-- `stringify()`
+> [!WARNING]
+> Storing your API key in client-facing applications exposes your API key.
+> Generate a temporary auth token on the server and pass it to your client.
-The method that you will most likely want to use will be `get()` which returns the full JSON object from the API, one level down.
+You can configure the following events.
+
+```typescript
+rt.on("open", ({ sessionId, expiresAt }) => console.log('Session ID:', sessionId, 'Expires at:', expiresAt));
+rt.on("close", (code: number, reason: string) => console.log('Closed', code, reason));
+rt.on("transcript", (transcript: TranscriptMessage) => console.log('Transcript:', transcript));
+rt.on("transcript.partial", (transcript: PartialTranscriptMessage) => console.log('Partial transcript:', transcript));
+rt.on("transcript.final", (transcript: FinalTranscriptMessage) => console.log('Final transcript:', transcript));
+rt.on("error", (error: Error) => console.error('Error', error));
+```
+
+After configuring your events, connect to the server.
+
+```typescript
+await rt.connect();
+```
+
+Send audio data.
+
+```typescript
+// Pseudo code for getting audio
+getAudio((chunk) => {
+ rt.sendAudio(chunk);
+});
+```
+
+Close the connection when you're finished.
+
+```typescript
+rt.close();
+```
+
+# Tests
+
+To run the test suite, first install the dependencies, then run `pnpm test`:
+
+```bash
+pnpm install
+pnpm test
+```
diff --git a/assemblyai.png b/assemblyai.png
new file mode 100644
index 0000000..dca925a
Binary files /dev/null and b/assemblyai.png differ
diff --git a/jest.config.rollup.ts b/jest.config.rollup.ts
new file mode 100644
index 0000000..c5b7901
--- /dev/null
+++ b/jest.config.rollup.ts
@@ -0,0 +1,14 @@
+import type { JestConfigWithTsJest } from "ts-jest";
+
+const jestConfig: JestConfigWithTsJest = {
+ preset: "ts-jest",
+ testEnvironment: "node",
+ collectCoverage: true,
+ moduleNameMapper: {
+ "^@/(.*)$": "/src/$1",
+ },
+};
+
+process.env.TESTDATA_DIR = "tests/static";
+
+export default jestConfig;
diff --git a/package.json b/package.json
index ba521c0..cfb97d6 100644
--- a/package.json
+++ b/package.json
@@ -1,31 +1,68 @@
{
"name": "assemblyai",
- "version": "1.0.1",
- "description": "",
- "main": "index.js",
- "scripts": {
- "test": "echo \"Error: no test specified\" && exit 1"
- },
+ "version": "2.0.0-beta",
+ "description": "The AssemblyAI Node.js 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.",
+ "main": "dist/index.js",
+ "module": "dist/index.esm.js",
+ "types": "dist/index.d.ts",
+ "typings": "dist/index.d.ts",
"repository": {
"type": "git",
- "url": "git+https://github.com/AssemblyAI/assemblyai-node-sdk.git"
+ "url": "git+https://github.com/AssemblyAI/assemblyai-typescript-sdk.git"
},
- "keywords": [],
- "author": "",
- "license": "ISC",
- "bugs": {
- "url": "https://github.com/AssemblyAI/assemblyai-node-sdk/issues"
+ "publishConfig": {
+ "tag": "beta",
+ "access": "public",
+ "registry": "https://registry.npmjs.org/"
},
- "homepage": "https://github.com/AssemblyAI/assemblyai-node-sdk#readme",
- "dependencies": {
- "request": "^2.88.0"
+ "scripts": {
+ "build": "pnpm clean && pnpm rollup -c",
+ "clean": "rimraf dist",
+ "lint": "tslint -p tsconfig.json",
+ "test": "pnpm lint && pnpm test:unit",
+ "test:unit": "jest --config jest.config.rollup.ts",
+ "prettier": "prettier --write 'src/**/*.ts'",
+ "generate-types": "tsx ./scripts/generate-types.ts && pnpm prettier"
},
+ "keywords": [
+ "AssemblyAI",
+ "Speech-to-text"
+ ],
+ "author": "AssemblyAI (https://www.assemblyai.com)",
+ "license": "MIT",
+ "homepage": "https://www.assemblyai.com/docs",
+ "files": [
+ "dist",
+ "src",
+ "types"
+ ],
"devDependencies": {
- "eslint": "^5.4.0",
- "eslint-config-standard": "^11.0.0",
- "eslint-plugin-import": "^2.14.0",
- "eslint-plugin-node": "^7.0.1",
- "eslint-plugin-promise": "^4.0.0",
- "eslint-plugin-standard": "^3.1.0"
+ "@types/jest": "^29.5.5",
+ "@types/node": "^20.5.7",
+ "@types/ws": "^8.5.5",
+ "dotenv": "^16.3.1",
+ "eslint": "^8.43.0",
+ "i": "^0.3.7",
+ "jest": "^29.5.0",
+ "jest-cli": "^29.5.0",
+ "jest-junit": "^16.0.0",
+ "jest-mock-extended": "^3.0.4",
+ "jest-websocket-mock": "^2.4.1",
+ "mock-socket": "^9.2.1",
+ "npm": "^9.7.1",
+ "openapi-typescript": "^6.6.1",
+ "prettier": "^2.8.8",
+ "rimraf": "^5.0.1",
+ "rollup": "^3.25.1",
+ "rollup-plugin-typescript2": "^0.34.1",
+ "ts-jest": "^29.1.0",
+ "ts-node": "^10.9.1",
+ "tslib": "^2.5.3",
+ "tslint": "^6.1.3",
+ "typescript": "^5.2.2"
+ },
+ "dependencies": {
+ "axios": "^1.4.0",
+ "ws": "^8.13.0"
}
}
diff --git a/rollup.config.js b/rollup.config.js
new file mode 100644
index 0000000..0060484
--- /dev/null
+++ b/rollup.config.js
@@ -0,0 +1,20 @@
+const pkg = require('./package.json')
+const ts = require('rollup-plugin-typescript2')
+
+const plugins = [
+ ts({
+ tsconfigOverride: { exclude: ['**/*.test.ts'] },
+ }),
+]
+
+module.exports = [
+ {
+ input: 'src/index.ts',
+ output: [
+ { file: pkg.main, format: 'cjs' },
+ { file: pkg.module, format: 'es' }
+ ],
+ plugins,
+ external: ['axios', 'fs/promises', 'ws']
+ },
+]
diff --git a/scripts/generate-types.ts b/scripts/generate-types.ts
new file mode 100644
index 0000000..22a2495
--- /dev/null
+++ b/scripts/generate-types.ts
@@ -0,0 +1,59 @@
+import openapiTS from "openapi-typescript";
+import fs from 'fs'
+
+async function generateTypes(apiSpecPath: string, outputPath: string) {
+ const localPath = new URL(apiSpecPath, import.meta.url);
+ let output = await openapiTS(localPath,
+ {
+ alphabetize: true,
+ exportType: true,
+ transform(schemaObject, metadata) {
+ 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";
+ }
+ }
+ });
+ const schemasPosition = output.indexOf('schemas: {') + 10;
+ output = output
+ // Remove everything before and after the schemas, as we're only interested in schemas.
+ .substring(schemasPosition, output.indexOf('\n };\n responses', schemasPosition))
+ // Turn components["schemas"]["{TYPE_NAME}"] into TYPE_NAME
+ .replace(/components\[\"schemas\"]\[\"(\w*)\"\]/gm, "$1")
+ .split('\n')
+ // De-indent everything by 4
+ .map(l => l.substring(4))
+ .map(l => {
+ if (l.trim() === '' || l.startsWith(' ') || l.startsWith('/')) return l;
+ // Add newlines after each type
+ if (l.endsWith(';')) l += "\n";
+ // Replace `{TYPE_NAME}: ` with `export type {TYPE_NAME} = ` for each type
+ l = l.replace(/(?!\s)(.*): /, "export type $1 = ")
+ return l;
+ })
+ .join('\n');
+
+ // Add file header
+ output = `// this file is generated by typescript/scripts/generate-types.ts
+/* tslint:disable */
+/* eslint-disable */
+
+/** OneOf type helpers */
+type Without = { [P in Exclude]?: never };
+type XOR = (T | U) extends object ? (Without & U) | (Without & T) : T | U;
+type OneOf = T extends [infer Only] ? Only : T extends [infer A, infer B, ...infer Rest] ? OneOf<[XOR, ...Rest]> : never;
+` + output;
+
+ fs.writeFileSync(outputPath, output)
+}
+
+generateTypes(
+ '../../spec/openapi.yml',
+ './src/types/openapi.generated.ts'
+)
+generateTypes(
+ '../../spec/asyncapi.yml',
+ './src/types/asyncapi.generated.ts'
+)
diff --git a/scripts/kitchensink.ts b/scripts/kitchensink.ts
new file mode 100644
index 0000000..fab1f45
--- /dev/null
+++ b/scripts/kitchensink.ts
@@ -0,0 +1,340 @@
+import { createReadStream } from 'fs'
+import 'dotenv/config'
+import AssemblyAI, { Transcript, CreateTranscriptParameters } from '../src/index';
+import { FinalTranscript, PartialTranscript, RealtimeTranscript } from '../src/types'
+
+const client = new AssemblyAI({
+ apiKey: process.env.ASSEMBLYAI_API_KEY || '',
+});
+
+(async function transcribeUsingRealtime() {
+ const useToken = false;
+ const serviceParams: any = {
+ sample_rate: 16_000,
+ word_boost: ['gore', 'climate']
+ };
+ if (useToken) {
+ serviceParams.token = await client.realtime.createTemporaryToken({ expires_in: 480 });
+ }
+ const rt = client.realtime.createService(serviceParams);
+
+ rt.on("open", ({ sessionId, expiresAt }) => {
+ console.log('Session ID:', sessionId, 'Expires At:', expiresAt);
+ });
+ rt.on("close", (code: number, reason: string) => console.log('Closed', code, reason))
+ rt.on("transcript", (transcript: RealtimeTranscript) => console.log('Transcript:', transcript));
+ rt.on("transcript.partial", (transcript: PartialTranscript) => console.log('Transcript:', transcript));
+ rt.on("transcript.final", (transcript: FinalTranscript) => console.log('Transcript:', transcript));
+ rt.on("error", (error: Error) => console.error('Error', error));
+
+
+ try {
+ await rt.connect();
+
+ const chunkSize = 8 * 1024;
+ const audio = createReadStream(
+ './tests/static/gore-short.wav',
+ { highWaterMark: chunkSize }
+ );
+ for await (const chunk of audio) {
+ if (chunk.length < chunkSize) continue;
+ rt.sendAudio(chunk);
+ await new Promise((resolve) =>
+ setTimeout(resolve, 300)
+ );
+ }
+ console.log('File end')
+
+ await rt.close();
+ } catch (error) {
+ console.error(error);
+ }
+})();
+
+const audioUrl = 'https://storage.googleapis.com/aai-docs-samples/espn.m4a';
+const createTranscriptParams: CreateTranscriptParameters = {
+ audio_url: audioUrl,
+ boost_param: 'high',
+ word_boost: ['Chicago', 'draft'],
+ disfluencies: true,
+ dual_channel: true,
+ format_text: false,
+ language_code: 'en',
+ punctuate: false,
+ speech_threshold: 0.5,
+};
+
+(async function createStandardTranscript() {
+ const transcript = await client.transcripts.create(createTranscriptParams);
+ console.log(transcript);
+ return transcript;
+})()
+ .then(async (transcript) => {
+ await exportAsSubtitles(transcript);
+ await getParagraphs(transcript);
+ await getSentences(transcript);
+ await searchTranscript(transcript);
+ await deleteTranscript(transcript);
+ });
+
+(async function runLemurModels() {
+ const transcript = await client.transcripts.create(createTranscriptParams);
+ await lemurSummary(transcript);
+ await lemurQuestionAnswer(transcript);
+ await lemurActionPoints(transcript);
+ await lemurCustomTask(transcript);
+ await deleteTranscript(transcript);
+})();
+
+(async function createTranscriptWithBadUrl() {
+ const transcript = await client.transcripts.create({
+ audio_url: 'https://storage.googleapis.com/api-docs-samples/oops.m4a'
+ });
+ console.log(transcript);
+ return transcript;
+})().then(async (transcript) => {
+ try {
+ await getParagraphs(transcript);
+ console.error("Error expected but not thrown.");
+ } catch (error) {
+ console.log("Error expected:", error.toString());
+ await deleteTranscript(transcript);
+ }
+});
+
+(async function createTranscriptWithNullUrl() {
+ try {
+ await client.transcripts.create({
+ audio_url: null as unknown as string
+ });
+ console.error("Error expected but not thrown.");
+ } catch (error) {
+ console.log("Error expected:", error.toString());
+ }
+})();
+
+(async function createTranscriptWithword_boost() {
+ const transcript = await client.transcripts.create({
+ ...createTranscriptParams,
+ boost_param: 'high',
+ word_boost: ['knee', 'hip'],
+ });
+ console.log(transcript);
+ return transcript;
+})().then(deleteTranscript);
+
+(async function createTranscriptWithSummarization() {
+ const transcript = await client.transcripts.create({
+ ...createTranscriptParams,
+ summarization: true,
+ summary_model: 'conversational',
+ summary_type: 'bullets_verbose',
+ punctuate: true,
+ format_text: true
+ })
+ console.log(transcript);
+ return transcript;
+})().then(deleteTranscript);
+
+(async function createTranscriptWithContentSafety() {
+ const transcript = await client.transcripts.create({
+ ...createTranscriptParams,
+ content_safety: true,
+ })
+ console.log(transcript);
+ return transcript;
+})().then(deleteTranscript);
+
+(async function createTranscriptWithCustomSpelling() {
+ const transcript = await client.transcripts.create({
+ ...createTranscriptParams,
+ custom_spelling: [
+ { from: ['quarterback', 'QB'], to: 'nickelback' },
+ { from: ['bear'], to: 'cub' },
+ ]
+ })
+ console.log(transcript);
+ return transcript;
+})().then(deleteTranscript);
+
+(async function createTranscriptWithEntityDetection() {
+ const transcript = await client.transcripts.create({
+ ...createTranscriptParams,
+ entity_detection: true,
+ })
+ console.log(transcript);
+ return transcript;
+})().then(deleteTranscript);
+
+(async function createTranscriptWithFilterProfanity() {
+ const transcript = await client.transcripts.create({
+ ...createTranscriptParams,
+ filter_profanity: true,
+ })
+ console.log(transcript);
+ return transcript;
+})().then(deleteTranscript);
+
+(async function createTranscriptWithTopicDetection() {
+ const transcript = await client.transcripts.create({
+ ...createTranscriptParams,
+ iab_categories: true
+ })
+ console.log(transcript);
+ return transcript;
+})().then(deleteTranscript);
+
+(async function createTranscriptWithLanguageDetection() {
+ const transcript = await client.transcripts.create({
+ ...createTranscriptParams,
+ language_code: undefined,
+ language_detection: true
+ })
+ console.log(transcript);
+ return transcript;
+})().then(deleteTranscript);
+
+(async function createTranscriptWithPiiRedaction() {
+ const transcript = await client.transcripts.create({
+ ...createTranscriptParams,
+ format_text: true,
+ redact_pii: true,
+ redact_pii_audio: true,
+ redact_pii_audio_quality: 'wav',
+ redact_pii_policies: [
+ 'injury',
+ 'medical_condition',
+ 'medical_process'
+ ],
+ redact_pii_sub: 'hash',
+ })
+ console.log(transcript);
+ return transcript;
+})().then(deleteTranscript);
+
+(async function createTranscriptWithSentimentAnalysis() {
+ const transcript = await client.transcripts.create({
+ ...createTranscriptParams,
+ punctuate: true,
+ sentiment_analysis: true,
+ })
+ console.log(transcript);
+ return transcript;
+})().then(deleteTranscript);
+
+(async function createTranscriptWithSpeakerLabels() {
+ const transcript = await client.transcripts.create({
+ ...createTranscriptParams,
+ dual_channel: false,
+ punctuate: true,
+ speaker_labels: true,
+ speakers_expected: 2,
+ })
+ console.log(transcript);
+ return transcript;
+})().then(deleteTranscript);
+
+(async function createTranscriptWithWebhook() {
+ const transcript = await client.transcripts.create({
+ ...createTranscriptParams,
+ webhook_auth_header_name: 'x-foo',
+ webhook_auth_header_value: 'bar',
+ webhook_url: 'https://www.assemblyai.com/404'
+ })
+ console.log(transcript);
+ return transcript;
+})().then(deleteTranscript);
+
+(async function listTranscripts() {
+ let nextPageUrl: string | null = null;
+ do {
+ const page = await client.transcripts.list(nextPageUrl)
+ console.log(page);
+ nextPageUrl = page.page_details.next_url;
+ } while (nextPageUrl !== null)
+})();
+
+async function searchTranscript(transcript: Transcript) {
+ console.error('Search is not yet implemented');
+ // const result = await client.transcripts.search(transcript.id, {
+ // words: ['draft', 'football']
+ // });
+ // console.log(result);
+}
+
+async function exportAsSubtitles(transcript: Transcript) {
+ const srt = await client.transcripts.subtitles(transcript.id, 'srt')
+ const vtt = await client.transcripts.subtitles(transcript.id, 'vtt')
+ console.log('SRT subtitles', srt);
+ console.log('VTT subtitles', vtt);
+}
+
+async function getParagraphs(transcript: Transcript) {
+ const paragraphs = await client.transcripts.paragraphs(transcript.id)
+ console.dir(paragraphs, { depth: null });
+}
+
+async function getSentences(transcript: Transcript) {
+ const sentences = await client.transcripts.sentences(transcript.id)
+ console.dir(sentences, { depth: null });
+}
+
+async function deleteTranscript(transcript: Transcript) {
+ await client.transcripts.delete(transcript.id);
+}
+
+const lemurContext = 'This is a podcast on the ESPN channel talking about NFL draft picks.';
+
+async function lemurSummary(transcript: Transcript) {
+ const response = await client.lemur.summary({
+ transcript_ids: [transcript.id],
+ context: lemurContext,
+ final_model: 'basic',
+ max_output_size: 3000,
+ answer_format: 'bullet points'
+ })
+ console.log(response.response);
+}
+
+async function lemurQuestionAnswer(transcript: Transcript) {
+ const response = await client.lemur.questionAnswer({
+ transcript_ids: [transcript.id],
+ questions: [
+ {
+ question: 'Which players were mentioned?',
+ context: lemurContext,
+ answer_format: ' ',
+ },
+ {
+ question: 'Were they excited',
+ context: lemurContext,
+ answer_options: ['yes', 'no']
+ }
+ ],
+ context: lemurContext,
+ final_model: 'basic',
+ max_output_size: 3000
+ })
+ console.log(response.response);
+}
+
+async function lemurActionPoints(transcript: Transcript) {
+ const response = await client.lemur.actionItems({
+ transcript_ids: [transcript.id],
+ context: lemurContext,
+ final_model: 'basic',
+ max_output_size: 3000
+ })
+ console.log(response.response);
+}
+
+async function lemurCustomTask(transcript: Transcript) {
+ const response = await client.lemur.task({
+ transcript_ids: [transcript.id],
+ prompt: 'List all the teams and their players that are mentioned.',
+ context: lemurContext,
+ final_model: 'basic',
+ max_output_size: 3000
+ })
+ console.log(response.response);
+}
diff --git a/src/Client.js b/src/Client.js
deleted file mode 100644
index cd96dcb..0000000
--- a/src/Client.js
+++ /dev/null
@@ -1,28 +0,0 @@
-let _apiKey = ''
-
-class Client {
- static set API_KEY (key) {
- _apiKey = key
- }
-
- static get API_KEY () {
- return _apiKey
- }
-
- static checkKey () {
- if (process.env.ASSEMBLYAI_API_KEY) {
- _apiKey = process.env.ASSEMBLYAI_API_KEY
- }
- if (!_apiKey) {
- throw new Error(`
- Unable to find the API Key.
- You can set this value by using the setAPIKey method.
- Example: """ const assemblyai = require('assemblyai')
- assemblyai.setAPIKey('example') """
- `)
- }
- return true
- }
-}
-
-module.exports = Client
diff --git a/src/api/Http/Request.js b/src/api/Http/Request.js
deleted file mode 100644
index f3c60b7..0000000
--- a/src/api/Http/Request.js
+++ /dev/null
@@ -1,108 +0,0 @@
-const request = require('request')
-const Client = require('../../Client')
-
-class Request {
- /**
- * Initializes the class
- * @param {Object} options The HTTP Options
- * @param {String} options.method The HTTP Method
- * @param {String} options.url THE HTTP URL
- * @param {Object} options.body optional HTTP Body
- */
- constructor (options) {
- this.method = options.method || 'GET'
- this.url = options.url || ''
- this.body = options.body || ''
- }
-
- /**
- * Sends an HTTP request using the node HTTP module
- *
- * @returns {Promise