Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# Changelog

## [4.41.8]

- Add `speakers` to `SpeakerIdentificationRequest` and export `SpeakerDescription` — enables passing rich speaker metadata (`name`, `role`, `description`) for speaker identification in Speech Understanding
- Add `force_translation` to `TranslationRequest` — enables translating audio even when the detected source language equals a target language
- Add `format_utterances` to `CustomFormattingRequest` — enables applying custom formatting at the utterance level

## [4.41.7]

- Add `summarization` to the speech understanding feature requests and responses (`SummarizationRequest`, `SummarizationResponse`): `summary_type`, `headline_length`, `approximate_chapters` and `effort`. The feature was already accepted by the API but missing from the SDK types, so setting it failed to type check
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "assemblyai",
"version": "4.41.7",
"version": "4.41.8",
"description": "The AssemblyAI JavaScript SDK provides an easy-to-use interface for interacting with the AssemblyAI API, which supports async and real-time transcription.",
"engines": {
"node": ">=18"
Expand Down
37 changes: 36 additions & 1 deletion src/types/openapi.generated.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1052,6 +1052,25 @@ export type SpeakerType = "role" | "name";
*/
export type SpeechUnderstandingEffort = "low" | "medium";

/**
* Speaker description for speaker identification with rich metadata
*/
export type SpeakerDescription = {
/**
* Speaker name (when speaker_type is 'name')
*/
name?: string;
/**
* Speaker role (when speaker_type is 'role')
*/
role?: string;
/**
* Description of the speaker's role or characteristics in the audio
*/
description?: string;
[key: string]: unknown;
};

/**
* Speaker identification configuration for speech understanding
*/
Expand All @@ -1061,9 +1080,13 @@ export type SpeakerIdentificationRequest = {
*/
speaker_type: SpeakerType;
/**
* Known speaker values (required when speaker_type is 'role')
* Known speaker values (required when speaker_type is 'role' if speakers is not provided)
*/
known_values?: string[];
/**
* Rich speaker metadata per speaker. Each entry should have name (when speaker_type is 'name') or role (when speaker_type is 'role').
*/
speakers?: SpeakerDescription[];
/**
* How much effort to spend on this task
*
Expand All @@ -1088,6 +1111,12 @@ export type TranslationRequest = {
* Whether to match the original utterance structure in translations (default: false)
*/
match_original_utterance?: boolean;
/**
* Whether to translate even when the detected source language equals a target language
*
* @defaultValue false
*/
force_translation?: boolean;
/**
* How much effort to spend on this task
*
Expand All @@ -1112,6 +1141,12 @@ export type CustomFormattingRequest = {
* Custom email format pattern (e.g., 'username\@domain.com')
*/
email?: string;
/**
* Whether to also format utterance-level text
*
* @defaultValue false
*/
format_utterances?: boolean;
/**
* How much effort to spend on this task
*
Expand Down
87 changes: 87 additions & 0 deletions tests/unit/speech-understanding-effort.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import fetchMock from "jest-fetch-mock";
import {
CustomFormattingRequest,
SpeakerDescription,
SpeakerIdentificationRequest,
SpeechUnderstandingEffort,
TranslationRequest,
Expand Down Expand Up @@ -125,6 +126,92 @@ describe("speech understanding effort", () => {
expect(speakerIdentification.effort).toBeUndefined();
});

it("should create transcript with speaker_identification speakers list", async () => {
const speakers: SpeakerDescription[] = [
{ name: "Alice", description: "Host of the podcast" },
{ name: "Bob", description: "Featured guest discussing AI", title: "Dr." },
];
const speakerIdentification: SpeakerIdentificationRequest = {
speaker_type: "name",
speakers,
effort: "medium",
};
mockSubmit();

const transcript = await assembly.transcripts.submit({
audio_url: remoteAudioURL,
speaker_labels: true,
speech_understanding: {
request: { speaker_identification: speakerIdentification },
},
});

expect(transcript.id).toBe(transcriptId);
expect(submittedRequest().speaker_identification).toEqual(speakerIdentification);
expect(submittedRequest().speaker_identification.speakers).toEqual(speakers);
});

it("should create transcript with speaker_identification speakers by role", async () => {
const speakers: SpeakerDescription[] = [
{ role: "Agent", description: "Customer support specialist" },
{ role: "Customer", description: "Account owner inquiring about billing" },
];
const speakerIdentification: SpeakerIdentificationRequest = {
speaker_type: "role",
speakers,
};
mockSubmit();

await assembly.transcripts.submit({
audio_url: remoteAudioURL,
speaker_labels: true,
speech_understanding: {
request: { speaker_identification: speakerIdentification },
},
});

expect(submittedRequest().speaker_identification.speaker_type).toBe("role");
expect(submittedRequest().speaker_identification.speakers).toEqual(speakers);
expect(submittedRequest().speaker_identification.known_values).toBeUndefined();
});

it("should create transcript with translation force_translation", async () => {
const translation: TranslationRequest = {
target_languages: ["es", "fr"],
force_translation: true,
effort: "medium",
};
mockSubmit();

await assembly.transcripts.submit({
audio_url: remoteAudioURL,
speech_understanding: { request: { translation } },
});

expect(submittedRequest().translation).toEqual(translation);
expect(submittedRequest().translation.force_translation).toBe(true);
});

it("should create transcript with custom_formatting format_utterances", async () => {
const customFormatting: CustomFormattingRequest = {
date: "mm/dd/yyyy",
phone_number: "(xxx)xxx-xxxx",
format_utterances: true,
effort: "medium",
};
mockSubmit();

await assembly.transcripts.submit({
audio_url: remoteAudioURL,
speech_understanding: {
request: { custom_formatting: customFormatting },
},
});

expect(submittedRequest().custom_formatting).toEqual(customFormatting);
expect(submittedRequest().custom_formatting.format_utterances).toBe(true);
});

it("should accept every documented effort value", () => {
const efforts: SpeechUnderstandingEffort[] = ["low", "medium"];

Expand Down