From 23f68ef6bd82997e7aef731ff597dcb139475854 Mon Sep 17 00:00:00 2001 From: pylrn Date: Tue, 20 Oct 2026 00:31:57 +0530 Subject: [PATCH] feat(types): add speakers, force_translation, and format_utterances to speech understanding --- CHANGELOG.md | 6 ++ src/types/openapi.generated.ts | 37 +++++++- .../unit/speech-understanding-effort.test.ts | 87 +++++++++++++++++++ 3 files changed, 129 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e1a167a..aeaef5e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog +## [4.41.7] + +- 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.6] - Add `rewrite_mode` to `DictationConfig` — the model tier that runs the dictation rewrite: `"fast"` (the server default) or `"smart"`, which follows detailed formatting instructions more reliably at higher latency. Unset, it is not sent. The `DictationRewriteMode` type is exported from the package root diff --git a/src/types/openapi.generated.ts b/src/types/openapi.generated.ts index 307d64f..c5fa278 100644 --- a/src/types/openapi.generated.ts +++ b/src/types/openapi.generated.ts @@ -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 */ @@ -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 * @@ -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 * @@ -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 * diff --git a/tests/unit/speech-understanding-effort.test.ts b/tests/unit/speech-understanding-effort.test.ts index 1a11806..08df0c9 100644 --- a/tests/unit/speech-understanding-effort.test.ts +++ b/tests/unit/speech-understanding-effort.test.ts @@ -1,6 +1,7 @@ import fetchMock from "jest-fetch-mock"; import { CustomFormattingRequest, + SpeakerDescription, SpeakerIdentificationRequest, SpeechUnderstandingEffort, TranslationRequest, @@ -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"];