@speech-sdk/core 0.5.2 → 0.6.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.
Files changed (115) hide show
  1. package/README.md +110 -1
  2. package/dist/__tests__/e2e/_save-audio.d.ts +11 -0
  3. package/dist/__tests__/e2e/_save-audio.d.ts.map +1 -0
  4. package/dist/__tests__/e2e/_save-audio.js +43 -0
  5. package/dist/__tests__/e2e/_save-audio.js.map +1 -0
  6. package/dist/audio-utils.d.ts +12 -0
  7. package/dist/audio-utils.d.ts.map +1 -0
  8. package/dist/audio-utils.js +53 -0
  9. package/dist/audio-utils.js.map +1 -0
  10. package/dist/conversation/dispatch.d.ts +17 -0
  11. package/dist/conversation/dispatch.d.ts.map +1 -0
  12. package/dist/conversation/dispatch.js +60 -0
  13. package/dist/conversation/dispatch.js.map +1 -0
  14. package/dist/conversation/errors.d.ts +23 -0
  15. package/dist/conversation/errors.d.ts.map +1 -0
  16. package/dist/conversation/errors.js +28 -0
  17. package/dist/conversation/errors.js.map +1 -0
  18. package/dist/conversation/pcm-concat.d.ts +37 -0
  19. package/dist/conversation/pcm-concat.d.ts.map +1 -0
  20. package/dist/conversation/pcm-concat.js +246 -0
  21. package/dist/conversation/pcm-concat.js.map +1 -0
  22. package/dist/conversation/stitch.d.ts +33 -0
  23. package/dist/conversation/stitch.d.ts.map +1 -0
  24. package/dist/conversation/stitch.js +78 -0
  25. package/dist/conversation/stitch.js.map +1 -0
  26. package/dist/conversation/types.d.ts +39 -0
  27. package/dist/conversation/types.d.ts.map +1 -0
  28. package/dist/conversation/types.js +2 -0
  29. package/dist/conversation/types.js.map +1 -0
  30. package/dist/conversation/validate.d.ts +19 -0
  31. package/dist/conversation/validate.d.ts.map +1 -0
  32. package/dist/conversation/validate.js +50 -0
  33. package/dist/conversation/validate.js.map +1 -0
  34. package/dist/errors.d.ts +3 -0
  35. package/dist/errors.d.ts.map +1 -1
  36. package/dist/errors.js +6 -0
  37. package/dist/errors.js.map +1 -1
  38. package/dist/generate-conversation.d.ts +6 -0
  39. package/dist/generate-conversation.d.ts.map +1 -0
  40. package/dist/generate-conversation.js +154 -0
  41. package/dist/generate-conversation.js.map +1 -0
  42. package/dist/generate-speech.d.ts +10 -0
  43. package/dist/generate-speech.d.ts.map +1 -1
  44. package/dist/generate-speech.js +30 -5
  45. package/dist/generate-speech.js.map +1 -1
  46. package/dist/provider-utils.d.ts +1 -0
  47. package/dist/provider-utils.d.ts.map +1 -1
  48. package/dist/provider-utils.js +5 -0
  49. package/dist/provider-utils.js.map +1 -1
  50. package/dist/providers/cartesia/index.d.ts +10 -0
  51. package/dist/providers/cartesia/index.d.ts.map +1 -1
  52. package/dist/providers/cartesia/index.js +18 -1
  53. package/dist/providers/cartesia/index.js.map +1 -1
  54. package/dist/providers/deepgram/index.d.ts +8 -0
  55. package/dist/providers/deepgram/index.d.ts.map +1 -1
  56. package/dist/providers/deepgram/index.js +39 -19
  57. package/dist/providers/deepgram/index.js.map +1 -1
  58. package/dist/providers/elevenlabs/index.d.ts +25 -0
  59. package/dist/providers/elevenlabs/index.d.ts.map +1 -1
  60. package/dist/providers/elevenlabs/index.js +56 -1
  61. package/dist/providers/elevenlabs/index.js.map +1 -1
  62. package/dist/providers/fal/index.d.ts +25 -5
  63. package/dist/providers/fal/index.d.ts.map +1 -1
  64. package/dist/providers/fal/index.js +73 -11
  65. package/dist/providers/fal/index.js.map +1 -1
  66. package/dist/providers/fish-audio/index.d.ts +24 -0
  67. package/dist/providers/fish-audio/index.d.ts.map +1 -1
  68. package/dist/providers/fish-audio/index.js +57 -1
  69. package/dist/providers/fish-audio/index.js.map +1 -1
  70. package/dist/providers/google/index.d.ts +25 -2
  71. package/dist/providers/google/index.d.ts.map +1 -1
  72. package/dist/providers/google/index.js +166 -51
  73. package/dist/providers/google/index.js.map +1 -1
  74. package/dist/providers/hume/index.d.ts +26 -0
  75. package/dist/providers/hume/index.d.ts.map +1 -1
  76. package/dist/providers/hume/index.js +58 -1
  77. package/dist/providers/hume/index.js.map +1 -1
  78. package/dist/providers/inworld/index.d.ts +9 -0
  79. package/dist/providers/inworld/index.d.ts.map +1 -1
  80. package/dist/providers/inworld/index.js +15 -4
  81. package/dist/providers/inworld/index.js.map +1 -1
  82. package/dist/providers/mistral/index.d.ts +6 -0
  83. package/dist/providers/mistral/index.d.ts.map +1 -1
  84. package/dist/providers/mistral/index.js +34 -13
  85. package/dist/providers/mistral/index.js.map +1 -1
  86. package/dist/providers/murf/index.d.ts +4 -0
  87. package/dist/providers/murf/index.d.ts.map +1 -1
  88. package/dist/providers/murf/index.js +15 -1
  89. package/dist/providers/murf/index.js.map +1 -1
  90. package/dist/providers/openai/index.d.ts +6 -0
  91. package/dist/providers/openai/index.d.ts.map +1 -1
  92. package/dist/providers/openai/index.js +12 -1
  93. package/dist/providers/openai/index.js.map +1 -1
  94. package/dist/providers/resemble/index.d.ts +6 -0
  95. package/dist/providers/resemble/index.d.ts.map +1 -1
  96. package/dist/providers/resemble/index.js +15 -1
  97. package/dist/providers/resemble/index.js.map +1 -1
  98. package/dist/providers/xai/index.d.ts +8 -0
  99. package/dist/providers/xai/index.d.ts.map +1 -1
  100. package/dist/providers/xai/index.js +14 -1
  101. package/dist/providers/xai/index.js.map +1 -1
  102. package/dist/resolve-provider.d.ts.map +1 -1
  103. package/dist/resolve-provider.js +0 -3
  104. package/dist/resolve-provider.js.map +1 -1
  105. package/dist/speech-provider.d.ts +24 -0
  106. package/dist/speech-provider.d.ts.map +1 -1
  107. package/dist/volume-adjust.d.ts +14 -0
  108. package/dist/volume-adjust.d.ts.map +1 -0
  109. package/dist/volume-adjust.js +27 -0
  110. package/dist/volume-adjust.js.map +1 -0
  111. package/package.json +11 -7
  112. package/dist/providers/unreal-speech/index.d.ts +0 -46
  113. package/dist/providers/unreal-speech/index.d.ts.map +0 -1
  114. package/dist/providers/unreal-speech/index.js +0 -96
  115. package/dist/providers/unreal-speech/index.js.map +0 -1
