@ai-sdk/fish-audio 2.0.0 → 3.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/CHANGELOG.md +10 -2
- package/dist/index.d.ts +30 -13
- package/dist/index.js +32 -8
- package/dist/index.js.map +1 -1
- package/package.json +7 -7
- package/src/fish-audio-provider.ts +10 -10
- package/src/fish-audio-speech-model.ts +25 -8
- package/src/fish-audio-transcription-model.ts +24 -7
package/CHANGELOG.md
CHANGED
|
@@ -1,7 +1,15 @@
|
|
|
1
1
|
# @ai-sdk/fish-audio
|
|
2
2
|
|
|
3
|
-
##
|
|
3
|
+
## 3.0.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Updated dependencies [3469d0c]
|
|
8
|
+
- @ai-sdk/provider@4.0.6
|
|
9
|
+
- @ai-sdk/provider-utils@5.0.23
|
|
10
|
+
|
|
11
|
+
## 3.0.0
|
|
4
12
|
|
|
5
13
|
### Major Changes
|
|
6
14
|
|
|
7
|
-
-
|
|
15
|
+
- e1f9b02: feat(fish-audio): add Fish Audio provider with speech and transcription models
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {
|
|
1
|
+
import * as _ai_sdk_provider from '@ai-sdk/provider';
|
|
2
|
+
import { SpeechModelV4, ProviderV4, TranscriptionModelV4 } from '@ai-sdk/provider';
|
|
3
|
+
import { FetchFunction, WORKFLOW_SERIALIZE, WORKFLOW_DESERIALIZE } from '@ai-sdk/provider-utils';
|
|
3
4
|
import { z } from 'zod/v4';
|
|
4
5
|
|
|
5
6
|
type FishAudioConfig = {
|
|
@@ -33,14 +34,22 @@ interface FishAudioSpeechModelConfig extends FishAudioConfig {
|
|
|
33
34
|
currentDate?: () => Date;
|
|
34
35
|
};
|
|
35
36
|
}
|
|
36
|
-
declare class FishAudioSpeechModel implements
|
|
37
|
+
declare class FishAudioSpeechModel implements SpeechModelV4 {
|
|
37
38
|
readonly modelId: FishAudioSpeechModelId;
|
|
38
39
|
private readonly config;
|
|
39
|
-
readonly specificationVersion = "
|
|
40
|
+
readonly specificationVersion = "v4";
|
|
40
41
|
get provider(): string;
|
|
42
|
+
static [WORKFLOW_SERIALIZE](model: FishAudioSpeechModel): {
|
|
43
|
+
modelId: string;
|
|
44
|
+
config: _ai_sdk_provider.JSONObject;
|
|
45
|
+
};
|
|
46
|
+
static [WORKFLOW_DESERIALIZE](options: {
|
|
47
|
+
modelId: FishAudioSpeechModelId;
|
|
48
|
+
config: FishAudioSpeechModelConfig;
|
|
49
|
+
}): FishAudioSpeechModel;
|
|
41
50
|
constructor(modelId: FishAudioSpeechModelId, config: FishAudioSpeechModelConfig);
|
|
42
51
|
private getArgs;
|
|
43
|
-
doGenerate(options: Parameters<
|
|
52
|
+
doGenerate(options: Parameters<SpeechModelV4['doGenerate']>[0]): Promise<Awaited<ReturnType<SpeechModelV4['doGenerate']>>>;
|
|
44
53
|
}
|
|
45
54
|
|
|
46
55
|
/**
|
|
@@ -55,30 +64,30 @@ declare class FishAudioSpeechModel implements SpeechModelV3 {
|
|
|
55
64
|
*/
|
|
56
65
|
type FishAudioTranscriptionModelId = 'transcribe-1' | (string & {});
|
|
57
66
|
|
|
58
|
-
interface FishAudioProvider extends
|
|
67
|
+
interface FishAudioProvider extends ProviderV4 {
|
|
59
68
|
(modelId: FishAudioSpeechModelId, settings?: {}): {
|
|
60
69
|
speech: FishAudioSpeechModel;
|
|
61
70
|
};
|
|
62
71
|
/**
|
|
63
72
|
* Creates a model for speech generation.
|
|
64
73
|
*/
|
|
65
|
-
speech(modelId: FishAudioSpeechModelId):
|
|
74
|
+
speech(modelId: FishAudioSpeechModelId): SpeechModelV4;
|
|
66
75
|
/**
|
|
67
76
|
* Creates a model for speech generation.
|
|
68
77
|
*
|
|
69
78
|
* Narrowed to required: Fish Audio always provides speech models.
|
|
70
79
|
*/
|
|
71
|
-
speechModel(modelId: FishAudioSpeechModelId):
|
|
80
|
+
speechModel(modelId: FishAudioSpeechModelId): SpeechModelV4;
|
|
72
81
|
/**
|
|
73
82
|
* Creates a model for transcription.
|
|
74
83
|
*/
|
|
75
|
-
transcription(modelId?: FishAudioTranscriptionModelId):
|
|
84
|
+
transcription(modelId?: FishAudioTranscriptionModelId): TranscriptionModelV4;
|
|
76
85
|
/**
|
|
77
86
|
* Creates a model for transcription.
|
|
78
87
|
*
|
|
79
88
|
* Narrowed to required: Fish Audio always provides a transcription model.
|
|
80
89
|
*/
|
|
81
|
-
transcriptionModel(modelId?: FishAudioTranscriptionModelId):
|
|
90
|
+
transcriptionModel(modelId?: FishAudioTranscriptionModelId): TranscriptionModelV4;
|
|
82
91
|
}
|
|
83
92
|
interface FishAudioProviderSettings {
|
|
84
93
|
/**
|
|
@@ -113,14 +122,22 @@ interface FishAudioTranscriptionModelConfig extends FishAudioConfig {
|
|
|
113
122
|
currentDate?: () => Date;
|
|
114
123
|
};
|
|
115
124
|
}
|
|
116
|
-
declare class FishAudioTranscriptionModel implements
|
|
125
|
+
declare class FishAudioTranscriptionModel implements TranscriptionModelV4 {
|
|
117
126
|
readonly modelId: FishAudioTranscriptionModelId;
|
|
118
127
|
private readonly config;
|
|
119
|
-
readonly specificationVersion = "
|
|
128
|
+
readonly specificationVersion = "v4";
|
|
120
129
|
get provider(): string;
|
|
130
|
+
static [WORKFLOW_SERIALIZE](model: FishAudioTranscriptionModel): {
|
|
131
|
+
modelId: string;
|
|
132
|
+
config: _ai_sdk_provider.JSONObject;
|
|
133
|
+
};
|
|
134
|
+
static [WORKFLOW_DESERIALIZE](options: {
|
|
135
|
+
modelId: FishAudioTranscriptionModelId;
|
|
136
|
+
config: FishAudioTranscriptionModelConfig;
|
|
137
|
+
}): FishAudioTranscriptionModel;
|
|
121
138
|
constructor(modelId: FishAudioTranscriptionModelId, config: FishAudioTranscriptionModelConfig);
|
|
122
139
|
private getArgs;
|
|
123
|
-
doGenerate(options: Parameters<
|
|
140
|
+
doGenerate(options: Parameters<TranscriptionModelV4['doGenerate']>[0]): Promise<Awaited<ReturnType<TranscriptionModelV4['doGenerate']>>>;
|
|
124
141
|
}
|
|
125
142
|
|
|
126
143
|
declare const fishAudioSpeechModelOptionsSchema: z.ZodObject<{
|
package/dist/index.js
CHANGED
|
@@ -12,7 +12,10 @@ import {
|
|
|
12
12
|
combineHeaders,
|
|
13
13
|
createBinaryResponseHandler,
|
|
14
14
|
parseProviderOptions,
|
|
15
|
-
postJsonToApi
|
|
15
|
+
postJsonToApi,
|
|
16
|
+
serializeModelOptions,
|
|
17
|
+
WORKFLOW_DESERIALIZE,
|
|
18
|
+
WORKFLOW_SERIALIZE
|
|
16
19
|
} from "@ai-sdk/provider-utils";
|
|
17
20
|
|
|
18
21
|
// src/fish-audio-error.ts
|
|
@@ -150,15 +153,24 @@ function resolveFormat({
|
|
|
150
153
|
}
|
|
151
154
|
return matched;
|
|
152
155
|
}
|
|
153
|
-
var FishAudioSpeechModel = class {
|
|
156
|
+
var FishAudioSpeechModel = class _FishAudioSpeechModel {
|
|
154
157
|
constructor(modelId, config) {
|
|
155
158
|
this.modelId = modelId;
|
|
156
159
|
this.config = config;
|
|
157
|
-
this.specificationVersion = "
|
|
160
|
+
this.specificationVersion = "v4";
|
|
158
161
|
}
|
|
159
162
|
get provider() {
|
|
160
163
|
return this.config.provider;
|
|
161
164
|
}
|
|
165
|
+
static [WORKFLOW_SERIALIZE](model) {
|
|
166
|
+
return serializeModelOptions({
|
|
167
|
+
modelId: model.modelId,
|
|
168
|
+
config: model.config
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
static [WORKFLOW_DESERIALIZE](options) {
|
|
172
|
+
return new _FishAudioSpeechModel(options.modelId, options.config);
|
|
173
|
+
}
|
|
162
174
|
async getArgs({
|
|
163
175
|
text,
|
|
164
176
|
voice,
|
|
@@ -335,7 +347,10 @@ import {
|
|
|
335
347
|
createJsonResponseHandler,
|
|
336
348
|
mediaTypeToExtension,
|
|
337
349
|
parseProviderOptions as parseProviderOptions2,
|
|
338
|
-
postFormDataToApi
|
|
350
|
+
postFormDataToApi,
|
|
351
|
+
serializeModelOptions as serializeModelOptions2,
|
|
352
|
+
WORKFLOW_DESERIALIZE as WORKFLOW_DESERIALIZE2,
|
|
353
|
+
WORKFLOW_SERIALIZE as WORKFLOW_SERIALIZE2
|
|
339
354
|
} from "@ai-sdk/provider-utils";
|
|
340
355
|
import { z as z4 } from "zod/v4";
|
|
341
356
|
|
|
@@ -363,15 +378,24 @@ var fishAudioTranscriptionModelOptionsSchema = z3.object({
|
|
|
363
378
|
});
|
|
364
379
|
|
|
365
380
|
// src/fish-audio-transcription-model.ts
|
|
366
|
-
var FishAudioTranscriptionModel = class {
|
|
381
|
+
var FishAudioTranscriptionModel = class _FishAudioTranscriptionModel {
|
|
367
382
|
constructor(modelId, config) {
|
|
368
383
|
this.modelId = modelId;
|
|
369
384
|
this.config = config;
|
|
370
|
-
this.specificationVersion = "
|
|
385
|
+
this.specificationVersion = "v4";
|
|
371
386
|
}
|
|
372
387
|
get provider() {
|
|
373
388
|
return this.config.provider;
|
|
374
389
|
}
|
|
390
|
+
static [WORKFLOW_SERIALIZE2](model) {
|
|
391
|
+
return serializeModelOptions2({
|
|
392
|
+
modelId: model.modelId,
|
|
393
|
+
config: model.config
|
|
394
|
+
});
|
|
395
|
+
}
|
|
396
|
+
static [WORKFLOW_DESERIALIZE2](options) {
|
|
397
|
+
return new _FishAudioTranscriptionModel(options.modelId, options.config);
|
|
398
|
+
}
|
|
375
399
|
async getArgs({
|
|
376
400
|
audio,
|
|
377
401
|
mediaType,
|
|
@@ -470,7 +494,7 @@ var fishAudioTranscriptionResponseSchema = z4.object({
|
|
|
470
494
|
});
|
|
471
495
|
|
|
472
496
|
// src/version.ts
|
|
473
|
-
var VERSION = true ? "
|
|
497
|
+
var VERSION = true ? "3.0.1" : "0.0.0-test";
|
|
474
498
|
|
|
475
499
|
// src/fish-audio-provider.ts
|
|
476
500
|
var DEFAULT_BASE_URL = "https://api.fish.audio";
|
|
@@ -505,7 +529,7 @@ function createFishAudio(options = {}) {
|
|
|
505
529
|
speech: createSpeechModel(modelId)
|
|
506
530
|
};
|
|
507
531
|
};
|
|
508
|
-
provider.specificationVersion = "
|
|
532
|
+
provider.specificationVersion = "v4";
|
|
509
533
|
provider.speech = createSpeechModel;
|
|
510
534
|
provider.speechModel = createSpeechModel;
|
|
511
535
|
provider.transcription = createTranscriptionModel;
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/fish-audio-provider.ts","../src/fish-audio-speech-model.ts","../src/fish-audio-error.ts","../src/fish-audio-speech-model-options.ts","../src/fish-audio-transcription-model.ts","../src/fish-audio-transcription-model-options.ts","../src/version.ts"],"sourcesContent":["import {\n NoSuchModelError,\n type ProviderV3,\n type SpeechModelV3,\n type TranscriptionModelV3,\n} from '@ai-sdk/provider';\nimport {\n loadApiKey,\n withUserAgentSuffix,\n type FetchFunction,\n} from '@ai-sdk/provider-utils';\nimport { FishAudioSpeechModel } from './fish-audio-speech-model';\nimport type { FishAudioSpeechModelId } from './fish-audio-speech-options';\nimport { FishAudioTranscriptionModel } from './fish-audio-transcription-model';\nimport type { FishAudioTranscriptionModelId } from './fish-audio-transcription-options';\nimport { VERSION } from './version';\n\nexport interface FishAudioProvider extends ProviderV3 {\n (\n modelId: FishAudioSpeechModelId,\n settings?: {},\n ): {\n speech: FishAudioSpeechModel;\n };\n\n /**\n * Creates a model for speech generation.\n */\n speech(modelId: FishAudioSpeechModelId): SpeechModelV3;\n\n /**\n * Creates a model for speech generation.\n *\n * Narrowed to required: Fish Audio always provides speech models.\n */\n speechModel(modelId: FishAudioSpeechModelId): SpeechModelV3;\n\n /**\n * Creates a model for transcription.\n */\n transcription(modelId?: FishAudioTranscriptionModelId): TranscriptionModelV3;\n\n /**\n * Creates a model for transcription.\n *\n * Narrowed to required: Fish Audio always provides a transcription model.\n */\n transcriptionModel(\n modelId?: FishAudioTranscriptionModelId,\n ): TranscriptionModelV3;\n}\n\nexport interface FishAudioProviderSettings {\n /**\n * API key for authenticating requests.\n */\n apiKey?: string;\n\n /**\n * Base URL for the API calls.\n */\n baseURL?: string;\n\n /**\n * Custom headers to include in the requests.\n */\n headers?: Record<string, string>;\n\n /**\n * Custom fetch implementation. You can use it as a middleware to intercept requests,\n * or to provide a custom fetch implementation for e.g. testing.\n */\n fetch?: FetchFunction;\n}\n\nconst DEFAULT_BASE_URL = 'https://api.fish.audio';\n\n/**\n * Create a Fish Audio provider instance.\n */\nexport function createFishAudio(\n options: FishAudioProviderSettings = {},\n): FishAudioProvider {\n const baseURL = options.baseURL?.replace(/\\/$/, '') ?? DEFAULT_BASE_URL;\n\n const getHeaders = () =>\n withUserAgentSuffix(\n {\n Authorization: `Bearer ${loadApiKey({\n apiKey: options.apiKey,\n environmentVariableName: 'FISH_AUDIO_API_KEY',\n description: 'Fish Audio',\n })}`,\n ...options.headers,\n },\n `ai-sdk/fish-audio/${VERSION}`,\n );\n\n const createSpeechModel = (modelId: FishAudioSpeechModelId) =>\n new FishAudioSpeechModel(modelId, {\n provider: 'fish-audio.speech',\n url: ({ path }) => `${baseURL}${path}`,\n headers: getHeaders,\n fetch: options.fetch,\n });\n\n // `/v1/asr` has no model selector, so the model ID is a routing label and\n // defaults to `transcribe-1`.\n const createTranscriptionModel = (\n modelId: FishAudioTranscriptionModelId = 'transcribe-1',\n ) =>\n new FishAudioTranscriptionModel(modelId, {\n provider: 'fish-audio.transcription',\n url: ({ path }) => `${baseURL}${path}`,\n headers: getHeaders,\n fetch: options.fetch,\n });\n\n const provider = function (modelId: FishAudioSpeechModelId) {\n return {\n speech: createSpeechModel(modelId),\n };\n };\n\n provider.specificationVersion = 'v3' as const;\n provider.speech = createSpeechModel;\n provider.speechModel = createSpeechModel;\n provider.transcription = createTranscriptionModel;\n provider.transcriptionModel = createTranscriptionModel;\n\n // Required ProviderV3 methods that are not supported\n provider.languageModel = (modelId: string) => {\n throw new NoSuchModelError({\n modelId,\n modelType: 'languageModel',\n message: 'Fish Audio does not provide language models',\n });\n };\n\n provider.embeddingModel = (modelId: string) => {\n throw new NoSuchModelError({\n modelId,\n modelType: 'embeddingModel',\n message: 'Fish Audio does not provide embedding models',\n });\n };\n provider.textEmbeddingModel = provider.embeddingModel;\n\n provider.imageModel = (modelId: string) => {\n throw new NoSuchModelError({\n modelId,\n modelType: 'imageModel',\n message: 'Fish Audio does not provide image models',\n });\n };\n\n return provider as FishAudioProvider;\n}\n\n/**\n * Default Fish Audio provider instance.\n */\nexport const fishAudio = createFishAudio();\n","import type { SharedV3Warning, SpeechModelV3 } from '@ai-sdk/provider';\nimport {\n combineHeaders,\n createBinaryResponseHandler,\n parseProviderOptions,\n postJsonToApi,\n} from '@ai-sdk/provider-utils';\nimport type { FishAudioConfig } from './fish-audio-config';\nimport { fishAudioFailedResponseHandler } from './fish-audio-error';\nimport type {\n FishAudioSpeechAPITypes,\n FishAudioSpeechFormat,\n FishAudioProsodyControl,\n} from './fish-audio-speech-api-types';\nimport { fishAudioSpeechModelOptionsSchema } from './fish-audio-speech-model-options';\nimport type { FishAudioSpeechModelId } from './fish-audio-speech-options';\n\ninterface FishAudioSpeechModelConfig extends FishAudioConfig {\n _internal?: {\n currentDate?: () => Date;\n };\n}\n\nconst SUPPORTED_FORMATS: FishAudioSpeechFormat[] = [\n 'wav',\n 'pcm',\n 'mp3',\n 'opus',\n];\n\nconst DEFAULT_FORMAT: FishAudioSpeechFormat = 'mp3';\n\n// Fish Audio accepts `prosody.speed` between 0.5 and 2.0.\nconst MIN_SPEED = 0.5;\nconst MAX_SPEED = 2;\n\nfunction resolveFormat({\n outputFormat,\n warnings,\n}: {\n outputFormat: string | undefined;\n warnings: SharedV3Warning[];\n}): FishAudioSpeechFormat {\n if (outputFormat == null) {\n return DEFAULT_FORMAT;\n }\n\n const normalized = outputFormat.toLowerCase();\n const matched = SUPPORTED_FORMATS.find(format => format === normalized);\n\n if (matched == null) {\n warnings.push({\n type: 'unsupported',\n feature: 'outputFormat',\n details: `Fish Audio does not support the output format \"${outputFormat}\". Falling back to ${DEFAULT_FORMAT}. Supported formats are ${SUPPORTED_FORMATS.join(', ')}.`,\n });\n return DEFAULT_FORMAT;\n }\n\n return matched;\n}\n\nexport class FishAudioSpeechModel implements SpeechModelV3 {\n readonly specificationVersion = 'v3';\n\n get provider(): string {\n return this.config.provider;\n }\n\n constructor(\n readonly modelId: FishAudioSpeechModelId,\n private readonly config: FishAudioSpeechModelConfig,\n ) {}\n\n private async getArgs({\n text,\n voice,\n outputFormat,\n instructions,\n language,\n speed,\n providerOptions,\n }: Parameters<SpeechModelV3['doGenerate']>[0]) {\n const warnings: SharedV3Warning[] = [];\n\n const fishAudioOptions = await parseProviderOptions({\n provider: 'fishAudio',\n providerOptions,\n schema: fishAudioSpeechModelOptionsSchema,\n });\n\n const format = resolveFormat({ outputFormat, warnings });\n\n const requestBody: FishAudioSpeechAPITypes = {\n text,\n format,\n };\n\n // `providerOptions.fishAudio.referenceId` wins over the generic `voice` so\n // that multi-speaker arrays are expressible.\n const referenceId = fishAudioOptions?.referenceId ?? voice;\n if (referenceId != null) {\n requestBody.reference_id = referenceId;\n }\n\n const prosody: FishAudioProsodyControl = {};\n\n if (speed != null) {\n if (speed >= MIN_SPEED && speed <= MAX_SPEED) {\n prosody.speed = speed;\n } else {\n warnings.push({\n type: 'unsupported',\n feature: 'speed',\n details: `Fish Audio speed must be between ${MIN_SPEED} and ${MAX_SPEED}. The speed option was ignored.`,\n });\n }\n }\n\n if (fishAudioOptions?.volume != null) {\n prosody.volume = fishAudioOptions.volume;\n }\n\n if (fishAudioOptions?.normalizeLoudness != null) {\n // Fish Audio accepts `normalize_loudness` on s1 but ignores it, so warn\n // rather than let it silently do nothing. Only s1 is known to ignore it;\n // unrecognized model IDs are left alone.\n if (this.modelId === 's1') {\n warnings.push({\n type: 'unsupported',\n feature: 'providerOptions.fishAudio.normalizeLoudness',\n details:\n 'Fish Audio ignores normalizeLoudness on s1. It is supported by the S2 family (s2-pro, s2.1-pro).',\n });\n } else {\n prosody.normalize_loudness = fishAudioOptions.normalizeLoudness;\n }\n }\n\n if (Object.keys(prosody).length > 0) {\n requestBody.prosody = prosody;\n }\n\n if (language != null) {\n warnings.push({\n type: 'unsupported',\n feature: 'language',\n details:\n 'Fish Audio infers the language from the input text and the selected voice, and has no language parameter. The language option was ignored.',\n });\n }\n\n if (instructions != null) {\n warnings.push({\n type: 'unsupported',\n feature: 'instructions',\n details:\n 'Fish Audio does not support instructions. The instructions option was ignored.',\n });\n }\n\n if (fishAudioOptions != null) {\n if (fishAudioOptions.sampleRate != null) {\n requestBody.sample_rate = fishAudioOptions.sampleRate;\n }\n\n if (fishAudioOptions.mp3Bitrate != null) {\n if (format === 'mp3') {\n requestBody.mp3_bitrate = fishAudioOptions.mp3Bitrate;\n } else {\n warnings.push({\n type: 'unsupported',\n feature: 'providerOptions.fishAudio.mp3Bitrate',\n details: `mp3Bitrate only applies to mp3 output. The option was ignored for ${format} output.`,\n });\n }\n }\n\n if (fishAudioOptions.opusBitrate != null) {\n if (format === 'opus') {\n requestBody.opus_bitrate = fishAudioOptions.opusBitrate;\n } else {\n warnings.push({\n type: 'unsupported',\n feature: 'providerOptions.fishAudio.opusBitrate',\n details: `opusBitrate only applies to opus output. The option was ignored for ${format} output.`,\n });\n }\n }\n\n if (fishAudioOptions.latency != null) {\n requestBody.latency = fishAudioOptions.latency;\n }\n\n if (fishAudioOptions.temperature != null) {\n requestBody.temperature = fishAudioOptions.temperature;\n }\n\n if (fishAudioOptions.topP != null) {\n requestBody.top_p = fishAudioOptions.topP;\n }\n\n if (fishAudioOptions.chunkLength != null) {\n requestBody.chunk_length = fishAudioOptions.chunkLength;\n }\n\n if (fishAudioOptions.minChunkLength != null) {\n requestBody.min_chunk_length = fishAudioOptions.minChunkLength;\n }\n\n if (fishAudioOptions.normalize != null) {\n requestBody.normalize = fishAudioOptions.normalize;\n }\n\n if (fishAudioOptions.maxNewTokens != null) {\n requestBody.max_new_tokens = fishAudioOptions.maxNewTokens;\n }\n\n if (fishAudioOptions.repetitionPenalty != null) {\n requestBody.repetition_penalty = fishAudioOptions.repetitionPenalty;\n }\n\n if (fishAudioOptions.conditionOnPreviousChunks != null) {\n requestBody.condition_on_previous_chunks =\n fishAudioOptions.conditionOnPreviousChunks;\n }\n\n if (fishAudioOptions.earlyStopThreshold != null) {\n requestBody.early_stop_threshold = fishAudioOptions.earlyStopThreshold;\n }\n\n if (fishAudioOptions.features != null) {\n requestBody.features = fishAudioOptions.features;\n }\n }\n\n return { requestBody, warnings };\n }\n\n async doGenerate(\n options: Parameters<SpeechModelV3['doGenerate']>[0],\n ): Promise<Awaited<ReturnType<SpeechModelV3['doGenerate']>>> {\n const currentDate = this.config._internal?.currentDate?.() ?? new Date();\n const { requestBody, warnings } = await this.getArgs(options);\n\n const {\n value: audio,\n responseHeaders,\n rawValue: rawResponse,\n } = await postJsonToApi({\n url: this.config.url({ path: '/v1/tts', modelId: this.modelId }),\n // Fish Audio selects the TTS model with a `model` HTTP header rather\n // than a request body field.\n headers: combineHeaders(\n this.config.headers?.(),\n { model: this.modelId },\n options.headers,\n ),\n body: requestBody,\n failedResponseHandler: fishAudioFailedResponseHandler,\n successfulResponseHandler: createBinaryResponseHandler(),\n abortSignal: options.abortSignal,\n fetch: this.config.fetch,\n });\n\n return {\n audio,\n warnings,\n request: {\n body: JSON.stringify(requestBody),\n },\n response: {\n timestamp: currentDate,\n modelId: this.modelId,\n headers: responseHeaders,\n body: rawResponse,\n },\n };\n }\n}\n","import { createJsonErrorResponseHandler } from '@ai-sdk/provider-utils';\nimport { z } from 'zod/v4';\n\n// Fish Audio returns `{ status, message }` for documented error responses\n// (401 no permission, 402 no payment).\n// https://docs.fish.audio/api-reference/endpoint/openapi-v1/text-to-speech\nexport const fishAudioErrorDataSchema = z.object({\n status: z.number().nullish(),\n message: z.string().nullish(),\n});\n\nexport type FishAudioErrorData = z.infer<typeof fishAudioErrorDataSchema>;\n\nexport const fishAudioFailedResponseHandler = createJsonErrorResponseHandler({\n errorSchema: fishAudioErrorDataSchema,\n errorToMessage: data => data.message ?? 'Unknown Fish Audio error',\n});\n","import { z } from 'zod/v4';\n\n// https://docs.fish.audio/api-reference/endpoint/openapi-v1/text-to-speech\nexport const fishAudioSpeechModelOptionsSchema = z.object({\n /**\n * Voice model ID(s). A single ID selects one speaker; an array enables\n * multi-speaker dialogue (S2-Pro models), in which case the text must mark\n * turns with speaker tokens such as `<|speaker:0|>`. The speaker index maps\n * to the position in this array.\n *\n * Takes precedence over the top-level `voice` option.\n */\n referenceId: z.union([z.string(), z.array(z.string())]).optional(),\n\n /**\n * Output sample rate in Hz. Falls back to the format default when unset\n * (44100 Hz for wav/pcm/mp3, 48000 Hz for opus).\n */\n sampleRate: z.number().int().positive().optional(),\n\n /**\n * Bitrate in kbps for mp3 output. Ignored for other formats.\n */\n mp3Bitrate: z\n .union([z.literal(64), z.literal(128), z.literal(192)])\n .optional(),\n\n /**\n * Bitrate in bps for opus output, where `-1000` selects automatic. Ignored\n * for other formats.\n */\n opusBitrate: z\n .union([\n z.literal(-1000),\n z.literal(24_000),\n z.literal(32_000),\n z.literal(48_000),\n z.literal(64_000),\n ])\n .optional(),\n\n /**\n * Latency/quality tradeoff. `normal` gives the best quality, `balanced`\n * reduces latency, and `low` is the fastest.\n */\n latency: z.enum(['low', 'normal', 'balanced']).optional(),\n\n /**\n * Volume offset in dB. Negative values are quieter.\n */\n volume: z.number().optional(),\n\n /**\n * Loudness normalization. Supported by the S2 family (`s2-pro` and\n * `s2.1-pro`). Fish Audio accepts it on `s1` but ignores it, so the provider\n * emits a warning in that case.\n */\n normalizeLoudness: z.boolean().optional(),\n\n /**\n * Governs expressiveness. Higher values are more varied, lower values more\n * consistent.\n */\n temperature: z.number().min(0).max(1).optional(),\n\n /**\n * Controls diversity via nucleus sampling.\n */\n topP: z.number().min(0).max(1).optional(),\n\n /**\n * Text segment size for processing.\n */\n chunkLength: z.number().int().min(100).max(300).optional(),\n\n /**\n * Minimum characters before splitting into a new chunk.\n */\n minChunkLength: z.number().int().min(0).max(100).optional(),\n\n /**\n * Text normalization for English and Chinese. Helps stability with numbers.\n */\n normalize: z.boolean().optional(),\n\n /**\n * Maximum audio tokens to generate per text chunk.\n */\n maxNewTokens: z.number().int().positive().optional(),\n\n /**\n * Values above 1.0 discourage repeated audio patterns.\n */\n repetitionPenalty: z.number().optional(),\n\n /**\n * Reuse prior audio as context for voice consistency across chunks.\n */\n conditionOnPreviousChunks: z.boolean().optional(),\n\n /**\n * Early-stop threshold used in batch processing.\n */\n earlyStopThreshold: z.number().min(0).max(1).optional(),\n\n /**\n * Request-scoped flags passed through to the inference backend, e.g.\n * `['quality-guard']`.\n */\n features: z.array(z.string()).optional(),\n});\n\nexport type FishAudioSpeechModelOptions = z.infer<\n typeof fishAudioSpeechModelOptionsSchema\n>;\n","import type { SharedV3Warning, TranscriptionModelV3 } from '@ai-sdk/provider';\nimport {\n combineHeaders,\n convertBase64ToUint8Array,\n createJsonResponseHandler,\n mediaTypeToExtension,\n parseProviderOptions,\n postFormDataToApi,\n} from '@ai-sdk/provider-utils';\nimport { z } from 'zod/v4';\nimport type { FishAudioConfig } from './fish-audio-config';\nimport { fishAudioFailedResponseHandler } from './fish-audio-error';\nimport { fishAudioTranscriptionModelOptionsSchema } from './fish-audio-transcription-model-options';\nimport type { FishAudioTranscriptionModelId } from './fish-audio-transcription-options';\n\ninterface FishAudioTranscriptionModelConfig extends FishAudioConfig {\n _internal?: {\n currentDate?: () => Date;\n };\n}\n\nexport class FishAudioTranscriptionModel implements TranscriptionModelV3 {\n readonly specificationVersion = 'v3';\n\n get provider(): string {\n return this.config.provider;\n }\n\n constructor(\n readonly modelId: FishAudioTranscriptionModelId,\n private readonly config: FishAudioTranscriptionModelConfig,\n ) {}\n\n private async getArgs({\n audio,\n mediaType,\n providerOptions,\n }: Parameters<TranscriptionModelV3['doGenerate']>[0]) {\n const warnings: SharedV3Warning[] = [];\n\n const fishAudioOptions = await parseProviderOptions({\n provider: 'fishAudio',\n providerOptions,\n schema: fishAudioTranscriptionModelOptionsSchema,\n });\n\n const formData = new FormData();\n const blob =\n audio instanceof Uint8Array\n ? new Blob([audio])\n : new Blob([convertBase64ToUint8Array(audio)]);\n\n formData.append(\n 'audio',\n new File([blob], 'audio', { type: mediaType }),\n `audio.${mediaTypeToExtension(mediaType)}`,\n );\n\n if (fishAudioOptions?.language != null) {\n formData.append('language', fishAudioOptions.language);\n }\n\n // Fish Audio defaults `ignore_timestamps` to true, which leaves the\n // transcription result without segments. Request timestamps by default and\n // let callers opt back out.\n formData.append(\n 'ignore_timestamps',\n String(fishAudioOptions?.ignoreTimestamps ?? false),\n );\n\n return { formData, warnings };\n }\n\n async doGenerate(\n options: Parameters<TranscriptionModelV3['doGenerate']>[0],\n ): Promise<Awaited<ReturnType<TranscriptionModelV3['doGenerate']>>> {\n const currentDate = this.config._internal?.currentDate?.() ?? new Date();\n const { formData, warnings } = await this.getArgs(options);\n\n const {\n value: response,\n responseHeaders,\n rawValue: rawResponse,\n } = await postFormDataToApi({\n url: this.config.url({ path: '/v1/asr', modelId: this.modelId }),\n headers: combineHeaders(this.config.headers?.(), options.headers),\n formData,\n failedResponseHandler: fishAudioFailedResponseHandler,\n successfulResponseHandler: createJsonResponseHandler(\n fishAudioTranscriptionResponseSchema,\n ),\n abortSignal: options.abortSignal,\n fetch: this.config.fetch,\n });\n\n const segments =\n response.segments?.map(segment => ({\n text: segment.text,\n startSecond: segment.start,\n endSecond: segment.end,\n })) ?? [];\n\n return {\n text: response.text,\n segments,\n // `language_code` is absent from the documented response schema but is\n // returned in practice, and reflects the detected language rather than\n // the requested one.\n language: response.language_code ?? undefined,\n durationInSeconds: response.duration ?? undefined,\n warnings,\n response: {\n timestamp: currentDate,\n modelId: this.modelId,\n headers: responseHeaders,\n body: rawResponse,\n },\n ...(response.language != null && {\n providerMetadata: {\n fishAudio: {\n // Human-readable display name, e.g. `English`. Its exact form is\n // not guaranteed, so `language` above (the ISO-639-1 code) is the\n // value to branch on.\n language: response.language,\n },\n },\n }),\n };\n }\n}\n\nconst fishAudioTranscriptionResponseSchema = z.object({\n text: z.string(),\n // `language` and `language_code` are undocumented but returned in practice.\n // Human-readable name, e.g. `English`.\n language: z.string().nullish(),\n // ISO-639-1 code, e.g. `en`.\n language_code: z.string().nullish(),\n duration: z.number().nullish(),\n segments: z\n .array(\n z.object({\n text: z.string(),\n start: z.number(),\n end: z.number(),\n }),\n )\n .nullish(),\n});\n","import { z } from 'zod/v4';\n\n// https://docs.fish.audio/api-reference/endpoint/openapi-v1/speech-to-text\nexport const fishAudioTranscriptionModelOptionsSchema = z.object({\n /**\n * Language of the audio.\n *\n * A hint only. Fish Audio passes it to the model, but auto-detection is\n * authoritative and overrides it, so this changes neither the transcript nor\n * the reported language. The detected language is reported as\n * `result.language`.\n */\n language: z.string().optional(),\n\n /**\n * Whether to skip precise timestamps. Mirrors the Fish Audio\n * `ignore_timestamps` parameter, whose API default is `true`.\n *\n * This provider defaults it to `false` so that `result.segments` is\n * populated. Fish Audio documents an added latency cost for audio shorter\n * than 30 seconds; set this to `true` to trade segments for that latency.\n */\n ignoreTimestamps: z.boolean().optional(),\n});\n\nexport type FishAudioTranscriptionModelOptions = z.infer<\n typeof fishAudioTranscriptionModelOptionsSchema\n>;\n","// Version string of this package injected at build time.\ndeclare const __PACKAGE_VERSION__: string | undefined;\nexport const VERSION: string =\n typeof __PACKAGE_VERSION__ !== 'undefined'\n ? __PACKAGE_VERSION__\n : '0.0.0-test';\n"],"mappings":"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","names":["z","combineHeaders","parseProviderOptions","z","z","parseProviderOptions","combineHeaders","z"]}
|
|
1
|
+
{"version":3,"sources":["../src/fish-audio-provider.ts","../src/fish-audio-speech-model.ts","../src/fish-audio-error.ts","../src/fish-audio-speech-model-options.ts","../src/fish-audio-transcription-model.ts","../src/fish-audio-transcription-model-options.ts","../src/version.ts"],"sourcesContent":["import {\n NoSuchModelError,\n type ProviderV4,\n type SpeechModelV4,\n type TranscriptionModelV4,\n} from '@ai-sdk/provider';\nimport {\n loadApiKey,\n withUserAgentSuffix,\n type FetchFunction,\n} from '@ai-sdk/provider-utils';\nimport { FishAudioSpeechModel } from './fish-audio-speech-model';\nimport type { FishAudioSpeechModelId } from './fish-audio-speech-options';\nimport { FishAudioTranscriptionModel } from './fish-audio-transcription-model';\nimport type { FishAudioTranscriptionModelId } from './fish-audio-transcription-options';\nimport { VERSION } from './version';\n\nexport interface FishAudioProvider extends ProviderV4 {\n (\n modelId: FishAudioSpeechModelId,\n settings?: {},\n ): {\n speech: FishAudioSpeechModel;\n };\n\n /**\n * Creates a model for speech generation.\n */\n speech(modelId: FishAudioSpeechModelId): SpeechModelV4;\n\n /**\n * Creates a model for speech generation.\n *\n * Narrowed to required: Fish Audio always provides speech models.\n */\n speechModel(modelId: FishAudioSpeechModelId): SpeechModelV4;\n\n /**\n * Creates a model for transcription.\n */\n transcription(modelId?: FishAudioTranscriptionModelId): TranscriptionModelV4;\n\n /**\n * Creates a model for transcription.\n *\n * Narrowed to required: Fish Audio always provides a transcription model.\n */\n transcriptionModel(\n modelId?: FishAudioTranscriptionModelId,\n ): TranscriptionModelV4;\n}\n\nexport interface FishAudioProviderSettings {\n /**\n * API key for authenticating requests.\n */\n apiKey?: string;\n\n /**\n * Base URL for the API calls.\n */\n baseURL?: string;\n\n /**\n * Custom headers to include in the requests.\n */\n headers?: Record<string, string>;\n\n /**\n * Custom fetch implementation. You can use it as a middleware to intercept requests,\n * or to provide a custom fetch implementation for e.g. testing.\n */\n fetch?: FetchFunction;\n}\n\nconst DEFAULT_BASE_URL = 'https://api.fish.audio';\n\n/**\n * Create a Fish Audio provider instance.\n */\nexport function createFishAudio(\n options: FishAudioProviderSettings = {},\n): FishAudioProvider {\n const baseURL = options.baseURL?.replace(/\\/$/, '') ?? DEFAULT_BASE_URL;\n\n const getHeaders = () =>\n withUserAgentSuffix(\n {\n Authorization: `Bearer ${loadApiKey({\n apiKey: options.apiKey,\n environmentVariableName: 'FISH_AUDIO_API_KEY',\n description: 'Fish Audio',\n })}`,\n ...options.headers,\n },\n `ai-sdk/fish-audio/${VERSION}`,\n );\n\n const createSpeechModel = (modelId: FishAudioSpeechModelId) =>\n new FishAudioSpeechModel(modelId, {\n provider: 'fish-audio.speech',\n url: ({ path }) => `${baseURL}${path}`,\n headers: getHeaders,\n fetch: options.fetch,\n });\n\n // `/v1/asr` has no model selector, so the model ID is a routing label and\n // defaults to `transcribe-1`.\n const createTranscriptionModel = (\n modelId: FishAudioTranscriptionModelId = 'transcribe-1',\n ) =>\n new FishAudioTranscriptionModel(modelId, {\n provider: 'fish-audio.transcription',\n url: ({ path }) => `${baseURL}${path}`,\n headers: getHeaders,\n fetch: options.fetch,\n });\n\n const provider = function (modelId: FishAudioSpeechModelId) {\n return {\n speech: createSpeechModel(modelId),\n };\n };\n\n provider.specificationVersion = 'v4' as const;\n provider.speech = createSpeechModel;\n provider.speechModel = createSpeechModel;\n provider.transcription = createTranscriptionModel;\n provider.transcriptionModel = createTranscriptionModel;\n\n // Required ProviderV4 methods that are not supported\n provider.languageModel = (modelId: string) => {\n throw new NoSuchModelError({\n modelId,\n modelType: 'languageModel',\n message: 'Fish Audio does not provide language models',\n });\n };\n\n provider.embeddingModel = (modelId: string) => {\n throw new NoSuchModelError({\n modelId,\n modelType: 'embeddingModel',\n message: 'Fish Audio does not provide embedding models',\n });\n };\n provider.textEmbeddingModel = provider.embeddingModel;\n\n provider.imageModel = (modelId: string) => {\n throw new NoSuchModelError({\n modelId,\n modelType: 'imageModel',\n message: 'Fish Audio does not provide image models',\n });\n };\n\n return provider as FishAudioProvider;\n}\n\n/**\n * Default Fish Audio provider instance.\n */\nexport const fishAudio = createFishAudio();\n","import type { SharedV4Warning, SpeechModelV4 } from '@ai-sdk/provider';\nimport {\n combineHeaders,\n createBinaryResponseHandler,\n parseProviderOptions,\n postJsonToApi,\n serializeModelOptions,\n WORKFLOW_DESERIALIZE,\n WORKFLOW_SERIALIZE,\n} from '@ai-sdk/provider-utils';\nimport type { FishAudioConfig } from './fish-audio-config';\nimport { fishAudioFailedResponseHandler } from './fish-audio-error';\nimport type {\n FishAudioSpeechAPITypes,\n FishAudioSpeechFormat,\n FishAudioProsodyControl,\n} from './fish-audio-speech-api-types';\nimport { fishAudioSpeechModelOptionsSchema } from './fish-audio-speech-model-options';\nimport type { FishAudioSpeechModelId } from './fish-audio-speech-options';\n\ninterface FishAudioSpeechModelConfig extends FishAudioConfig {\n _internal?: {\n currentDate?: () => Date;\n };\n}\n\nconst SUPPORTED_FORMATS: FishAudioSpeechFormat[] = [\n 'wav',\n 'pcm',\n 'mp3',\n 'opus',\n];\n\nconst DEFAULT_FORMAT: FishAudioSpeechFormat = 'mp3';\n\n// Fish Audio accepts `prosody.speed` between 0.5 and 2.0.\nconst MIN_SPEED = 0.5;\nconst MAX_SPEED = 2;\n\nfunction resolveFormat({\n outputFormat,\n warnings,\n}: {\n outputFormat: string | undefined;\n warnings: SharedV4Warning[];\n}): FishAudioSpeechFormat {\n if (outputFormat == null) {\n return DEFAULT_FORMAT;\n }\n\n const normalized = outputFormat.toLowerCase();\n const matched = SUPPORTED_FORMATS.find(format => format === normalized);\n\n if (matched == null) {\n warnings.push({\n type: 'unsupported',\n feature: 'outputFormat',\n details: `Fish Audio does not support the output format \"${outputFormat}\". Falling back to ${DEFAULT_FORMAT}. Supported formats are ${SUPPORTED_FORMATS.join(', ')}.`,\n });\n return DEFAULT_FORMAT;\n }\n\n return matched;\n}\n\nexport class FishAudioSpeechModel implements SpeechModelV4 {\n readonly specificationVersion = 'v4';\n\n get provider(): string {\n return this.config.provider;\n }\n\n static [WORKFLOW_SERIALIZE](model: FishAudioSpeechModel) {\n return serializeModelOptions({\n modelId: model.modelId,\n config: model.config,\n });\n }\n\n static [WORKFLOW_DESERIALIZE](options: {\n modelId: FishAudioSpeechModelId;\n config: FishAudioSpeechModelConfig;\n }) {\n return new FishAudioSpeechModel(options.modelId, options.config);\n }\n\n constructor(\n readonly modelId: FishAudioSpeechModelId,\n private readonly config: FishAudioSpeechModelConfig,\n ) {}\n\n private async getArgs({\n text,\n voice,\n outputFormat,\n instructions,\n language,\n speed,\n providerOptions,\n }: Parameters<SpeechModelV4['doGenerate']>[0]) {\n const warnings: SharedV4Warning[] = [];\n\n const fishAudioOptions = await parseProviderOptions({\n provider: 'fishAudio',\n providerOptions,\n schema: fishAudioSpeechModelOptionsSchema,\n });\n\n const format = resolveFormat({ outputFormat, warnings });\n\n const requestBody: FishAudioSpeechAPITypes = {\n text,\n format,\n };\n\n // `providerOptions.fishAudio.referenceId` wins over the generic `voice` so\n // that multi-speaker arrays are expressible.\n const referenceId = fishAudioOptions?.referenceId ?? voice;\n if (referenceId != null) {\n requestBody.reference_id = referenceId;\n }\n\n const prosody: FishAudioProsodyControl = {};\n\n if (speed != null) {\n if (speed >= MIN_SPEED && speed <= MAX_SPEED) {\n prosody.speed = speed;\n } else {\n warnings.push({\n type: 'unsupported',\n feature: 'speed',\n details: `Fish Audio speed must be between ${MIN_SPEED} and ${MAX_SPEED}. The speed option was ignored.`,\n });\n }\n }\n\n if (fishAudioOptions?.volume != null) {\n prosody.volume = fishAudioOptions.volume;\n }\n\n if (fishAudioOptions?.normalizeLoudness != null) {\n // Fish Audio accepts `normalize_loudness` on s1 but ignores it, so warn\n // rather than let it silently do nothing. Only s1 is known to ignore it;\n // unrecognized model IDs are left alone.\n if (this.modelId === 's1') {\n warnings.push({\n type: 'unsupported',\n feature: 'providerOptions.fishAudio.normalizeLoudness',\n details:\n 'Fish Audio ignores normalizeLoudness on s1. It is supported by the S2 family (s2-pro, s2.1-pro).',\n });\n } else {\n prosody.normalize_loudness = fishAudioOptions.normalizeLoudness;\n }\n }\n\n if (Object.keys(prosody).length > 0) {\n requestBody.prosody = prosody;\n }\n\n if (language != null) {\n warnings.push({\n type: 'unsupported',\n feature: 'language',\n details:\n 'Fish Audio infers the language from the input text and the selected voice, and has no language parameter. The language option was ignored.',\n });\n }\n\n if (instructions != null) {\n warnings.push({\n type: 'unsupported',\n feature: 'instructions',\n details:\n 'Fish Audio does not support instructions. The instructions option was ignored.',\n });\n }\n\n if (fishAudioOptions != null) {\n if (fishAudioOptions.sampleRate != null) {\n requestBody.sample_rate = fishAudioOptions.sampleRate;\n }\n\n if (fishAudioOptions.mp3Bitrate != null) {\n if (format === 'mp3') {\n requestBody.mp3_bitrate = fishAudioOptions.mp3Bitrate;\n } else {\n warnings.push({\n type: 'unsupported',\n feature: 'providerOptions.fishAudio.mp3Bitrate',\n details: `mp3Bitrate only applies to mp3 output. The option was ignored for ${format} output.`,\n });\n }\n }\n\n if (fishAudioOptions.opusBitrate != null) {\n if (format === 'opus') {\n requestBody.opus_bitrate = fishAudioOptions.opusBitrate;\n } else {\n warnings.push({\n type: 'unsupported',\n feature: 'providerOptions.fishAudio.opusBitrate',\n details: `opusBitrate only applies to opus output. The option was ignored for ${format} output.`,\n });\n }\n }\n\n if (fishAudioOptions.latency != null) {\n requestBody.latency = fishAudioOptions.latency;\n }\n\n if (fishAudioOptions.temperature != null) {\n requestBody.temperature = fishAudioOptions.temperature;\n }\n\n if (fishAudioOptions.topP != null) {\n requestBody.top_p = fishAudioOptions.topP;\n }\n\n if (fishAudioOptions.chunkLength != null) {\n requestBody.chunk_length = fishAudioOptions.chunkLength;\n }\n\n if (fishAudioOptions.minChunkLength != null) {\n requestBody.min_chunk_length = fishAudioOptions.minChunkLength;\n }\n\n if (fishAudioOptions.normalize != null) {\n requestBody.normalize = fishAudioOptions.normalize;\n }\n\n if (fishAudioOptions.maxNewTokens != null) {\n requestBody.max_new_tokens = fishAudioOptions.maxNewTokens;\n }\n\n if (fishAudioOptions.repetitionPenalty != null) {\n requestBody.repetition_penalty = fishAudioOptions.repetitionPenalty;\n }\n\n if (fishAudioOptions.conditionOnPreviousChunks != null) {\n requestBody.condition_on_previous_chunks =\n fishAudioOptions.conditionOnPreviousChunks;\n }\n\n if (fishAudioOptions.earlyStopThreshold != null) {\n requestBody.early_stop_threshold = fishAudioOptions.earlyStopThreshold;\n }\n\n if (fishAudioOptions.features != null) {\n requestBody.features = fishAudioOptions.features;\n }\n }\n\n return { requestBody, warnings };\n }\n\n async doGenerate(\n options: Parameters<SpeechModelV4['doGenerate']>[0],\n ): Promise<Awaited<ReturnType<SpeechModelV4['doGenerate']>>> {\n const currentDate = this.config._internal?.currentDate?.() ?? new Date();\n const { requestBody, warnings } = await this.getArgs(options);\n\n const {\n value: audio,\n responseHeaders,\n rawValue: rawResponse,\n } = await postJsonToApi({\n url: this.config.url({ path: '/v1/tts', modelId: this.modelId }),\n // Fish Audio selects the TTS model with a `model` HTTP header rather\n // than a request body field.\n headers: combineHeaders(\n this.config.headers?.(),\n { model: this.modelId },\n options.headers,\n ),\n body: requestBody,\n failedResponseHandler: fishAudioFailedResponseHandler,\n successfulResponseHandler: createBinaryResponseHandler(),\n abortSignal: options.abortSignal,\n fetch: this.config.fetch,\n });\n\n return {\n audio,\n warnings,\n request: {\n body: JSON.stringify(requestBody),\n },\n response: {\n timestamp: currentDate,\n modelId: this.modelId,\n headers: responseHeaders,\n body: rawResponse,\n },\n };\n }\n}\n","import { createJsonErrorResponseHandler } from '@ai-sdk/provider-utils';\nimport { z } from 'zod/v4';\n\n// Fish Audio returns `{ status, message }` for documented error responses\n// (401 no permission, 402 no payment).\n// https://docs.fish.audio/api-reference/endpoint/openapi-v1/text-to-speech\nexport const fishAudioErrorDataSchema = z.object({\n status: z.number().nullish(),\n message: z.string().nullish(),\n});\n\nexport type FishAudioErrorData = z.infer<typeof fishAudioErrorDataSchema>;\n\nexport const fishAudioFailedResponseHandler = createJsonErrorResponseHandler({\n errorSchema: fishAudioErrorDataSchema,\n errorToMessage: data => data.message ?? 'Unknown Fish Audio error',\n});\n","import { z } from 'zod/v4';\n\n// https://docs.fish.audio/api-reference/endpoint/openapi-v1/text-to-speech\nexport const fishAudioSpeechModelOptionsSchema = z.object({\n /**\n * Voice model ID(s). A single ID selects one speaker; an array enables\n * multi-speaker dialogue (S2-Pro models), in which case the text must mark\n * turns with speaker tokens such as `<|speaker:0|>`. The speaker index maps\n * to the position in this array.\n *\n * Takes precedence over the top-level `voice` option.\n */\n referenceId: z.union([z.string(), z.array(z.string())]).optional(),\n\n /**\n * Output sample rate in Hz. Falls back to the format default when unset\n * (44100 Hz for wav/pcm/mp3, 48000 Hz for opus).\n */\n sampleRate: z.number().int().positive().optional(),\n\n /**\n * Bitrate in kbps for mp3 output. Ignored for other formats.\n */\n mp3Bitrate: z\n .union([z.literal(64), z.literal(128), z.literal(192)])\n .optional(),\n\n /**\n * Bitrate in bps for opus output, where `-1000` selects automatic. Ignored\n * for other formats.\n */\n opusBitrate: z\n .union([\n z.literal(-1000),\n z.literal(24_000),\n z.literal(32_000),\n z.literal(48_000),\n z.literal(64_000),\n ])\n .optional(),\n\n /**\n * Latency/quality tradeoff. `normal` gives the best quality, `balanced`\n * reduces latency, and `low` is the fastest.\n */\n latency: z.enum(['low', 'normal', 'balanced']).optional(),\n\n /**\n * Volume offset in dB. Negative values are quieter.\n */\n volume: z.number().optional(),\n\n /**\n * Loudness normalization. Supported by the S2 family (`s2-pro` and\n * `s2.1-pro`). Fish Audio accepts it on `s1` but ignores it, so the provider\n * emits a warning in that case.\n */\n normalizeLoudness: z.boolean().optional(),\n\n /**\n * Governs expressiveness. Higher values are more varied, lower values more\n * consistent.\n */\n temperature: z.number().min(0).max(1).optional(),\n\n /**\n * Controls diversity via nucleus sampling.\n */\n topP: z.number().min(0).max(1).optional(),\n\n /**\n * Text segment size for processing.\n */\n chunkLength: z.number().int().min(100).max(300).optional(),\n\n /**\n * Minimum characters before splitting into a new chunk.\n */\n minChunkLength: z.number().int().min(0).max(100).optional(),\n\n /**\n * Text normalization for English and Chinese. Helps stability with numbers.\n */\n normalize: z.boolean().optional(),\n\n /**\n * Maximum audio tokens to generate per text chunk.\n */\n maxNewTokens: z.number().int().positive().optional(),\n\n /**\n * Values above 1.0 discourage repeated audio patterns.\n */\n repetitionPenalty: z.number().optional(),\n\n /**\n * Reuse prior audio as context for voice consistency across chunks.\n */\n conditionOnPreviousChunks: z.boolean().optional(),\n\n /**\n * Early-stop threshold used in batch processing.\n */\n earlyStopThreshold: z.number().min(0).max(1).optional(),\n\n /**\n * Request-scoped flags passed through to the inference backend, e.g.\n * `['quality-guard']`.\n */\n features: z.array(z.string()).optional(),\n});\n\nexport type FishAudioSpeechModelOptions = z.infer<\n typeof fishAudioSpeechModelOptionsSchema\n>;\n","import type { SharedV4Warning, TranscriptionModelV4 } from '@ai-sdk/provider';\nimport {\n combineHeaders,\n convertBase64ToUint8Array,\n createJsonResponseHandler,\n mediaTypeToExtension,\n parseProviderOptions,\n postFormDataToApi,\n serializeModelOptions,\n WORKFLOW_DESERIALIZE,\n WORKFLOW_SERIALIZE,\n} from '@ai-sdk/provider-utils';\nimport { z } from 'zod/v4';\nimport type { FishAudioConfig } from './fish-audio-config';\nimport { fishAudioFailedResponseHandler } from './fish-audio-error';\nimport { fishAudioTranscriptionModelOptionsSchema } from './fish-audio-transcription-model-options';\nimport type { FishAudioTranscriptionModelId } from './fish-audio-transcription-options';\n\ninterface FishAudioTranscriptionModelConfig extends FishAudioConfig {\n _internal?: {\n currentDate?: () => Date;\n };\n}\n\nexport class FishAudioTranscriptionModel implements TranscriptionModelV4 {\n readonly specificationVersion = 'v4';\n\n get provider(): string {\n return this.config.provider;\n }\n\n static [WORKFLOW_SERIALIZE](model: FishAudioTranscriptionModel) {\n return serializeModelOptions({\n modelId: model.modelId,\n config: model.config,\n });\n }\n\n static [WORKFLOW_DESERIALIZE](options: {\n modelId: FishAudioTranscriptionModelId;\n config: FishAudioTranscriptionModelConfig;\n }) {\n return new FishAudioTranscriptionModel(options.modelId, options.config);\n }\n\n constructor(\n readonly modelId: FishAudioTranscriptionModelId,\n private readonly config: FishAudioTranscriptionModelConfig,\n ) {}\n\n private async getArgs({\n audio,\n mediaType,\n providerOptions,\n }: Parameters<TranscriptionModelV4['doGenerate']>[0]) {\n const warnings: SharedV4Warning[] = [];\n\n const fishAudioOptions = await parseProviderOptions({\n provider: 'fishAudio',\n providerOptions,\n schema: fishAudioTranscriptionModelOptionsSchema,\n });\n\n const formData = new FormData();\n const blob =\n audio instanceof Uint8Array\n ? new Blob([audio])\n : new Blob([convertBase64ToUint8Array(audio)]);\n\n formData.append(\n 'audio',\n new File([blob], 'audio', { type: mediaType }),\n `audio.${mediaTypeToExtension(mediaType)}`,\n );\n\n if (fishAudioOptions?.language != null) {\n formData.append('language', fishAudioOptions.language);\n }\n\n // Fish Audio defaults `ignore_timestamps` to true, which leaves the\n // transcription result without segments. Request timestamps by default and\n // let callers opt back out.\n formData.append(\n 'ignore_timestamps',\n String(fishAudioOptions?.ignoreTimestamps ?? false),\n );\n\n return { formData, warnings };\n }\n\n async doGenerate(\n options: Parameters<TranscriptionModelV4['doGenerate']>[0],\n ): Promise<Awaited<ReturnType<TranscriptionModelV4['doGenerate']>>> {\n const currentDate = this.config._internal?.currentDate?.() ?? new Date();\n const { formData, warnings } = await this.getArgs(options);\n\n const {\n value: response,\n responseHeaders,\n rawValue: rawResponse,\n } = await postFormDataToApi({\n url: this.config.url({ path: '/v1/asr', modelId: this.modelId }),\n headers: combineHeaders(this.config.headers?.(), options.headers),\n formData,\n failedResponseHandler: fishAudioFailedResponseHandler,\n successfulResponseHandler: createJsonResponseHandler(\n fishAudioTranscriptionResponseSchema,\n ),\n abortSignal: options.abortSignal,\n fetch: this.config.fetch,\n });\n\n const segments =\n response.segments?.map(segment => ({\n text: segment.text,\n startSecond: segment.start,\n endSecond: segment.end,\n })) ?? [];\n\n return {\n text: response.text,\n segments,\n // `language_code` is absent from the documented response schema but is\n // returned in practice, and reflects the detected language rather than\n // the requested one.\n language: response.language_code ?? undefined,\n durationInSeconds: response.duration ?? undefined,\n warnings,\n response: {\n timestamp: currentDate,\n modelId: this.modelId,\n headers: responseHeaders,\n body: rawResponse,\n },\n ...(response.language != null && {\n providerMetadata: {\n fishAudio: {\n // Human-readable display name, e.g. `English`. Its exact form is\n // not guaranteed, so `language` above (the ISO-639-1 code) is the\n // value to branch on.\n language: response.language,\n },\n },\n }),\n };\n }\n}\n\nconst fishAudioTranscriptionResponseSchema = z.object({\n text: z.string(),\n // `language` and `language_code` are undocumented but returned in practice.\n // Human-readable name, e.g. `English`.\n language: z.string().nullish(),\n // ISO-639-1 code, e.g. `en`.\n language_code: z.string().nullish(),\n duration: z.number().nullish(),\n segments: z\n .array(\n z.object({\n text: z.string(),\n start: z.number(),\n end: z.number(),\n }),\n )\n .nullish(),\n});\n","import { z } from 'zod/v4';\n\n// https://docs.fish.audio/api-reference/endpoint/openapi-v1/speech-to-text\nexport const fishAudioTranscriptionModelOptionsSchema = z.object({\n /**\n * Language of the audio.\n *\n * A hint only. Fish Audio passes it to the model, but auto-detection is\n * authoritative and overrides it, so this changes neither the transcript nor\n * the reported language. The detected language is reported as\n * `result.language`.\n */\n language: z.string().optional(),\n\n /**\n * Whether to skip precise timestamps. Mirrors the Fish Audio\n * `ignore_timestamps` parameter, whose API default is `true`.\n *\n * This provider defaults it to `false` so that `result.segments` is\n * populated. Fish Audio documents an added latency cost for audio shorter\n * than 30 seconds; set this to `true` to trade segments for that latency.\n */\n ignoreTimestamps: z.boolean().optional(),\n});\n\nexport type FishAudioTranscriptionModelOptions = z.infer<\n typeof fishAudioTranscriptionModelOptionsSchema\n>;\n","// Version string of this package injected at build time.\ndeclare const __PACKAGE_VERSION__: string | undefined;\nexport const VERSION: string =\n typeof __PACKAGE_VERSION__ !== 'undefined'\n ? __PACKAGE_VERSION__\n : '0.0.0-test';\n"],"mappings":"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","names":["z","combineHeaders","parseProviderOptions","serializeModelOptions","WORKFLOW_DESERIALIZE","WORKFLOW_SERIALIZE","z","z","WORKFLOW_SERIALIZE","serializeModelOptions","WORKFLOW_DESERIALIZE","parseProviderOptions","combineHeaders","z"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ai-sdk/fish-audio",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "3.0.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"sideEffects": false,
|
|
@@ -29,22 +29,22 @@
|
|
|
29
29
|
}
|
|
30
30
|
},
|
|
31
31
|
"dependencies": {
|
|
32
|
-
"@ai-sdk/provider": "
|
|
33
|
-
"@ai-sdk/provider-utils": "
|
|
32
|
+
"@ai-sdk/provider": "4.0.6",
|
|
33
|
+
"@ai-sdk/provider-utils": "5.0.23"
|
|
34
34
|
},
|
|
35
35
|
"devDependencies": {
|
|
36
|
-
"@types/node": "
|
|
37
|
-
"tsup": "^8",
|
|
36
|
+
"@types/node": "22.19.19",
|
|
37
|
+
"tsup": "^8.5.1",
|
|
38
38
|
"typescript": "5.6.3",
|
|
39
39
|
"zod": "3.25.76",
|
|
40
|
-
"@ai-sdk/test-server": "
|
|
40
|
+
"@ai-sdk/test-server": "2.0.1",
|
|
41
41
|
"@vercel/ai-tsconfig": "0.0.0"
|
|
42
42
|
},
|
|
43
43
|
"peerDependencies": {
|
|
44
44
|
"zod": "^3.25.76 || ^4.1.8"
|
|
45
45
|
},
|
|
46
46
|
"engines": {
|
|
47
|
-
"node": ">=
|
|
47
|
+
"node": ">=22"
|
|
48
48
|
},
|
|
49
49
|
"publishConfig": {
|
|
50
50
|
"access": "public",
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import {
|
|
2
2
|
NoSuchModelError,
|
|
3
|
-
type
|
|
4
|
-
type
|
|
5
|
-
type
|
|
3
|
+
type ProviderV4,
|
|
4
|
+
type SpeechModelV4,
|
|
5
|
+
type TranscriptionModelV4,
|
|
6
6
|
} from '@ai-sdk/provider';
|
|
7
7
|
import {
|
|
8
8
|
loadApiKey,
|
|
@@ -15,7 +15,7 @@ import { FishAudioTranscriptionModel } from './fish-audio-transcription-model';
|
|
|
15
15
|
import type { FishAudioTranscriptionModelId } from './fish-audio-transcription-options';
|
|
16
16
|
import { VERSION } from './version';
|
|
17
17
|
|
|
18
|
-
export interface FishAudioProvider extends
|
|
18
|
+
export interface FishAudioProvider extends ProviderV4 {
|
|
19
19
|
(
|
|
20
20
|
modelId: FishAudioSpeechModelId,
|
|
21
21
|
settings?: {},
|
|
@@ -26,19 +26,19 @@ export interface FishAudioProvider extends ProviderV3 {
|
|
|
26
26
|
/**
|
|
27
27
|
* Creates a model for speech generation.
|
|
28
28
|
*/
|
|
29
|
-
speech(modelId: FishAudioSpeechModelId):
|
|
29
|
+
speech(modelId: FishAudioSpeechModelId): SpeechModelV4;
|
|
30
30
|
|
|
31
31
|
/**
|
|
32
32
|
* Creates a model for speech generation.
|
|
33
33
|
*
|
|
34
34
|
* Narrowed to required: Fish Audio always provides speech models.
|
|
35
35
|
*/
|
|
36
|
-
speechModel(modelId: FishAudioSpeechModelId):
|
|
36
|
+
speechModel(modelId: FishAudioSpeechModelId): SpeechModelV4;
|
|
37
37
|
|
|
38
38
|
/**
|
|
39
39
|
* Creates a model for transcription.
|
|
40
40
|
*/
|
|
41
|
-
transcription(modelId?: FishAudioTranscriptionModelId):
|
|
41
|
+
transcription(modelId?: FishAudioTranscriptionModelId): TranscriptionModelV4;
|
|
42
42
|
|
|
43
43
|
/**
|
|
44
44
|
* Creates a model for transcription.
|
|
@@ -47,7 +47,7 @@ export interface FishAudioProvider extends ProviderV3 {
|
|
|
47
47
|
*/
|
|
48
48
|
transcriptionModel(
|
|
49
49
|
modelId?: FishAudioTranscriptionModelId,
|
|
50
|
-
):
|
|
50
|
+
): TranscriptionModelV4;
|
|
51
51
|
}
|
|
52
52
|
|
|
53
53
|
export interface FishAudioProviderSettings {
|
|
@@ -122,13 +122,13 @@ export function createFishAudio(
|
|
|
122
122
|
};
|
|
123
123
|
};
|
|
124
124
|
|
|
125
|
-
provider.specificationVersion = '
|
|
125
|
+
provider.specificationVersion = 'v4' as const;
|
|
126
126
|
provider.speech = createSpeechModel;
|
|
127
127
|
provider.speechModel = createSpeechModel;
|
|
128
128
|
provider.transcription = createTranscriptionModel;
|
|
129
129
|
provider.transcriptionModel = createTranscriptionModel;
|
|
130
130
|
|
|
131
|
-
// Required
|
|
131
|
+
// Required ProviderV4 methods that are not supported
|
|
132
132
|
provider.languageModel = (modelId: string) => {
|
|
133
133
|
throw new NoSuchModelError({
|
|
134
134
|
modelId,
|
|
@@ -1,9 +1,12 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { SharedV4Warning, SpeechModelV4 } from '@ai-sdk/provider';
|
|
2
2
|
import {
|
|
3
3
|
combineHeaders,
|
|
4
4
|
createBinaryResponseHandler,
|
|
5
5
|
parseProviderOptions,
|
|
6
6
|
postJsonToApi,
|
|
7
|
+
serializeModelOptions,
|
|
8
|
+
WORKFLOW_DESERIALIZE,
|
|
9
|
+
WORKFLOW_SERIALIZE,
|
|
7
10
|
} from '@ai-sdk/provider-utils';
|
|
8
11
|
import type { FishAudioConfig } from './fish-audio-config';
|
|
9
12
|
import { fishAudioFailedResponseHandler } from './fish-audio-error';
|
|
@@ -39,7 +42,7 @@ function resolveFormat({
|
|
|
39
42
|
warnings,
|
|
40
43
|
}: {
|
|
41
44
|
outputFormat: string | undefined;
|
|
42
|
-
warnings:
|
|
45
|
+
warnings: SharedV4Warning[];
|
|
43
46
|
}): FishAudioSpeechFormat {
|
|
44
47
|
if (outputFormat == null) {
|
|
45
48
|
return DEFAULT_FORMAT;
|
|
@@ -60,13 +63,27 @@ function resolveFormat({
|
|
|
60
63
|
return matched;
|
|
61
64
|
}
|
|
62
65
|
|
|
63
|
-
export class FishAudioSpeechModel implements
|
|
64
|
-
readonly specificationVersion = '
|
|
66
|
+
export class FishAudioSpeechModel implements SpeechModelV4 {
|
|
67
|
+
readonly specificationVersion = 'v4';
|
|
65
68
|
|
|
66
69
|
get provider(): string {
|
|
67
70
|
return this.config.provider;
|
|
68
71
|
}
|
|
69
72
|
|
|
73
|
+
static [WORKFLOW_SERIALIZE](model: FishAudioSpeechModel) {
|
|
74
|
+
return serializeModelOptions({
|
|
75
|
+
modelId: model.modelId,
|
|
76
|
+
config: model.config,
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
static [WORKFLOW_DESERIALIZE](options: {
|
|
81
|
+
modelId: FishAudioSpeechModelId;
|
|
82
|
+
config: FishAudioSpeechModelConfig;
|
|
83
|
+
}) {
|
|
84
|
+
return new FishAudioSpeechModel(options.modelId, options.config);
|
|
85
|
+
}
|
|
86
|
+
|
|
70
87
|
constructor(
|
|
71
88
|
readonly modelId: FishAudioSpeechModelId,
|
|
72
89
|
private readonly config: FishAudioSpeechModelConfig,
|
|
@@ -80,8 +97,8 @@ export class FishAudioSpeechModel implements SpeechModelV3 {
|
|
|
80
97
|
language,
|
|
81
98
|
speed,
|
|
82
99
|
providerOptions,
|
|
83
|
-
}: Parameters<
|
|
84
|
-
const warnings:
|
|
100
|
+
}: Parameters<SpeechModelV4['doGenerate']>[0]) {
|
|
101
|
+
const warnings: SharedV4Warning[] = [];
|
|
85
102
|
|
|
86
103
|
const fishAudioOptions = await parseProviderOptions({
|
|
87
104
|
provider: 'fishAudio',
|
|
@@ -238,8 +255,8 @@ export class FishAudioSpeechModel implements SpeechModelV3 {
|
|
|
238
255
|
}
|
|
239
256
|
|
|
240
257
|
async doGenerate(
|
|
241
|
-
options: Parameters<
|
|
242
|
-
): Promise<Awaited<ReturnType<
|
|
258
|
+
options: Parameters<SpeechModelV4['doGenerate']>[0],
|
|
259
|
+
): Promise<Awaited<ReturnType<SpeechModelV4['doGenerate']>>> {
|
|
243
260
|
const currentDate = this.config._internal?.currentDate?.() ?? new Date();
|
|
244
261
|
const { requestBody, warnings } = await this.getArgs(options);
|
|
245
262
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { SharedV4Warning, TranscriptionModelV4 } from '@ai-sdk/provider';
|
|
2
2
|
import {
|
|
3
3
|
combineHeaders,
|
|
4
4
|
convertBase64ToUint8Array,
|
|
@@ -6,6 +6,9 @@ import {
|
|
|
6
6
|
mediaTypeToExtension,
|
|
7
7
|
parseProviderOptions,
|
|
8
8
|
postFormDataToApi,
|
|
9
|
+
serializeModelOptions,
|
|
10
|
+
WORKFLOW_DESERIALIZE,
|
|
11
|
+
WORKFLOW_SERIALIZE,
|
|
9
12
|
} from '@ai-sdk/provider-utils';
|
|
10
13
|
import { z } from 'zod/v4';
|
|
11
14
|
import type { FishAudioConfig } from './fish-audio-config';
|
|
@@ -19,13 +22,27 @@ interface FishAudioTranscriptionModelConfig extends FishAudioConfig {
|
|
|
19
22
|
};
|
|
20
23
|
}
|
|
21
24
|
|
|
22
|
-
export class FishAudioTranscriptionModel implements
|
|
23
|
-
readonly specificationVersion = '
|
|
25
|
+
export class FishAudioTranscriptionModel implements TranscriptionModelV4 {
|
|
26
|
+
readonly specificationVersion = 'v4';
|
|
24
27
|
|
|
25
28
|
get provider(): string {
|
|
26
29
|
return this.config.provider;
|
|
27
30
|
}
|
|
28
31
|
|
|
32
|
+
static [WORKFLOW_SERIALIZE](model: FishAudioTranscriptionModel) {
|
|
33
|
+
return serializeModelOptions({
|
|
34
|
+
modelId: model.modelId,
|
|
35
|
+
config: model.config,
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
static [WORKFLOW_DESERIALIZE](options: {
|
|
40
|
+
modelId: FishAudioTranscriptionModelId;
|
|
41
|
+
config: FishAudioTranscriptionModelConfig;
|
|
42
|
+
}) {
|
|
43
|
+
return new FishAudioTranscriptionModel(options.modelId, options.config);
|
|
44
|
+
}
|
|
45
|
+
|
|
29
46
|
constructor(
|
|
30
47
|
readonly modelId: FishAudioTranscriptionModelId,
|
|
31
48
|
private readonly config: FishAudioTranscriptionModelConfig,
|
|
@@ -35,8 +52,8 @@ export class FishAudioTranscriptionModel implements TranscriptionModelV3 {
|
|
|
35
52
|
audio,
|
|
36
53
|
mediaType,
|
|
37
54
|
providerOptions,
|
|
38
|
-
}: Parameters<
|
|
39
|
-
const warnings:
|
|
55
|
+
}: Parameters<TranscriptionModelV4['doGenerate']>[0]) {
|
|
56
|
+
const warnings: SharedV4Warning[] = [];
|
|
40
57
|
|
|
41
58
|
const fishAudioOptions = await parseProviderOptions({
|
|
42
59
|
provider: 'fishAudio',
|
|
@@ -72,8 +89,8 @@ export class FishAudioTranscriptionModel implements TranscriptionModelV3 {
|
|
|
72
89
|
}
|
|
73
90
|
|
|
74
91
|
async doGenerate(
|
|
75
|
-
options: Parameters<
|
|
76
|
-
): Promise<Awaited<ReturnType<
|
|
92
|
+
options: Parameters<TranscriptionModelV4['doGenerate']>[0],
|
|
93
|
+
): Promise<Awaited<ReturnType<TranscriptionModelV4['doGenerate']>>> {
|
|
77
94
|
const currentDate = this.config._internal?.currentDate?.() ?? new Date();
|
|
78
95
|
const { formData, warnings } = await this.getArgs(options);
|
|
79
96
|
|