@ai-sdk/xai 5.0.14 → 5.0.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +36 -0
- package/dist/index.d.ts +11 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +71 -54
- package/dist/index.js.map +1 -1
- package/docs/01-xai.mdx +37 -18
- package/package.json +5 -5
- package/src/files/xai-files.ts +1 -1
- package/src/index.ts +4 -1
- package/src/responses/xai-responses-language-model.ts +1 -0
- package/src/xai-image-model-options.ts +2 -2
- package/src/xai-image-model.ts +7 -4
- package/src/xai-image-settings.ts +1 -0
- package/src/xai-provider.ts +7 -4
- package/src/xai-transcription-model-options.ts +15 -2
- package/src/xai-transcription-model.ts +71 -90
package/docs/01-xai.mdx
CHANGED
|
@@ -828,11 +828,13 @@ const { traceId, duration, audioTimestamps } = result.providerMetadata.xai;
|
|
|
828
828
|
## Transcription Models
|
|
829
829
|
|
|
830
830
|
You can create models that call the [xAI Speech to Text API](https://docs.x.ai/developers/model-capabilities/audio/speech-to-text)
|
|
831
|
-
using the `.transcription()` factory method.
|
|
832
|
-
|
|
831
|
+
using the `.transcription()` factory method. The model identifier is optional:
|
|
832
|
+
pass `grok-voice-transcribe-2.0` to pin a model, or omit it to use xAI's
|
|
833
|
+
default transcription model. `grok-voice-transcribe-1.0` is retired, and
|
|
834
|
+
requests to it are routed to `grok-voice-transcribe-2.0`.
|
|
833
835
|
|
|
834
836
|
```ts
|
|
835
|
-
const model = xai.transcription();
|
|
837
|
+
const model = xai.transcription('grok-voice-transcribe-2.0');
|
|
836
838
|
```
|
|
837
839
|
|
|
838
840
|
Use xAI transcription models with the `transcribe` function:
|
|
@@ -871,9 +873,13 @@ const result = await transcribe({
|
|
|
871
873
|
});
|
|
872
874
|
```
|
|
873
875
|
|
|
874
|
-
- **audioFormat** _`pcm` | `mulaw` | `alaw`_
|
|
876
|
+
- **audioFormat** _`pcm` | `mulaw` | `alaw` | `opus`_
|
|
875
877
|
|
|
876
|
-
|
|
878
|
+
Input audio encoding for raw, headerless audio (`pcm`, `mulaw`, `alaw`).
|
|
879
|
+
Container formats such as Ogg/Opus are auto-detected, so do not set
|
|
880
|
+
`audioFormat` for them. `opus` is supported for streaming transcription only:
|
|
881
|
+
each audio chunk must be exactly one raw Opus packet (not Ogg), and an
|
|
882
|
+
`audio/opus` input audio type maps to `opus` automatically.
|
|
877
883
|
|
|
878
884
|
- **sampleRate** _8000 | 16000 | 22050 | 24000 | 44100 | 48000_
|
|
879
885
|
|
|
@@ -907,6 +913,11 @@ const result = await transcribe({
|
|
|
907
913
|
|
|
908
914
|
Includes filler words such as `uh` and `um` in the transcript.
|
|
909
915
|
|
|
916
|
+
- **vadThreshold** _number_
|
|
917
|
+
|
|
918
|
+
Voice activity detection threshold. Range: 0.0-1.0. Defaults to `0.5` for
|
|
919
|
+
`transcribe` and `0.08` for streaming. `0` disables the filter.
|
|
920
|
+
|
|
910
921
|
- **streaming** _object_
|
|
911
922
|
|
|
912
923
|
Options for streaming speech-to-text over WebSocket. Use with `experimental_streamTranscribe`.
|
|
@@ -928,9 +939,10 @@ const result = await transcribe({
|
|
|
928
939
|
|
|
929
940
|
### Model Capabilities
|
|
930
941
|
|
|
931
|
-
| Model
|
|
932
|
-
|
|
|
933
|
-
| `default`
|
|
942
|
+
| Model | Request/Response | Streaming | Word Timestamps | Diarization | Multichannel |
|
|
943
|
+
| --------------------------- | ---------------- | --------- | --------------- | ----------- | ------------ |
|
|
944
|
+
| `default` | <Check /> | <Check /> | <Check /> | <Check /> | <Check /> |
|
|
945
|
+
| `grok-voice-transcribe-2.0` | <Check /> | <Check /> | <Check /> | <Check /> | <Check /> |
|
|
934
946
|
|
|
935
947
|
<Note>
|
|
936
948
|
Word timestamps, diarization results, and segments are only returned on the
|
|
@@ -1053,22 +1065,29 @@ const { images } = await generateImage({
|
|
|
1053
1065
|
});
|
|
1054
1066
|
```
|
|
1055
1067
|
|
|
1056
|
-
- **resolution** _'1k' | '2k'_
|
|
1068
|
+
- **resolution** _'1k' | '1.5k' | '2k'_
|
|
1057
1069
|
|
|
1058
|
-
Output resolution
|
|
1059
|
-
|
|
1060
|
-
`grok-imagine-image
|
|
1070
|
+
Output resolution: `1k` (default, ~1024×1024), `1.5k` (~1408×1408), or `2k`
|
|
1071
|
+
(~2048×2048). Actual dimensions vary based on aspect ratio.
|
|
1072
|
+
`grok-imagine-image` does not support `1.5k`.
|
|
1061
1073
|
|
|
1062
|
-
- **quality** _'low' | 'medium' | 'high'_
|
|
1074
|
+
- **quality** _'low' | 'medium' | 'high' | 'auto'_
|
|
1063
1075
|
|
|
1064
|
-
Image quality level.
|
|
1076
|
+
Image quality level. Only supported by `grok-imagine-image-2.0`, which accepts
|
|
1077
|
+
`low`, `medium`, and `auto`. `auto` is the default when omitted: it serves
|
|
1078
|
+
`low` for generation and `medium` for editing, billed at the quality served.
|
|
1079
|
+
`high` is not documented by xAI but is still accepted by older models, and is
|
|
1080
|
+
kept for backward compatibility.
|
|
1065
1081
|
|
|
1066
1082
|
### Image Model Capabilities
|
|
1067
1083
|
|
|
1068
|
-
| Model | Resolution
|
|
1069
|
-
| ------------------------ |
|
|
1070
|
-
| `grok-imagine-image-
|
|
1071
|
-
| `grok-imagine-image`
|
|
1084
|
+
| Model | Resolution | Aspect Ratios | Image Editing |
|
|
1085
|
+
| ------------------------ | ------------------ | -------------------------------------------------------------------------------------------------------------------------- | ------------- |
|
|
1086
|
+
| `grok-imagine-image-2.0` | `1k`, `1.5k`, `2k` | `1:1`, `16:9`, `9:16`, `4:3`, `3:4`, `3:2`, `2:3`, `2:1`, `1:2`, `19.5:9`, `9:19.5`, `20:9`, `9:20`, `21:9`, `5:2`, `auto` | <Check /> |
|
|
1087
|
+
| `grok-imagine-image-pro` | `1k`, `1.5k`, `2k` | `1:1`, `16:9`, `9:16`, `4:3`, `3:4`, `3:2`, `2:3`, `2:1`, `1:2`, `19.5:9`, `9:19.5`, `20:9`, `9:20`, `auto` | <Check /> |
|
|
1088
|
+
| `grok-imagine-image` | `1k` | `1:1`, `16:9`, `9:16`, `4:3`, `3:4`, `3:2`, `2:3`, `2:1`, `1:2`, `19.5:9`, `9:19.5`, `20:9`, `9:20`, `auto` | <Check /> |
|
|
1089
|
+
|
|
1090
|
+
`grok-imagine-image-2.0` is xAI's latest image model.
|
|
1072
1091
|
|
|
1073
1092
|
## Video Models
|
|
1074
1093
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ai-sdk/xai",
|
|
3
|
-
"version": "5.0.
|
|
3
|
+
"version": "5.0.16",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"sideEffects": false,
|
|
@@ -29,15 +29,15 @@
|
|
|
29
29
|
}
|
|
30
30
|
},
|
|
31
31
|
"dependencies": {
|
|
32
|
-
"@ai-sdk/provider": "4.0.
|
|
33
|
-
"@ai-sdk/provider-utils": "5.0.
|
|
32
|
+
"@ai-sdk/provider": "4.0.23",
|
|
33
|
+
"@ai-sdk/provider-utils": "5.0.55"
|
|
34
34
|
},
|
|
35
35
|
"devDependencies": {
|
|
36
|
-
"@ai-sdk/test-server": "2.0.
|
|
36
|
+
"@ai-sdk/test-server": "2.0.4",
|
|
37
37
|
"@types/node": "22.19.19",
|
|
38
38
|
"@vercel/ai-tsconfig": "0.0.0",
|
|
39
39
|
"tsdown": "^0.23.0",
|
|
40
|
-
"typescript": "
|
|
40
|
+
"typescript": "6.0.3",
|
|
41
41
|
"zod": "3.25.76"
|
|
42
42
|
},
|
|
43
43
|
"peerDependencies": {
|
package/src/files/xai-files.ts
CHANGED
|
@@ -152,7 +152,7 @@ export class XaiFiles implements FilesV4 {
|
|
|
152
152
|
} else {
|
|
153
153
|
const fileBytes = convertInlineFileDataToUint8Array(data);
|
|
154
154
|
|
|
155
|
-
const blob = new Blob([fileBytes], {
|
|
155
|
+
const blob = new Blob([fileBytes as Uint8Array<ArrayBuffer>], {
|
|
156
156
|
type: mediaType,
|
|
157
157
|
});
|
|
158
158
|
|
package/src/index.ts
CHANGED
|
@@ -17,7 +17,10 @@ export type {
|
|
|
17
17
|
XaiVideoModelOptions as XaiVideoProviderOptions,
|
|
18
18
|
} from './xai-video-model-options';
|
|
19
19
|
export type { XaiSpeechModelOptions } from './xai-speech-model-options';
|
|
20
|
-
export type {
|
|
20
|
+
export type {
|
|
21
|
+
XaiTranscriptionModelId,
|
|
22
|
+
XaiTranscriptionModelOptions,
|
|
23
|
+
} from './xai-transcription-model-options';
|
|
21
24
|
export type { XaiFilesOptions } from './files/xai-files-options';
|
|
22
25
|
export { createXai, xai } from './xai-provider';
|
|
23
26
|
export type { XaiProvider, XaiProviderSettings } from './xai-provider';
|
|
@@ -4,8 +4,8 @@ export const xaiImageModelOptions = z.object({
|
|
|
4
4
|
aspect_ratio: z.string().optional(),
|
|
5
5
|
output_format: z.string().optional(),
|
|
6
6
|
sync_mode: z.boolean().optional(),
|
|
7
|
-
resolution: z.enum(['1k', '2k']).optional(),
|
|
8
|
-
quality: z.enum(['low', 'medium', 'high']).optional(),
|
|
7
|
+
resolution: z.enum(['1k', '1.5k', '2k']).optional(),
|
|
8
|
+
quality: z.enum(['low', 'medium', 'high', 'auto']).optional(),
|
|
9
9
|
user: z.string().optional(),
|
|
10
10
|
});
|
|
11
11
|
|
package/src/xai-image-model.ts
CHANGED
|
@@ -28,15 +28,18 @@ interface XaiImageModelConfig {
|
|
|
28
28
|
};
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
+
const fileInputModelIds: ReadonlySet<string> = new Set<XaiImageModelId>([
|
|
32
|
+
'grok-imagine-image',
|
|
33
|
+
'grok-imagine-image-2.0',
|
|
34
|
+
'grok-imagine-image-pro',
|
|
35
|
+
]);
|
|
36
|
+
|
|
31
37
|
export class XaiImageModel implements ImageModelV4 {
|
|
32
38
|
readonly specificationVersion = 'v4';
|
|
33
39
|
readonly maxImagesPerCall = 3;
|
|
34
40
|
|
|
35
41
|
get supportsFileInputs(): boolean | undefined {
|
|
36
|
-
return this.modelId
|
|
37
|
-
this.modelId === 'grok-imagine-image-pro'
|
|
38
|
-
? true
|
|
39
|
-
: undefined;
|
|
42
|
+
return fileInputModelIds.has(this.modelId) ? true : undefined;
|
|
40
43
|
}
|
|
41
44
|
|
|
42
45
|
get supportsMaskInputs(): boolean | undefined {
|
package/src/xai-provider.ts
CHANGED
|
@@ -32,6 +32,7 @@ import { XaiVideoModel } from './xai-video-model';
|
|
|
32
32
|
import type { XaiVideoModelId } from './xai-video-settings';
|
|
33
33
|
import { XaiSpeechModel } from './xai-speech-model';
|
|
34
34
|
import { XaiTranscriptionModel } from './xai-transcription-model';
|
|
35
|
+
import type { XaiTranscriptionModelId } from './xai-transcription-model-options';
|
|
35
36
|
|
|
36
37
|
export interface XaiProvider extends ProviderV4 {
|
|
37
38
|
(modelId: XaiResponsesModelId): LanguageModelV4;
|
|
@@ -88,13 +89,15 @@ export interface XaiProvider extends ProviderV4 {
|
|
|
88
89
|
|
|
89
90
|
/**
|
|
90
91
|
* Creates an xAI model for speech-to-text transcription.
|
|
92
|
+
* When `modelId` is omitted, xAI's default transcription model is used.
|
|
91
93
|
*/
|
|
92
|
-
transcription(): TranscriptionModelV4;
|
|
94
|
+
transcription(modelId?: XaiTranscriptionModelId): TranscriptionModelV4;
|
|
93
95
|
|
|
94
96
|
/**
|
|
95
97
|
* Creates an xAI model for speech-to-text transcription.
|
|
98
|
+
* When `modelId` is omitted, xAI's default transcription model is used.
|
|
96
99
|
*/
|
|
97
|
-
transcriptionModel(): TranscriptionModelV4;
|
|
100
|
+
transcriptionModel(modelId?: XaiTranscriptionModelId): TranscriptionModelV4;
|
|
98
101
|
|
|
99
102
|
/**
|
|
100
103
|
* Returns the xAI files interface for uploading files.
|
|
@@ -204,8 +207,8 @@ export function createXai(options: XaiProviderSettings = {}): XaiProvider {
|
|
|
204
207
|
});
|
|
205
208
|
};
|
|
206
209
|
|
|
207
|
-
const createTranscriptionModel = () => {
|
|
208
|
-
return new XaiTranscriptionModel(
|
|
210
|
+
const createTranscriptionModel = (modelId: XaiTranscriptionModelId = '') => {
|
|
211
|
+
return new XaiTranscriptionModel(modelId, {
|
|
209
212
|
provider: 'xai.transcription',
|
|
210
213
|
baseURL,
|
|
211
214
|
headers: getHeaders,
|
|
@@ -5,13 +5,20 @@ import {
|
|
|
5
5
|
} from '@ai-sdk/provider-utils';
|
|
6
6
|
import { z } from 'zod/v4';
|
|
7
7
|
|
|
8
|
+
export type XaiTranscriptionModelId =
|
|
9
|
+
| 'grok-voice-transcribe-2.0'
|
|
10
|
+
| (string & {});
|
|
11
|
+
|
|
8
12
|
export const xaiTranscriptionModelOptionsSchema = lazySchema(() =>
|
|
9
13
|
zodSchema(
|
|
10
14
|
z.object({
|
|
11
15
|
/**
|
|
12
|
-
*
|
|
16
|
+
* Input audio encoding for raw, headerless audio: `pcm`, `mulaw`, or
|
|
17
|
+
* `alaw`. Container formats such as Ogg/Opus are auto-detected, so do
|
|
18
|
+
* not set this for them. `opus` is for streaming only, with one raw Opus
|
|
19
|
+
* packet per chunk.
|
|
13
20
|
*/
|
|
14
|
-
audioFormat: z.enum(['pcm', 'mulaw', 'alaw']).nullish(),
|
|
21
|
+
audioFormat: z.enum(['pcm', 'mulaw', 'alaw', 'opus']).nullish(),
|
|
15
22
|
|
|
16
23
|
/**
|
|
17
24
|
* Sample rate of the input audio in Hz.
|
|
@@ -62,6 +69,12 @@ export const xaiTranscriptionModelOptionsSchema = lazySchema(() =>
|
|
|
62
69
|
*/
|
|
63
70
|
fillerWords: z.boolean().nullish(),
|
|
64
71
|
|
|
72
|
+
/**
|
|
73
|
+
* Voice activity detection threshold between 0 and 1. Defaults to 0.5
|
|
74
|
+
* for `transcribe` and 0.08 for streaming. 0 disables the filter.
|
|
75
|
+
*/
|
|
76
|
+
vadThreshold: z.number().min(0).max(1).optional(),
|
|
77
|
+
|
|
65
78
|
/**
|
|
66
79
|
* Options for streaming speech-to-text over WebSocket.
|
|
67
80
|
*/
|
|
@@ -27,6 +27,7 @@ import { z } from 'zod/v4';
|
|
|
27
27
|
import { xaiFailedResponseHandler } from './xai-error';
|
|
28
28
|
import {
|
|
29
29
|
xaiTranscriptionModelOptionsSchema,
|
|
30
|
+
type XaiTranscriptionModelId,
|
|
30
31
|
type XaiTranscriptionModelOptions,
|
|
31
32
|
} from './xai-transcription-model-options';
|
|
32
33
|
|
|
@@ -64,7 +65,7 @@ export class XaiTranscriptionModel implements TranscriptionModelV4 {
|
|
|
64
65
|
}
|
|
65
66
|
|
|
66
67
|
static [WORKFLOW_DESERIALIZE](options: {
|
|
67
|
-
modelId:
|
|
68
|
+
modelId: XaiTranscriptionModelId;
|
|
68
69
|
config: XaiTranscriptionModelConfig;
|
|
69
70
|
}) {
|
|
70
71
|
return new XaiTranscriptionModel(options.modelId, options.config);
|
|
@@ -75,7 +76,7 @@ export class XaiTranscriptionModel implements TranscriptionModelV4 {
|
|
|
75
76
|
}
|
|
76
77
|
|
|
77
78
|
constructor(
|
|
78
|
-
readonly modelId:
|
|
79
|
+
readonly modelId: XaiTranscriptionModelId,
|
|
79
80
|
private readonly config: XaiTranscriptionModelConfig,
|
|
80
81
|
) {}
|
|
81
82
|
|
|
@@ -92,36 +93,15 @@ export class XaiTranscriptionModel implements TranscriptionModelV4 {
|
|
|
92
93
|
});
|
|
93
94
|
|
|
94
95
|
const formData = new FormData();
|
|
95
|
-
|
|
96
|
+
appendXaiSttParams(formData, {
|
|
97
|
+
...getXaiSttParams(this.modelId, xaiOptions),
|
|
96
98
|
audio_format: xaiOptions?.audioFormat,
|
|
97
|
-
sample_rate: xaiOptions?.sampleRate,
|
|
98
|
-
language: xaiOptions?.language,
|
|
99
99
|
format: xaiOptions?.format,
|
|
100
|
-
|
|
101
|
-
channels: xaiOptions?.channels,
|
|
102
|
-
diarize: xaiOptions?.diarize,
|
|
103
|
-
filler_words: xaiOptions?.fillerWords,
|
|
104
|
-
};
|
|
105
|
-
|
|
106
|
-
for (const [key, value] of Object.entries(transcriptionOptions)) {
|
|
107
|
-
if (value != null) {
|
|
108
|
-
formData.append(key, String(value));
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
if (xaiOptions?.keyterm != null) {
|
|
113
|
-
const keyterms = Array.isArray(xaiOptions.keyterm)
|
|
114
|
-
? xaiOptions.keyterm
|
|
115
|
-
: [xaiOptions.keyterm];
|
|
116
|
-
|
|
117
|
-
for (const keyterm of keyterms) {
|
|
118
|
-
formData.append('keyterm', keyterm);
|
|
119
|
-
}
|
|
120
|
-
}
|
|
100
|
+
});
|
|
121
101
|
|
|
122
102
|
const blob =
|
|
123
103
|
audio instanceof Uint8Array
|
|
124
|
-
? new Blob([audio])
|
|
104
|
+
? new Blob([audio as Uint8Array<ArrayBuffer>])
|
|
125
105
|
: new Blob([convertBase64ToUint8Array(audio)]);
|
|
126
106
|
const fileExtension = mediaTypeToExtension(mediaType);
|
|
127
107
|
|
|
@@ -174,6 +154,13 @@ export class XaiTranscriptionModel implements TranscriptionModelV4 {
|
|
|
174
154
|
headers: responseHeaders,
|
|
175
155
|
body: rawResponse,
|
|
176
156
|
},
|
|
157
|
+
...(response.words?.some(word => word.speaker != null) && {
|
|
158
|
+
providerMetadata: {
|
|
159
|
+
xai: {
|
|
160
|
+
words: response.words,
|
|
161
|
+
},
|
|
162
|
+
},
|
|
163
|
+
}),
|
|
177
164
|
};
|
|
178
165
|
}
|
|
179
166
|
|
|
@@ -208,20 +195,21 @@ export class XaiTranscriptionModel implements TranscriptionModelV4 {
|
|
|
208
195
|
|
|
209
196
|
if (
|
|
210
197
|
xaiOptions?.audioFormat == null &&
|
|
211
|
-
!
|
|
198
|
+
!inputAudioFormatEncodings.has(options.inputAudioFormat.type)
|
|
212
199
|
) {
|
|
213
200
|
warnings.push({
|
|
214
201
|
type: 'other',
|
|
215
202
|
message:
|
|
216
203
|
`Unrecognized inputAudioFormat.type "${options.inputAudioFormat.type}"; ` +
|
|
217
204
|
`falling back to raw PCM encoding. ` +
|
|
218
|
-
`Use
|
|
205
|
+
`Use ${[...inputAudioFormatEncodings.keys()].join(', ')}, ` +
|
|
219
206
|
`or set providerOptions.xai.audioFormat explicitly.`,
|
|
220
207
|
});
|
|
221
208
|
}
|
|
222
209
|
|
|
223
210
|
const url = buildXaiStreamingTranscriptionUrl({
|
|
224
211
|
baseURL: this.config.baseURL ?? 'https://api.x.ai/v1',
|
|
212
|
+
modelId: this.modelId,
|
|
225
213
|
inputAudioFormat: options.inputAudioFormat,
|
|
226
214
|
providerOptions: xaiOptions,
|
|
227
215
|
});
|
|
@@ -466,85 +454,77 @@ function createXaiStreamingTranscriptionStream({
|
|
|
466
454
|
|
|
467
455
|
function buildXaiStreamingTranscriptionUrl({
|
|
468
456
|
baseURL,
|
|
457
|
+
modelId,
|
|
469
458
|
inputAudioFormat,
|
|
470
459
|
providerOptions,
|
|
471
460
|
}: {
|
|
472
461
|
baseURL: string;
|
|
462
|
+
modelId: XaiTranscriptionModelId;
|
|
473
463
|
inputAudioFormat: TranscriptionModelV4StreamOptions['inputAudioFormat'];
|
|
474
464
|
providerOptions: XaiTranscriptionModelOptions | undefined;
|
|
475
465
|
}) {
|
|
476
466
|
const url = toWebSocketUrl(`${baseURL}/stt`);
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
providerOptions?.
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
appendSearchParam(url, 'filler_words', providerOptions?.fillerWords);
|
|
492
|
-
appendSearchParam(url, 'multichannel', providerOptions?.multichannel);
|
|
493
|
-
appendSearchParam(url, 'channels', providerOptions?.channels);
|
|
494
|
-
appendSearchParam(
|
|
495
|
-
url,
|
|
496
|
-
'interim_results',
|
|
497
|
-
providerOptions?.streaming?.interimResults,
|
|
498
|
-
);
|
|
499
|
-
appendSearchParam(
|
|
500
|
-
url,
|
|
501
|
-
'endpointing',
|
|
502
|
-
providerOptions?.streaming?.endpointing,
|
|
503
|
-
);
|
|
504
|
-
appendSearchParam(url, 'smart_turn', providerOptions?.streaming?.smartTurn);
|
|
505
|
-
appendSearchParam(
|
|
506
|
-
url,
|
|
507
|
-
'smart_turn_timeout',
|
|
508
|
-
providerOptions?.streaming?.smartTurnTimeout,
|
|
509
|
-
);
|
|
510
|
-
|
|
511
|
-
if (providerOptions?.keyterm != null) {
|
|
512
|
-
const keyterms = Array.isArray(providerOptions.keyterm)
|
|
513
|
-
? providerOptions.keyterm
|
|
514
|
-
: [providerOptions.keyterm];
|
|
515
|
-
for (const keyterm of keyterms) {
|
|
516
|
-
url.searchParams.append('keyterm', keyterm);
|
|
517
|
-
}
|
|
518
|
-
}
|
|
467
|
+
const params = getXaiSttParams(modelId, providerOptions);
|
|
468
|
+
|
|
469
|
+
appendXaiSttParams(url.searchParams, {
|
|
470
|
+
...params,
|
|
471
|
+
sample_rate: params.sample_rate ?? inputAudioFormat.rate,
|
|
472
|
+
encoding:
|
|
473
|
+
providerOptions?.audioFormat ??
|
|
474
|
+
inputAudioFormatEncodings.get(inputAudioFormat.type) ??
|
|
475
|
+
'pcm',
|
|
476
|
+
interim_results: providerOptions?.streaming?.interimResults,
|
|
477
|
+
endpointing: providerOptions?.streaming?.endpointing,
|
|
478
|
+
smart_turn: providerOptions?.streaming?.smartTurn,
|
|
479
|
+
smart_turn_timeout: providerOptions?.streaming?.smartTurnTimeout,
|
|
480
|
+
});
|
|
519
481
|
|
|
520
482
|
return url;
|
|
521
483
|
}
|
|
522
484
|
|
|
523
|
-
function
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
value: string | number | boolean | null | undefined,
|
|
485
|
+
function getXaiSttParams(
|
|
486
|
+
modelId: XaiTranscriptionModelId,
|
|
487
|
+
options: XaiTranscriptionModelOptions | undefined,
|
|
527
488
|
) {
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
489
|
+
return {
|
|
490
|
+
model: modelId || undefined,
|
|
491
|
+
sample_rate: options?.sampleRate,
|
|
492
|
+
language: options?.language,
|
|
493
|
+
multichannel: options?.multichannel,
|
|
494
|
+
channels: options?.channels,
|
|
495
|
+
diarize: options?.diarize,
|
|
496
|
+
filler_words: options?.fillerWords,
|
|
497
|
+
vad_threshold: options?.vadThreshold,
|
|
498
|
+
keyterm: options?.keyterm,
|
|
499
|
+
};
|
|
535
500
|
}
|
|
536
501
|
|
|
537
|
-
function
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
502
|
+
function appendXaiSttParams(
|
|
503
|
+
target: { append(name: string, value: string): void },
|
|
504
|
+
params: Record<
|
|
505
|
+
string,
|
|
506
|
+
string | number | boolean | string[] | null | undefined
|
|
507
|
+
>,
|
|
508
|
+
) {
|
|
509
|
+
for (const [key, value] of Object.entries(params)) {
|
|
510
|
+
for (const item of Array.isArray(value) ? value : [value]) {
|
|
511
|
+
if (item != null) {
|
|
512
|
+
target.append(key, String(item));
|
|
513
|
+
}
|
|
514
|
+
}
|
|
545
515
|
}
|
|
546
516
|
}
|
|
547
517
|
|
|
518
|
+
const inputAudioFormatEncodings = new Map<
|
|
519
|
+
string,
|
|
520
|
+
NonNullable<XaiTranscriptionModelOptions['audioFormat']>
|
|
521
|
+
>([
|
|
522
|
+
['audio/pcm', 'pcm'],
|
|
523
|
+
['audio/pcmu', 'mulaw'],
|
|
524
|
+
['audio/pcma', 'alaw'],
|
|
525
|
+
['audio/opus', 'opus'],
|
|
526
|
+
]);
|
|
527
|
+
|
|
548
528
|
function channelId(channelIndex: number | undefined): string | undefined {
|
|
549
529
|
return channelIndex == null ? undefined : `channel-${channelIndex}`;
|
|
550
530
|
}
|
|
@@ -568,6 +548,7 @@ const xaiTranscriptionResponseSchema = z.object({
|
|
|
568
548
|
text: z.string(),
|
|
569
549
|
start: z.number(),
|
|
570
550
|
end: z.number(),
|
|
551
|
+
speaker: z.number().nullish(),
|
|
571
552
|
}),
|
|
572
553
|
)
|
|
573
554
|
.nullish(),
|