package/README.md CHANGED
@@ -42,6 +42,23 @@ result.audio.base64; // string (lazy-computed)
42
42
  result.audio.mediaType; // "audio/mpeg"
43
43
  ```
44
44
 
45
+ ### Volume normalization
46
+
47
+ Pass `volumeDbfs` to RMS-normalize the output to an absolute target loudness (must be ≤ 0; lower is quieter; -20 is the broadcast/podcast voice convention with ~20 dB of peak headroom):
48
+
49
+ ```ts
50
+ const result = await generateSpeech({
51
+ model: 'openai/gpt-4o-mini-tts',
52
+ text: 'Hello from speech-sdk!',
53
+ voice: 'alloy',
54
+ volumeDbfs: -20,
55
+ });
56
+
57
+ result.audio.mediaType; // "audio/wav" — re-encoded after normalization
58
+ ```
59
+
60
+ When `volumeDbfs` is set the SDK transparently asks the provider for its decodable PCM/WAV mode, normalizes the samples, and returns 16-bit mono WAV — so the response `mediaType` switches to `audio/wav` regardless of the provider's native default. Throws `VolumeAdjustmentUnsupportedError` if the provider has no decodable output mode.
61
+
45
62
  ## Streaming
46
63
 
47
64
  Use `streamSpeech()` instead of `generateSpeech()` to receive audio bytes incrementally as the provider produces them. The result's `audio` field is a standard `ReadableStream<Uint8Array>` that works in Node, Edge runtimes, and browsers.
@@ -117,6 +134,93 @@ Calling `streamSpeech()` on a model that doesn't declare the `"streaming"` featu
117
134
 
118
135
  Retries apply only to the initial request, until response headers arrive. Once bytes start flowing, mid-stream errors propagate to the `ReadableStream` consumer as a stream error and are not retried. Pass `maxRetries` (default `2`) and an `abortSignal` the same way as `generateSpeech()`.
119
136
 
137
+ ## Conversations
138
+
139
+ `generateConversation()` produces a single multi-voice audio clip from an ordered array of turns. It picks the best path automatically:
140
+
141
+ - **Native dialogue** — when every turn shares one model and that provider has a real multi-speaker dialogue endpoint, the SDK makes a single API call and returns the provider's natural mix. Works with **ElevenLabs v3**, **Google Gemini TTS** (exactly 2 voices), **Hume Octave**, **Fish Audio S2-Pro**, and **fal Dia**.
142
+ - **Stitch fallback** — when turns span multiple providers, or the chosen model has no native dialogue endpoint, the SDK calls `generateSpeech()` per turn in parallel, normalizes each result to PCM, RMS-levels them so quieter providers don't get drowned out, inserts a configurable silence between turns, and returns a single WAV.
143
+
144
+ ```ts
145
+ import { generateConversation } from "@speech-sdk/core/conversation";
146
+
147
+ const result = await generateConversation({
148
+ turns: [
149
+ { model: "openai/tts-1", voice: "nova", text: "Hi, I'm hosted by OpenAI." },
150
+ { model: "elevenlabs/eleven_multilingual_v2", voice: "JBFqnCBsd6RMkjVDRZzb", text: "And I'm hosted by ElevenLabs." },
151
+ { model: "google/gemini-3.1-flash-tts-preview", voice: "Kore", text: "I'm Gemini three-point-one flash TTS." },
152
+ { model: "hume/octave-2", voice: "Kora", text: "And I'm Hume Octave. Thanks for listening." },
153
+ ],
154
+ });
155
+
156
+ result.audio.uint8Array; // Uint8Array of one combined WAV
157
+ result.audio.mediaType; // "audio/wav"
158
+ ```
159
+
160
+ The return type is the standard `SpeechResult`, so it composes with everything else in the SDK.
161
+
162
+ ### Conversation options
163
+
164
+ ```ts
165
+ generateConversation({
166
+ model?: string | ResolvedModel, // default model for all turns
167
+ turns: ConversationTurn[], // 1..N turns; up to 4 unique voices
168
+ gapMs?: number, // silence between turns (stitch path), default 300
169
+ normalizeVolume?: boolean, // RMS-level the output, default true
170
+ volumeDbfs?: number, // RMS target loudness in dBFS (≤0), default -20
171
+ maxConcurrency?: number, // cap parallel generateSpeech calls, default 6
172
+ maxRetries?: number, // per-turn retries, default 2
173
+ apiKey?: string,
174
+ providerOptions?: Record<string, unknown>, // forwarded to every provider; per-turn override available
175
+ abortSignal?: AbortSignal,
176
+ headers?: Record<string, string>,
177
+ });
178
+
179
+ interface ConversationTurn {
180
+ voice: Voice; // required
181
+ text: string; // required, non-empty
182
+ model?: string | ResolvedModel; // per-turn override of the top-level model
183
+ providerOptions?: Record<string, unknown>,
184
+ }
185
+ ```
186
+
187
+ ### Volume normalization
188
+
189
+ `normalizeVolume: true` (the default) RMS-normalizes the output to an absolute target loudness — broadcast/podcast voice convention — so two `generateConversation` calls produce comparable levels regardless of provider mix or content. The target defaults to **−20 dBFS** (~20 dB of peak headroom), and is configurable via `volumeDbfs` (must be ≤ 0; lower is quieter).
190
+
191
+ ```ts
192
+ await generateConversation({
193
+ turns: [...],
194
+ volumeDbfs: -16, // a touch louder than the default
195
+ });
196
+ ```
197
+
198
+ Normalization runs on **both paths** — stitched multi-provider conversations and single-provider native dialogue. On the native path the SDK transparently asks the provider for its decodable PCM/WAV mode (via `getStitchOptions`), levels the result, and re-encodes as 16-bit mono WAV — so the response `mediaType` becomes `audio/wav` whenever normalization runs. If a native dialogue provider can't emit decodable audio, the request still succeeds but a `warning` is appended explaining that volume normalization was skipped.
199
+
200
+ Pass `normalizeVolume: false` to skip normalization entirely (zero work) and keep the raw provider audio bytes and `mediaType` untouched.
201
+
202
+ ### Errors
203
+
204
+ Conversation-specific errors (importable from `@speech-sdk/core/conversation/errors`):
205
+
206
+ | Error | When |
207
+ |---|---|
208
+ | `ConversationInputError` | Validation failure — empty turns, blank text, more than 4 unique voices, or a turn missing a model |
209
+ | `DialogueConstraintError` | A native-dialogue provider was selected but the conversation violates its constraints (e.g. 3 voices on Gemini, which requires exactly 2) |
210
+ | `StitchUnsupportedError` | The stitch path was selected but a chosen provider/model can't emit PCM/WAV |
211
+
212
+ ### Native dialogue caps
213
+
214
+ | Provider | Native dialogue model | Voice constraints |
215
+ |---|---|---|
216
+ | ElevenLabs | `eleven_v3` | 1–10 voices, ≤ 2,000 total chars |
217
+ | Google | `gemini-2.5-flash-preview-tts`, `gemini-2.5-pro-preview-tts`, `gemini-3.1-flash-tts-preview` | **Exactly 2 voices** (API requirement) |
218
+ | Hume | `octave-1`, `octave-2` | 1–4 voices |
219
+ | Fish Audio | `s2-pro` | 1–4 voices |
220
+ | fal | `dia-tts` | 1–2 voices |
221
+
222
+ Across the SDK, conversations are capped at **4 unique voices** total regardless of provider.
223
+
120
224
  ## Supported Providers
121
225
 
122
226
  Use `provider/model` strings. Passing just the provider name uses its default model.
@@ -131,7 +235,6 @@ Use `provider/model` strings. Passing just the provider name uses its default mo
131
235
  | [Inworld](https://docs.inworld.ai/tts) | `inworld` | `inworld-tts-1.5-max` | `INWORLD_API_KEY` | [API Reference](https://docs.inworld.ai/tts/api-reference) |
132
236
  | [Google (Gemini TTS)](https://docs.cloud.google.com/text-to-speech/docs/gemini-tts) | `google` | `gemini-2.5-flash-preview-tts` | `GOOGLE_API_KEY` | [API Reference](https://ai.google.dev/gemini-api/docs/text-generation) |
133
237
  | [Fish Audio](https://docs.fish.audio) | `fish-audio` | `s2-pro` | `FISH_AUDIO_API_KEY` | [API Reference](https://docs.fish.audio/developer-guide/core-features/text-to-speech) |
134
- | [Unreal Speech](https://docs.v8.unrealspeech.com) | `unreal-speech` | `default` | `UNREAL_SPEECH_API_KEY` | [API Reference](https://docs.v8.unrealspeech.com) |
135
238
  | [Murf](https://murf.ai/api/docs) | `murf` | `GEN2` | `MURF_API_KEY` | [API Reference](https://murf.ai/api/docs/api-reference/text-to-speech/generate) |
136
239
  | [Resemble](https://docs.resemble.ai) | `resemble` | `default` | `RESEMBLE_API_KEY` | [API Reference](https://docs.resemble.ai/api-reference/text-to-speech/synthesize) |
137
240
  | [fal](https://fal.ai/models) | `fal-ai` | *(user-specified)* | `FAL_API_KEY` | [API Reference](https://fal.ai/models) |
@@ -304,6 +407,12 @@ pnpm run typecheck # type-check without emitting
304
407
 
305
408
  E2E tests hit real provider APIs. Set the relevant API key environment variables in a `.env` file or export them in your shell.
306
409
 
410
+ Set `SPEECH_SDK_E2E_OUTPUT_DIR` to have the conversation e2e tests write their generated audio to disk (useful for sampling/comparing provider output):
411
+
412
+ ```bash
413
+ SPEECH_SDK_E2E_OUTPUT_DIR=~/Downloads/convos pnpm run test:e2e
414
+ ```
415
+
307
416
  ## License
308
417
 
309
418
  MIT
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Write a test-generated audio file to `SPEECH_SDK_E2E_OUTPUT_DIR` if the env
3
+ * var is set. No-op otherwise, so normal CI runs don't produce artifacts.
4
+ * Intended to let conversation e2e tests double as a way to sample provider
5
+ * output (e.g. `SPEECH_SDK_E2E_OUTPUT_DIR=~/Downloads/convos pnpm test:e2e`).
6
+ */
7
+ export declare function maybeSaveAudio(name: string, audio: {
8
+ uint8Array: Uint8Array;
9
+ mediaType: string;
10
+ }): Promise<void>;
11
+ //# sourceMappingURL=_save-audio.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"_save-audio.d.ts","sourceRoot":"","sources":["../../../src/__tests__/e2e/_save-audio.ts"],"names":[],"mappings":"AAyBA;;;;;GAKG;AACH,wBAAsB,cAAc,CAClC,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE;IAAE,UAAU,EAAE,UAAU,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,GACnD,OAAO,CAAC,IAAI,CAAC,CAYf"}
@@ -0,0 +1,43 @@
1
+ import { mkdir, writeFile } from "node:fs/promises";
2
+ import { join } from "node:path";
3
+ function extFor(mediaType) {
4
+ if (mediaType.includes("wav")) {
5
+ return "wav";
6
+ }
7
+ if (mediaType.includes("mpeg") || mediaType.includes("mp3")) {
8
+ return "mp3";
9
+ }
10
+ if (mediaType.includes("ogg")) {
11
+ return "ogg";
12
+ }
13
+ if (mediaType.includes("flac")) {
14
+ return "flac";
15
+ }
16
+ if (mediaType.includes("opus")) {
17
+ return "opus";
18
+ }
19
+ if (mediaType.includes("pcm")) {
20
+ return "pcm";
21
+ }
22
+ return "bin";
23
+ }
24
+ /**
25
+ * Write a test-generated audio file to `SPEECH_SDK_E2E_OUTPUT_DIR` if the env
26
+ * var is set. No-op otherwise, so normal CI runs don't produce artifacts.
27
+ * Intended to let conversation e2e tests double as a way to sample provider
28
+ * output (e.g. `SPEECH_SDK_E2E_OUTPUT_DIR=~/Downloads/convos pnpm test:e2e`).
29
+ */
30
+ export async function maybeSaveAudio(name, audio) {
31
+ const dir = process.env.SPEECH_SDK_E2E_OUTPUT_DIR;
32
+ if (!dir) {
33
+ return;
34
+ }
35
+ const expanded = dir.startsWith("~")
36
+ ? join(process.env.HOME ?? "", dir.slice(1))
37
+ : dir;
38
+ await mkdir(expanded, { recursive: true });
39
+ const file = join(expanded, `${name}.${extFor(audio.mediaType)}`);
40
+ await writeFile(file, audio.uint8Array);
41
+ console.log(`[maybeSaveAudio] wrote ${file}`);
42
+ }
43
+ //# sourceMappingURL=_save-audio.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"_save-audio.js","sourceRoot":"","sources":["../../../src/__tests__/e2e/_save-audio.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,SAAS,MAAM,CAAC,SAAiB;IAC/B,IAAI,SAAS,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;QAC9B,OAAO,KAAK,CAAC;IACf,CAAC;IACD,IAAI,SAAS,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,SAAS,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;QAC5D,OAAO,KAAK,CAAC;IACf,CAAC;IACD,IAAI,SAAS,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;QAC9B,OAAO,KAAK,CAAC;IACf,CAAC;IACD,IAAI,SAAS,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;QAC/B,OAAO,MAAM,CAAC;IAChB,CAAC;IACD,IAAI,SAAS,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;QAC/B,OAAO,MAAM,CAAC;IAChB,CAAC;IACD,IAAI,SAAS,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;QAC9B,OAAO,KAAK,CAAC;IACf,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,IAAY,EACZ,KAAoD;IAEpD,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,yBAAyB,CAAC;IAClD,IAAI,CAAC,GAAG,EAAE,CAAC;QACT,OAAO;IACT,CAAC;IACD,MAAM,QAAQ,GAAG,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC;QAClC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,EAAE,EAAE,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QAC5C,CAAC,CAAC,GAAG,CAAC;IACR,MAAM,KAAK,CAAC,QAAQ,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC3C,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,EAAE,GAAG,IAAI,IAAI,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC;IAClE,MAAM,SAAS,CAAC,IAAI,EAAE,KAAK,CAAC,UAAU,CAAC,CAAC;IACxC,OAAO,CAAC,GAAG,CAAC,0BAA0B,IAAI,EAAE,CAAC,CAAC;AAChD,CAAC"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Parse a numeric parameter from a mediaType string (e.g. "audio/pcm;rate=24000").
3
+ * Returns undefined if missing or non-positive.
4
+ */
5
+ export declare function parseMediaTypeParam(mediaType: string, name: string): number | undefined;
6
+ /**
7
+ * Wrap raw 16-bit little-endian mono PCM bytes in a WAV container.
8
+ * Cross-platform (browser, Node, edge) via mediabunny's container ops —
9
+ * does not require the WebCodecs encoder.
10
+ */
11
+ export declare function wrapPcm16Mono(pcm: Uint8Array, sampleRate: number): Promise<Uint8Array>;
12
+ //# sourceMappingURL=audio-utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"audio-utils.d.ts","sourceRoot":"","sources":["../src/audio-utils.ts"],"names":[],"mappings":"AAUA;;;GAGG;AACH,wBAAgB,mBAAmB,CACjC,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,MAAM,GACX,MAAM,GAAG,SAAS,CAcpB;AAED;;;;GAIG;AACH,wBAAsB,aAAa,CACjC,GAAG,EAAE,UAAU,EACf,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,UAAU,CAAC,CA2BrB"}
@@ -0,0 +1,53 @@
1
+ import { BufferTarget, EncodedAudioPacketSource, EncodedPacket, Output, WavOutputFormat, } from "mediabunny";
2
+ const PARAM_REGEX_CACHE = new Map();
3
+ /**
4
+ * Parse a numeric parameter from a mediaType string (e.g. "audio/pcm;rate=24000").
5
+ * Returns undefined if missing or non-positive.
6
+ */
7
+ export function parseMediaTypeParam(mediaType, name) {
8
+ let re = PARAM_REGEX_CACHE.get(name);
9
+ if (!re) {
10
+ // End boundary required: digits must be followed by ;, whitespace, or
11
+ // end-of-string. Rejects values like "rate=24000x".
12
+ re = new RegExp(`(?:^|;)\\s*${name}=(\\d+)(?=$|;|\\s)`, "i");
13
+ PARAM_REGEX_CACHE.set(name, re);
14
+ }
15
+ const match = mediaType.match(re);
16
+ if (!match) {
17
+ return undefined;
18
+ }
19
+ const value = Number(match[1]);
20
+ return Number.isFinite(value) && value > 0 ? value : undefined;
21
+ }
22
+ /**
23
+ * Wrap raw 16-bit little-endian mono PCM bytes in a WAV container.
24
+ * Cross-platform (browser, Node, edge) via mediabunny's container ops —
25
+ * does not require the WebCodecs encoder.
26
+ */
27
+ export async function wrapPcm16Mono(pcm, sampleRate) {
28
+ const output = new Output({
29
+ format: new WavOutputFormat(),
30
+ target: new BufferTarget(),
31
+ });
32
+ const source = new EncodedAudioPacketSource("pcm-s16");
33
+ output.addAudioTrack(source);
34
+ await output.start();
35
+ // 2 bytes per sample, mono.
36
+ const numSamples = pcm.length / 2;
37
+ const durationSeconds = numSamples / sampleRate;
38
+ const packet = new EncodedPacket(pcm, "key", 0, durationSeconds, 0);
39
+ await source.add(packet, {
40
+ decoderConfig: {
41
+ codec: "pcm-s16",
42
+ numberOfChannels: 1,
43
+ sampleRate,
44
+ },
45
+ });
46
+ await output.finalize();
47
+ const buffer = output.target.buffer;
48
+ if (!buffer) {
49
+ throw new Error("audio-utils: WavOutputFormat produced no buffer");
50
+ }
51
+ return new Uint8Array(buffer);
52
+ }
53
+ //# sourceMappingURL=audio-utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"audio-utils.js","sourceRoot":"","sources":["../src/audio-utils.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,YAAY,EACZ,wBAAwB,EACxB,aAAa,EACb,MAAM,EACN,eAAe,GAChB,MAAM,YAAY,CAAC;AAEpB,MAAM,iBAAiB,GAAG,IAAI,GAAG,EAAkB,CAAC;AAEpD;;;GAGG;AACH,MAAM,UAAU,mBAAmB,CACjC,SAAiB,EACjB,IAAY;IAEZ,IAAI,EAAE,GAAG,iBAAiB,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IACrC,IAAI,CAAC,EAAE,EAAE,CAAC;QACR,sEAAsE;QACtE,oDAAoD;QACpD,EAAE,GAAG,IAAI,MAAM,CAAC,cAAc,IAAI,oBAAoB,EAAE,GAAG,CAAC,CAAC;QAC7D,iBAAiB,CAAC,GAAG,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;IAClC,CAAC;IACD,MAAM,KAAK,GAAG,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IAClC,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IAC/B,OAAO,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC;AACjE,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,GAAe,EACf,UAAkB;IAElB,MAAM,MAAM,GAAG,IAAI,MAAM,CAAC;QACxB,MAAM,EAAE,IAAI,eAAe,EAAE;QAC7B,MAAM,EAAE,IAAI,YAAY,EAAE;KAC3B,CAAC,CAAC;IACH,MAAM,MAAM,GAAG,IAAI,wBAAwB,CAAC,SAAS,CAAC,CAAC;IACvD,MAAM,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC;IAC7B,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC;IAErB,4BAA4B;IAC5B,MAAM,UAAU,GAAG,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC;IAClC,MAAM,eAAe,GAAG,UAAU,GAAG,UAAU,CAAC;IAChD,MAAM,MAAM,GAAG,IAAI,aAAa,CAAC,GAAG,EAAE,KAAK,EAAE,CAAC,EAAE,eAAe,EAAE,CAAC,CAAC,CAAC;IACpE,MAAM,MAAM,CAAC,GAAG,CAAC,MAAM,EAAE;QACvB,aAAa,EAAE;YACb,KAAK,EAAE,SAAS;YAChB,gBAAgB,EAAE,CAAC;YACnB,UAAU;SACX;KACF,CAAC,CAAC;IAEH,MAAM,MAAM,CAAC,QAAQ,EAAE,CAAC;IACxB,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC;IACpC,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,MAAM,IAAI,KAAK,CAAC,iDAAiD,CAAC,CAAC;IACrE,CAAC;IACD,OAAO,IAAI,UAAU,CAAC,MAAM,CAAC,CAAC;AAChC,CAAC"}
@@ -0,0 +1,17 @@
1
+ import type { ResolvedModel, Voice } from "../speech-provider.js";
2
+ import type { ConversationTurn } from "./types.js";
3
+ export type ConversationPath = {
4
+ kind: "native";
5
+ resolved: ResolvedModel<Voice>;
6
+ } | {
7
+ kind: "stitch";
8
+ stitchOptionsPerTurn: readonly {
9
+ providerOptions: Record<string, unknown>;
10
+ mediaType: string;
11
+ }[];
12
+ };
13
+ export declare function chooseConversationPath(input: {
14
+ resolvedPerTurn: readonly ResolvedModel<Voice>[];
15
+ turns: readonly ConversationTurn<Voice>[];
16
+ }): ConversationPath;
17
+ //# sourceMappingURL=dispatch.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dispatch.d.ts","sourceRoot":"","sources":["../../src/conversation/dispatch.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,KAAK,EAAE,MAAM,uBAAuB,CAAC;AAElE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAGnD,MAAM,MAAM,gBAAgB,GACxB;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,QAAQ,EAAE,aAAa,CAAC,KAAK,CAAC,CAAA;CAAE,GAClD;IACE,IAAI,EAAE,QAAQ,CAAC;IACf,oBAAoB,EAAE,SAAS;QAC7B,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QACzC,SAAS,EAAE,MAAM,CAAC;KACnB,EAAE,CAAC;CACL,CAAC;AAEN,wBAAgB,sBAAsB,CAAC,KAAK,EAAE;IAC5C,eAAe,EAAE,SAAS,aAAa,CAAC,KAAK,CAAC,EAAE,CAAC;IACjD,KAAK,EAAE,SAAS,gBAAgB,CAAC,KAAK,CAAC,EAAE,CAAC;CAC3C,GAAG,gBAAgB,CAkCnB"}
@@ -0,0 +1,60 @@
1
+ import { DialogueConstraintError, StitchUnsupportedError } from "./errors.js";
2
+ import { newVoiceKeyContext, voiceKey } from "./validate.js";
3
+ export function chooseConversationPath(input) {
4
+ const { resolvedPerTurn, turns } = input;
5
+ // Compare by provider instance reference, not just provider id, so two
6
+ // factories of the same provider with different apiKey/baseURL/fetch
7
+ // configs are not silently merged into one.
8
+ const first = resolvedPerTurn[0];
9
+ const allSame = resolvedPerTurn.every((r) => r.provider === first.provider && r.modelId === first.modelId);
10
+ if (allSame) {
11
+ const { provider, modelId } = first;
12
+ if (provider.generateDialogue && provider.dialogueCapabilities) {
13
+ const caps = provider.dialogueCapabilities(modelId);
14
+ if (caps) {
15
+ assertNativeConstraints({ provider, modelId, caps, turns });
16
+ return { kind: "native", resolved: first };
17
+ }
18
+ }
19
+ }
20
+ // Stitch path — every resolved (provider, modelId) must support getStitchOptions.
21
+ const stitchOptionsPerTurn = resolvedPerTurn.map((r) => {
22
+ const opts = r.provider.getStitchOptions?.(r.modelId);
23
+ if (!opts) {
24
+ throw new StitchUnsupportedError({
25
+ provider: r.provider.id,
26
+ model: r.modelId,
27
+ });
28
+ }
29
+ return opts;
30
+ });
31
+ return { kind: "stitch", stitchOptionsPerTurn };
32
+ }
33
+ function assertNativeConstraints(args) {
34
+ const { provider, modelId, caps, turns } = args;
35
+ const ctx = newVoiceKeyContext();
36
+ const unique = new Set(turns.map((t) => voiceKey(t.voice, ctx.refIds, ctx.refCounter))).size;
37
+ if (unique < caps.minVoices || unique > caps.maxVoices) {
38
+ const rule = caps.minVoices === caps.maxVoices
39
+ ? `exactly ${caps.minVoices} unique voices`
40
+ : `between ${caps.minVoices} and ${caps.maxVoices} unique voices`;
41
+ throw new DialogueConstraintError({
42
+ provider: provider.id,
43
+ model: modelId,
44
+ rule,
45
+ observed: `${unique} unique voices`,
46
+ });
47
+ }
48
+ if (caps.maxTotalChars != null) {
49
+ const total = turns.reduce((n, t) => n + t.text.length, 0);
50
+ if (total > caps.maxTotalChars) {
51
+ throw new DialogueConstraintError({
52
+ provider: provider.id,
53
+ model: modelId,
54
+ rule: `total characters <= ${caps.maxTotalChars}`,
55
+ observed: `${total} characters`,
56
+ });
57
+ }
58
+ }
59
+ }
60
+ //# sourceMappingURL=dispatch.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dispatch.js","sourceRoot":"","sources":["../../src/conversation/dispatch.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,uBAAuB,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAC;AAE9E,OAAO,EAAE,kBAAkB,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAY7D,MAAM,UAAU,sBAAsB,CAAC,KAGtC;IACC,MAAM,EAAE,eAAe,EAAE,KAAK,EAAE,GAAG,KAAK,CAAC;IAEzC,uEAAuE;IACvE,qEAAqE;IACrE,4CAA4C;IAC5C,MAAM,KAAK,GAAG,eAAe,CAAC,CAAC,CAAC,CAAC;IACjC,MAAM,OAAO,GAAG,eAAe,CAAC,KAAK,CACnC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,KAAK,CAAC,QAAQ,IAAI,CAAC,CAAC,OAAO,KAAK,KAAK,CAAC,OAAO,CACpE,CAAC;IAEF,IAAI,OAAO,EAAE,CAAC;QACZ,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,GAAG,KAAK,CAAC;QACpC,IAAI,QAAQ,CAAC,gBAAgB,IAAI,QAAQ,CAAC,oBAAoB,EAAE,CAAC;YAC/D,MAAM,IAAI,GAAG,QAAQ,CAAC,oBAAoB,CAAC,OAAO,CAAC,CAAC;YACpD,IAAI,IAAI,EAAE,CAAC;gBACT,uBAAuB,CAAC,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;gBAC5D,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC;YAC7C,CAAC;QACH,CAAC;IACH,CAAC;IAED,kFAAkF;IAClF,MAAM,oBAAoB,GAAG,eAAe,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;QACrD,MAAM,IAAI,GAAG,CAAC,CAAC,QAAQ,CAAC,gBAAgB,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;QACtD,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,MAAM,IAAI,sBAAsB,CAAC;gBAC/B,QAAQ,EAAE,CAAC,CAAC,QAAQ,CAAC,EAAE;gBACvB,KAAK,EAAE,CAAC,CAAC,OAAO;aACjB,CAAC,CAAC;QACL,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC,CAAC,CAAC;IACH,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,oBAAoB,EAAE,CAAC;AAClD,CAAC;AAED,SAAS,uBAAuB,CAAC,IAKhC;IACC,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,IAAI,CAAC;IAEhD,MAAM,GAAG,GAAG,kBAAkB,EAAE,CAAC;IACjC,MAAM,MAAM,GAAG,IAAI,GAAG,CACpB,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,UAAU,CAAC,CAAC,CAChE,CAAC,IAAI,CAAC;IAEP,IAAI,MAAM,GAAG,IAAI,CAAC,SAAS,IAAI,MAAM,GAAG,IAAI,CAAC,SAAS,EAAE,CAAC;QACvD,MAAM,IAAI,GACR,IAAI,CAAC,SAAS,KAAK,IAAI,CAAC,SAAS;YAC/B,CAAC,CAAC,WAAW,IAAI,CAAC,SAAS,gBAAgB;YAC3C,CAAC,CAAC,WAAW,IAAI,CAAC,SAAS,QAAQ,IAAI,CAAC,SAAS,gBAAgB,CAAC;QACtE,MAAM,IAAI,uBAAuB,CAAC;YAChC,QAAQ,EAAE,QAAQ,CAAC,EAAE;YACrB,KAAK,EAAE,OAAO;YACd,IAAI;YACJ,QAAQ,EAAE,GAAG,MAAM,gBAAgB;SACpC,CAAC,CAAC;IACL,CAAC;IAED,IAAI,IAAI,CAAC,aAAa,IAAI,IAAI,EAAE,CAAC;QAC/B,MAAM,KAAK,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;QAC3D,IAAI,KAAK,GAAG,IAAI,CAAC,aAAa,EAAE,CAAC;YAC/B,MAAM,IAAI,uBAAuB,CAAC;gBAChC,QAAQ,EAAE,QAAQ,CAAC,EAAE;gBACrB,KAAK,EAAE,OAAO;gBACd,IAAI,EAAE,uBAAuB,IAAI,CAAC,aAAa,EAAE;gBACjD,QAAQ,EAAE,GAAG,KAAK,aAAa;aAChC,CAAC,CAAC;QACL,CAAC;IACH,CAAC;AACH,CAAC"}
@@ -0,0 +1,23 @@
1
+ import { SpeechSDKError } from "../errors.js";
2
+ export declare class ConversationInputError extends SpeechSDKError {
3
+ constructor(message: string);
4
+ }
5
+ export declare class DialogueConstraintError extends SpeechSDKError {
6
+ readonly provider: string;
7
+ readonly model: string;
8
+ constructor(options: {
9
+ provider: string;
10
+ model: string;
11
+ rule: string;
12
+ observed: string;
13
+ });
14
+ }
15
+ export declare class StitchUnsupportedError extends SpeechSDKError {
16
+ readonly provider: string;
17
+ readonly model: string;
18
+ constructor(options: {
19
+ provider: string;
20
+ model: string;
21
+ });
22
+ }
23
+ //# sourceMappingURL=errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/conversation/errors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAE9C,qBAAa,sBAAuB,SAAQ,cAAc;gBAC5C,OAAO,EAAE,MAAM;CAI5B;AAED,qBAAa,uBAAwB,SAAQ,cAAc;IACzD,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;gBAEX,OAAO,EAAE;QACnB,QAAQ,EAAE,MAAM,CAAC;QACjB,KAAK,EAAE,MAAM,CAAC;QACd,IAAI,EAAE,MAAM,CAAC;QACb,QAAQ,EAAE,MAAM,CAAC;KAClB;CAQF;AAED,qBAAa,sBAAuB,SAAQ,cAAc;IACxD,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;gBAEX,OAAO,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE;CAQzD"}
@@ -0,0 +1,28 @@
1
+ import { SpeechSDKError } from "../errors.js";
2
+ export class ConversationInputError extends SpeechSDKError {
3
+ constructor(message) {
4
+ super(message);
5
+ this.name = "ConversationInputError";
6
+ }
7
+ }
8
+ export class DialogueConstraintError extends SpeechSDKError {
9
+ provider;
10
+ model;
11
+ constructor(options) {
12
+ super(`${options.provider}/${options.model} native dialogue requires ${options.rule}; got ${options.observed}.`);
13
+ this.name = "DialogueConstraintError";
14
+ this.provider = options.provider;
15
+ this.model = options.model;
16
+ }
17
+ }
18
+ export class StitchUnsupportedError extends SpeechSDKError {
19
+ provider;
20
+ model;
21
+ constructor(options) {
22
+ super(`${options.provider}/${options.model} cannot be used in a stitched conversation: provider does not support PCM/WAV output for this model.`);
23
+ this.name = "StitchUnsupportedError";
24
+ this.provider = options.provider;
25
+ this.model = options.model;
26
+ }
27
+ }
28
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/conversation/errors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAE9C,MAAM,OAAO,sBAAuB,SAAQ,cAAc;IACxD,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,wBAAwB,CAAC;IACvC,CAAC;CACF;AAED,MAAM,OAAO,uBAAwB,SAAQ,cAAc;IAChD,QAAQ,CAAS;IACjB,KAAK,CAAS;IAEvB,YAAY,OAKX;QACC,KAAK,CACH,GAAG,OAAO,CAAC,QAAQ,IAAI,OAAO,CAAC,KAAK,6BAA6B,OAAO,CAAC,IAAI,SAAS,OAAO,CAAC,QAAQ,GAAG,CAC1G,CAAC;QACF,IAAI,CAAC,IAAI,GAAG,yBAAyB,CAAC;QACtC,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC;QACjC,IAAI,CAAC,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC;IAC7B,CAAC;CACF;AAED,MAAM,OAAO,sBAAuB,SAAQ,cAAc;IAC/C,QAAQ,CAAS;IACjB,KAAK,CAAS;IAEvB,YAAY,OAA4C;QACtD,KAAK,CACH,GAAG,OAAO,CAAC,QAAQ,IAAI,OAAO,CAAC,KAAK,sGAAsG,CAC3I,CAAC;QACF,IAAI,CAAC,IAAI,GAAG,wBAAwB,CAAC;QACrC,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC;QACjC,IAAI,CAAC,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC;IAC7B,CAAC;CACF"}
@@ -0,0 +1,37 @@
1
+ export interface Pcm16Segment {
2
+ readonly channels: number;
3
+ readonly pcm: Int16Array;
4
+ readonly sampleRate: number;
5
+ }
6
+ /** Decode a provider response to mono 16-bit PCM + its native sample rate. */
7
+ export declare function decodeToPcm16(data: Uint8Array, mediaType: string): Pcm16Segment;
8
+ /**
9
+ * Default RMS target: −20 dBFS — broadcast/podcast voice loudness convention
10
+ * with ~20 dB peak headroom. Comfortable to listen to and leaves room for
11
+ * typical TTS peaks not to clip.
12
+ */
13
+ export declare const DEFAULT_VOLUME_DBFS = -20;
14
+ /** Convert a dBFS level (≤ 0) to the equivalent int16 RMS amplitude. */
15
+ export declare function dbfsToInt16Rms(dbfs: number): number;
16
+ /**
17
+ * RMS-normalize each segment to an absolute target amplitude. Each segment
18
+ * is processed independently — no cross-segment dependency — so:
19
+ * - The output level is the same across runs regardless of input mix.
20
+ * - Two `generateConversation` calls produce comparable loudness even
21
+ * with completely different content.
22
+ *
23
+ * Silent segments pass through unchanged. Output is clamped to int16
24
+ * range, so a quiet segment with rare peaks may clip slightly when
25
+ * boosted; the default target leaves ~20 dB headroom to make this rare
26
+ * for typical TTS content.
27
+ */
28
+ export declare function normalizeRms(segments: readonly Pcm16Segment[], targetRmsAmplitude?: number): Pcm16Segment[];
29
+ /**
30
+ * Resample each segment to `targetSampleRate` mono, interleave with `gapMs`
31
+ * silence, and mux the result as a WAV file via mediabunny.
32
+ */
33
+ export declare function concatPcmToWav(segments: readonly Pcm16Segment[], options: {
34
+ gapMs: number;
35
+ targetSampleRate: number;
36
+ }): Promise<Uint8Array>;
37
+ //# sourceMappingURL=pcm-concat.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pcm-concat.d.ts","sourceRoot":"","sources":["../../src/conversation/pcm-concat.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,GAAG,EAAE,UAAU,CAAC;IACzB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;CAC7B;AAwED,8EAA8E;AAC9E,wBAAgB,aAAa,CAC3B,IAAI,EAAE,UAAU,EAChB,SAAS,EAAE,MAAM,GAChB,YAAY,CAqCd;AAkHD;;;;GAIG;AACH,eAAO,MAAM,mBAAmB,MAAM,CAAC;AAEvC,wEAAwE;AACxE,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEnD;AAID;;;;;;;;;;;GAWG;AACH,wBAAgB,YAAY,CAC1B,QAAQ,EAAE,SAAS,YAAY,EAAE,EACjC,kBAAkB,SAA2B,GAC5C,YAAY,EAAE,CAQhB;AAED;;;GAGG;AACH,wBAAsB,cAAc,CAClC,QAAQ,EAAE,SAAS,YAAY,EAAE,EACjC,OAAO,EAAE;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,gBAAgB,EAAE,MAAM,CAAA;CAAE,GACnD,OAAO,CAAC,UAAU,CAAC,CA8BrB"}