@breeze.blue/sdk 0.21.0 → 0.22.0

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 CHANGED
@@ -1,5 +1,20 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.22.0
4
+
5
+ - Select PCM or MP3 for realtime TTS sessions and preserve the format across managed connections.
6
+ - Export output-format choices shared with the public API while retaining historical conversion profiles.
7
+ - Breaking: remove `visibility` and `primaryCategoryCode` from `voices.savePreview(...)` and `voices.edit(...)`, and remove reference-sample upload arguments from `voices.edit(...)`.
8
+ - Keep official catalog assignment, publication and reference-sample replacement available through authorized low-level HTTP requests or the CLI. Category search and Clone uploads remain available.
9
+ - Voice Clone accepts `referenceLanguageCode: "zh"` to use Qwen ASR for a Chinese reference sample. Omitting it keeps automatic language detection.
10
+ - Check complete Voice and History request fields against public OpenAPI with a shared, operation-specific historical compatibility whitelist.
11
+
12
+ ## 0.21.1
13
+
14
+ - Document Voice Design guidance: omitted or null samples 1–4 per preview; explicit values still accept 1–10.
15
+
16
+ - Clarify speaker boost docs: instructions are always applied; boost is ignored with non-empty instructions and guidance above 1, otherwise guidance is applied as 1. Realtime needs a new session to add instructions only when boost applies with requested guidance above 1.
17
+
3
18
  ## 0.21.0
4
19
 
5
20
  - Support request-scoped speaker boost across HTTP and realtime TTS, with performance instructions taking priority when guidance exceeds 1.
package/README.md CHANGED
@@ -7,7 +7,7 @@ models, and account usage.
7
7
  The root entrypoint is safe to import in Node, browser, and edge runtimes. Local
8
8
  audio playback helpers live in the Node-only `@breeze.blue/sdk/node` subpath.
9
9
 
10
- Guidance accepts 1–10; when omitted, the default 1 is used. HTTP speed and volume are per request and default to 1. Use `voiceSettings: { useSpeakerBoost: true }` for closer similarity to the reference voice (default false): it is ignored with non-empty instructions and guidance above 1, and otherwise instructions are not used. Realtime fixes boost at session creation; create a new session to change instructions while boost applies. Pass `removeBackgroundNoise: true` to denoise a clone sample (default false).
10
+ TTS guidance accepts 1–10; when omitted, the default 1 is used. Voice Design accepts 1–10; omitting guidance or passing null samples uniformly between 1–4 for each preview, rounded to one decimal place. HTTP speed and volume are per request and default to 1. Use `voiceSettings: { useSpeakerBoost: true }` for closer similarity to the reference voice (default false): it is ignored with non-empty instructions and guidance above 1, otherwise guidance is applied as 1; instructions are always applied. Realtime fixes boost at session creation; when boost applies with requested guidance above 1, create a new session to add instructions. Pass `removeBackgroundNoise: true` to denoise a clone sample (default false).
11
11
 
12
12
  ## Install
13
13
 
@@ -107,8 +107,10 @@ If the job is still active, `downloadAudio(...)` rejects with
107
107
  `BreezeBlueGenerationNotReadyError`; read `error.retryAfter` before retrying.
108
108
 
109
109
  Use realtime text-to-speech when one WebSocket connection should handle multiple
110
- conversation turns. Realtime audio is fixed to raw `pcm_s16le`, 24000 Hz, mono,
111
- 16-bit frames.
110
+ conversation turns. Realtime supports PCM (default) or MP3 at 24 kHz mono.
111
+ PCM uses raw signed 16-bit little-endian samples. Pass `outputFormat: "mp3"` to
112
+ `realtime.createSession`, `realtime.connect`, or `realtime.connectManaged` to select MP3.
113
+ Each turn's final MP3 bytes arrive before `turn.done`.
112
114
 
113
115
  Realtime needs a `WebSocket` implementation. Browsers, edge runtimes, and
