@ai-sdk/fal 3.0.0-beta.3 → 3.0.0-beta.31
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 +247 -8
- package/README.md +2 -0
- package/dist/index.d.ts +8 -8
- package/dist/index.js +308 -238
- package/dist/index.js.map +1 -1
- package/package.json +11 -11
- package/src/fal-config.ts +2 -2
- package/src/{fal-image-options.ts → fal-image-model-options.ts} +5 -1
- package/src/fal-image-model.ts +30 -13
- package/src/fal-provider.ts +18 -18
- package/src/fal-speech-model-options.ts +21 -0
- package/src/fal-speech-model.ts +28 -30
- package/src/fal-transcription-model-options.ts +43 -0
- package/src/fal-transcription-model.ts +31 -55
- package/src/fal-video-model-options.ts +39 -0
- package/src/fal-video-model.ts +13 -48
- package/src/index.ts +4 -4
- package/dist/index.d.mts +0 -156
- package/dist/index.mjs +0 -1126
- package/dist/index.mjs.map +0 -1
package/src/fal-provider.ts
CHANGED
|
@@ -1,24 +1,24 @@
|
|
|
1
1
|
import {
|
|
2
|
-
Experimental_VideoModelV3,
|
|
3
|
-
ImageModelV3,
|
|
4
2
|
NoSuchModelError,
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
3
|
+
type Experimental_VideoModelV4,
|
|
4
|
+
type ImageModelV4,
|
|
5
|
+
type ProviderV4,
|
|
6
|
+
type SpeechModelV4,
|
|
7
|
+
type TranscriptionModelV4,
|
|
8
8
|
} from '@ai-sdk/provider';
|
|
9
|
-
import type { FetchFunction } from '@ai-sdk/provider-utils';
|
|
10
9
|
import {
|
|
11
10
|
withoutTrailingSlash,
|
|
12
11
|
withUserAgentSuffix,
|
|
12
|
+
type FetchFunction,
|
|
13
13
|
} from '@ai-sdk/provider-utils';
|
|
14
14
|
import { FalImageModel } from './fal-image-model';
|
|
15
|
-
import { FalImageModelId } from './fal-image-settings';
|
|
16
|
-
import { FalTranscriptionModelId } from './fal-transcription-options';
|
|
15
|
+
import type { FalImageModelId } from './fal-image-settings';
|
|
16
|
+
import type { FalTranscriptionModelId } from './fal-transcription-options';
|
|
17
17
|
import { FalTranscriptionModel } from './fal-transcription-model';
|
|
18
|
-
import { FalSpeechModelId } from './fal-speech-settings';
|
|
18
|
+
import type { FalSpeechModelId } from './fal-speech-settings';
|
|
19
19
|
import { FalSpeechModel } from './fal-speech-model';
|
|
20
20
|
import { FalVideoModel } from './fal-video-model';
|
|
21
|
-
import { FalVideoModelId } from './fal-video-settings';
|
|
21
|
+
import type { FalVideoModelId } from './fal-video-settings';
|
|
22
22
|
import { VERSION } from './version';
|
|
23
23
|
|
|
24
24
|
export interface FalProviderSettings {
|
|
@@ -46,36 +46,36 @@ export interface FalProviderSettings {
|
|
|
46
46
|
fetch?: FetchFunction;
|
|
47
47
|
}
|
|
48
48
|
|
|
49
|
-
export interface FalProvider extends
|
|
49
|
+
export interface FalProvider extends ProviderV4 {
|
|
50
50
|
/**
|
|
51
51
|
* Creates a model for image generation.
|
|
52
52
|
*/
|
|
53
|
-
image(modelId: FalImageModelId):
|
|
53
|
+
image(modelId: FalImageModelId): ImageModelV4;
|
|
54
54
|
|
|
55
55
|
/**
|
|
56
56
|
* Creates a model for image generation.
|
|
57
57
|
*/
|
|
58
|
-
imageModel(modelId: FalImageModelId):
|
|
58
|
+
imageModel(modelId: FalImageModelId): ImageModelV4;
|
|
59
59
|
|
|
60
60
|
/**
|
|
61
61
|
* Creates a model for transcription.
|
|
62
62
|
*/
|
|
63
|
-
transcription(modelId: FalTranscriptionModelId):
|
|
63
|
+
transcription(modelId: FalTranscriptionModelId): TranscriptionModelV4;
|
|
64
64
|
|
|
65
65
|
/**
|
|
66
66
|
* Creates a model for video generation.
|
|
67
67
|
*/
|
|
68
|
-
video(modelId: FalVideoModelId):
|
|
68
|
+
video(modelId: FalVideoModelId): Experimental_VideoModelV4;
|
|
69
69
|
|
|
70
70
|
/**
|
|
71
71
|
* Creates a model for video generation.
|
|
72
72
|
*/
|
|
73
|
-
videoModel(modelId: FalVideoModelId):
|
|
73
|
+
videoModel(modelId: FalVideoModelId): Experimental_VideoModelV4;
|
|
74
74
|
|
|
75
75
|
/**
|
|
76
76
|
* Creates a model for speech generation.
|
|
77
77
|
*/
|
|
78
|
-
speech(modelId: FalSpeechModelId):
|
|
78
|
+
speech(modelId: FalSpeechModelId): SpeechModelV4;
|
|
79
79
|
|
|
80
80
|
/**
|
|
81
81
|
* @deprecated Use `embeddingModel` instead.
|
|
@@ -182,7 +182,7 @@ export function createFal(options: FalProviderSettings = {}): FalProvider {
|
|
|
182
182
|
};
|
|
183
183
|
|
|
184
184
|
return {
|
|
185
|
-
specificationVersion: '
|
|
185
|
+
specificationVersion: 'v4' as const,
|
|
186
186
|
imageModel: createImageModel,
|
|
187
187
|
image: createImageModel,
|
|
188
188
|
languageModel: (modelId: string) => {
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { z } from 'zod/v4';
|
|
2
|
+
import { FAL_EMOTIONS, FAL_LANGUAGE_BOOSTS } from './fal-api-types';
|
|
3
|
+
|
|
4
|
+
export const falSpeechModelOptionsSchema = z.looseObject({
|
|
5
|
+
voice_setting: z
|
|
6
|
+
.object({
|
|
7
|
+
speed: z.number().nullish(),
|
|
8
|
+
vol: z.number().nullish(),
|
|
9
|
+
voice_id: z.string().nullish(),
|
|
10
|
+
pitch: z.number().nullish(),
|
|
11
|
+
english_normalization: z.boolean().nullish(),
|
|
12
|
+
emotion: z.enum(FAL_EMOTIONS).nullish(),
|
|
13
|
+
})
|
|
14
|
+
.partial()
|
|
15
|
+
.nullish(),
|
|
16
|
+
audio_setting: z.record(z.string(), z.unknown()).nullish(),
|
|
17
|
+
language_boost: z.enum(FAL_LANGUAGE_BOOSTS).nullish(),
|
|
18
|
+
pronunciation_dict: z.record(z.string(), z.string()).nullish(),
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
export type FalSpeechModelOptions = z.infer<typeof falSpeechModelOptionsSchema>;
|
package/src/fal-speech-model.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { SpeechModelV4, SharedV4Warning } from '@ai-sdk/provider';
|
|
2
2
|
import {
|
|
3
3
|
combineHeaders,
|
|
4
4
|
createBinaryResponseHandler,
|
|
@@ -7,31 +7,15 @@ import {
|
|
|
7
7
|
getFromApi,
|
|
8
8
|
parseProviderOptions,
|
|
9
9
|
postJsonToApi,
|
|
10
|
+
serializeModelOptions,
|
|
11
|
+
WORKFLOW_SERIALIZE,
|
|
12
|
+
WORKFLOW_DESERIALIZE,
|
|
10
13
|
} from '@ai-sdk/provider-utils';
|
|
11
14
|
import { z } from 'zod/v4';
|
|
12
|
-
import { FalConfig } from './fal-config';
|
|
15
|
+
import type { FalConfig } from './fal-config';
|
|
13
16
|
import { falFailedResponseHandler } from './fal-error';
|
|
14
|
-
import {
|
|
15
|
-
import { FalSpeechModelId } from './fal-speech-settings';
|
|
16
|
-
|
|
17
|
-
const falSpeechModelOptionsSchema = z.looseObject({
|
|
18
|
-
voice_setting: z
|
|
19
|
-
.object({
|
|
20
|
-
speed: z.number().nullish(),
|
|
21
|
-
vol: z.number().nullish(),
|
|
22
|
-
voice_id: z.string().nullish(),
|
|
23
|
-
pitch: z.number().nullish(),
|
|
24
|
-
english_normalization: z.boolean().nullish(),
|
|
25
|
-
emotion: z.enum(FAL_EMOTIONS).nullish(),
|
|
26
|
-
})
|
|
27
|
-
.partial()
|
|
28
|
-
.nullish(),
|
|
29
|
-
audio_setting: z.record(z.string(), z.unknown()).nullish(),
|
|
30
|
-
language_boost: z.enum(FAL_LANGUAGE_BOOSTS).nullish(),
|
|
31
|
-
pronunciation_dict: z.record(z.string(), z.string()).nullish(),
|
|
32
|
-
});
|
|
33
|
-
|
|
34
|
-
export type FalSpeechModelOptions = z.infer<typeof falSpeechModelOptionsSchema>;
|
|
17
|
+
import { falSpeechModelOptionsSchema } from './fal-speech-model-options';
|
|
18
|
+
import type { FalSpeechModelId } from './fal-speech-settings';
|
|
35
19
|
|
|
36
20
|
interface FalSpeechModelConfig extends FalConfig {
|
|
37
21
|
_internal?: {
|
|
@@ -39,13 +23,27 @@ interface FalSpeechModelConfig extends FalConfig {
|
|
|
39
23
|
};
|
|
40
24
|
}
|
|
41
25
|
|
|
42
|
-
export class FalSpeechModel implements
|
|
43
|
-
readonly specificationVersion = '
|
|
26
|
+
export class FalSpeechModel implements SpeechModelV4 {
|
|
27
|
+
readonly specificationVersion = 'v4';
|
|
44
28
|
|
|
45
29
|
get provider(): string {
|
|
46
30
|
return this.config.provider;
|
|
47
31
|
}
|
|
48
32
|
|
|
33
|
+
static [WORKFLOW_SERIALIZE](model: FalSpeechModel) {
|
|
34
|
+
return serializeModelOptions({
|
|
35
|
+
modelId: model.modelId,
|
|
36
|
+
config: model.config,
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
static [WORKFLOW_DESERIALIZE](options: {
|
|
41
|
+
modelId: FalSpeechModelId;
|
|
42
|
+
config: FalSpeechModelConfig;
|
|
43
|
+
}) {
|
|
44
|
+
return new FalSpeechModel(options.modelId, options.config);
|
|
45
|
+
}
|
|
46
|
+
|
|
49
47
|
constructor(
|
|
50
48
|
readonly modelId: FalSpeechModelId,
|
|
51
49
|
private readonly config: FalSpeechModelConfig,
|
|
@@ -58,8 +56,8 @@ export class FalSpeechModel implements SpeechModelV3 {
|
|
|
58
56
|
speed,
|
|
59
57
|
language,
|
|
60
58
|
providerOptions,
|
|
61
|
-
}: Parameters<
|
|
62
|
-
const warnings:
|
|
59
|
+
}: Parameters<SpeechModelV4['doGenerate']>[0]) {
|
|
60
|
+
const warnings: SharedV4Warning[] = [];
|
|
63
61
|
|
|
64
62
|
const falOptions = await parseProviderOptions({
|
|
65
63
|
provider: 'fal',
|
|
@@ -98,8 +96,8 @@ export class FalSpeechModel implements SpeechModelV3 {
|
|
|
98
96
|
}
|
|
99
97
|
|
|
100
98
|
async doGenerate(
|
|
101
|
-
options: Parameters<
|
|
102
|
-
): Promise<Awaited<ReturnType<
|
|
99
|
+
options: Parameters<SpeechModelV4['doGenerate']>[0],
|
|
100
|
+
): Promise<Awaited<ReturnType<SpeechModelV4['doGenerate']>>> {
|
|
103
101
|
const currentDate = this.config._internal?.currentDate?.() ?? new Date();
|
|
104
102
|
const { requestBody, warnings } = await this.getArgs(options);
|
|
105
103
|
|
|
@@ -112,7 +110,7 @@ export class FalSpeechModel implements SpeechModelV3 {
|
|
|
112
110
|
path: `https://fal.run/${this.modelId}`,
|
|
113
111
|
modelId: this.modelId,
|
|
114
112
|
}),
|
|
115
|
-
headers: combineHeaders(this.config.headers(), options.headers),
|
|
113
|
+
headers: combineHeaders(this.config.headers?.(), options.headers),
|
|
116
114
|
body: requestBody,
|
|
117
115
|
failedResponseHandler: falFailedResponseHandler,
|
|
118
116
|
successfulResponseHandler: createJsonResponseHandler(
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { z } from 'zod/v4';
|
|
2
|
+
|
|
3
|
+
// https://fal.ai/models/fal-ai/whisper/api?platform=http
|
|
4
|
+
export const falTranscriptionModelOptionsSchema = z.object({
|
|
5
|
+
/**
|
|
6
|
+
* Language of the audio file. If set to null, the language will be automatically detected. Defaults to null.
|
|
7
|
+
*
|
|
8
|
+
* If translate is selected as the task, the audio will be translated to English, regardless of the language selected.
|
|
9
|
+
*/
|
|
10
|
+
language: z
|
|
11
|
+
.union([z.enum(['en']), z.string()])
|
|
12
|
+
.nullish()
|
|
13
|
+
.default('en'),
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Whether to diarize the audio file. Defaults to true.
|
|
17
|
+
*/
|
|
18
|
+
diarize: z.boolean().nullish().default(true),
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Level of the chunks to return. Either segment or word. Default value: "segment"
|
|
22
|
+
*/
|
|
23
|
+
chunkLevel: z.enum(['segment', 'word']).nullish().default('segment'),
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Version of the model to use. All of the models are the Whisper large variant. Default value: "3"
|
|
27
|
+
*/
|
|
28
|
+
version: z.enum(['3']).nullish().default('3'),
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Default value: 64
|
|
32
|
+
*/
|
|
33
|
+
batchSize: z.number().nullish().default(64),
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Number of speakers in the audio file. Defaults to null. If not provided, the number of speakers will be automatically detected.
|
|
37
|
+
*/
|
|
38
|
+
numSpeakers: z.number().nullable().nullish(),
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
export type FalTranscriptionModelOptions = z.infer<
|
|
42
|
+
typeof falTranscriptionModelOptionsSchema
|
|
43
|
+
>;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
AISDKError,
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
type TranscriptionModelV4,
|
|
4
|
+
type SharedV4Warning,
|
|
5
5
|
} from '@ai-sdk/provider';
|
|
6
6
|
import {
|
|
7
7
|
combineHeaders,
|
|
@@ -12,54 +12,16 @@ import {
|
|
|
12
12
|
getFromApi,
|
|
13
13
|
parseProviderOptions,
|
|
14
14
|
postJsonToApi,
|
|
15
|
+
serializeModelOptions,
|
|
16
|
+
WORKFLOW_SERIALIZE,
|
|
17
|
+
WORKFLOW_DESERIALIZE,
|
|
15
18
|
} from '@ai-sdk/provider-utils';
|
|
16
19
|
import { z } from 'zod/v4';
|
|
17
|
-
import { FalConfig } from './fal-config';
|
|
20
|
+
import type { FalConfig } from './fal-config';
|
|
18
21
|
import { falErrorDataSchema, falFailedResponseHandler } from './fal-error';
|
|
19
|
-
import {
|
|
20
|
-
import {
|
|
21
|
-
|
|
22
|
-
// https://fal.ai/models/fal-ai/whisper/api?platform=http
|
|
23
|
-
const falTranscriptionModelOptionsSchema = z.object({
|
|
24
|
-
/**
|
|
25
|
-
* Language of the audio file. If set to null, the language will be automatically detected. Defaults to null.
|
|
26
|
-
*
|
|
27
|
-
* If translate is selected as the task, the audio will be translated to English, regardless of the language selected.
|
|
28
|
-
*/
|
|
29
|
-
language: z
|
|
30
|
-
.union([z.enum(['en']), z.string()])
|
|
31
|
-
.nullish()
|
|
32
|
-
.default('en'),
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
* Whether to diarize the audio file. Defaults to true.
|
|
36
|
-
*/
|
|
37
|
-
diarize: z.boolean().nullish().default(true),
|
|
38
|
-
|
|
39
|
-
/**
|
|
40
|
-
* Level of the chunks to return. Either segment or word. Default value: "segment"
|
|
41
|
-
*/
|
|
42
|
-
chunkLevel: z.enum(['segment', 'word']).nullish().default('segment'),
|
|
43
|
-
|
|
44
|
-
/**
|
|
45
|
-
* Version of the model to use. All of the models are the Whisper large variant. Default value: "3"
|
|
46
|
-
*/
|
|
47
|
-
version: z.enum(['3']).nullish().default('3'),
|
|
48
|
-
|
|
49
|
-
/**
|
|
50
|
-
* Default value: 64
|
|
51
|
-
*/
|
|
52
|
-
batchSize: z.number().nullish().default(64),
|
|
53
|
-
|
|
54
|
-
/**
|
|
55
|
-
* Number of speakers in the audio file. Defaults to null. If not provided, the number of speakers will be automatically detected.
|
|
56
|
-
*/
|
|
57
|
-
numSpeakers: z.number().nullable().nullish(),
|
|
58
|
-
});
|
|
59
|
-
|
|
60
|
-
export type FalTranscriptionModelOptions = z.infer<
|
|
61
|
-
typeof falTranscriptionModelOptionsSchema
|
|
62
|
-
>;
|
|
22
|
+
import { falTranscriptionModelOptionsSchema } from './fal-transcription-model-options';
|
|
23
|
+
import type { FalTranscriptionModelId } from './fal-transcription-options';
|
|
24
|
+
import type { FalTranscriptionAPITypes } from './fal-api-types';
|
|
63
25
|
|
|
64
26
|
interface FalTranscriptionModelConfig extends FalConfig {
|
|
65
27
|
_internal?: {
|
|
@@ -67,13 +29,27 @@ interface FalTranscriptionModelConfig extends FalConfig {
|
|
|
67
29
|
};
|
|
68
30
|
}
|
|
69
31
|
|
|
70
|
-
export class FalTranscriptionModel implements
|
|
71
|
-
readonly specificationVersion = '
|
|
32
|
+
export class FalTranscriptionModel implements TranscriptionModelV4 {
|
|
33
|
+
readonly specificationVersion = 'v4';
|
|
72
34
|
|
|
73
35
|
get provider(): string {
|
|
74
36
|
return this.config.provider;
|
|
75
37
|
}
|
|
76
38
|
|
|
39
|
+
static [WORKFLOW_SERIALIZE](model: FalTranscriptionModel) {
|
|
40
|
+
return serializeModelOptions({
|
|
41
|
+
modelId: model.modelId,
|
|
42
|
+
config: model.config,
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
static [WORKFLOW_DESERIALIZE](options: {
|
|
47
|
+
modelId: FalTranscriptionModelId;
|
|
48
|
+
config: FalTranscriptionModelConfig;
|
|
49
|
+
}) {
|
|
50
|
+
return new FalTranscriptionModel(options.modelId, options.config);
|
|
51
|
+
}
|
|
52
|
+
|
|
77
53
|
constructor(
|
|
78
54
|
readonly modelId: FalTranscriptionModelId,
|
|
79
55
|
private readonly config: FalTranscriptionModelConfig,
|
|
@@ -81,8 +57,8 @@ export class FalTranscriptionModel implements TranscriptionModelV3 {
|
|
|
81
57
|
|
|
82
58
|
private async getArgs({
|
|
83
59
|
providerOptions,
|
|
84
|
-
}: Parameters<
|
|
85
|
-
const warnings:
|
|
60
|
+
}: Parameters<TranscriptionModelV4['doGenerate']>[0]) {
|
|
61
|
+
const warnings: SharedV4Warning[] = [];
|
|
86
62
|
|
|
87
63
|
// Parse provider options
|
|
88
64
|
const falOptions = await parseProviderOptions({
|
|
@@ -121,8 +97,8 @@ export class FalTranscriptionModel implements TranscriptionModelV3 {
|
|
|
121
97
|
}
|
|
122
98
|
|
|
123
99
|
async doGenerate(
|
|
124
|
-
options: Parameters<
|
|
125
|
-
): Promise<Awaited<ReturnType<
|
|
100
|
+
options: Parameters<TranscriptionModelV4['doGenerate']>[0],
|
|
101
|
+
): Promise<Awaited<ReturnType<TranscriptionModelV4['doGenerate']>>> {
|
|
126
102
|
const currentDate = this.config._internal?.currentDate?.() ?? new Date();
|
|
127
103
|
const { body, warnings } = await this.getArgs(options);
|
|
128
104
|
|
|
@@ -138,7 +114,7 @@ export class FalTranscriptionModel implements TranscriptionModelV3 {
|
|
|
138
114
|
path: `https://queue.fal.run/fal-ai/${this.modelId}`,
|
|
139
115
|
modelId: this.modelId,
|
|
140
116
|
}),
|
|
141
|
-
headers: combineHeaders(this.config.headers(), options.headers),
|
|
117
|
+
headers: combineHeaders(this.config.headers?.(), options.headers),
|
|
142
118
|
body: {
|
|
143
119
|
...body,
|
|
144
120
|
audio_url: audioUrl,
|
|
@@ -170,7 +146,7 @@ export class FalTranscriptionModel implements TranscriptionModelV3 {
|
|
|
170
146
|
path: `https://queue.fal.run/fal-ai/${this.modelId}/requests/${queueResponse.request_id}`,
|
|
171
147
|
modelId: this.modelId,
|
|
172
148
|
}),
|
|
173
|
-
headers: combineHeaders(this.config.headers(), options.headers),
|
|
149
|
+
headers: combineHeaders(this.config.headers?.(), options.headers),
|
|
174
150
|
failedResponseHandler: async ({
|
|
175
151
|
requestBodyValues,
|
|
176
152
|
response,
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { lazySchema, zodSchema } from '@ai-sdk/provider-utils';
|
|
2
|
+
import { z } from 'zod/v4';
|
|
3
|
+
|
|
4
|
+
export type FalVideoModelOptions = {
|
|
5
|
+
loop?: boolean | null;
|
|
6
|
+
motionStrength?: number | null;
|
|
7
|
+
pollIntervalMs?: number | null;
|
|
8
|
+
pollTimeoutMs?: number | null;
|
|
9
|
+
resolution?: string | null;
|
|
10
|
+
negativePrompt?: string | null;
|
|
11
|
+
promptOptimizer?: boolean | null;
|
|
12
|
+
[key: string]: unknown; // For passthrough
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
// Provider options schema for FAL video generation
|
|
16
|
+
export const falVideoModelOptionsSchema = lazySchema(() =>
|
|
17
|
+
zodSchema(
|
|
18
|
+
z
|
|
19
|
+
.object({
|
|
20
|
+
// Video loop - only for Luma models
|
|
21
|
+
loop: z.boolean().nullish(),
|
|
22
|
+
|
|
23
|
+
// Motion strength (provider-specific)
|
|
24
|
+
motionStrength: z.number().min(0).max(1).nullish(),
|
|
25
|
+
|
|
26
|
+
// Polling configuration
|
|
27
|
+
pollIntervalMs: z.number().positive().nullish(),
|
|
28
|
+
pollTimeoutMs: z.number().positive().nullish(),
|
|
29
|
+
|
|
30
|
+
// Resolution (model-specific, e.g., '480p', '720p', '1080p')
|
|
31
|
+
resolution: z.string().nullish(),
|
|
32
|
+
|
|
33
|
+
// Model-specific parameters
|
|
34
|
+
negativePrompt: z.string().nullish(),
|
|
35
|
+
promptOptimizer: z.boolean().nullish(),
|
|
36
|
+
})
|
|
37
|
+
.passthrough(),
|
|
38
|
+
),
|
|
39
|
+
);
|
package/src/fal-video-model.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
AISDKError,
|
|
3
|
-
type
|
|
4
|
-
type
|
|
3
|
+
type Experimental_VideoModelV4,
|
|
4
|
+
type SharedV4Warning,
|
|
5
5
|
} from '@ai-sdk/provider';
|
|
6
6
|
import {
|
|
7
7
|
combineHeaders,
|
|
@@ -10,61 +10,26 @@ import {
|
|
|
10
10
|
createJsonResponseHandler,
|
|
11
11
|
delay,
|
|
12
12
|
getFromApi,
|
|
13
|
-
lazySchema,
|
|
14
13
|
parseProviderOptions,
|
|
15
14
|
postJsonToApi,
|
|
16
|
-
zodSchema,
|
|
17
15
|
} from '@ai-sdk/provider-utils';
|
|
18
16
|
import { z } from 'zod/v4';
|
|
19
17
|
import type { FalConfig } from './fal-config';
|
|
20
18
|
import { falErrorDataSchema, falFailedResponseHandler } from './fal-error';
|
|
19
|
+
import {
|
|
20
|
+
falVideoModelOptionsSchema,
|
|
21
|
+
type FalVideoModelOptions,
|
|
22
|
+
} from './fal-video-model-options';
|
|
21
23
|
import type { FalVideoModelId } from './fal-video-settings';
|
|
22
24
|
|
|
23
|
-
export type FalVideoModelOptions = {
|
|
24
|
-
loop?: boolean | null;
|
|
25
|
-
motionStrength?: number | null;
|
|
26
|
-
pollIntervalMs?: number | null;
|
|
27
|
-
pollTimeoutMs?: number | null;
|
|
28
|
-
resolution?: string | null;
|
|
29
|
-
negativePrompt?: string | null;
|
|
30
|
-
promptOptimizer?: boolean | null;
|
|
31
|
-
[key: string]: unknown; // For passthrough
|
|
32
|
-
};
|
|
33
|
-
|
|
34
|
-
// Provider options schema for FAL video generation
|
|
35
|
-
export const falVideoModelOptionsSchema = lazySchema(() =>
|
|
36
|
-
zodSchema(
|
|
37
|
-
z
|
|
38
|
-
.object({
|
|
39
|
-
// Video loop - only for Luma models
|
|
40
|
-
loop: z.boolean().nullish(),
|
|
41
|
-
|
|
42
|
-
// Motion strength (provider-specific)
|
|
43
|
-
motionStrength: z.number().min(0).max(1).nullish(),
|
|
44
|
-
|
|
45
|
-
// Polling configuration
|
|
46
|
-
pollIntervalMs: z.number().positive().nullish(),
|
|
47
|
-
pollTimeoutMs: z.number().positive().nullish(),
|
|
48
|
-
|
|
49
|
-
// Resolution (model-specific, e.g., '480p', '720p', '1080p')
|
|
50
|
-
resolution: z.string().nullish(),
|
|
51
|
-
|
|
52
|
-
// Model-specific parameters
|
|
53
|
-
negativePrompt: z.string().nullish(),
|
|
54
|
-
promptOptimizer: z.boolean().nullish(),
|
|
55
|
-
})
|
|
56
|
-
.passthrough(),
|
|
57
|
-
),
|
|
58
|
-
);
|
|
59
|
-
|
|
60
25
|
interface FalVideoModelConfig extends FalConfig {
|
|
61
26
|
_internal?: {
|
|
62
27
|
currentDate?: () => Date;
|
|
63
28
|
};
|
|
64
29
|
}
|
|
65
30
|
|
|
66
|
-
export class FalVideoModel implements
|
|
67
|
-
readonly specificationVersion = '
|
|
31
|
+
export class FalVideoModel implements Experimental_VideoModelV4 {
|
|
32
|
+
readonly specificationVersion = 'v4';
|
|
68
33
|
readonly maxVideosPerCall = 1; // FAL video models support 1 video at a time
|
|
69
34
|
|
|
70
35
|
get provider(): string {
|
|
@@ -81,10 +46,10 @@ export class FalVideoModel implements Experimental_VideoModelV3 {
|
|
|
81
46
|
) {}
|
|
82
47
|
|
|
83
48
|
async doGenerate(
|
|
84
|
-
options: Parameters<
|
|
85
|
-
): Promise<Awaited<ReturnType<
|
|
49
|
+
options: Parameters<Experimental_VideoModelV4['doGenerate']>[0],
|
|
50
|
+
): Promise<Awaited<ReturnType<Experimental_VideoModelV4['doGenerate']>>> {
|
|
86
51
|
const currentDate = this.config._internal?.currentDate?.() ?? new Date();
|
|
87
|
-
const warnings:
|
|
52
|
+
const warnings: SharedV4Warning[] = [];
|
|
88
53
|
|
|
89
54
|
const falOptions = (await parseProviderOptions({
|
|
90
55
|
provider: 'fal',
|
|
@@ -158,7 +123,7 @@ export class FalVideoModel implements Experimental_VideoModelV3 {
|
|
|
158
123
|
path: `https://queue.fal.run/fal-ai/${this.normalizedModelId}`,
|
|
159
124
|
modelId: this.modelId,
|
|
160
125
|
}),
|
|
161
|
-
headers: combineHeaders(this.config.headers(), options.headers),
|
|
126
|
+
headers: combineHeaders(this.config.headers?.(), options.headers),
|
|
162
127
|
body,
|
|
163
128
|
failedResponseHandler: falFailedResponseHandler,
|
|
164
129
|
successfulResponseHandler:
|
|
@@ -189,7 +154,7 @@ export class FalVideoModel implements Experimental_VideoModelV3 {
|
|
|
189
154
|
path: responseUrl,
|
|
190
155
|
modelId: this.modelId,
|
|
191
156
|
}),
|
|
192
|
-
headers: combineHeaders(this.config.headers(), options.headers),
|
|
157
|
+
headers: combineHeaders(this.config.headers?.(), options.headers),
|
|
193
158
|
failedResponseHandler: async ({
|
|
194
159
|
response,
|
|
195
160
|
url,
|
package/src/index.ts
CHANGED
|
@@ -4,13 +4,13 @@ export type {
|
|
|
4
4
|
FalImageModelOptions,
|
|
5
5
|
/** @deprecated Use `FalImageModelOptions` instead. */
|
|
6
6
|
FalImageModelOptions as FalImageProviderOptions,
|
|
7
|
-
} from './fal-image-options';
|
|
8
|
-
export type { FalSpeechModelOptions } from './fal-speech-model';
|
|
9
|
-
export type { FalTranscriptionModelOptions } from './fal-transcription-model';
|
|
7
|
+
} from './fal-image-model-options';
|
|
8
|
+
export type { FalSpeechModelOptions } from './fal-speech-model-options';
|
|
9
|
+
export type { FalTranscriptionModelOptions } from './fal-transcription-model-options';
|
|
10
10
|
export type {
|
|
11
11
|
FalVideoModelOptions,
|
|
12
12
|
/** @deprecated Use `FalVideoModelOptions` instead. */
|
|
13
13
|
FalVideoModelOptions as FalVideoProviderOptions,
|
|
14
|
-
} from './fal-video-model';
|
|
14
|
+
} from './fal-video-model-options';
|
|
15
15
|
export type { FalVideoModelId } from './fal-video-settings';
|
|
16
16
|
export { VERSION } from './version';
|