@soniox/node 1.1.2 → 2.0.1

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/dist/index.d.mts CHANGED
@@ -1,6 +1,8 @@
1
1
  //#region src/constants.d.ts
2
2
  declare const SONIOX_API_BASE_URL = "https://api.soniox.com";
3
3
  declare const SONIOX_API_WS_URL = "wss://stt-rt.soniox.com/transcribe-websocket";
4
+ declare const SONIOX_TTS_API_BASE_URL = "https://tts-rt.soniox.com";
5
+ declare const SONIOX_TTS_WS_URL = "wss://tts-rt.soniox.com/tts-websocket";
4
6
  declare const SONIOX_TMP_API_KEY_USAGE_TYPE = "transcribe_websocket";
5
7
  declare const SONIOX_TMP_API_KEY_DURATION_MIN = 1;
6
8
  declare const SONIOX_TMP_API_KEY_DURATION_MAX = 3600;
@@ -13,19 +15,40 @@ declare const SONIOX_API_WEBHOOK_SECRET_ENV = "SONIOX_API_WEBHOOK_SECRET";
13
15
  */
14
16
  type RealtimeErrorCode = 'auth_error' | 'bad_request' | 'quota_exceeded' | 'connection_error' | 'network_error' | 'aborted' | 'state_error' | 'realtime_error';
15
17
  /**
16
- * All possible SDK error codes
18
+ * Error codes for HTTP client errors
19
+ */
20
+ type HttpErrorCode = 'network_error' | 'timeout' | 'aborted' | 'http_error' | 'parse_error';
21
+ /**
22
+ * HTTP methods supported by the client
23
+ */
24
+ type HttpMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE' | 'HEAD';
25
+ /**
26
+ * Error details for SonioxHttpError
27
+ */
28
+ interface HttpErrorDetails {
29
+ code: HttpErrorCode;
30
+ message: string;
31
+ url: string;
32
+ method: HttpMethod;
33
+ statusCode?: number | undefined;
34
+ headers?: Record<string, string> | undefined;
35
+ /** Response body text (capped at 4KB) */
36
+ bodyText?: string | undefined;
37
+ cause?: unknown;
38
+ }
39
+ /**
40
+ * All possible SDK error codes (real-time + HTTP-specific codes)
17
41
  */
18
- type SonioxErrorCode$1 = RealtimeErrorCode | 'soniox_error';
42
+ type SonioxErrorCode = RealtimeErrorCode | 'soniox_error' | HttpErrorCode;
19
43
  //#endregion
20
44
  //#region ../core/src/errors.d.ts
