@breeze.blue/sdk 0.18.0 → 0.19.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,11 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.19.0
4
+
5
+ - Create Voice Remix candidates from custom descriptions or curated presets, with automatic input preparation and Expressive (4) as the default strength.
6
+ - List Remix presets, reuse a prepared performance across candidates, and read source metadata and original-audio comparisons.
7
+ - Retry Remix submissions with an idempotency key and save candidates using their source voice's name and description by default.
8
+
3
9
  ## 0.18.0
4
10
 
5
11
  - Create asynchronous speech jobs with word timestamps and read timing from completed job results.
package/README.md CHANGED
@@ -488,6 +488,45 @@ while (localized.status !== "ready") {
488
488
  generatedVoiceId = localized.generatedVoiceId!;
489
489
  ```
490
490
 
491
+ Voice Remix creates a same-language candidate from an owned or official voice
492
+ and a custom description or preset. Each successful candidate uses the Voice Design candidate
493
+ price. The source remains unchanged.
494
+
495
+ ```ts
496
+ const remixJob = await client.voices.createRemixPreview({
497
+ voiceId: firstVoiceId,
498
+ prompt: "Make the voice warmer and more expressive.",
499
+ guidanceScale: 4,
500
+ });
501
+ let remix = await client.voices.getRemixPreview(remixJob.generationJobId);
502
+ while (remix.status !== "ready") {
503
+ if (remix.status === "failed" || remix.status === "cancelled") {
504
+ throw new Error(remix.error?.detail ?? remix.status);
505
+ }
506
+ await new Promise((resolve) => setTimeout(resolve, 2000));
507
+ remix = await client.voices.getRemixPreview(remixJob.generationJobId);
508
+ }
509
+ generatedVoiceId = remix.generatedVoiceId!;
510
+ ```
511
+
512
+ Use `streamPreview` and `savePreview` with the generated ID to audition and save
513
+ a private, independent voice. A client timeout leaves the server job running.
514
+
515
+ Custom input is enhanced into an instruction and matching script in the source
516
+ language. List templates with `client.voices.listRemixPresets()` and pass
517
+ `presetId` instead of `prompt` to use one. Edited templates are enhanced;
518
+ unchanged templates are translated only when the source language differs.
519
+
520
+ To compare strengths, call `client.voices.prepareRemixPreview(...)` first and
521
+ pass its `preparationToken` to each create call with the same input. The token
522
+ lasts 24 hours. Values 2 / 4 / 6 / 8 mean Stable / Expressive / Creative / Intense;
523
+ 4 is the default. Web Auto compares separate candidates at 4, 6, and 8.
524
+ Use `options.headers["Idempotency-Key"]` to retry uncertain submissions safely,
525
+ with a distinct key per candidate. Status includes `comparisonAudioUrl`,
526
+ `comparisonText`, and `sourceVoice`. Saving without `voiceName` or
527
+ `voiceDescription` uses the source values.
528
+ See the [Voice Remix guide](https://docs.breezeblue.ai/guides/voice-remix).
529
+
491
530
  For the fastest first audio, generate one design preview as a live 24 kHz mono
492
531
  PCM response. The Node `stream()` helper consumes the response body directly;
493
532
  a clean end means `generatedVoiceId` is ready to save:
@@ -612,3 +651,5 @@ Stream audio and word/token timestamps with `client.textToSpeech.streamWithTimes
612
651
  For a complete response, use `client.textToSpeech.convertWithTimestamps(...)`. It returns base64 audio, its content type, and the full word/token timestamp list. Decode the audio before saving or playback. See [Speech timing](https://docs.breezeblue.ai/guides/speech-timing) and [Convert with timestamps](https://docs.breezeblue.ai/api-reference/text-to-speech/convert-with-timestamps).
613
652
 
614
653
  For background generation with timing, use `client.textToSpeech.createJobWithTimestamps(...)`. Poll with `client.generationJobs.get(jobId)`; a ready job includes `wordTimestamps` and the audio download URL.
654
+
655
+ Clone preview creation accepts an omitted name. The server uses the filename stem or `Cloned Voice`; saving a Clone preview without a name keeps its preview name. Other preview types still require a save name. Explicit names longer than 80 Unicode characters are rejected.
package/dist/client.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { SpeechTimingStream, type SpeechWithTimestamps } from "./timestamps.js";
2
2
  import { AudioResponse } from "./audio.js";
3
- import type { AudioRequestOptions, BreezeBlueWebSocket, AsyncTextToSpeechJob, Balance, BreezeBlueClientOptions, CurrentApiKeyResponse, GenericStatus, GenerationJob, HistoryItem, HistoryList, HistoryListParams, Model, RequestOptions, RealtimeTextToSpeechConnectOptions, RealtimeTextToSpeechEvent, RealtimeTextToSpeechManagedConnectOptions, RealtimeTextToSpeechMessage, RealtimeTextToSpeechSession, RealtimeTextToSpeechSessionRequest, SavedVoice, SaveVoiceRequest, StreamTextToSpeechOptions, TextToSpeechRequest, TtsEnhanceRequest, TtsEnhanceResponse, Usage, UsageParams, Voice, VoiceClonePreview, VoiceClonePreviewRequest, VoiceDesignRequest, VoiceDesignResponse, VoiceDesignStreamRequest, VoiceEditRequest, VoiceList, VoiceLocalizeJob, VoiceLocalizePreviewRequest, VoiceLocalizePreviewStatus, VoiceMetadataOptions, VoiceRandomParams, VoiceSearchParams, VoiceSettings } from "./types.js";
3
+ import type { AudioRequestOptions, BreezeBlueWebSocket, AsyncTextToSpeechJob, Balance, BreezeBlueClientOptions, CurrentApiKeyResponse, GenericStatus, GenerationJob, HistoryItem, HistoryList, HistoryListParams, Model, RequestOptions, RealtimeTextToSpeechConnectOptions, RealtimeTextToSpeechEvent, RealtimeTextToSpeechManagedConnectOptions, RealtimeTextToSpeechMessage, RealtimeTextToSpeechSession, RealtimeTextToSpeechSessionRequest, SavedVoice, SaveVoiceRequest, StreamTextToSpeechOptions, TextToSpeechRequest, TtsEnhanceRequest, TtsEnhanceResponse, Usage, UsageParams, Voice, VoiceClonePreview, VoiceClonePreviewRequest, VoiceDesignRequest, VoiceDesignResponse, VoiceDesignStreamRequest, VoiceEditRequest, VoiceList, VoiceLocalizeJob, VoiceLocalizePreviewRequest, VoiceLocalizePreviewStatus, VoiceRemixPreviewRequest, VoiceRemixPrepareRequest, VoiceRemixPresets, VoiceRemixPreparation, VoiceRemixJob, VoiceRemixPreviewStatus, VoiceMetadataOptions, VoiceRandomParams, VoiceSearchParams, VoiceSettings } from "./types.js";
4
4
  export declare class BreezeBlueClient {
5
5
  readonly apiKey: string | undefined;
6
6
  readonly baseUrl: string;
@@ -252,6 +252,14 @@ declare class VoicesResource {
252
252
  * A clean end means `generatedVoiceId` is ready for {@link savePreview}.
253
253
  */
254
254
  streamDesignPreview(request: VoiceDesignStreamRequest, options?: RequestOptions): Promise<AudioResponse>;
255
+ /** List curated voice changes and their sample recordings. */
256
+ listRemixPresets(options?: RequestOptions): Promise<VoiceRemixPresets>;
257
+ /** Prepare once without generating audio; reuse the token for 24 hours with the same input. */
258
+ prepareRemixPreview(request: VoiceRemixPrepareRequest, options?: RequestOptions): Promise<VoiceRemixPreparation>;
259
+ /** Create one candidate. Custom input is enhanced automatically; guidance defaults to 4. */
260
+ createRemixPreview(request: VoiceRemixPreviewRequest, options?: RequestOptions): Promise<VoiceRemixJob>;
261
+ /** A polling timeout does not cancel the server task. Keep the job ID to resume polling. */
262
+ getRemixPreview(generationJobId: string, options?: RequestOptions): Promise<VoiceRemixPreviewStatus>;
255
263
  /**
256
264
  * Start a preview that speaks an existing voice in another language.
257
265
  * Localization runs as a background job: poll the returned
@@ -266,9 +274,9 @@ declare class VoicesResource {
266
274
  * is set only when the job ends in `failed`.
267
275
  */
268
276
  getLocalizePreview(generationJobId: string, options?: RequestOptions): Promise<VoiceLocalizePreviewStatus>;
269
- /** Download the completed audio of a clone or design preview. */
277
+ /** Download a ready Design, Clone, Remix or Localize preview. */
270
278
  streamPreview(generatedVoiceId: string, options?: AudioRequestOptions): Promise<AudioResponse>;
271
- /** Persist a clone or design preview as a real voice asset. */
279
+ /** Save a ready preview; Remix defaults name and description to its source. */
272
280
  savePreview(request: SaveVoiceRequest, options?: RequestOptions): Promise<SavedVoice>;
273
281
  }
274
282
  declare class HistoryResource {
package/dist/client.js CHANGED
@@ -1580,6 +1580,22 @@ class VoicesResource {
1580
1580
  streamDesignPreview(request, options) {
1581
1581
  return this.client.requestAudio("POST", "/v1/voice-previews/design/stream", undefined, request, options);
1582
1582
  }
1583
+ /** List curated voice changes and their sample recordings. */
1584
+ listRemixPresets(options) {
1585
+ return this.client.requestJson("GET", "/v1/voice-previews/remix/presets", undefined, undefined, options);
1586
+ }
1587
+ /** Prepare once without generating audio; reuse the token for 24 hours with the same input. */
1588
+ prepareRemixPreview(request, options) {
1589
+ return this.client.requestJson("POST", "/v1/voice-previews/remix/prepare", undefined, request, options);
1590
+ }
1591
+ /** Create one candidate. Custom input is enhanced automatically; guidance defaults to 4. */
1592
+ createRemixPreview(request, options) {
1593
+ return this.client.requestJson("POST", "/v1/voice-previews/remix", undefined, request, options);
1594
+ }
1595
+ /** A polling timeout does not cancel the server task. Keep the job ID to resume polling. */
1596
+ getRemixPreview(generationJobId, options) {
1597
+ return this.client.requestJson("GET", `/v1/voice-previews/remix/${encodeURIComponent(generationJobId)}`, undefined, undefined, options);
1598
+ }
1583
1599
  /**
1584
1600
  * Start a preview that speaks an existing voice in another language.
1585
1601
  * Localization runs as a background job: poll the returned
@@ -1598,11 +1614,11 @@ class VoicesResource {
1598
1614
  getLocalizePreview(generationJobId, options) {
1599
1615
  return this.client.requestJson("GET", `/v1/voice-previews/localize/${encodeURIComponent(generationJobId)}`, undefined, undefined, options);
1600
1616
  }
1601
- /** Download the completed audio of a clone or design preview. */
1617
+ /** Download a ready Design, Clone, Remix or Localize preview. */
1602
1618
  streamPreview(generatedVoiceId, options = {}) {
1603
1619
  return this.client.requestAudio("GET", `/v1/voice-previews/${encodeURIComponent(generatedVoiceId)}/stream`, { outputFormat: options.outputFormat }, undefined, options);
1604
1620
  }
1605
- /** Persist a clone or design preview as a real voice asset. */
1621
+ /** Save a ready preview; Remix defaults name and description to its source. */
1606
1622
  async savePreview(request, options) {
1607
1623
  const result = await this.client.requestJson("POST", `/v1/voice-previews/${encodeURIComponent(request.generatedVoiceId)}/save`, undefined, {
1608
1624
  voiceName: request.voiceName,
@@ -1754,6 +1770,9 @@ function mergeHeaders(headers, input) {
1754
1770
  new Headers(input).forEach((value, key) => headers.set(key, value));
1755
1771
  }
1756
1772
  function clonePreviewForm(request) {
1773
+ if (request.name != null && typeof request.name !== "string") {
1774
+ throw new BreezeBlueConfigurationError("Clone name must be a string or null.");
1775
+ }
1757
1776
  if (request.removeBackgroundNoise) {
1758
1777
  throw new BreezeBlueConfigurationError("removeBackgroundNoise is not supported by the Breeze Developer API.");
1759
1778
  }
@@ -1763,7 +1782,7 @@ function clonePreviewForm(request) {
1763
1782
  }
1764
1783
  }
1765
1784
  const form = new FormData();
1766
- form.set("name", request.name);
1785
+ appendOptional(form, "name", request.name ?? undefined);
1767
1786
  appendOptional(form, "description", request.description);
1768
1787
  for (const file of normalizeFiles(request.file, request.files, { required: true })) {
1769
1788
  appendFile(form, "files", file);
package/dist/types.d.ts CHANGED
@@ -401,7 +401,7 @@ export interface UploadFile {
401
401
  contentType?: string;
402
402
  }
403
403
  export interface VoiceClonePreviewRequest {
404
- name: string;
404
+ name?: string | null;
405
405
  file?: UploadData | UploadFile;
406
406
  files?: Array<UploadData | UploadFile>;
407
407
  description?: string;
@@ -454,6 +454,56 @@ export interface VoiceDesignResponse {
454
454
  previews: VoiceDesignPreview[];
455
455
  text: string;
456
456
  }
457
+ export interface VoiceRemixPrepareRequest {
458
+ voiceId: string;
459
+ prompt?: string;
460
+ presetId?: string;
461
+ }
462
+ export interface VoiceRemixPreviewRequest extends VoiceRemixPrepareRequest {
463
+ guidanceScale?: number;
464
+ preparationToken?: string;
465
+ }
466
+ export interface VoiceRemixSource {
467
+ voiceId: string | null;
468
+ name: string | null;
469
+ description: string | null;
470
+ }
471
+ export interface VoiceRemixPreset {
472
+ id: string;
473
+ category: string;
474
+ name: string;
475
+ prompt: string;
476
+ script: string;
477
+ language: string;
478
+ guidanceScale: number;
479
+ previewAudioUrl: string;
480
+ }
481
+ export interface VoiceRemixPresets {
482
+ presets: VoiceRemixPreset[];
483
+ exampleVoiceId: string;
484
+ }
485
+ export interface VoiceRemixPreparation {
486
+ preparationToken: string;
487
+ languageCode: VoiceLanguageCode;
488
+ instruction: string;
489
+ text: string;
490
+ sourceVoice: VoiceRemixSource;
491
+ }
492
+ export interface VoiceRemixJob {
493
+ generationJobId: string;
494
+ status: string;
495
+ }
496
+ export interface VoiceRemixPreviewStatus extends VoiceRemixJob {
497
+ languageCode?: VoiceLanguageCode | null;
498
+ generatedVoiceId?: string | null;
499
+ text?: string | null;
500
+ error?: GenerationJobError | null;
501
+ instruction?: string | null;
502
+ guidanceScale?: number | null;
503
+ sourceVoice?: VoiceRemixSource | null;
504
+ comparisonAudioUrl?: string | null;
505
+ comparisonText?: string | null;
506
+ }
457
507
  export interface VoiceLocalizePreviewRequest {
458
508
  voiceId: string;
459
509
  languageCode: VoiceLanguageCode;
@@ -473,7 +523,7 @@ export interface VoiceLocalizePreviewStatus {
473
523
  }
474
524
  export interface SaveVoiceRequest {
475
525
  generatedVoiceId: string;
476
- voiceName: string;
526
+ voiceName?: string | null;
477
527
  voiceDescription?: string | null;
478
528
  tags?: string[];
479
529
  primaryCategoryCode?: string;
package/dist/version.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- export declare const SDK_VERSION = "0.18.0";
1
+ export declare const SDK_VERSION = "0.19.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.18.0";
1
+ export const SDK_VERSION = "0.19.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.18.0",
3
+ "version": "0.19.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>",