114
116
  Node 22+ provide a global one; on Node 20, pass a constructor (for example the
@@ -396,8 +398,7 @@ Streaming text-to-speech defaults to `pcm` to reduce time to first audio. Pass
396
398
  format explicitly.
397
399
 
398
400
  Sync and async text-to-speech also take a sample rate and, for the lossy encodings, a bitrate, such as
399
- `{ outputFormat: "wav_48000" }`. Breeze resamples its native 24000 Hz output for
400
- downstream compatibility; profiles carrying a sample rate are not available for streaming.
401
+ `{ outputFormat: "wav_24000" }`. Profiles carrying a sample rate apply to sync and async conversion; streaming uses bare encoding names.
401
402
 
402
403
  ## Voices
403
404
 
@@ -564,7 +565,9 @@ const saved = await client.voices.savePreview({
564
565
  });
565
566
  ```
566
567
 
567
- Edit or delete a saved voice:
568
+ Saved previews are private to your account. Editing a voice's metadata preserves its visibility.
569
+
570
+ Edit a saved voice's name, description, tags, or Voice Metadata, or delete it:
568
571
 
569
572
  ```ts
570
573
  await client.voices.edit(saved.voiceId, {
package/dist/client.js CHANGED
@@ -163,6 +163,7 @@ class RealtimeTextToSpeechResource {
163
163
  voiceSettings: request.voiceSettings == null ? request.voiceSettings : { guidanceScale: request.voiceSettings.guidanceScale, useSpeakerBoost: request.voiceSettings.useSpeakerBoost },
164
164
  inactivityTimeoutSeconds: request.inactivityTimeoutSeconds,
165
165
  enableLogging: request.enableLogging,
166
+ outputFormat: request.outputFormat,
166
167
  }, options);
167
168
  }
168
169
  async connect(voiceId, options = {}) {
@@ -170,7 +171,7 @@ class RealtimeTextToSpeechResource {
170
171
  options.websocketUrl !== undefined ||
171
172
  options.directWebsocketUrl !== undefined) && hasRealtimeSessionParams(options)) {
172
173
  console.warn("@breeze.blue/sdk: realtime.connect ignores modelId, languageCode, instructions, voiceSettings, " +
173
- "inactivityTimeoutSeconds, and enableLogging when session credentials are provided. " +
174
+ "inactivityTimeoutSeconds, outputFormat, and enableLogging when session credentials are provided. " +
174
175
  "Configure these initial values when creating the realtime session instead. " +
175
176
  "To change instructions between turns, call connection.updateInstructions() and wait for session.updated.");
176
177
  }
@@ -185,6 +186,7 @@ class RealtimeTextToSpeechResource {
185
186
  voiceSettings: options.voiceSettings,
186
187
  inactivityTimeoutSeconds: options.inactivityTimeoutSeconds,
187
188
  enableLogging: options.enableLogging,
189
+ outputFormat: options.outputFormat,
188
190
  }, {
189
191
  signal: options.signal,
190
192
  timeout: options.timeout,
@@ -226,7 +228,7 @@ class RealtimeTextToSpeechResource {
226
228
  async connectManaged(voiceId, options = {}) {
227
229
  if (options.sessionFactory !== undefined && hasRealtimeSessionParams(options)) {
228
230
  console.warn("@breeze.blue/sdk: realtime.connectManaged cannot apply modelId, languageCode, instructions, " +
229
- "voiceSettings, inactivityTimeoutSeconds, or enableLogging when sessionFactory is provided. " +
231
+ "voiceSettings, inactivityTimeoutSeconds, outputFormat, or enableLogging when sessionFactory is provided. " +
230
232
  "Configure these when the factory creates each realtime session. After connecting, confirmed " +
231
233
  "updateInstructions() values are carried across managed physical sessions.");
232
234
  }
@@ -237,6 +239,7 @@ class RealtimeTextToSpeechResource {
237
239
  voiceSettings: options.voiceSettings,
238
240
  inactivityTimeoutSeconds: options.inactivityTimeoutSeconds,
239
241
  enableLogging: options.enableLogging,
242
+ outputFormat: options.outputFormat,
240
243
  };
241
244
  const connectionTimeout = options.timeout ?? this.client.timeout ?? DEFAULT_REALTIME_HANDSHAKE_TIMEOUT_MS;
242
245
  const createConnection = async (signal) => {
@@ -272,7 +275,8 @@ function hasRealtimeSessionParams(options) {
272
275
  options.instructions !== undefined ||
273
276
  options.voiceSettings !== undefined ||
274
277
  options.inactivityTimeoutSeconds !== undefined ||
275
- options.enableLogging !== undefined);
278
+ options.enableLogging !== undefined ||
279
+ options.outputFormat !== undefined);
276
280
  }
277
281
  function realtimeClientSecretSubprotocols(clientSecret) {
278
282
  if (!/^[A-Za-z0-9_-]+\.[A-Za-z0-9_-]{43}$/.test(clientSecret)) {
@@ -1634,8 +1638,6 @@ class VoicesResource {
1634
1638
  voiceName: request.voiceName,
1635
1639
  voiceDescription: request.voiceDescription,
1636
1640
  tags: request.tags,
1637
- primaryCategoryCode: request.primaryCategoryCode,
1638
- visibility: request.visibility,
1639
1641
  languageCode: request.languageCode,
1640
1642
  gender: request.gender,
1641
1643
  age: request.age,
@@ -1789,6 +1791,7 @@ function clonePreviewForm(request) {
1789
1791
  const form = new FormData();
1790
1792
  appendOptional(form, "name", request.name ?? undefined);
1791
1793
  appendOptional(form, "description", request.description);
1794
+ appendOptional(form, "reference_language_code", request.referenceLanguageCode);
1792
1795
  appendOptional(form, "remove_background_noise", request.removeBackgroundNoise ?? false);
1793
1796
  for (const file of normalizeFiles(request.file, request.files, { required: true })) {
1794
1797
  appendFile(form, "files", file);
@@ -1803,8 +1806,6 @@ function voiceEditForm(request) {
1803
1806
  for (const tag of request.tags)
1804
1807
  form.append("tags", tag);
1805
1808
  }
1806
- appendOptional(form, "primary_category_code", request.primaryCategoryCode);
1807
- appendOptional(form, "visibility", request.visibility);
1808
1809
  appendOptional(form, "language_code", request.languageCode);
1809
1810
  appendNullable(form, "gender", request.gender);
1810
1811
  appendNullable(form, "age", request.age);
@@ -1818,9 +1819,6 @@ function voiceEditForm(request) {
1818
1819
  }
1819
1820
  }
1820
1821
  appendNullable(form, "accent", request.accent);
1821
- for (const file of normalizeFiles(request.file, request.files, { required: false })) {
1822
- appendFile(form, "files", file);
1823
- }
1824
1822
  return form;
1825
1823
  }
1826
1824
  function stripHiddenVoiceFields(voice) {
package/dist/index.d.ts CHANGED
@@ -8,3 +8,4 @@ export { SpeechTimingStream } from "./timestamps.js";
8
8
  export type { SpeechTimingChunk, SpeechWithTimestamps, WordTimestamp } from "./timestamps.js";
9
9
  export * from "./studio.js";
10
10
  export type * from "./studio-types.js";
11
+ export * from "./output-formats.js";
package/dist/index.js CHANGED
@@ -5,3 +5,4 @@ export { SDK_NAME, SDK_VERSION } from "./version.js";
5
5
  export * from "./voice-metadata.js";
6
6
  export { SpeechTimingStream } from "./timestamps.js";
7
7
  export * from "./studio.js";
8
+ export * from "./output-formats.js";
@@ -0,0 +1,10 @@
1
+ export declare const AUDIO_ENCODINGS: readonly ["mp3", "wav", "flac", "pcm", "aac", "opus"];
2
+ export declare const TTS_OUTPUT_FORMATS: readonly ["mp3", "wav", "flac", "pcm", "aac", "opus", "mp3_24000_64", "mp3_24000_96", "mp3_24000_128", "mp3_24000_160", "wav_24000", "pcm_24000", "flac_24000", "aac_24000_128"];
3
+ export declare const STREAMING_OUTPUT_FORMATS: readonly ["pcm", "mp3", "wav"];
4
+ export declare const REALTIME_OUTPUT_FORMATS: readonly ["pcm", "mp3"];
5
+ export type TtsOutputFormat = typeof TTS_OUTPUT_FORMATS[number] | (string & {});
6
+ export type StreamingOutputFormat = typeof STREAMING_OUTPUT_FORMATS[number];
7
+ export type RealtimeOutputFormat = typeof REALTIME_OUTPUT_FORMATS[number];
8
+ export declare const DEFAULT_TTS_OUTPUT_FORMAT = "mp3";
9
+ export declare const DEFAULT_STREAM_OUTPUT_FORMAT = "pcm";
10
+ export declare const DEFAULT_REALTIME_OUTPUT_FORMAT = "pcm";
@@ -0,0 +1,8 @@
1
+ // Generated from generation_runtime.output_formats; do not edit by hand.
2
+ export const AUDIO_ENCODINGS = ["mp3", "wav", "flac", "pcm", "aac", "opus"];
3
+ export const TTS_OUTPUT_FORMATS = ["mp3", "wav", "flac", "pcm", "aac", "opus", "mp3_24000_64", "mp3_24000_96", "mp3_24000_128", "mp3_24000_160", "wav_24000", "pcm_24000", "flac_24000", "aac_24000_128"];
4
+ export const STREAMING_OUTPUT_FORMATS = ["pcm", "mp3", "wav"];
5
+ export const REALTIME_OUTPUT_FORMATS = ["pcm", "mp3"];
6
+ export const DEFAULT_TTS_OUTPUT_FORMAT = "mp3";
7
+ export const DEFAULT_STREAM_OUTPUT_FORMAT = "pcm";
8
+ export const DEFAULT_REALTIME_OUTPUT_FORMAT = "pcm";
package/dist/types.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import type { TtsOutputFormat, RealtimeOutputFormat } from "./output-formats.js";
1
2
  import type { WordTimestamp } from "./timestamps.js";
2
3
  import type { VoiceAccent, VoiceWritableAccent, VoiceAge, VoiceGender, VoiceLanguageCode, VoiceTone } from "./voice-metadata.js";
3
4
  export type JsonObject = Record<string, unknown>;
@@ -20,7 +21,7 @@ export interface RequestOptions {
20
21
  timeout?: number;
21
22
  }
22
23
  export interface AudioRequestOptions extends RequestOptions {
23
- outputFormat?: string;
24
+ outputFormat?: TtsOutputFormat;
24
25
  }
25
26
  export interface StreamTextToSpeechOptions extends AudioRequestOptions {
26
27
  enableLogging?: boolean;
@@ -38,6 +39,7 @@ export interface BreezeBlueWebSocket {
38
39
  close(code?: number, reason?: string): void;
39
40
  }
40
41
  export interface RealtimeTextToSpeechSessionRequest {
42
+ outputFormat?: RealtimeOutputFormat;
41
43
  modelId?: string;
42
44
  languageCode?: string;
43
45
  instructions?: string;
@@ -49,7 +51,8 @@ export interface RealtimeTextToSpeechAudioFormat {
49
51
  codec: "pcm_s16le" | string;
50
52
  sampleRate: number;
51
53
  channels: number;
52
- sampleWidthBits: number;
54
+ sampleWidthBits?: number | null;
55
+ bitrateKbps?: number;
53
56
  }
54
57
  export interface RealtimeTextToSpeechSession {
55
58
  clientSecret: string;
@@ -227,7 +230,7 @@ export type RealtimeTextToSpeechMessage = RealtimeTextToSpeechEvent | RealtimeTe
227
230
  export interface TtsVoiceSettings {
228
231
  /** Generation guidance strength (1–10). Omitted or null uses the default 1. */
229
232
  guidanceScale?: number | null;
230
- /** Default false. Ignored with non-empty instructions and guidanceScale > 1; otherwise instructions are not used. */
233
+ /** Default false. Ignored with non-empty instructions and guidanceScale > 1; otherwise guidanceScale is applied as 1. Instructions are always applied. */
231
234
  useSpeakerBoost?: boolean;
232
235
  /** Pitch-preserving speed (0.5–2.0). */
233
236
  speed?: number;
@@ -386,6 +389,7 @@ export interface UploadFile {
386
389
  contentType?: string;
387
390
  }
388
391
  export interface VoiceClonePreviewRequest {
392
+ referenceLanguageCode?: "zh";
389
393
  name?: string | null;
390
394
  file?: UploadData | UploadFile;
391
395
  files?: Array<UploadData | UploadFile>;
@@ -400,21 +404,18 @@ export interface VoiceEditRequest {
400
404
  name?: string;
401
405
  description?: string;
402
406
  tags?: string[];
403
- primaryCategoryCode?: string;
404
- visibility?: "private" | "public" | string;
405
407
  languageCode?: VoiceLanguageCode;
406
408
  gender?: VoiceGender | null;
407
409
  age?: VoiceAge | null;
408
410
  tone?: VoiceTone[];
409
411
  accent?: VoiceWritableAccent | null;
410
- file?: UploadData | UploadFile;
411
- files?: Array<UploadData | UploadFile>;
412
412
  }
413
413
  export interface VoiceDesignRequest {
414
414
  voiceDescription: string;
415
415
  text?: string;
416
416
  modelId?: string;
417
417
  languageCode?: VoiceLanguageCode;
418
+ /** Voice Design accepts 1–10; omitted or null samples 1–4 per preview, rounded to one decimal place. */
418
419
  guidanceScale?: number | null;
419
420
  previewCount?: number;
420
421
  }
@@ -423,6 +424,7 @@ export interface VoiceDesignStreamRequest {
423
424
  text?: string;
424
425
  modelId?: string;
425
426
  languageCode?: VoiceLanguageCode;
427
+ /** Voice Design accepts 1–10; omitted or null samples 1–4 per preview, rounded to one decimal place. */
426
428
  guidanceScale?: number | null;
427
429
  }
428
430
  export interface VoiceDesignPreview {
@@ -507,8 +509,6 @@ export interface SaveVoiceRequest {
507
509
  voiceName?: string | null;
508
510
  voiceDescription?: string | null;
509
511
  tags?: string[];
510
- primaryCategoryCode?: string;
511
- visibility?: "private" | "public" | string;
512
512
  languageCode: VoiceLanguageCode;
513
513
  gender?: VoiceGender | null;
514
514
  age?: VoiceAge | null;
package/dist/version.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- export declare const SDK_VERSION = "0.21.0";
1
+ export declare const SDK_VERSION = "0.22.0";
2
2
  export declare const SDK_NAME = "@breeze.blue/sdk";
package/dist/version.js CHANGED
@@ -1,2 +1,2 @@
1
- export const SDK_VERSION = "0.21.0";
1
+ export const SDK_VERSION = "0.22.0";
2
2
  export const SDK_NAME = "@breeze.blue/sdk";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@breeze.blue/sdk",
3
- "version": "0.21.0",
3
+ "version": "0.22.0",
4
4
  "description": "ESM-first TypeScript SDK for the Breeze Blue Developer API.",
5
5
  "license": "MIT",
6
6
  "author": "Breeze Blue <support@breezeblue.ai>",