21
-
22
45
  declare class SonioxError extends Error {
23
46
  /**
24
47
  * Error code describing the type of error.
25
48
  * Typed as `string` at the base level to allow subclasses (e.g. HTTP errors)
26
49
  * to use their own error code unions.
27
50
  */
28
- readonly code: SonioxErrorCode$1 | (string & {});
51
+ readonly code: SonioxErrorCode | (string & {});
29
52
  /**
30
53
  * HTTP status code when applicable (e.g., 401 for auth errors, 500 for server errors).
31
54
  */
@@ -34,7 +57,36 @@ declare class SonioxError extends Error {
34
57
  * The underlying error that caused this error, if any.
35
58
  */
36
59
  readonly cause: unknown;
37
- constructor(message: string, code?: SonioxErrorCode$1 | (string & {}), statusCode?: number, cause?: unknown);
60
+ constructor(message: string, code?: SonioxErrorCode | (string & {}), statusCode?: number, cause?: unknown);
61
+ /**
62
+ * Creates a human-readable string representation
63
+ */
64
+ toString(): string;
65
+ /**
66
+ * Converts to a plain object for logging/serialization
67
+ */
68
+ toJSON(): Record<string, unknown>;
69
+ }
70
+ //#endregion
71
+ //#region ../core/src/http-errors.d.ts
72
+ /**
73
+ * HTTP error class for all HTTP-related failures (REST API).
74
+ *
75
+ * Thrown when HTTP requests fail due to network issues, timeouts,
76
+ * server errors, or response parsing failures.
77
+ */
78
+ declare class SonioxHttpError extends SonioxError {
79
+ /** Categorized HTTP error code */
80
+ readonly code: HttpErrorCode;
81
+ /** Request URL */
82
+ readonly url: string;
83
+ /** HTTP method */
84
+ readonly method: HttpMethod;
85
+ /** Response headers (only for http_error) */
86
+ readonly headers: Record<string, string> | undefined;
87
+ /** Response body text, capped at 4KB (only for http_error/parse_error) */
88
+ readonly bodyText: string | undefined;
89
+ constructor(details: HttpErrorDetails);
38
90
  /**
39
91
  * Creates a human-readable string representation
40
92
  */
@@ -44,6 +96,39 @@ declare class SonioxError extends Error {
44
96
  */
45
97
  toJSON(): Record<string, unknown>;
46
98
  }
99
+ /**
100
+ * Creates a network error
101
+ */
102
+ declare function createNetworkError(url: string, method: HttpMethod, cause: unknown): SonioxHttpError;
103
+ /**
104
+ * Creates a timeout error
105
+ */
106
+ declare function createTimeoutError(url: string, method: HttpMethod, timeoutMs: number): SonioxHttpError;
107
+ /**
108
+ * Creates an abort error
109
+ */
110
+ declare function createAbortError(url: string, method: HttpMethod, cause?: unknown): SonioxHttpError;
111
+ /**
112
+ * Creates an HTTP error (non-2xx status)
113
+ */
114
+ declare function createHttpError(url: string, method: HttpMethod, statusCode: number, headers: Record<string, string>, bodyText: string): SonioxHttpError;
115
+ /**
116
+ * Creates a parse error (invalid JSON, etc.)
117
+ */
118
+ declare function createParseError(url: string, method: HttpMethod, bodyText: string, cause: unknown): SonioxHttpError;
119
+ /**
120
+ * Type guard to check if an error is an AbortError
121
+ */
122
+ declare function isAbortError(error: unknown): boolean;
123
+ /**
124
+ * Type guard to check if an error is any SonioxError (base class).
125
+ * This catches all SDK errors including HTTP and real-time errors.
126
+ */
127
+ declare function isSonioxError(error: unknown): error is SonioxError;
128
+ /**
129
+ * Type guard to check if an error is a SonioxHttpError
130
+ */
131
+ declare function isSonioxHttpError(error: unknown): error is SonioxHttpError;
47
132
  //#endregion
48
133
  //#region ../core/src/types/transcriptions.d.ts
49
134
  /**
@@ -218,6 +303,13 @@ type SttSessionOptions = {
218
303
  * @default 5000
219
304
  */
220
305
  keepalive_interval_ms?: number | undefined;
306
+ /**
307
+ * Maximum time to wait for the WebSocket connection to open (milliseconds).
308
+ * If the connection is not established within this time, a
309
+ * {@link ConnectionError} with message "Connection timed out" is thrown.
310
+ * @default 20000
311
+ */
312
+ connect_timeout_ms?: number | undefined;
221
313
  };
222
314
  /**
223
315
  * A single token from the real-time transcription.
@@ -431,6 +523,14 @@ type RealtimeEvent = {
431
523
  * Session lifecycle states.
432
524
  */
433
525
  type SttSessionState = 'idle' | 'connecting' | 'connected' | 'finishing' | 'finished' | 'canceled' | 'closed' | 'error';
526
+ /**
527
+ * Reason for a state transition.
528
+ *
529
+ * Provided as an optional field on `state_change` events so consumers
530
+ * can distinguish user-initiated actions from automatic reconnections,
531
+ * connection failures, etc.
532
+ */
533
+ type StateChangeReason = 'user_action' | 'connected' | 'connection_lost' | 'reconnecting' | 'reconnected' | 'error' | 'finished';
434
534
  /**
435
535
  * Event handlers for the STT session.
436
536
  */
@@ -473,6 +573,7 @@ type SttSessionEvents = {
473
573
  state_change: (update: {
474
574
  old_state: SttSessionState;
475
575
  new_state: SttSessionState;
576
+ reason?: StateChangeReason;
476
577
  }) => void;
477
578
  };
478
579
  /**
@@ -496,6 +597,368 @@ type SendStreamOptions = {
496
597
  finish?: boolean | undefined;
497
598
  };
498
599
  //#endregion
600
+ //#region ../core/src/realtime/errors.d.ts
601
+ /**
602
+ * Base error class for all real-time (WebSocket) SDK errors
603
+ */
604
+ declare class RealtimeError extends SonioxError {
605
+ /** Real-time error code */
606
+ readonly code: RealtimeErrorCode;
607
+ /**
608
+ * Original response payload for debugging.
609
+ * Contains the raw WebSocket message that caused the error.
610
+ */
611
+ readonly raw: unknown;
612
+ constructor(message: string, code?: RealtimeErrorCode, statusCode?: number, raw?: unknown);
613
+ /**
614
+ * Creates a human-readable string representation
615
+ */
616
+ toString(): string;
617
+ /**
618
+ * Converts to a plain object for logging/serialization
619
+ */
620
+ toJSON(): Record<string, unknown>;
621
+ }
622
+ /**
623
+ * Authentication error (401).
624
+ * Thrown when the API key is invalid or expired.
625
+ */
626
+ declare class AuthError extends RealtimeError {
627
+ constructor(message: string, statusCode?: number, raw?: unknown);
628
+ }
629
+ /**
630
+ * Bad request error (400).
631
+ * Thrown for invalid configuration or parameters.
632
+ */
633
+ declare class BadRequestError extends RealtimeError {
634
+ constructor(message: string, statusCode?: number, raw?: unknown);
635
+ }
636
+ /**
637
+ * Quota error (402, 429).
638
+ * Thrown when rate limits are exceeded or quota is exhausted.
639
+ */
640
+ declare class QuotaError extends RealtimeError {
641
+ constructor(message: string, statusCode?: number, raw?: unknown);
642
+ }
643
+ /**
644
+ * Connection error.
645
+ * Thrown for WebSocket connection failures and transport errors.
646
+ */
647
+ declare class ConnectionError extends RealtimeError {
648
+ constructor(message: string, raw?: unknown);
649
+ }
650
+ /**
651
+ * Network error.
652
+ * Thrown for server-side network issues (408, 500, 503).
653
+ */
654
+ declare class NetworkError extends RealtimeError {
655
+ constructor(message: string, statusCode?: number, raw?: unknown);
656
+ }
657
+ /**
658
+ * Abort error.
659
+ * Thrown when an operation is cancelled via AbortSignal.
660
+ */
661
+ declare class AbortError extends RealtimeError {
662
+ constructor(message?: string);
663
+ }
664
+ /**
665
+ * State error.
666
+ * Thrown when an operation is attempted in an invalid state.
667
+ */
668
+ declare class StateError extends RealtimeError {
669
+ constructor(message: string);
670
+ }
671
+ //#endregion
672
+ //#region ../core/src/types/tts.d.ts
673
+ /**
674
+ * Supported audio formats for Text-to-Speech output.
675
+ */
676
+ type TtsAudioFormat = 'pcm_f32le' | 'pcm_s16le' | 'pcm_mulaw' | 'pcm_alaw' | 'wav' | 'aac' | 'mp3' | 'opus' | 'flac' | (string & {});
677
+ /**
678
+ * Input for creating a TTS stream. All fields are optional and are merged
679
+ * with `tts_defaults` from the resolved connection config. After merging,
680
+ * `model`, `language`, `voice`, and `audio_format` must be present.
681
+ */
682
+ type TtsStreamInput = {
683
+ /**
684
+ * Text-to-Speech model to use.
685
+ * @example 'tts-rt-v1-preview'
686
+ */
687
+ model?: string | undefined;
688
+ /**
689
+ * Language code for speech generation.
690
+ * @example 'en'
691
+ */
692
+ language?: string | undefined;
693
+ /**
694
+ * Voice identifier.
695
+ * @example 'Adrian'
696
+ */
697
+ voice?: string | undefined;
698
+ /**
699
+ * Output audio format
700
+ * @example 'wav'
701
+ */
702
+ audio_format?: TtsAudioFormat | undefined;
703
+ /**
704
+ * Output sample rate in Hz. Required for raw PCM formats.
705
+ */
706
+ sample_rate?: number | undefined;
707
+ /**
708
+ * Codec bitrate in bps (for compressed formats).
709
+ */
710
+ bitrate?: number | undefined;
711
+ /**
712
+ * Client-generated stream identifier. Must be unique among active streams
713
+ * on the same connection. Auto-generated if omitted.
714
+ */
715
+ stream_id?: string | undefined;
716
+ };
717
+ /**
718
+ * Fully resolved TTS stream config sent over the WebSocket.
719
+ * All required fields are present after merging input with defaults.
720
+ */
721
+ type TtsStreamConfig = {
722
+ model: string;
723
+ language: string;
724
+ voice: string;
725
+ audio_format: string;
726
+ sample_rate?: number | undefined;
727
+ bitrate?: number | undefined;
728
+ stream_id: string;
729
+ };
730
+ /**
731
+ * Events emitted by a TTS WebSocket connection.
732
+ */
733
+ type TtsConnectionEvents = {
734
+ /**
735
+ * A connection-level error occurred. Always a {@link RealtimeError}
736
+ * subclass (e.g. {@link ConnectionError}, {@link NetworkError},
737
+ * {@link AuthError}).
738
+ */
739
+ error: (error: RealtimeError) => void;
740
+ /** The WebSocket connection was closed. */
741
+ close: () => void;
742
+ };
743
+ /**
744
+ * Options for creating a TTS connection.
745
+ */
746
+ type TtsConnectionOptions = {
747
+ /**
748
+ * Interval for sending keepalive messages (milliseconds).
749
+ * @default 5000
750
+ * @minimum 1000
751
+ */
752
+ keepalive_interval_ms?: number | undefined;
753
+ /**
754
+ * Maximum time to wait for the WebSocket connection to open (milliseconds).
755
+ * @default 20000
756
+ */
757
+ connect_timeout_ms?: number | undefined;
758
+ };
759
+ /**
760
+ * Events emitted by a TTS stream.
761
+ */
762
+ type TtsStreamEvents = {
763
+ /** Decoded audio chunk received. */
764
+ audio: (chunk: Uint8Array) => void;
765
+ /** Server marked the final audio payload for this stream. */
766
+ audioEnd: () => void;
767
+ /** Stream has been fully terminated by the server. */
768
+ terminated: () => void;
769
+ /**
770
+ * A stream-level error occurred. Always a {@link RealtimeError}
771
+ * subclass mapped from the server `error_code` / `error_message`.
772
+ */
773
+ error: (error: RealtimeError) => void;
774
+ };
775
+ /**
776
+ * Lifecycle states for a TTS stream.
777
+ */
778
+ type TtsStreamState = 'active' | 'finishing' | 'ended' | 'error';
779
+ /**
780
+ * Raw JSON event received from the TTS WebSocket server.
781
+ */
782
+ type TtsEvent = {
783
+ stream_id?: string | undefined;
784
+ audio?: string | undefined;
785
+ audio_end?: boolean | undefined;
786
+ terminated?: boolean | undefined;
787
+ error_code?: number | undefined;
788
+ error_message?: string | undefined;
789
+ };
790
+ /**
791
+ * Options for REST TTS generation (`generate` / `generateStream`).
792
+ */
793
+ type GenerateSpeechOptions = {
794
+ /** Input text to generate as speech. */
795
+ text: string;
796
+ /** Text-to-Speech model to use. @default 'tts-rt-v1-preview' */
797
+ model?: string | undefined;
798
+ /** Language code. @default 'en' */
799
+ language?: string | undefined;
800
+ /** Voice identifier. */
801
+ voice: string;
802
+ /**
803
+ * Output audio format
804
+ * @default 'wav'
805
+ */
806
+ audio_format?: string | undefined;
807
+ /** Output sample rate in Hz. Required for raw PCM formats. */
808
+ sample_rate?: number | undefined;
809
+ /** Codec bitrate in bps (for compressed formats). */
810
+ bitrate?: number | undefined;
811
+ /** Optional AbortSignal for cancellation. */
812
+ signal?: AbortSignal | undefined;
813
+ };
814
+ /**
815
+ * A Text-to-Speech voice.
816
+ */
817
+ type TtsVoice = {
818
+ /** Unique identifier of the voice. */
819
+ id: string;
820
+ };
821
+ /**
822
+ * A Text-to-Speech model.
823
+ */
824
+ type TtsModel = {
825
+ /** Unique identifier of the model. */
826
+ id: string;
827
+ /** If this is an alias, the id of the aliased model. */
828
+ aliased_model_id?: string | null;
829
+ /** Name of the model. */
830
+ name: string;
831
+ /** Voices supported by this model. */
832
+ voices: TtsVoice[];
833
+ };
834
+ //#endregion
835
+ //#region ../core/src/connection.d.ts
836
+ /**
837
+ * Soniox deployment region.
838
+ *
839
+ * Defined regions:
840
+ * - `'eu'` — European Union (`*.eu.soniox.com`)
841
+ * - `'jp'` — Japan (`*.jp.soniox.com`)
842
+ * - `undefined` — Default (United States). The US region has no subdomain.
843
+ *
844
+ * A region name (other than `'us'`) is shorthand for setting `base_domain`
845
+ * to `{region}.soniox.com`. The string `'us'` is accepted and normalized to
846
+ * the default (United States) base domain; there is no `us.soniox.com` host.
847
+ *
848
+ * The type stays open (`string & {}`) for forward compatibility with regions
849
+ * added after this SDK version was published, but passing an unknown region
850
+ * simply prepends it as a subdomain and may not resolve.
851
+ *
852
+ * @see https://soniox.com/docs/stt/data-residency
853
+ */
854
+ type SonioxRegion = 'eu' | 'jp' | (string & {});
855
+ /**
856
+ * Connection configuration for Soniox APIs.
857
+ *
858
+ * Can be provided as a plain object (sync) or returned from an async function
859
+ * to support fetching configuration from a server at runtime.
860
+ */
861
+ type SonioxConnectionConfig = {
862
+ /** API key for authentication. */
863
+ api_key: string;
864
+ /**
865
+ * Deployment region. Determines which regional endpoints are used.
866
+ * Leave `undefined` for the default (US) region.
867
+ *
868
+ * Shorthand for `base_domain: '{region}.soniox.com'`.
869
+ * `base_domain` takes precedence when both are provided.
870
+ *
871
+ * @see https://soniox.com/docs/stt/data-residency
872
+ */
873
+ region?: SonioxRegion | undefined;
874
+ /**
875
+ * Base domain for all Soniox service URLs.
876
+ *
877
+ * A single override that derives all four service endpoints:
878
+ * - `api_domain` → `https://api.{base_domain}`
879
+ * - `stt_ws_url` → `wss://stt-rt.{base_domain}/transcribe-websocket`
880
+ * - `tts_api_url` → `https://tts-rt.{base_domain}`
881
+ * - `tts_ws_url` → `wss://tts-rt.{base_domain}/tts-websocket`
882
+ *
883
+ * Takes precedence over `region`. Individual URL fields (`api_domain`,
884
+ * `stt_ws_url`, etc.) still take final precedence over this value.
885
+ *
886
+ * @example 'eu.soniox.com'
887
+ */
888
+ base_domain?: string | undefined;
889
+ /**
890
+ * REST API domain override (e.g. `'https://api.eu.soniox.com'`).
891
+ * When set, takes precedence over the region-derived domain.
892
+ */
893
+ api_domain?: string | undefined;
894
+ /**
895
+ * STT WebSocket URL override (e.g. `'wss://stt-rt.eu.soniox.com/transcribe-websocket'`).
896
+ * When set, takes precedence over the region-derived URL.
897
+ */
898
+ stt_ws_url?: string | undefined;
899
+ /**
900
+ * TTS REST API URL override (e.g. `'https://tts-rt.eu.soniox.com'`).
901
+ * When set, takes precedence over the region-derived URL.
902
+ */
903
+ tts_api_url?: string | undefined;
904
+ /**
905
+ * TTS WebSocket URL override (e.g. `'wss://tts-rt.eu.soniox.com/tts-websocket'`).
906
+ * When set, takes precedence over the region-derived URL.
907
+ */
908
+ tts_ws_url?: string | undefined;
909
+ /**
910
+ * Server-provided STT session defaults (model, language hints, context, etc.).
911
+ *
912
+ * Available to the `session_config` function passed to `client.realtime.record()`,
913
+ * allowing server-driven defaults. Not applied automatically — the caller must
914
+ * explicitly spread them.
915
+ */
916
+ stt_defaults?: Partial<SttSessionConfig> | undefined;
917
+ /**
918
+ * Server-provided TTS stream defaults (model, voice, language, audio_format, etc.).
919
+ *
920
+ * Automatically merged as the base layer when opening TTS streams.
921
+ * Caller-provided fields override these defaults.
922
+ */
923
+ tts_defaults?: Partial<TtsStreamConfig> | undefined;
924
+ /**
925
+ * @deprecated Use `stt_defaults` instead. Kept as an alias for backward
926
+ * compatibility; the resolver treats it as equivalent to `stt_defaults`
927
+ * when that field is absent. Planned for removal in the next major version.
928
+ */
929
+ session_defaults?: Partial<SttSessionConfig> | undefined;
930
+ };
931
+ /**
932
+ * Fully resolved connection configuration with all URLs determined.
933
+ */
934
+ type ResolvedConnectionConfig = {
935
+ api_key: string;
936
+ api_domain: string;
937
+ stt_ws_url: string;
938
+ tts_api_url: string;
939
+ tts_ws_url: string;
940
+ /** Server-provided STT session defaults (empty object when not provided). */
941
+ stt_defaults: Partial<SttSessionConfig>;
942
+ /** Server-provided TTS stream defaults (empty object when not provided). */
943
+ tts_defaults: Partial<TtsStreamConfig>;
944
+ /**
945
+ * @deprecated Use `stt_defaults` instead. Kept in the resolver output as
946
+ * an alias for backward compatibility; planned for removal in the next
947
+ * major version.
948
+ */
949
+ session_defaults: Partial<SttSessionConfig>;
950
+ };
951
+ /**
952
+ * Resolve a {@link SonioxConnectionConfig} into fully qualified URLs.
953
+ *
954
+ * Resolution priority (highest → lowest) for each URL:
955
+ * 1. Explicit field (`api_domain`, `stt_ws_url`, `tts_api_url`, `tts_ws_url`)
956
+ * 2. Derived from `base_domain`
957
+ * 3. Derived from `region` → `{region}.soniox.com`
958
+ * 4. Default US base domain (`soniox.com`)
959
+ */
960
+ declare function resolveConnectionConfig(config: SonioxConnectionConfig): ResolvedConnectionConfig;
961
+ //#endregion
499
962
  //#region ../core/src/realtime/stt.d.ts
500
963
  /**
501
964
  * Real-time Speech-to-Text session
@@ -521,10 +984,12 @@ type SendStreamOptions = {
521
984
  declare class RealtimeSttSession implements AsyncIterable<RealtimeEvent> {
522
985
  private readonly emitter;
523
986
  private readonly eventQueue;
987
+ private iteratorAttached;
524
988
  private readonly apiKey;
525
989
  private readonly wsBaseUrl;
526
990
  private readonly config;
527
991
  private readonly keepaliveIntervalMs;
992
+ private readonly connectTimeoutMs;
528
993
  private readonly signal;
529
994
  private ws;
530
995
  private _state;
@@ -608,8 +1073,25 @@ declare class RealtimeSttSession implements AsyncIterable<RealtimeEvent> {
608
1073
  off<E extends keyof SttSessionEvents>(event: E, handler: SttSessionEvents[E]): this;
609
1074
  /**
610
1075
  * Async iterator for consuming events.
1076
+ *
1077
+ * The returned iterator's `return()` resets the internal iterator-attach
1078
+ * flag and drops any buffered events, so consumers that exit `for await`
1079
+ * early (via `break` etc.) stop accruing memory while the session keeps
1080
+ * running.
611
1081
  */
612
1082
  [Symbol.asyncIterator](): AsyncIterator<RealtimeEvent>;
1083
+ /**
1084
+ * @internal Debug-only: forcefully close the underlying WebSocket to
1085
+ * simulate an unexpected network disconnection.
1086
+ */
1087
+ __debugForceDisconnect(): void;
1088
+ /**
1089
+ * Push an event to the async iterator queue only when a consumer has
1090
+ * attached via `[Symbol.asyncIterator]()`. Listener-only consumers
1091
+ * (the documented `.on()` pattern) never drain the queue, so pushing
1092
+ * unconditionally would leak buffered events on long-running sessions.
1093
+ */
1094
+ private enqueueIfIterating;
613
1095
  private createWebSocket;
614
1096
  private handleMessage;
615
1097
  private handleClose;
@@ -626,6 +1108,196 @@ declare class RealtimeSttSession implements AsyncIterable<RealtimeEvent> {
626
1108
  private updateKeepalive;
627
1109
  }
628
1110
  //#endregion
1111
+ //#region ../core/src/realtime/emitter.d.ts
1112
+ /**
1113
+ * A minimal, runtime-agnostic typed event emitter.
1114
+ * Does not depend on Node.js EventEmitter.
1115
+ */
1116
+ declare class TypedEmitter<Events extends Record<string, (...args: any[]) => void>> {
1117
+ private listeners;
1118
+ private readonly errorEvent;
1119
+ /**
1120
+ * Register an event handler.
1121
+ */
1122
+ on<E extends keyof Events>(event: E, handler: Events[E]): this;
1123
+ /**
1124
+ * Register a one-time event handler.
1125
+ */
1126
+ once<E extends keyof Events>(event: E, handler: Events[E]): this;
1127
+ /**
1128
+ * Remove an event handler.
1129
+ */
1130
+ off<E extends keyof Events>(event: E, handler: Events[E]): this;
1131
+ /**
1132
+ * Emit an event to all registered handlers.
1133
+ * Handler errors do not prevent other handlers from running.
1134
+ * Errors are reported to an `error` event if present, otherwise rethrown async.
1135
+ */
1136
+ emit<E extends keyof Events>(event: E, ...args: Parameters<Events[E]>): void;
1137
+ /**
1138
+ * Remove all event handlers.
1139
+ */
1140
+ removeAllListeners(event?: keyof Events): void;
1141
+ private reportListenerError;
1142
+ private normalizeError;
1143
+ private scheduleThrow;
1144
+ }
1145
+ //#endregion
1146
+ //#region ../core/src/realtime/tts.d.ts
1147
+ /**
1148
+ * Handle for one TTS stream on a WebSocket connection.
1149
+ *
1150
+ * Emits typed events and supports async iteration over decoded audio chunks.
1151
+ *
1152
+ * @example Event-based
1153
+ * ```typescript
1154
+ * stream.on('audio', (chunk) => process(chunk));
1155
+ * stream.on('terminated', () => console.log('done'));
1156
+ * stream.sendText("Hello world");
1157
+ * stream.finish();
1158
+ * ```
1159
+ *
1160
+ * @example Async iteration
1161
+ * ```typescript
1162
+ * stream.sendText("Hello world");
1163
+ * stream.finish();
1164
+ * for await (const chunk of stream) {
1165
+ * process(chunk);
1166
+ * }
1167
+ * ```
1168
+ */
1169
+ declare class RealtimeTtsStream extends TypedEmitter<TtsStreamEvents> implements AsyncIterable<Uint8Array> {
1170
+ readonly streamId: string;
1171
+ private _state;
1172
+ private readonly audioQueue;
1173
+ private iteratorAttached;
1174
+ private readonly connection;
1175
+ private readonly ownsConnection;
1176
+ /** @internal */
1177
+ constructor(streamId: string, connection: RealtimeTtsConnection, ownsConnection: boolean);
1178
+ /** Current stream lifecycle state. */
1179
+ get state(): TtsStreamState;
1180
+ /**
1181
+ * Send one text chunk to the TTS stream.
1182
+ *
1183
+ * @param text - Text to synthesize
1184
+ * @param options.end - If true, signals this is the final text chunk
1185
+ */
1186
+ sendText(text: string, options?: {
1187
+ end?: boolean;
1188
+ }): void;
1189
+ /**
1190
+ * Pipe an async iterable of text chunks into the stream.
1191
+ * Automatically calls {@link finish} when the iterable completes.
1192
+ *
1193
+ * Designed for concurrent use: call `sendStream()` and consume audio
1194
+ * via `for await` or events simultaneously.
1195
+ *
1196
+ * @example LLM token piping
1197
+ * ```typescript
1198
+ * stream.sendStream(llmTokenStream);
1199
+ * for await (const audio of stream) { forward(audio); }
1200
+ * ```
1201
+ */
1202
+ sendStream(source: AsyncIterable<string>): Promise<void>;
1203
+ /**
1204
+ * Signal that no more text will be sent for this stream.
1205
+ * The server will finish generating audio and send `terminated`.
1206
+ */
1207
+ finish(): void;
1208
+ /**
1209
+ * Cancel this stream. The server will stop generating and send `terminated`.
1210
+ */
1211
+ cancel(): void;
1212
+ /**
1213
+ * Close this stream. For single-stream usage (created via `tts(input)`),
1214
+ * also closes the underlying WebSocket connection.
1215
+ */
1216
+ close(): void;
1217
+ /**
1218
+ * Async iterator that yields decoded audio chunks.
1219
+ *
1220
+ * The returned iterator's `return()` resets the internal iterator-attach
1221
+ * flag and drops any buffered audio, so consumers that exit `for await`
1222
+ * early (via `break` etc.) stop accruing memory while the stream keeps
1223
+ * receiving server audio.
1224
+ */
1225
+ [Symbol.asyncIterator](): AsyncIterator<Uint8Array>;
1226
+ /**
1227
+ * Push an audio chunk to the async iterator queue only when a consumer
1228
+ * has attached via `[Symbol.asyncIterator]()`. Listener-only consumers
1229
+ * (the documented `.on('audio', ...)` pattern) never drain the queue,
1230
+ * so pushing unconditionally would leak buffered chunks.
1231
+ */
1232
+ private enqueueIfIterating;
1233
+ /** @internal Dispatch a server event to this stream. */
1234
+ _handleEvent(event: TtsEvent): void;
1235
+ /** @internal Force-end this stream (connection closing). */
1236
+ _forceEnd(): void;
1237
+ private _endStream;
1238
+ }
1239
+ /**
1240
+ * WebSocket connection for real-time Text-to-Speech.
1241
+ *
1242
+ * Supports up to 5 concurrent streams multiplexed by `stream_id`.
1243
+ * The connection automatically sends keepalive messages while open.
1244
+ *
1245
+ * @example Multi-stream
1246
+ * ```typescript
1247
+ * const conn = new RealtimeTtsConnection(apiKey, wsUrl, ttsDefaults);
1248
+ * await conn.connect();
1249
+ *
1250
+ * const s1 = conn.stream({ model, voice, language, audio_format });
1251
+ * s1.sendText("Hello");
1252
+ * s1.finish();
1253
+ * for await (const chunk of s1) { ... }
1254
+ *
1255
+ * conn.close();
1256
+ * ```
1257
+ */
1258
+ declare class RealtimeTtsConnection extends TypedEmitter<TtsConnectionEvents> {
1259
+ private readonly apiKey;
1260
+ private readonly wsUrl;
1261
+ private readonly ttsDefaults;
1262
+ private readonly keepaliveIntervalMs;
1263
+ private readonly connectTimeoutMs;
1264
+ private ws;
1265
+ private connected;
1266
+ private connecting;
1267
+ private keepaliveTimer;
1268
+ private readonly activeStreams;
1269
+ constructor(apiKey: string, wsUrl: string, ttsDefaults?: Partial<TtsStreamConfig>, options?: TtsConnectionOptions);
1270
+ /** Whether the WebSocket is connected. */
1271
+ get isConnected(): boolean;
1272
+ /**
1273
+ * Open the WebSocket connection and start keepalive.
1274
+ * Called automatically by {@link stream} if not yet connected.
1275
+ */
1276
+ connect(): Promise<void>;
1277
+ /**
1278
+ * Open a new TTS stream on this connection.
1279
+ * Auto-connects if the WebSocket is not yet open.
1280
+ *
1281
+ * @param input - Stream configuration (merged with tts_defaults)
1282
+ * @returns A ready-to-use stream handle
1283
+ */
1284
+ stream(input?: TtsStreamInput): Promise<RealtimeTtsStream>;
1285
+ /** @internal Open a stream, optionally marking it as connection-owning. */
1286
+ _openStream(input: TtsStreamInput, ownsConnection: boolean): Promise<RealtimeTtsStream>;
1287
+ /**
1288
+ * Close the WebSocket connection and terminate all active streams.
1289
+ */
1290
+ close(): void;
1291
+ /** @internal Send a JSON payload on the WebSocket. */
1292
+ _sendJson(payload: Record<string, unknown>): void;
1293
+ /** @internal Remove a stream from the active set. */
1294
+ _deactivateStream(streamId: string): void;
1295
+ private createWebSocket;
1296
+ private handleMessage;
1297
+ private startKeepalive;
1298
+ private stopKeepalive;
1299
+ }
1300
+ //#endregion
629
1301
  //#region ../core/src/realtime/segments.d.ts
630
1302
  /**
631
1303
  * Groups real-time tokens into segments based on specified grouping keys.
@@ -698,104 +1370,52 @@ declare class RealtimeUtteranceBuffer {
698
1370
  reset(): void;
699
1371
  }
700
1372
  //#endregion
701
- //#region ../core/src/realtime/errors.d.ts
1373
+ //#region ../core/src/tts-rest.d.ts
702
1374
  /**
703
- * Base error class for all real-time (WebSocket) SDK errors
1375
+ * Browser-safe REST client for TTS generation.
1376
+ *
1377
+ * Provides `generate()` (buffered) and `generateStream()` (streaming)
1378
+ * using only `globalThis.fetch`. HTTP failures are surfaced as
1379
+ * {@link SonioxHttpError}, matching the rest of the Soniox SDK.
1380
+ *
1381
+ * Authentication uses the `Authorization: Bearer <api_key>` header.
1382
+ *
1383
+ * @example
1384
+ * ```typescript
1385
+ * const client = new TtsRestClient(apiKey, 'https://tts-rt.soniox.com');
1386
+ * const audio = await client.generate({ text: 'Hello', voice: 'Adrian' });
1387
+ * ```
704
1388
  */
705
- declare class RealtimeError extends SonioxError {
706
- /** Real-time error code */
707
- readonly code: RealtimeErrorCode;
1389
+ declare class TtsRestClient {
1390
+ private readonly apiKey;
1391
+ private readonly ttsApiUrl;
1392
+ constructor(apiKey: string, ttsApiUrl: string);
708
1393
  /**
709
- * Original response payload for debugging.
710
- * Contains the raw WebSocket message that caused the error.
1394
+ * Generate speech audio from text. Returns the full audio as a `Uint8Array`.
1395
+ *
1396
+ * @throws {@link SonioxHttpError} on non-2xx responses, network failures,
1397
+ * or aborted requests.
711
1398
  */
712
- readonly raw: unknown;
713
- constructor(message: string, code?: RealtimeErrorCode, statusCode?: number, raw?: unknown);
1399
+ generate(options: GenerateSpeechOptions): Promise<Uint8Array>;
714
1400
  /**
715
- * Creates a human-readable string representation
1401
+ * Generate speech audio from text as a streaming async iterable.
1402
+ *
1403
+ * Yields `Uint8Array` chunks as they arrive from the server response body.
1404
+ * Lower time-to-first-audio than {@link generate}.
1405
+ *
1406
+ * **Known limitation:** Mid-stream server errors (reported via HTTP trailers)
1407
+ * cannot be detected through the `fetch` API. The iterator may end early
1408
+ * without an explicit error. Use WebSocket TTS for reliable error detection.
1409
+ *
1410
+ * @throws {@link SonioxHttpError} on non-2xx responses, network failures,
1411
+ * or aborted requests (before the stream starts).
716
1412
  */
717
- toString(): string;
1413
+ generateStream(options: GenerateSpeechOptions): AsyncIterable<Uint8Array>;
718
1414
  /**
719
- * Converts to a plain object for logging/serialization
1415
+ * Internal request helper. Performs the fetch, maps network/abort failures
1416
+ * to {@link SonioxHttpError}, and throws on non-2xx responses.
720
1417
  */
721
- toJSON(): Record<string, unknown>;
722
- }
723
- /**
724
- * Authentication error (401).
725
- * Thrown when the API key is invalid or expired.
726
- */
727
- declare class AuthError extends RealtimeError {
728
- constructor(message: string, statusCode?: number, raw?: unknown);
729
- }
730
- /**
731
- * Bad request error (400).
732
- * Thrown for invalid configuration or parameters.
733
- */
734
- declare class BadRequestError extends RealtimeError {
735
- constructor(message: string, statusCode?: number, raw?: unknown);
736
- }
737
- /**
738
- * Quota error (402, 429).
739
- * Thrown when rate limits are exceeded or quota is exhausted.
740
- */
741
- declare class QuotaError extends RealtimeError {
742
- constructor(message: string, statusCode?: number, raw?: unknown);
743
- }
744
- /**
745
- * Connection error.
746
- * Thrown for WebSocket connection failures and transport errors.
747
- */
748
- declare class ConnectionError extends RealtimeError {
749
- constructor(message: string, raw?: unknown);
750
- }
751
- /**
752
- * Network error.
753
- * Thrown for server-side network issues (408, 500, 503).
754
- */
755
- declare class NetworkError extends RealtimeError {
756
- constructor(message: string, statusCode?: number, raw?: unknown);
757
- }
758
- /**
759
- * Abort error.
760
- * Thrown when an operation is cancelled via AbortSignal.
761
- */
762
- declare class AbortError extends RealtimeError {
763
- constructor(message?: string);
764
- }
765
- /**
766
- * State error.
767
- * Thrown when an operation is attempted in an invalid state.
768
- */
769
- declare class StateError extends RealtimeError {
770
- constructor(message: string);
771
- }
772
- //#endregion
773
- //#region src/types/public/errors.d.ts
774
- /**
775
- * Error codes for HTTP client errors
776
- */
777
- type HttpErrorCode = 'network_error' | 'timeout' | 'aborted' | 'http_error' | 'parse_error';
778
- /**
779
- * All possible SDK error codes (core real-time + HTTP-specific codes)
780
- */
781
- type SonioxErrorCode = RealtimeErrorCode | 'soniox_error' | HttpErrorCode;
782
- /**
783
- * HTTP methods supported by the client
784
- */
785
- type HttpMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE' | 'HEAD';
786
- /**
787
- * Error details for SonioxHttpError
788
- */
789
- interface HttpErrorDetails {
790
- code: HttpErrorCode;
791
- message: string;
792
- url: string;
793
- method: HttpMethod;
794
- statusCode?: number | undefined;
795
- headers?: Record<string, string> | undefined;
796
- /** Response body text (capped at 4KB) */
797
- bodyText?: string | undefined;
798
- cause?: unknown;
1418
+ private sendRequest;
799
1419
  }
800
1420
  //#endregion
801
1421
  //#region src/types/public/http.d.ts
@@ -947,12 +1567,31 @@ type RealtimeClientOptions = {
947
1567
  */
948
1568
  api_key: string;
949
1569
  /**
950
- * WebSocket base URL for real-time connections.
1570
+ * STT WebSocket base URL for real-time connections.
951
1571
  * @default 'wss://stt-rt.soniox.com/transcribe-websocket'
952
1572
  */
953
1573
  ws_base_url: string;
954
1574
  /**
955
- * Default session options applied to all real-time sessions.
1575
+ * TTS WebSocket URL for real-time connections.
1576
+ * @default 'wss://tts-rt.soniox.com/tts-websocket'
1577
+ */
1578
+ tts_ws_url: string;
1579
+ /**
1580
+ * STT session config defaults. Merged as the base layer when opening
1581
+ * STT sessions via `realtime.stt(config)`; caller fields override.
1582
+ */
1583
+ stt_defaults?: Partial<SttSessionConfig> | undefined;
1584
+ /**
1585
+ * TTS stream config defaults. Merged as the base layer when opening
1586
+ * TTS streams via `realtime.tts(...)`; caller fields override.
1587
+ */
1588
+ tts_defaults?: Partial<TtsStreamConfig> | undefined;
1589
+ /**
1590
+ * Default TTS connection options.
1591
+ */
1592
+ tts_connection_options?: TtsConnectionOptions | undefined;
1593
+ /**
1594
+ * Default session options applied to all real-time STT sessions.
956
1595
  * Can be overridden per-session.
957
1596
  */
958
1597
  default_session_options?: SttSessionOptions | undefined;
@@ -1825,7 +2464,7 @@ type HonoLikeContext = {
1825
2464
  };
1826
2465
  //#endregion
1827
2466
  //#region src/types/public/index.d.ts
1828
- type TemporaryApiKeyUsageType = 'transcribe_websocket';
2467
+ type TemporaryApiKeyUsageType = 'transcribe_websocket' | 'tts_rt';
1829
2468
  type TemporaryApiKeyRequest = {
1830
2469
  /**
1831
2470
  * Intended usage of the temporary API key.
@@ -1859,16 +2498,44 @@ type TemporaryApiKeyResponse = {
1859
2498
  */
1860
2499
  type RealtimeOptions = {
1861
2500
  /**
1862
- * WebSocket base URL for real-time connections.
2501
+ * STT WebSocket base URL for real-time connections.
1863
2502
  * Falls back to SONIOX_WS_URL environment variable,
1864
2503
  * then to 'wss://stt-rt.soniox.com/transcribe-websocket'.
1865
2504
  */
1866
2505
  ws_base_url?: string | undefined;
1867
2506
  /**
1868
- * Default session options applied to all real-time sessions.
2507
+ * TTS WebSocket URL for real-time connections.
2508
+ * Falls back to SONIOX_TTS_WS_URL environment variable,
2509
+ * then to 'wss://tts-rt.soniox.com/tts-websocket'.
2510
+ */
2511
+ tts_ws_url?: string | undefined;
2512
+ /**
2513
+ * Default TTS connection options (keepalive interval, connect timeout).
2514
+ */
2515
+ tts_connection_options?: TtsConnectionOptions | undefined;
2516
+ /**
2517
+ * Default session options applied to all real-time STT sessions.
1869
2518
  * Can be overridden per-session.
1870
2519
  */
1871
2520
  default_session_options?: SttSessionOptions | undefined;
2521
+ /**
2522
+ * Default STT session config fields (model, language hints, context, etc.).
2523
+ *
2524
+ * Merged as the base layer when opening STT sessions via
2525
+ * `client.realtime.stt(config)`. Fields on the caller-provided `config`
2526
+ * override these defaults. Equivalent to
2527
+ * {@link SonioxConnectionConfig.stt_defaults} on the web/react clients.
2528
+ */
2529
+ stt_defaults?: Partial<SttSessionConfig> | undefined;
2530
+ /**
2531
+ * Default TTS stream config fields (model, voice, language, audio_format, etc.).
2532
+ *
2533
+ * Merged as the base layer when opening TTS streams via
2534
+ * `client.realtime.tts(...)`. Fields on the caller-provided
2535
+ * {@link TtsStreamInput} override these defaults. Equivalent to
2536
+ * {@link SonioxConnectionConfig.tts_defaults} on the web/react clients.
2537
+ */
2538
+ tts_defaults?: Partial<TtsStreamConfig> | undefined;
1872
2539
  };
1873
2540
  type SonioxNodeClientOptions = {
1874
2541
  /**
@@ -1876,16 +2543,62 @@ type SonioxNodeClientOptions = {
1876
2543
  * Falls back to SONIOX_API_KEY environment variable if not provided.
1877
2544
  */
1878
2545
  api_key?: string;
2546
+ /**
2547
+ * Deployment region. Determines which regional endpoints are used
2548
+ * for both the REST API and real-time WebSocket connections.
2549
+ *
2550
+ * Leave `undefined` for the default (US) region.
2551
+ * Shorthand for `base_domain: '{region}.soniox.com'`.
2552
+ * `base_domain` takes precedence when both are provided.
2553
+ *
2554
+ * @see https://soniox.com/docs/stt/data-residency
2555
+ */
2556
+ region?: SonioxRegion | undefined;
2557
+ /**
2558
+ * Base domain for all Soniox service URLs.
2559
+ *
2560
+ * A single override that derives all service endpoints from the pattern
2561
+ * `{service}.{base_domain}`. Takes precedence over `region`.
2562
+ * Falls back to SONIOX_BASE_DOMAIN environment variable.
2563
+ * Individual URL fields (`base_url`, `tts_api_url`, `realtime.ws_base_url`,
2564
+ * `realtime.tts_ws_url`) still take final precedence.
2565
+ *
2566
+ * @example 'eu.soniox.com'
2567
+ */
2568
+ base_domain?: string | undefined;
1879
2569
  /**
1880
2570
  * Base URL for the REST API.
1881
2571
  * Falls back to SONIOX_API_BASE_URL environment variable,
1882
- * then to 'https://api.soniox.com'.
2572
+ * then to the region-derived URL, then to 'https://api.soniox.com'.
1883
2573
  */
1884
2574
  base_url?: string;
2575
+ /**
2576
+ * TTS REST API URL.
2577
+ * Falls back to SONIOX_TTS_API_URL environment variable,
2578
+ * then to the region-derived URL, then to 'https://tts-rt.soniox.com'.
2579
+ */
2580
+ tts_api_url?: string;
1885
2581
  /**
1886
2582
  * Custom HTTP client implementation.
1887
2583
  */
1888
2584
  http_client?: HttpClient;
2585
+ /**
2586
+ * Default STT session config fields applied to every real-time STT session
2587
+ * opened via `client.realtime.stt(config)`. Caller-provided fields override.
2588
+ *
2589
+ * Equivalent to {@link SonioxConnectionConfig.stt_defaults} on the
2590
+ * web/react clients. Prefer this when you want the same defaults
2591
+ * across your whole Node process.
2592
+ */
2593
+ stt_defaults?: Partial<SttSessionConfig> | undefined;
2594
+ /**
2595
+ * Default TTS stream config fields applied to every real-time TTS stream
2596
+ * opened via `client.realtime.tts(...)`. Caller-provided fields override.
2597
+ *
2598
+ * Equivalent to {@link SonioxConnectionConfig.tts_defaults} on the
2599
+ * web/react clients.
2600
+ */
2601
+ tts_defaults?: Partial<TtsStreamConfig> | undefined;
1889
2602
  /**
1890
2603
  * Real-time API configuration options.
1891
2604
  */
@@ -1902,6 +2615,19 @@ declare class SonioxAuthAPI {
1902
2615
  * @param request - Request parameters for the temporary key
1903
2616
  * @param signal - Optional AbortSignal for cancellation
1904
2617
  * @returns The temporary API key response
2618
+ *
2619
+ * @example
2620
+ * ```typescript
2621
+ * const sttKey = await client.auth.createTemporaryKey({
2622
+ * usage_type: 'transcribe_websocket',
2623
+ * expires_in_seconds: 300,
2624
+ * });
2625
+ *
2626
+ * const ttsKey = await client.auth.createTemporaryKey({
2627
+ * usage_type: 'tts_rt',
2628
+ * expires_in_seconds: 300,
2629
+ * });
2630
+ * ```
1905
2631
  */
1906
2632
  createTemporaryKey(request: TemporaryApiKeyRequest, signal?: AbortSignal): Promise<TemporaryApiKeyResponse>;
1907
2633
  }
@@ -2721,6 +3447,59 @@ declare class SonioxSttApi {
2721
3447
  destroy_all(options?: DeleteAllTranscriptionsOptions): Promise<void>;
2722
3448
  }
2723
3449
  //#endregion
3450
+ //#region src/async/tts.d.ts
3451
+ /**
3452
+ * REST API for Text-to-Speech generation and TTS model listing.
3453
+ *
3454
+ * Accessed via `client.tts` on {@link SonioxNodeClient}.
3455
+ *
3456
+ * Inherits browser-safe `generate()` and `generateStream()` from
3457
+ * `TtsRestClient` in `@soniox/core`, and adds Node-specific methods
3458
+ * `generateToFile()` and `listModels()`.
3459
+ */
3460
+ declare class SonioxTtsApi extends TtsRestClient {
3461
+ private readonly http;
3462
+ constructor(apiKey: string, ttsApiUrl: string, http: HttpClient);
3463
+ /**
3464
+ * Generate speech audio and write to a file or writable stream.
3465
+ *
3466
+ * @param output - File path (string) or a `WritableStream<Uint8Array>`
3467
+ * @param options - Generation options
3468
+ * @returns Number of bytes written
3469
+ *
3470
+ * @example Write to file
3471
+ * ```typescript
3472
+ * const bytes = await client.tts.generateToFile('output.wav', {
3473
+ * text: 'Hello world',
3474
+ * voice: 'Adrian',
3475
+ * language: 'en',
3476
+ * });
3477
+ * ```
3478
+ *
3479
+ * @example Write to a writable stream
3480
+ * ```typescript
3481
+ * const bytes = await client.tts.generateToFile(writableStream, {
3482
+ * text: 'Hello world',
3483
+ * voice: 'Adrian',
3484
+ * language: 'en',
3485
+ * });
3486
+ * ```
3487
+ */
3488
+ generateToFile(output: string | WritableStream<Uint8Array>, options: GenerateSpeechOptions): Promise<number>;
3489
+ /**
3490
+ * List available TTS models and their voices.
3491
+ *
3492
+ * @example
3493
+ * ```typescript
3494
+ * const models = await client.tts.listModels();
3495
+ * for (const model of models) {
3496
+ * console.log(model.id, model.voices.map(v => v.id));
3497
+ * }
3498
+ * ```
3499
+ */
3500
+ listModels(signal?: AbortSignal): Promise<TtsModel[]>;
3501
+ }
3502
+ //#endregion
2724
3503
  //#region src/async/webhooks.d.ts
2725
3504
  /**
2726
3505
  * Webhook utilities API accessible via client.webhooks
@@ -2799,48 +3578,134 @@ declare class SonioxWebhooksAPI {
2799
3578
  //#endregion
2800
3579
  //#region src/realtime/index.d.ts
2801
3580
  /**
2802
- * Real-time API factory for creating STT sessions.
3581
+ * Callable TTS factory with `.multiStream()` for multi-stream connections.
3582
+ */
3583
+ interface TtsFactory {
3584
+ /**
3585
+ * Create a single-stream TTS connection.
3586
+ * Opens a WebSocket, starts one stream, and returns a ready-to-use stream
3587
+ * that owns its connection (closing the stream closes the connection).
3588
+ *
3589
+ * @example
3590
+ * ```typescript
3591
+ * const stream = await client.realtime.tts({
3592
+ * model: 'tts-rt-v1-preview',
3593
+ * voice: 'Adrian',
3594
+ * language: 'en',
3595
+ * audio_format: 'wav',
3596
+ * });
3597
+ * stream.sendText("Hello world");
3598
+ * stream.finish();
3599
+ * for await (const chunk of stream) { process(chunk); }
3600
+ * ```
3601
+ */
3602
+ (input?: TtsStreamInput): Promise<RealtimeTtsStream>;
3603
+ /**
3604
+ * Create a multi-stream TTS connection.
3605
+ * Opens a single WebSocket that can host up to 5 concurrent streams.
3606
+ *
3607
+ * @example
3608
+ * ```typescript
3609
+ * const conn = await client.realtime.tts.multiStream();
3610
+ * const s1 = await conn.stream({
3611
+ * model: 'tts-rt-v1-preview',
3612
+ * voice: 'Adrian',
3613
+ * language: 'en',
3614
+ * audio_format: 'wav',
3615
+ * });
3616
+ * // Use any voice returned by client.tts.listModels()
3617
+ * const s2 = await conn.stream({
3618
+ * model: 'tts-rt-v1-preview',
3619
+ * voice: someOtherVoice,
3620
+ * language: 'en',
3621
+ * audio_format: 'wav',
3622
+ * });
3623
+ * ```
3624
+ */
3625
+ multiStream(): Promise<RealtimeTtsConnection>;
3626
+ }
3627
+ /**
3628
+ * Real-time API factory for creating STT sessions and TTS connections.
2803
3629
  *
2804
- * @example
3630
+ * @example STT
3631
+ * ```typescript
3632
+ * const session = client.realtime.stt({ model: 'stt-rt-v4' });
3633
+ * await session.connect();
3634
+ * ```
3635
+ *
3636
+ * @example TTS (single stream)
2805
3637
  * ```typescript
2806
- * const session = client.realtime.stt({
2807
- * model: 'stt-rt-v4',
2808
- * enable_endpoint_detection: true,
3638
+ * const stream = await client.realtime.tts({
3639
+ * model: 'tts-rt-v1-preview',
3640
+ * voice: 'Adrian',
3641
+ * language: 'en',
3642
+ * audio_format: 'wav',
2809
3643
  * });
3644
+ * stream.sendText("Hello");
3645
+ * stream.finish();
3646
+ * for await (const chunk of stream) { ... }
3647
+ * ```
2810
3648
  *
2811
- * await session.connect();
3649
+ * @example TTS (multi-stream)
3650
+ * ```typescript
3651
+ * const conn = await client.realtime.tts.multiStream();
3652
+ * const stream = await conn.stream({
3653
+ * model: 'tts-rt-v1-preview',
3654
+ * voice: 'Adrian',
3655
+ * language: 'en',
3656
+ * audio_format: 'wav',
3657
+ * });
2812
3658
  * ```
2813
3659
  */
2814
3660
  declare class SonioxRealtimeApi {
2815
3661
  private readonly options;
3662
+ readonly tts: TtsFactory;
2816
3663
  constructor(options: RealtimeClientOptions);
2817
3664
  /**
2818
3665
  * Create a new Speech-to-Text session.
2819
3666
  *
2820
- * @param config - Session configuration (sent to server)
2821
- * @param options - Session options (SDK-level settings)
2822
- * @returns New STT session instance
3667
+ * `config` is shallow-merged on top of `stt_defaults` from the client
3668
+ * options; caller-provided fields override the defaults.
2823
3669
  */
2824
3670
  stt(config: SttSessionConfig, options?: SttSessionOptions): RealtimeSttSession;
3671
+ private createSingleTtsStream;
3672
+ private createTtsConnection;
2825
3673
  }
2826
3674
  //#endregion
2827
3675
  //#region src/client.d.ts
2828
3676
  /**
2829
3677
  * Soniox Node Client
2830
- * @returns {SonioxNodeClient}
2831
3678
  *
2832
3679
  * @example
2833
3680
  * ```typescript
2834
3681
  * import { SonioxNodeClient } from '@soniox/node';
2835
3682
  *
2836
- * const client = new SonioxNodeClient({
2837
- * api_key: 'your-api-key',
3683
+ * // Default (US) region
3684
+ * const client = new SonioxNodeClient({ api_key: 'your-api-key' });
3685
+ *
3686
+ * // EU region
3687
+ * const client = new SonioxNodeClient({ api_key: 'your-api-key', region: 'eu' });
3688
+ *
3689
+ * // REST TTS
3690
+ * const audio = await client.tts.generate({
3691
+ * text: 'Hello',
3692
+ * voice: 'Adrian',
3693
+ * language: 'en',
3694
+ * });
3695
+ *
3696
+ * // WebSocket TTS
3697
+ * const stream = await client.realtime.tts({
3698
+ * model: 'tts-rt-v1-preview',
3699
+ * voice: 'Adrian',
3700
+ * language: 'en',
3701
+ * audio_format: 'wav',
2838
3702
  * });
2839
3703
  * ```
2840
3704
  */
2841
3705
  declare class SonioxNodeClient {
2842
3706
  readonly files: SonioxFilesAPI;
2843
3707
  readonly stt: SonioxSttApi;
3708
+ readonly tts: SonioxTtsApi;
2844
3709
  readonly models: SonioxModelsAPI;
2845
3710
  readonly webhooks: SonioxWebhooksAPI;
2846
3711
  readonly auth: SonioxAuthAPI;
@@ -2932,68 +3797,6 @@ declare class FetchHttpClient implements HttpClient {
2932
3797
  private normalizeError;
2933
3798
  }
2934
3799
  //#endregion
2935
- //#region src/http/errors.d.ts
2936
- /**
2937
- * HTTP error class for all HTTP-related failures (REST API).
2938
- *
2939
- * Thrown when HTTP requests fail due to network issues, timeouts,
2940
- * server errors, or response parsing failures.
2941
- */
2942
- declare class SonioxHttpError extends SonioxError {
2943
- /** Categorized HTTP error code */
2944
- readonly code: HttpErrorCode;
2945
- /** Request URL */
2946
- readonly url: string;
2947
- /** HTTP method */
2948
- readonly method: HttpMethod;
2949
- /** Response headers (only for http_error) */
2950
- readonly headers: Record<string, string> | undefined;
2951
- /** Response body text, capped at 4KB (only for http_error/parse_error) */
2952
- readonly bodyText: string | undefined;
2953
- constructor(details: HttpErrorDetails);
2954
- /**
2955
- * Creates a human-readable string representation
2956
- */
2957
- toString(): string;
2958
- /**
2959
- * Converts to a plain object for logging/serialization
2960
- */
2961
- toJSON(): Record<string, unknown>;
2962
- }
2963
- /**
2964
- * Creates a network error
2965
- */
2966
- declare function createNetworkError(url: string, method: HttpMethod, cause: unknown): SonioxHttpError;
2967
- /**
2968
- * Creates a timeout error
2969
- */
2970
- declare function createTimeoutError(url: string, method: HttpMethod, timeoutMs: number): SonioxHttpError;
2971
- /**
2972
- * Creates an abort error
2973
- */
2974
- declare function createAbortError(url: string, method: HttpMethod, cause?: unknown): SonioxHttpError;
2975
- /**
2976
- * Creates an HTTP error (non-2xx status)
2977
- */
2978
- declare function createHttpError(url: string, method: HttpMethod, statusCode: number, headers: Record<string, string>, bodyText: string): SonioxHttpError;
2979
- /**
2980
- * Creates a parse error (invalid JSON, etc.)
2981
- */
2982
- declare function createParseError(url: string, method: HttpMethod, bodyText: string, cause: unknown): SonioxHttpError;
2983
- /**
2984
- * Type guard to check if an error is an AbortError
2985
- */
2986
- declare function isAbortError(error: unknown): boolean;
2987
- /**
2988
- * Type guard to check if an error is any SonioxError (base class).
2989
- * This catches all SDK errors including HTTP and real-time errors.
2990
- */
2991
- declare function isSonioxError(error: unknown): error is SonioxError;
2992
- /**
2993
- * Type guard to check if an error is a SonioxHttpError
2994
- */
2995
- declare function isSonioxHttpError(error: unknown): error is SonioxHttpError;
2996
- //#endregion
2997
3800
  //#region src/http/url.d.ts
2998
3801
  /**
2999
3802
  * Builds a complete URL from base URL, path, and query parameters
@@ -3008,5 +3811,5 @@ declare function normalizeHeaders(headers: Headers): Record<string, string>;
3008
3811
  */
3009
3812
  declare function mergeHeaders(...headerObjects: (Record<string, string> | undefined)[]): Record<string, string>;
3010
3813
  //#endregion
3011
- export { AbortError, type AudioData, type AudioFormat, AuthError, BadRequestError, type CleanupTarget, ConnectionError, type ContextGeneralEntry, type ContextTranslationTerm, type CreateTranscriptionOptions, type DeleteAllFilesOptions, type DeleteAllTranscriptionsOptions, type ExpressLikeRequest, type FastifyLikeRequest, FetchHttpClient, type FileIdentifier, FileListResult, type HandleWebhookOptions, type HonoLikeContext, type HttpClient, type HttpClientOptions, type HttpErrorCode, type HttpErrorDetails, type HttpMethod, type HttpObservabilityHooks, type HttpRequest, type HttpRequestBody, type HttpRequestMeta, type HttpResponse, type HttpResponseMeta, type HttpResponseType, type ISonioxTranscript, type ISonioxTranscription, type ListFilesOptions, type ListFilesResponse, type ListTranscriptionsOptions, type ListTranscriptionsResponse, type NestJSLikeRequest, NetworkError, type OneWayTranslationConfig, type QueryParams, QuotaError, type RealtimeClientOptions, RealtimeError, type RealtimeErrorCode, type RealtimeEvent, RealtimeOptions, type RealtimeResult, type RealtimeSegment, RealtimeSegmentBuffer, type RealtimeSegmentBufferOptions, type RealtimeSegmentOptions, RealtimeSttSession, type RealtimeToken, type RealtimeUtterance, RealtimeUtteranceBuffer, type RealtimeUtteranceBufferOptions, SONIOX_API_BASE_URL, SONIOX_API_WEBHOOK_HEADER_ENV, SONIOX_API_WEBHOOK_SECRET_ENV, SONIOX_API_WS_URL, SONIOX_TMP_API_KEY_DURATION_MAX, SONIOX_TMP_API_KEY_DURATION_MIN, SONIOX_TMP_API_KEY_USAGE_TYPE, type SegmentGroupKey, type SegmentTranscriptOptions, type SendStreamOptions, SonioxError, type SonioxErrorCode, SonioxFile, type SonioxFileData, SonioxHttpError, type SonioxLanguage, type SonioxModel, SonioxNodeClient, SonioxNodeClientOptions, SonioxRealtimeApi, SonioxTranscript, SonioxTranscription, type SonioxTranscriptionData, type SonioxTranscriptionMode, type SonioxTranslationTarget, StateError, type SttSessionConfig, type SttSessionEvents, type SttSessionOptions, type SttSessionState, TemporaryApiKeyRequest, TemporaryApiKeyResponse, TemporaryApiKeyUsageType, type TranscribeBaseOptions, type TranscribeFromFile, type TranscribeFromFileId, type TranscribeFromFileIdOptions, type TranscribeFromFileOptions, type TranscribeFromUrl, type TranscribeFromUrlOptions, type TranscribeOptions, type TranscriptResponse, type TranscriptSegment, type TranscriptToken, type TranscriptionContext, type TranscriptionIdentifier, TranscriptionListResult, type TranscriptionStatus, type TranslationConfig, type TwoWayTranslationConfig, type UploadFileInput, type UploadFileOptions, type WaitOptions, type WebhookAuthConfig, type WebhookEvent, type WebhookEventStatus, type WebhookHandlerResult, type WebhookHandlerResultWithFetch, type WebhookHeaders, buildUrl, createAbortError, createHttpError, createNetworkError, createParseError, createTimeoutError, isAbortError, isSonioxError, isSonioxHttpError, mergeHeaders, normalizeHeaders, segmentRealtimeTokens, segmentTranscript };
3814
+ export { AbortError, type AudioData, type AudioFormat, AuthError, BadRequestError, type CleanupTarget, ConnectionError, type ContextGeneralEntry, type ContextTranslationTerm, type CreateTranscriptionOptions, type DeleteAllFilesOptions, type DeleteAllTranscriptionsOptions, type ExpressLikeRequest, type FastifyLikeRequest, FetchHttpClient, type FileIdentifier, FileListResult, type GenerateSpeechOptions, type HandleWebhookOptions, type HonoLikeContext, type HttpClient, type HttpClientOptions, type HttpErrorCode, type HttpErrorDetails, type HttpMethod, type HttpObservabilityHooks, type HttpRequest, type HttpRequestBody, type HttpRequestMeta, type HttpResponse, type HttpResponseMeta, type HttpResponseType, type ISonioxTranscript, type ISonioxTranscription, type ListFilesOptions, type ListFilesResponse, type ListTranscriptionsOptions, type ListTranscriptionsResponse, type NestJSLikeRequest, NetworkError, type OneWayTranslationConfig, type QueryParams, QuotaError, type RealtimeClientOptions, RealtimeError, type RealtimeErrorCode, type RealtimeEvent, RealtimeOptions, type RealtimeResult, type RealtimeSegment, RealtimeSegmentBuffer, type RealtimeSegmentBufferOptions, type RealtimeSegmentOptions, RealtimeSttSession, type RealtimeToken, RealtimeTtsConnection, RealtimeTtsStream, type RealtimeUtterance, RealtimeUtteranceBuffer, type RealtimeUtteranceBufferOptions, type ResolvedConnectionConfig, SONIOX_API_BASE_URL, SONIOX_API_WEBHOOK_HEADER_ENV, SONIOX_API_WEBHOOK_SECRET_ENV, SONIOX_API_WS_URL, SONIOX_TMP_API_KEY_DURATION_MAX, SONIOX_TMP_API_KEY_DURATION_MIN, SONIOX_TMP_API_KEY_USAGE_TYPE, SONIOX_TTS_API_BASE_URL, SONIOX_TTS_WS_URL, type SegmentGroupKey, type SegmentTranscriptOptions, type SendStreamOptions, type SonioxConnectionConfig, SonioxError, type SonioxErrorCode, SonioxFile, type SonioxFileData, SonioxHttpError, type SonioxLanguage, type SonioxModel, SonioxNodeClient, SonioxNodeClientOptions, SonioxRealtimeApi, type SonioxRegion, SonioxTranscript, SonioxTranscription, type SonioxTranscriptionData, type SonioxTranscriptionMode, type SonioxTranslationTarget, SonioxTtsApi, StateError, type SttSessionConfig, type SttSessionEvents, type SttSessionOptions, type SttSessionState, TemporaryApiKeyRequest, TemporaryApiKeyResponse, TemporaryApiKeyUsageType, type TranscribeBaseOptions, type TranscribeFromFile, type TranscribeFromFileId, type TranscribeFromFileIdOptions, type TranscribeFromFileOptions, type TranscribeFromUrl, type TranscribeFromUrlOptions, type TranscribeOptions, type TranscriptResponse, type TranscriptSegment, type TranscriptToken, type TranscriptionContext, type TranscriptionIdentifier, TranscriptionListResult, type TranscriptionStatus, type TranslationConfig, type TtsAudioFormat, type TtsConnectionEvents, type TtsConnectionOptions, type TtsEvent, type TtsModel, type TtsStreamConfig, type TtsStreamEvents, type TtsStreamInput, type TtsStreamState, type TtsVoice, type TwoWayTranslationConfig, type UploadFileInput, type UploadFileOptions, type WaitOptions, type WebhookAuthConfig, type WebhookEvent, type WebhookEventStatus, type WebhookHandlerResult, type WebhookHandlerResultWithFetch, type WebhookHeaders, buildUrl, createAbortError, createHttpError, createNetworkError, createParseError, createTimeoutError, isAbortError, isSonioxError, isSonioxHttpError, mergeHeaders, normalizeHeaders, resolveConnectionConfig, segmentRealtimeTokens, segmentTranscript };
3012
3815
  //# sourceMappingURL=index.d.mts.map